summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp')
-rw-r--r--c/src/lib/libbsp/i386/i386ex/Makefile.in6
-rw-r--r--c/src/lib/libbsp/i386/i386ex/network/Makefile.in60
-rw-r--r--c/src/lib/libbsp/i386/i386ex/network/netexterns.h5
-rw-r--r--c/src/lib/libbsp/i386/i386ex/network/network.c463
-rw-r--r--c/src/lib/libbsp/i386/i386ex/network/uti596.h24
-rw-r--r--c/src/lib/libbsp/i386/i386ex/wrapup/Makefile.in6
6 files changed, 399 insertions, 165 deletions
diff --git a/c/src/lib/libbsp/i386/i386ex/Makefile.in b/c/src/lib/libbsp/i386/i386ex/Makefile.in
index 2000a7c0ca..22f260cb9e 100644
--- a/c/src/lib/libbsp/i386/i386ex/Makefile.in
+++ b/c/src/lib/libbsp/i386/i386ex/Makefile.in
@@ -11,9 +11,9 @@ PROJECT_ROOT = @PROJECT_ROOT@
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/directory.cfg
-# # We only build the Network library if HAS_NETWORKING was defined
-# NETWORK_yes_V = network
-# NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
+# We only build the Network library if HAS_NETWORKING was defined
+NETWORK_yes_V = network
+NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# wrapup is the one that actually builds and installs the library
# from the individual .rel files built in other directories
diff --git a/c/src/lib/libbsp/i386/i386ex/network/Makefile.in b/c/src/lib/libbsp/i386/i386ex/network/Makefile.in
new file mode 100644
index 0000000000..0e32218ea3
--- /dev/null
+++ b/c/src/lib/libbsp/i386/i386ex/network/Makefile.in
@@ -0,0 +1,60 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/network.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=network
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+# Assembly source names, if any, go here -- minus the .s
+S_PIECES=
+S_FILES=$(S_PIECES:%=%.s)
+S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o)
+
+SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
+OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS += -O0
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
diff --git a/c/src/lib/libbsp/i386/i386ex/network/netexterns.h b/c/src/lib/libbsp/i386/i386ex/network/netexterns.h
index 26ddc806a9..76259b7bae 100644
--- a/c/src/lib/libbsp/i386/i386ex/network/netexterns.h
+++ b/c/src/lib/libbsp/i386/i386ex/network/netexterns.h
@@ -1,3 +1,7 @@
+/*
+ * $Id$
+ */
+
#ifndef NET_EXTERNS_H
#define NET_EXTERNS_H
@@ -9,5 +13,6 @@ extern int uti596_attach(struct rtems_bsdnet_ifconfig *);
extern int uti596dump(char * );
extern void uti596reset(void);
extern void uti596Diagnose(int);
+extern void uti596_request_reset(void);
#endif
diff --git a/c/src/lib/libbsp/i386/i386ex/network/network.c b/c/src/lib/libbsp/i386/i386ex/network/network.c
index b126e4e623..5a97a00a11 100644
--- a/c/src/lib/libbsp/i386/i386ex/network/network.c
+++ b/c/src/lib/libbsp/i386/i386ex/network/network.c
@@ -1,4 +1,8 @@
-/* uti596.c: An 82596 ethernet driver for rtems-bsd. */
+/* uti596.c: An 82596 ethernet driver for rtems-bsd.
+ *
+ * $Id$
+ */
+
void dump_scb(void);
#ifdef DBG_VERSION
@@ -10,15 +14,10 @@ void dump_scb(void);
#define KERNEL
-int forceResetRX = 0;
-int forceResetTX = 0;
-
-
/*
EII: Oct 16 : Version 0.0
-
*/
#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
@@ -29,9 +28,6 @@ int forceResetTX = 0;
struct i596_rfd *pISR_Rfd;
-
-#define MY_PRINT_1( msg, p1 ) { char buffer[80]; int i,j; sprintf(buffer, msg, p1 );j=strlen(buffer); for ( i=0;i<j;i++) outbyte(buffer[i]); }
-
void show_buffers (void);
void show_queues(void);
@@ -67,13 +63,11 @@ int count_rx = 0;
#include <asm.h>
-int reset_bit_test = 0;
/* #include "../misc/utils.h" */
static struct uti596_softc uti596_softc;
-void uti596rxStart(int);
int uti596packetNumber = 0;
static int scbStatus;
@@ -108,6 +102,7 @@ char uti596initSetup[] = {
#define INTERRUPT_EVENT RTEMS_EVENT_1
#define START_TRANSMIT_EVENT RTEMS_EVENT_2
+#define NIC_RESET_EVENT RTEMS_EVENT_3
#define RBUF_SIZE 1520
@@ -130,6 +125,7 @@ rtems_isr uti596DynamicInterruptHandler (rtems_vector_number);
void uti596_txDaemon (void *);
void uti596_rxDaemon (void *);
+void uti596_resetDaemon (void *);
void uti596_stop (struct uti596_softc *);
static void uti596_start (struct ifnet *);
@@ -139,6 +135,7 @@ void uti596reset (void);
void uti596_stats (struct uti596_softc *);
void uti596_initialize_hardware(struct uti596_softc *);
+void uti596_reset_hardware(struct uti596_softc *);
void uti596clearListStatus(struct i596_rfd *);
void uti596addPolledCmd(struct i596_cmd *);
@@ -172,15 +169,34 @@ void send_packet(struct ifnet *, struct mbuf *);
break; \
} \
}
+/*************************************************************************/
+
+void
+uti596_request_reset(void){
+ uti596_softc.nic_reset = 0;
+ sc = rtems_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT);
+ if ( sc != RTEMS_SUCCESSFUL )
+ rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc));
+}
+
+static void uti596_maskOn(const rtems_irq_connect_data* irq)
+{
+ /*
+ * code should be moved from initialize_hardware
+ * to this location ?
+ */
+ (void) BSP_irq_enable_at_i8259s (irq->name);
+}
-static void nopOn(const rtems_irq_connect_data* notUsed)
+static void uti596_maskOff(const rtems_irq_connect_data* irq)
{
/*
* code should be moved from initialize_hardware
* to this location ?
*/
+ (void) BSP_irq_disable_at_i8259s (irq->name);
}
static int uti596_isOn(const rtems_irq_connect_data* irq)
@@ -277,6 +293,8 @@ int uti596_initRFA(int num)
uti596_softc.savedCount = 0;
+ uti596_softc.nop.cmd.command = CmdNOp; /* initialize the nop command */
+
return (i); /* the number of allocated buffers */
}
@@ -326,12 +344,7 @@ void uti596supplyFD(struct i596_rfd * pRfd )
pLastRfd -> next = pRfd;
pLastRfd -> cmd &= ~CMD_EOL; /* RESET_EL : reset EL bit to 0 */
uti596_softc.countRFD++; /* Lets assume we add it successfully
- If not, the RFD may be used, and may decrement countRFD < 0 !!*/
- /* if (uti596_softc.countRFD > UTI_596_RFD_NUMBER) {
- printf( "Supply: Count too high, count == %d, when adding %p\n",uti596_softc.countRFD, pRfd);
- dumpQ();
- }
- */
+ If not, the RFD may be used, and may decrement countRFD < 0 !!*/
/*
* Check if the last RFD was used while appending.
*/
@@ -353,14 +366,12 @@ void uti596supplyFD(struct i596_rfd * pRfd )
* The RFD being added was not touched by the 82596
*/
if (uti596_softc.pLastUnkRFD != I596_NULL ) {
- /* printf("Before appending\n");
- dumpQ(); */
+
uti596append(&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */
uti596_softc.pEndSavedQueue = pRfd;
uti596_softc.savedCount++;
uti596_softc.countRFD--;
- /* printf("Last UNK must be NULL: %p\n",uti596_softc.pLastUnkRFD);
- dumpQ(); */
+
}
else {
uti596_softc.pEndRFA = pRfd; /* the RFA has been extended */
@@ -369,17 +380,21 @@ void uti596supplyFD(struct i596_rfd * pRfd )
uti596_softc.countRFD > 1 ) { /* was == 2 */
uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL; /* Ensure that beginRFA is not EOL */
- UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List is buggered\n");
+ UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n");
UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n");
UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n");
#ifdef DBG_START
- printf("B");
-#endif
- uti596rxStart(SCB_STAT_RNR); /*Ack the RNR interrupt */
-
+ printf("Supply FD: starting receiver");
+#endif
+ /* start the receiver */
+ UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n");
+ uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;
+ uti596_softc.scb.command = RX_START | SCB_STAT_RNR; /* Don't ack RNR! The receiver should be stopped in this case */
+ UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n");
+ outport_byte(CHAN_ATTN, 0);
}
}
- return;
+ return;
}
}
@@ -398,14 +413,6 @@ void uti596supplyFD(struct i596_rfd * pRfd )
}
}
-void uti596rxStart(int cmd)
-{
- UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n");
- uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;
- uti596_softc.scb.command = RX_START | cmd; /* Don't ack RNR! The receiver should be stopped in this case */
- UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n");
- outport_byte(CHAN_ATTN, 0);
-}
static void
uti596_start (struct ifnet *ifp)
@@ -441,8 +448,9 @@ uti596_initialize_hardware(struct uti596_softc *sc)
/* change the scp address */
-
+#ifdef DBG_INIT
printf("Change the SCP address\n");
+#endif
/*
* Set the DMA mode to enable the 82596 to become a bus-master
@@ -490,8 +498,8 @@ uti596_initialize_hardware(struct uti596_softc *sc)
*/
sc->irqInfo.name = UTI_596_IRQ;
sc->irqInfo.hdl = ( void * ) uti596DynamicInterruptHandler;
- sc->irqInfo.on = nopOn;
- sc->irqInfo.off = nopOn;
+ sc->irqInfo.on = uti596_maskOn;
+ sc->irqInfo.off = uti596_maskOff;
sc->irqInfo.isOn = uti596_isOn;
status_code = BSP_install_rtems_irq_handler (&sc->irqInfo);
@@ -502,17 +510,6 @@ uti596_initialize_hardware(struct uti596_softc *sc)
/* Initialize the 82596 memory ( Transmit buffers ) */
uti596_initMem(sc);
- /*
- * Create a semaphore to guard the critical sections within 596raw
- * IS THIS NEEDED W/ FreeBSD?
- */
- /* sc->semaphore_name = rtems_build_name('I','5','9','6');
- status_code = rtems_semaphore_create(sc->semaphore_name,
- UTI596_MUTEX,
- RTEMS_DEFAULT_ATTRIBUTES,
- RTEMS_NO_PRIORITY,
- &sc->semaphore_id);
- */
#ifdef DBG_INIT
printf("After attach, status of board = 0x%x\n", sc->scb.status );
#endif
@@ -520,6 +517,80 @@ uti596_initialize_hardware(struct uti596_softc *sc)
}
+void
+uti596_reset_hardware(struct uti596_softc *sc)
+{
+ int boguscnt = 1000;
+
+ /* reset the board */
+ outport_word( PORT_ADDR, 0 );
+ outport_word( PORT_ADDR, 0 );
+
+#ifdef DBG_RESET
+ printf("reset_hardware:Scp address %p\n", sc->pScp);
+#endif
+ sc->pScp = (struct i596_scp *)
+ ((((int)uti596_softc.pScp) + 0xf) & 0xfffffff0);
+
+#ifdef DBG_RESET
+ printf("reset_hardware:change scp address to : %p\n",sc->pScp);
+#endif
+
+
+ /* change the scp address */
+#ifdef DBG_RESET
+ printf("Change the SCP address\n");
+#endif
+
+ /*
+ * Set the DMA mode to enable the 82596 to become a bus-master
+ */
+ outport_byte(DMA_MASK_REG,DMA_DISABLE); /* disable_dma */
+ outport_byte(DMA_MODE_REG,DMA_MODE_CASCADE); /* set dma mode */
+ outport_byte(DMA_MASK_REG,DMA_ENABLE); /* enable dma */
+
+ /* reset the board */
+ outport_word( PORT_ADDR, 0 );
+ outport_word( PORT_ADDR, 0 );
+
+ outport_word(PORT_ADDR, ((((int)uti596_softc.pScp) & 0xffff) | 2 ));
+ outport_word(PORT_ADDR, (( (int)uti596_softc.pScp) >> 16 ) & 0xffff );
+
+ /* This is linear mode, LOCK function is disabled */
+
+ sc->pScp->sysbus = 0x00540000;
+ sc->pScp->iscp = &sc->iscp;
+ sc->iscp.scb = &sc->scb;
+ sc->iscp.stat = 0x0001;
+
+ sc->pCmdHead = sc->scb.pCmd = I596_NULL;
+
+#ifdef DBG_596
+ printf("reset_hardware: starting i82596.\n");
+#endif
+
+ /* Pass the scb address to the 596 */
+ outport_word(CHAN_ATTN,0);
+
+ while (sc->iscp.stat)
+ if (--boguscnt == 0)
+ {
+ printf("reset_hardware: timed out with status %4.4lx\n",
+ sc->iscp.stat );
+ break;
+ }
+
+ /* clear the command word */
+ sc->scb.command = 0;
+
+#ifdef DBG_RESET
+ printf("After reset_hardware, status of board = 0x%x\n", sc->scb.status );
+#endif
+
+ outport_word(0x380, 0xf); /* reset the LED's */
+}
+
+
/***********************************************************************
* Function: uti596_initMem
*
@@ -702,7 +773,7 @@ uti596_rxDaemon(void *arg)
struct i596_rfd *pRfd;
ISR_Level level;
- int tid,i;
+ int tid;
rtems_event_set events;
struct ether_header *eh;
@@ -872,65 +943,128 @@ uti596clearListStatus(struct i596_rfd *pRfd)
}
}
-
- /* static inline */ void uti596reset_bit_test()
- {
- reset_bit_test = 1;
- }
-
void uti596reset(void)
{
- int i;
+ int i,count;
+ struct uti596_softc *sc = &uti596_softc;
+ /* struct i596_rfd * pRfd; */
-#ifdef DBG_596_RESET
- printf ("i596reset\n");
+#ifdef DBG_RESET
+ printf ("reset: begins\n");
#endif
- uti596_initialize_hardware(&uti596_softc); /* resets the ethernet hardware, now must re-config */
- uti596Diagnose(1); /* verbose diagnosis */
+ sc->resetDone = 0;
+ sc->irqInfo.off(&sc->irqInfo);
+
+ UTI_WAIT_COMMAND_ACCEPTED(10000, "reset: wait for previous command complete");
+
+ /* abort ALL of the current work */
+ sc->scb.command = CUC_ABORT | RX_ABORT;
- uti596_softc.set_conf.cmd.command = CmdConfigure;
- memcpy (uti596_softc.set_conf.data, uti596initSetup, 14);
- uti596addPolledCmd( (struct i596_cmd *) &uti596_softc.set_conf);
+ outport_word(CHAN_ATTN,0);
+ UTI_WAIT_COMMAND_ACCEPTED(4000, "reset: abort requested");
+
+ uti596_reset_hardware(&uti596_softc); /* reset the ethernet hardware. must re-config */
+
+#ifdef DBG_RESET
+ uti596Diagnose(1);
+#endif
+
+ sc->set_conf.cmd.command = CmdConfigure;
+ memcpy (sc->set_conf.data, uti596initSetup, 14);
+ uti596addPolledCmd( (struct i596_cmd *) &sc->set_conf);
+
+ /****
+ * POLL
+ ****/
- while( !uti596_softc.set_conf.cmd.status & STAT_C )
+ count = 2000;
+ while( !( sc->set_conf.cmd.status & STAT_C ) && --count )
printf(".");
-
- printf("Configure completed\n");
-#ifdef DBG_596
- printf("Setting Address\n");
+
+ if ( count )
+ printf("Configure OK, count = %d\n",count);
+ else
+ printf("***reset: Configure failed\n");
+
+ /*
+ * Create the IA setup command
+ */
+
+#ifdef DBG_RESET
+ printf("reset: Setting Address\n");
#endif
- uti596_softc.set_add.cmd.command = CmdSASetup;
+ sc->set_add.cmd.command = CmdSASetup;
for ( i=0; i<6; i++)
- uti596_softc.set_add.data[i]= uti596_softc.arpcom.ac_enaddr[i];
+ sc->set_add.data[i]=sc->arpcom.ac_enaddr[i];
- uti596_softc.cmdOk = 0;
- uti596addCmd((struct i596_cmd *)&uti596_softc.set_add);
- /*******/
- while( !uti596_softc.set_add.cmd.status & STAT_C )
+ sc->cmdOk = 0;
+ uti596addPolledCmd((struct i596_cmd *)&sc->set_add);
+
+ count = 2000;
+ while( !(sc->set_add.cmd.status & STAT_C ) && --count)
printf(".");
+
+ if ( count )
+ printf ("Reset Set Address OK, count= %d\n",count);
+ else
+ printf("Reset Set Address Failed\n");
/*******/
-#ifdef DBG_596
- printf( "After initialization, status and command: 0x%x, 0x%x\n",
- uti596_softc.scb.status, uti596_softc.scb.status);
+#ifdef DBG_RESET
+ printf( "After reset, status and command: 0x%x, 0x%x\n",
+ sc->scb.status, sc->scb.status);
#endif
- if ( uti596_softc.pLastUnkRFD != I596_NULL ) {
- uti596_softc. pEndRFA = uti596_softc. pLastUnkRFD; /* The end position can be updated */
- uti596_softc. pLastUnkRFD = I596_NULL;
+
+
+ /* restore the RFA */
+
+ dumpQ();
+
+ if ( sc->pLastUnkRFD != I596_NULL ) {
+ sc-> pEndRFA = sc->pLastUnkRFD; /* The end position can be updated */
+ sc-> pLastUnkRFD = I596_NULL;
}
- /* clear status in RFA */
- uti596clearListStatus(uti596_softc.pBeginRFA );
- uti596clearListStatus(uti596_softc.pSavedRfdQueue );
- uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;
+ sc->pEndRFA->next = sc->pSavedRfdQueue;
+ if ( sc->pSavedRfdQueue != I596_NULL ) {
+ sc->pEndRFA = sc->pEndSavedQueue;
+ sc->pSavedRfdQueue = sc->pEndSavedQueue = I596_NULL;
+ sc -> countRFD = sc->rxBdCount ;
+ }
+
+ /* if ( sc->pInboundFrameQueue != I596_NULL ){
+ do {
+ pRfd = sc->pInboundFrameQueue->next;
+ sc->pEndRFA -> next = sc->pInboundFrameQueue;
+ sc->pInboundFrameQueue = pRfd;
+ } while( pRfd != I596_NULL ) ;
+
+ }
+ */
+
+ sc->scb.pRfd = sc->pBeginRFA; /* readdress the head of the RFA in the SCB */
+
+ uti596clearListStatus(sc->pBeginRFA );
+
+ dumpQ(); /* purely for testing */
+
+ sc->irqInfo.on(&sc->irqInfo); /* moved here. Was originally after command issued. */
+ sc->scb.command = RX_START;
- uti596_softc.scb.command = RX_START;
outport_word(CHAN_ATTN,0 );
- UTI_WAIT_COMMAND_ACCEPTED(4000, "init");
+ UTI_WAIT_COMMAND_ACCEPTED(4000, "reset");
+
+ sc->resetDone = 1;
+
+ sc->started = 1;
+
+ /* uti596addCmd(&uti506_softc.nop); */ /* just for fun */
- uti596_softc.started = 1;
+#ifdef DBG_RESET
+ printf("reset: complete\n");
+#endif
}
/***********************************************************************
@@ -992,11 +1126,6 @@ void uti596reset(void)
pCmd->status = 0;
pCmd->command |= (CMD_EOL | CMD_INTR ); /* all commands last in list & return an interrupt */
- if ( reset_bit_test ){
- pCmd->command |= 0x0080;
- printf("Issuing cmd: %#x\n", pCmd->command);
- reset_bit_test = 0;
- }
pCmd->next = I596_NULL;
@@ -1150,6 +1279,37 @@ uti596_txDaemon (void *arg)
}
+/*
+ * NIC reset daemon.
+ */
+void
+uti596_resetDaemon (void *arg)
+{
+ struct uti596_softc *sc = (struct uti596_softc *)arg;
+ rtems_event_set events;
+ /* struct ifnet *ifp = &sc->arpcom.ac_if; */
+
+ for (;;) {
+ /*
+ * Wait for reset event from ISR
+ */
+ rtems_bsdnet_event_receive (NIC_RESET_EVENT,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT, &events);
+
+ printf("reset daemon: Resetting NIC\n");
+
+ sc->stats.nic_reset_count++;
+ /*
+ * Reinitialize the network card
+ */
+ rtems_bsdnet_semaphore_obtain ();
+ uti596reset();
+ rtems_bsdnet_semaphore_release ();
+ }
+}
+
+
/***********************************************************************
* Function: send_packet
*
@@ -1178,34 +1338,6 @@ void send_packet(struct ifnet *ifp, struct mbuf *m)
int bd_count = 0;
rtems_event_set events;
- /*
- * Block all competing threads. IS THIS NOW NEEDED? I THINK NOT
- */
-
- /* while(1) {
-#ifdef DBG_RAW
- rtems_task_ident (0, 0, &tid);
- printf("0x%x Waiting for semaphore\n", tid);
-#endif
- status = rtems_semaphore_obtain(sc->semaphore_id,
- RTEMS_WAIT,
- RTEMS_NO_TIMEOUT);
-
- if ( status == RTEMS_SUCCESSFUL ){
-#ifdef DBG_RAW
- printf("0x%x Got semaphore\n", tid);
-#endif
- break;
- }
- else
- {
-#ifdef DBG_RAW
- printf("0x%x Waits on semaphore\n", tid);
-#endif
- sc->txRawWait++;
- }
- }
- */
/*
* For all mbufs in the chain,
* fill a transmit buffer descriptor
@@ -1340,8 +1472,6 @@ void send_packet(struct ifnet *ifp, struct mbuf *m)
m = n;
}
- /* We have finished with this critical section */
- /* rtems_semaphore_release(sc->semaphore_id); */
}
@@ -1751,6 +1881,7 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
}
+
/***********************************************************************
* Function: uti596DynamicInterruptHandler
*
@@ -1782,23 +1913,42 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
UTI_WAIT_COMMAND_ACCEPTED(20000, "****ERROR:ACK");
}
else {
- printk("\n***INFO:ISR won't wait\n");
+ printk("\n***INFO:ISR won't process now\n");
return;
}
}
else {
- printk("\n***WARNING: Nothing to ACK\n");
- return;
+ printk("\n***ERROR: Spurious interrupt. Resetting...\n");
+ uti596_softc.nic_reset = 1;
}
- if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) )
- printk("\n*****ERROR:Command Complete, CNA available: %#x\n", scbStatus);
-
- if ( !(scbStatus & SCB_STAT_CX) && (scbStatus & SCB_STAT_CNA) )
- printk("\n*****ERROR: CNA went unavailable, NO CX:%#x\n",scbStatus);
+ if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) ){
+ printk("\n*****ERROR: Command Complete, and CNA available: 0x%x\nResetting...", scbStatus);
+ uti596_softc.nic_reset = 1;
+ return;
+ }
+
+ if ( !(scbStatus & SCB_STAT_CX) && (scbStatus & SCB_STAT_CNA) ) {
+ printk("\n*****ERROR: CNA, NO CX:0x%x\nResetting...",scbStatus);
+ uti596_softc.nic_reset = 1;
+ return;
+ }
+
+ if ( scbStatus & SCB_CUS_SUSPENDED ) {
+ printk("\n*****ERROR: Command unit suspended!:0x%x\nResetting...",scbStatus);
+ uti596_softc.nic_reset = 1;
+ return;
+ }
+
+ if ( scbStatus & RU_SUSPENDED ) {
+ printk("\n*****ERROR: Receive unit suspended!:0x%x\nResetting...",scbStatus);
+ uti596_softc.nic_reset = 1;
+ return;
+ }
- if ( scbStatus & SCB_STAT_RNR )
+ if ( scbStatus & SCB_STAT_RNR ) {
printk("\n*****WARNING: RNR %x\n",scbStatus);
+ }
/*
* Receive Unit Control
@@ -1809,18 +1959,9 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
#ifdef DBG_FR
printk("\nISR:FR\n");
#endif
- if ( uti596_softc.pBeginRFA == I596_NULL || !( uti596_softc.pBeginRFA -> stat & STAT_C ) ||
- forceResetRX ) {
-
- /* if ( !forceResetRX )
- printk("****ERROR: FR interrupt and NO complete FR!\n");
- else
- printk("****INFO: RX reset requested\n");
- */
- forceResetRX = 0;
- printk("****INFO: Resetting board ( rx ) commented out\n");
+ if ( uti596_softc.pBeginRFA == I596_NULL || !( uti596_softc.pBeginRFA -> stat & STAT_C)){
dump_scb();
- /* uti596reset(); */
+ uti596_softc.nic_reset = 1;
}
else
while ( uti596_softc.pBeginRFA != I596_NULL &&
@@ -1896,7 +2037,7 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
/*
* For ALL completed commands
*/
- if ( pIsrCmd != I596_NULL && pIsrCmd->status & STAT_C && !forceResetTX ){
+ if ( pIsrCmd != I596_NULL && pIsrCmd->status & STAT_C ){
#ifdef DBG_RAW_ISR
printk("ISR:pIsrCmd != NULL\n");
@@ -2012,19 +2153,13 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
pIsrCmd = uti596_softc.pCmdHead; /* next command */
if ( pIsrCmd != I596_NULL )
printk("****WARNING: more commands in list, but no start to NIC\n");
- } /* end if completed */
+ } /* end if pIsrCmd != NULL && pIsrCmd->stat & STAT_C */
else {
- /* if ( !forceResetTX )
- printk("*****ERROR:CX but no command is completed\n");
- else
- printk("*****INFO:forcing an ethernet card reset\n");
- */
/* Reset the ethernet card, and wake the transmitter (if necessary) */
printk("****INFO: Resetting board ( tx )\n");
- forceResetTX = 0;
- uti596reset();
+ uti596_softc.nic_reset = 1;
if ( uti596_softc.txDaemonTid){ /* Ensure that a transmitter is waiting */
/* printk("*****INFO:Wake Transmitter\n"); */
sc = rtems_event_send (uti596_softc.txDaemonTid,
@@ -2197,6 +2332,17 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
printk("X\n");
#endif
count_rx=0;
+
+ /*
+ * Do this last, to ensure that the reset is called at the right time.
+ */
+ if ( uti596_softc.nic_reset ){
+ uti596_softc.nic_reset = 0;
+ sc = rtems_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT);
+ if ( sc != RTEMS_SUCCESSFUL )
+ rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc));
+ }
+
return;
}
@@ -2402,9 +2548,13 @@ uti596_stats(struct uti596_softc *sc)
printf ("Rx Fifo Errors:%-8u\n", sc->stats.rx_fifo_errors);
printf ("Rx Framing Errors:%-8u", sc->stats.rx_frame_errors);
printf ("Rx crc errors:%-8u\n", sc->stats.rx_crc_errors);
+
printf ("TX WAITS: %-8lu\n", sc->txRawWait);
+ printf ("NIC resets: %-8u\n", sc->stats.nic_reset_count);
+
printf("NIC reports\n");
+
dump_scb();
}
@@ -2522,9 +2672,10 @@ void uti596_init(void * arg){
* Start driver tasks
*/
- sc->txDaemonTid = rtems_bsdnet_newproc ("UTtx", 4096, uti596_txDaemon, sc);
- sc->rxDaemonTid = rtems_bsdnet_newproc ("UTrx", 4096, uti596_rxDaemon, sc);
-
+ sc->txDaemonTid = rtems_bsdnet_newproc ("UTtx", 2*4096, uti596_txDaemon, sc);
+ sc->rxDaemonTid = rtems_bsdnet_newproc ("UTrx", 2*4096, uti596_rxDaemon, sc);
+ sc->resetDaemonTid = rtems_bsdnet_newproc ("UTrt", 2*4096,
+ uti596_resetDaemon, sc);
}
/*
* Enable receiver
diff --git a/c/src/lib/libbsp/i386/i386ex/network/uti596.h b/c/src/lib/libbsp/i386/i386ex/network/uti596.h
index 0471ccdc4d..5448362a22 100644
--- a/c/src/lib/libbsp/i386/i386ex/network/uti596.h
+++ b/c/src/lib/libbsp/i386/i386ex/network/uti596.h
@@ -4,6 +4,8 @@
/*
* EII: March 11: Created v. 0.0
* Jan 12/98 Added STAT bits, s11-=s5 and max_colls.
+ *
+ * $Id$
*/
#ifndef UTI596_H
@@ -48,6 +50,9 @@ struct enet_statistics{
int tx_fifo_errors;
int tx_heartbeat_errors;
int tx_window_errors;
+
+ /* NIC reset errors */
+ int nic_reset_count; /* The number of times uti596reset() has been called. */
};
@@ -78,6 +83,10 @@ enum commands {
#define SCB_STAT_CNA 0x2000 /* Cmd unit Not Active */
#define SCB_STAT_RNR 0x1000 /* Receiver Not Ready */
+#define SCB_CUS_SUSPENDED 0x0100
+#define SCB_CUS_ACTIVE 0x0200
+
+
#define STAT_C 0x8000 /* Set to 1 after execution */
#define STAT_B 0x4000 /* 1 : Cmd being executed, 0 : Cmd done. */
#define STAT_OK 0x2000 /* 1: Command executed ok 0 : Error */
@@ -105,11 +114,10 @@ enum commands {
#define RX_SUSPEND 0x0030
#define RX_ABORT 0x0040
-#define RU_SUSPENDED 0x001
+#define RU_SUSPENDED 0x0010
#define RU_NO_RESOURCES 0x0020
#define RU_READY 0x0040
-
#define IO_ADDR 0x360
#define PORT_ADDR IO_ADDR
@@ -190,7 +198,14 @@ struct i596_configure {
char data[16];
};
+struct i596_nop {
+ struct i596_cmd cmd;
+};
+struct i596_tdr {
+ struct i596_cmd cmd;
+ unsigned int data;
+};
#define RX_RING_SIZE 8
@@ -237,7 +252,8 @@ struct uti596_softc {
struct i596_scb scb;
struct i596_set_add set_add;
struct i596_configure set_conf;
- struct i596_cmd tdr;
+ struct i596_tdr tdr;
+ struct i596_nop nop;
unsigned long stat;
struct tx_cmd *pTxCmd;
struct i596_tbd *pTbd;
@@ -254,6 +270,7 @@ struct uti596_softc {
rtems_id rxDaemonTid;
rtems_id txDaemonTid;
+ rtems_id resetDaemonTid;
struct enet_statistics stats;
int started;
@@ -272,5 +289,6 @@ struct uti596_softc {
rtems_id semaphore_id;
char zeroes[64];
unsigned long rawsndcnt;
+ int nic_reset; /* flag is for requesting that ISR issue a reset quest */
} ;
#endif
diff --git a/c/src/lib/libbsp/i386/i386ex/wrapup/Makefile.in b/c/src/lib/libbsp/i386/i386ex/wrapup/Makefile.in
index 60a923b569..ce00bb7ffb 100644
--- a/c/src/lib/libbsp/i386/i386ex/wrapup/Makefile.in
+++ b/c/src/lib/libbsp/i386/i386ex/wrapup/Makefile.in
@@ -11,9 +11,9 @@ PROJECT_ROOT = @PROJECT_ROOT@
BSP_PIECES=startup clock console timer $(NETWORK)
GENERIC_PIECES=
-# # We only build the Network library if HAS_NETWORKING was defined
-# NETWORK_yes_V = network
-# NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
+# We only build the Network library if HAS_NETWORKING was defined
+NETWORK_yes_V = network
+NETWORK = $(NETWORK_$(HAS_NETWORKING)_V)
# bummer; have to use $foreach since % pattern subst rules only replace 1x
OBJS=$(foreach piece, $(BSP_PIECES), ../$(piece)/$(ARCH)/$(piece).rel) \