diff options
Diffstat (limited to 'c/src/lib/libbsp')
-rw-r--r-- | c/src/lib/libbsp/i386/i386ex/Makefile.in | 6 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/i386ex/network/Makefile.in | 60 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/i386ex/network/netexterns.h | 5 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/i386ex/network/network.c | 463 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/i386ex/network/uti596.h | 24 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/i386ex/wrapup/Makefile.in | 6 |
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) \ |