summaryrefslogtreecommitdiffstats
path: root/c/src
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-03-01 23:50:22 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-03-01 23:50:22 +0000
commit9d813800b3b582853de841479b6c1f96818b2071 (patch)
treea2574f3ccb416c856601eccbf221645f7990d13b /c/src
parentPatch from Eric Norum <eric@skatter.usask.ca> to eliminate external (diff)
downloadrtems-9d813800b3b582853de841479b6c1f96818b2071.tar.bz2
Updated Ethernet driver from Erik Ivanenko <erik.ivanenko@utoronto.ca>.
Comments follow: Please find attached, the updated network driver. I have verified that it is working as expected, by timestamping the error messages generated from the ISR. If you've taken a look inside, the network driver has a reset thread in addition to the RX and TX threads. It is possible to avoid the additional reset thread by allowing the TX driver to time out and then checking status bits set by the ISR. However, this approach demands that a transmission is necessary for the NIC to be reset. Due to Eric V's ISR handling, I suppose that the reset routine could be called from the "ISR" itself, due to the 8259 interrupt mode, and that the interrupt is acknowledged prior to running the "ISR". (Providing that no NIC interrupts are generated during reset -- I worry about re-entrancy. ) This would be a minor improvement, but you know, I don't want to make this driver my lifes work. ---------------------------------------------------------------------- ----------------------------------------------------------------------
Diffstat (limited to 'c/src')
-rw-r--r--c/src/lib/libbsp/i386/i386ex/network/network.c178
1 files changed, 112 insertions, 66 deletions
diff --git a/c/src/lib/libbsp/i386/i386ex/network/network.c b/c/src/lib/libbsp/i386/i386ex/network/network.c
index 5a97a00a11..0e7ae7dc1c 100644
--- a/c/src/lib/libbsp/i386/i386ex/network/network.c
+++ b/c/src/lib/libbsp/i386/i386ex/network/network.c
@@ -4,6 +4,7 @@
*/
void dump_scb(void);
+void printk_time(void);
#ifdef DBG_VERSION
#define BREAKPOINT() asm(" int $3");
@@ -34,10 +35,7 @@ void show_queues(void);
void outbyte(char);
void dumpQ(void);
-#define UTI_596_ASSERT( condition, str )
-/*
- * { if (!( condition ) ) printf(str); }
- */
+#define UTI_596_ASSERT( condition, str ) { if (!( condition ) ) printk(str); }
int count_rx = 0;
/* static char *version = "uti596.c:v0.0 11/13/97\n"; */
@@ -106,7 +104,6 @@ char uti596initSetup[] = {
#define RBUF_SIZE 1520
-#define UTI_596_RFD_NUMBER 4
/*
* Local Routines
@@ -259,7 +256,7 @@ int uti596_initRFA(int num)
} /* end for */
uti596_softc.pEndRFA -> next = I596_NULL;
- UTI_596_ASSERT(uti596_softc.countRFD == UTI_596_RFD_NUMBER,"INIT:WRONG RFD COUNT\n" );
+ UTI_596_ASSERT(uti596_softc.countRFD == RX_BUF_COUNT,"INIT:WRONG RFD COUNT\n" );
#ifdef DBG_596_RFA
printf ( "Head of RFA is buffer %p\nEnd of RFA is buffer %p \n",
@@ -521,6 +518,10 @@ void
uti596_reset_hardware(struct uti596_softc *sc)
{
int boguscnt = 1000;
+ rtems_status_code status_code;
+ struct i596_cmd *pCmd;
+
+ pCmd = sc->pCmdHead; /* This is a tx command for sure (99.99999%) */
/* reset the board */
outport_word( PORT_ADDR, 0 );
@@ -564,6 +565,18 @@ uti596_reset_hardware(struct uti596_softc *sc)
sc->iscp.stat = 0x0001;
sc->pCmdHead = sc->scb.pCmd = I596_NULL;
+ /*
+ * Wake the transmitter if needed.
+ */
+ if ( uti596_softc.txDaemonTid && pCmd != I596_NULL ){
+ printf("****RESET: wakes transmitter!\n");
+ status_code = rtems_event_send (uti596_softc.txDaemonTid,
+ INTERRUPT_EVENT);
+
+ if ( status_code != RTEMS_SUCCESSFUL )
+ printk("****ERROR:Could NOT send event to tid 0x%x : %s\n",
+ uti596_softc.txDaemonTid, rtems_status_text (status_code) );
+ }
#ifdef DBG_596
printf("reset_hardware: starting i82596.\n");
@@ -959,10 +972,13 @@ void uti596reset(void)
UTI_WAIT_COMMAND_ACCEPTED(10000, "reset: wait for previous command complete");
/* abort ALL of the current work */
- sc->scb.command = CUC_ABORT | RX_ABORT;
-
- outport_word(CHAN_ATTN,0);
- UTI_WAIT_COMMAND_ACCEPTED(4000, "reset: abort requested");
+ /* FEB 17 REMOVED
+ >>>>>
+ sc->scb.command = CUC_ABORT | RX_ABORT;
+ 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 */
@@ -1010,7 +1026,9 @@ void uti596reset(void)
else
printf("Reset Set Address Failed\n");
/*******/
-
+
+ sc->pCmdHead = sc->pCmdTail = sc->scb.pCmd = I596_NULL; /* Feb 17. clear these out */
+
#ifdef DBG_RESET
printf( "After reset, status and command: 0x%x, 0x%x\n",
sc->scb.status, sc->scb.status);
@@ -1020,7 +1038,7 @@ void uti596reset(void)
/* restore the RFA */
- dumpQ();
+ /*dumpQ();*/
if ( sc->pLastUnkRFD != I596_NULL ) {
sc-> pEndRFA = sc->pLastUnkRFD; /* The end position can be updated */
@@ -1048,18 +1066,18 @@ void uti596reset(void)
uti596clearListStatus(sc->pBeginRFA );
- dumpQ(); /* purely for testing */
+ /* dumpQ();*/
- sc->irqInfo.on(&sc->irqInfo); /* moved here. Was originally after command issued. */
+ printf("Reset:Starting NIC\n");
sc->scb.command = RX_START;
-
+ sc->started = 1; /* we assume that the start works */
+ sc->resetDone = 1; /* moved here from after channel attn. */
outport_word(CHAN_ATTN,0 );
UTI_WAIT_COMMAND_ACCEPTED(4000, "reset");
+ printf("Reset:Start complete \n");
+ UTI_596_ASSERT(sc->pCmdHead == I596_NULL, "Reset: CMD not cleared\n");
+ sc->irqInfo.on(&sc->irqInfo); /* moved back here. Tried it before RX command issued. */
- sc->resetDone = 1;
-
- sc->started = 1;
-
/* uti596addCmd(&uti506_softc.nop); */ /* just for fun */
#ifdef DBG_RESET
@@ -1223,16 +1241,12 @@ void uti596addPolledCmd(struct i596_cmd *pCmd)
uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd;
- UTI_WAIT_COMMAND_ACCEPTED(10000,"Add Polled command: wait prev"); /* ensure prev command complete */
+ UTI_WAIT_COMMAND_ACCEPTED(10000,"Add Polled command: wait prev");
uti596_softc.scb.command = CUC_START;
outport_word (CHAN_ATTN,0);
- UTI_WAIT_COMMAND_ACCEPTED(2000000,"Add Polled command: start"); /* ensure previous command complete */
- /* if ( !(pCmd -> status & STAT_C ) ){
- printf("****FAILED poll command\n");
- }
- */
+ UTI_WAIT_COMMAND_ACCEPTED(2000000,"Add Polled command: start");
uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = I596_NULL;
#ifdef DBG_596
@@ -1262,18 +1276,22 @@ uti596_txDaemon (void *arg)
RTEMS_NO_TIMEOUT, &events);
/*
- * Send packets till queue is empty
+ * Send packets till queue is empty.
+ * Ensure that irq is on before sending.
*/
for (;;) {
- /*
- * Get the next mbuf chain to transmit.
- */
- IF_DEQUEUE(&ifp->if_snd, m);
- if (!m)
- break;
-
- send_packet (ifp, m); /* blocks */
- }
+ /* Feb 17: No need to make sure a reset is in progress,
+ * Since reset daemon runs at same priority as this thread
+ */
+ /*
+ * Get the next mbuf chain to transmit.
+ */
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (!m)
+ break;
+
+ send_packet (ifp, m); /* blocks */
+ } /* end for */
ifp->if_flags &= ~IFF_OACTIVE; /* no more to send, mark output inactive */
}
}
@@ -1287,6 +1305,8 @@ uti596_resetDaemon (void *arg)
{
struct uti596_softc *sc = (struct uti596_softc *)arg;
rtems_event_set events;
+ rtems_time_of_day tm_struct;
+
/* struct ifnet *ifp = &sc->arpcom.ac_if; */
for (;;) {
@@ -1297,7 +1317,9 @@ uti596_resetDaemon (void *arg)
RTEMS_EVENT_ANY | RTEMS_WAIT,
RTEMS_NO_TIMEOUT, &events);
- printf("reset daemon: Resetting NIC\n");
+ rtems_clock_get(RTEMS_CLOCK_GET_TOD, &tm_struct);
+ printf("reset daemon: Resetting NIC @ %d:%d:%d \n",
+ tm_struct.hour, tm_struct.minute, tm_struct.second);
sc->stats.nic_reset_count++;
/*
@@ -1900,6 +1922,12 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
UTI_WAIT_COMMAND_ACCEPTED(20000, "****ERROR:on ISR entry");
+ if ( !(i8259s_cache & 0x20 )) {
+ printk("****Error: network ISR running, no IRR!\n");
+ printk("****Error: i8259s_cache = 0x%x\n",i8259s_cache );
+ printk_time();
+ }
+
scbStatus = uti596_softc.scb.status & 0xf000;
if ( scbStatus ){
@@ -1913,7 +1941,7 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
UTI_WAIT_COMMAND_ACCEPTED(20000, "****ERROR:ACK");
}
else {
- printk("\n***INFO:ISR won't process now\n");
+ printk("***INFO: ACK'd w/o processing. status = %x\n", scbStatus);
return;
}
}
@@ -1923,31 +1951,39 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
}
if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) ){
+ printk_time();
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_time();
printk("\n*****ERROR: CNA, NO CX:0x%x\nResetting...",scbStatus);
uti596_softc.nic_reset = 1;
return;
}
if ( scbStatus & SCB_CUS_SUSPENDED ) {
+ printk_time();
printk("\n*****ERROR: Command unit suspended!:0x%x\nResetting...",scbStatus);
uti596_softc.nic_reset = 1;
return;
}
if ( scbStatus & RU_SUSPENDED ) {
+ printk_time();
printk("\n*****ERROR: Receive unit suspended!:0x%x\nResetting...",scbStatus);
uti596_softc.nic_reset = 1;
return;
}
if ( scbStatus & SCB_STAT_RNR ) {
+ printk_time();
printk("\n*****WARNING: RNR %x\n",scbStatus);
+ printk("*****INFO: RFD cmd: %x status:%x\n",
+ uti596_softc.pBeginRFA -> cmd,
+ uti596_softc.pBeginRFA -> stat);
}
/*
@@ -2018,7 +2054,6 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
uti596_softc.pEndRFA = I596_NULL;
if ( uti596_softc.countRFD != 0 ) {
printk("****ERROR:Count is %d, but begin ptr is NULL\n",uti596_softc.countRFD );
- dumpQ();
}
}
@@ -2044,7 +2079,7 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
#endif
/*
- * Adjust the drivers command block list
+ * Adjust the command block list
*/
uti596_softc.pCmdHead = pIsrCmd -> next;
@@ -2097,7 +2132,7 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
#ifdef DBG_ISR
printk("wake TX:0x%x\n",uti596_softc.txDaemonTid);
#endif
- if ( uti596_softc.txDaemonTid ){ /* Ensure that the transmitter is waiting */
+ if ( uti596_softc.txDaemonTid ){ /* Ensure that the transmitter is present */
sc = rtems_event_send (uti596_softc.txDaemonTid,
INTERRUPT_EVENT);
@@ -2155,22 +2190,23 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
printk("****WARNING: more commands in list, but no start to NIC\n");
} /* end if pIsrCmd != NULL && pIsrCmd->stat & STAT_C */
else {
-
- /* Reset the ethernet card, and wake the transmitter (if necessary) */
-
- printk("****INFO: Resetting board ( tx )\n");
- 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,
- INTERRUPT_EVENT);
+ if ( pIsrCmd != I596_NULL ) { /* The command MAY be NULL from a RESET */
- if ( sc != RTEMS_SUCCESSFUL )
- printk("****ERROR:Could NOT send event to tid 0x%x : %s\n",uti596_softc.txDaemonTid, rtems_status_text (sc) );
+ /* Reset the ethernet card, and wake the transmitter (if necessary) */
+ printk_time();
+ printk("****INFO: Request board reset ( tx )\n");
+ uti596_softc.nic_reset = 1;
+ if ( uti596_softc.txDaemonTid){ /* Ensure that a transmitter is present */
+ sc = rtems_event_send (uti596_softc.txDaemonTid,
+ INTERRUPT_EVENT);
+
+ if ( sc != RTEMS_SUCCESSFUL )
+ printk("****ERROR:Could NOT send event to tid 0x%x : %s\n",uti596_softc.txDaemonTid, rtems_status_text (sc) );
#ifdef DBG_RAW_ISR
- else
- printk("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid);
+ else
+ printk("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid);
#endif
+ }
}
}
} /* end if command complete */
@@ -2203,7 +2239,6 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
if (uti596_softc.pEndRFA -> next != uti596_softc.pLastUnkRFD){
printk("***ERROR:UNK: %p not end->next: %p, end: %p\n",
uti596_softc.pLastUnkRFD,uti596_softc.pEndRFA -> next,uti596_softc.pEndRFA);
- dumpQ();
printk("***INFO:countRFD now %d\n", uti596_softc.countRFD);
printk("\n\n");
@@ -2223,7 +2258,6 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
#ifdef DEBUG_RFA
if ( uti596_softc.countRFD != 0 ) {
printk("****INFO:About to set begin to NULL, with count == %d\n", uti596_softc.countRFD );
- dumpQ();
printk("\n\n");
}
#endif
@@ -2246,7 +2280,6 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
#ifdef DEBUG_RFA
if(uti596_softc.countRFD != 0) {
printk("****ERROR:Begin pointer is NULL, but count == %d\n",uti596_softc.countRFD);
- dumpQ();
}
#endif
uti596_softc.pBeginRFA = uti596_softc.pSavedRfdQueue;
@@ -2257,7 +2290,6 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
#ifdef DEBUG_RFA
if ( uti596_softc.countRFD <= 0) {
printk("****ERROR:Begin pointer is not NULL, but count == %d\n",uti596_softc.countRFD);
- dumpQ();
}
#endif
UTI_596_ASSERT( uti596_softc.pEndRFA != I596_NULL, "****WARNING: END RFA IS NULL\n");
@@ -2283,9 +2315,15 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
printk("The list starts here %p\n",uti596_softc.pBeginRFA );
#endif
- if ( uti596_softc.countRFD > 1 && /* there is at least TWO */
- !( uti596_softc.pBeginRFA -> stat & (STAT_C | STAT_B ))) { /* restart when not in use !! */
-
+ if ( uti596_softc.countRFD > 1) {
+ /****REMOVED FEB 18.
+ &&
+ !( uti596_softc.pBeginRFA -> stat & (STAT_C | STAT_B ))) {
+ *****/
+ printk_time();
+ printk("****INFO: pBeginRFA -> stat = 0x%x\n",uti596_softc.pBeginRFA -> stat);
+ printk("****INFO: pBeginRFA -> cmd = 0x%x\n",uti596_softc.pBeginRFA -> cmd);
+ uti596_softc.pBeginRFA -> stat = 0;
UTI_596_ASSERT(uti596_softc.scb.command == 0, "****ERROR:scb command must be zero\n");
uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;
/* start RX here */
@@ -2293,7 +2331,8 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
uti596_softc.scb.command = RX_START; /* should this also be CU start? */
outport_word(CHAN_ATTN, 0);
}
- else {
+ /*****REMOVED FEB 18.
+ else {
printk("****WARNING: Receiver NOT Started -- countRFD = %d\n", uti596_softc.countRFD);
printk("82596 cmd: 0x%x, status: 0x%x RFA len: %d\n",
uti596_softc.scb.command,
@@ -2304,14 +2343,14 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
for ( pISR_Rfd = uti596_softc.pBeginRFA;
pISR_Rfd != I596_NULL;
pISR_Rfd = pISR_Rfd->next)
- printk("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
+ printk("Frame @ %x, status: %x, cmd: %x\n",
pISR_Rfd, pISR_Rfd->stat, pISR_Rfd->cmd);
printk("\nInbound: \n");
for ( pISR_Rfd = uti596_softc.pInboundFrameQueue;
pISR_Rfd != I596_NULL;
pISR_Rfd = pISR_Rfd->next)
- printk("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
+ printk("Frame @ %x, status: %x, cmd: %x\n",
pISR_Rfd, pISR_Rfd->stat, pISR_Rfd->cmd);
@@ -2319,14 +2358,15 @@ int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
for ( pISR_Rfd = uti596_softc.pSavedRfdQueue;
pISR_Rfd != I596_NULL;
pISR_Rfd = pISR_Rfd->next)
- printk("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
+ printk("Frame @ %x, status: %x, cmd: %x\n",
pISR_Rfd, pISR_Rfd->stat, pISR_Rfd->cmd);
printk("\nUnknown: %p\n",uti596_softc.pLastUnkRFD);
}
+ *****/
} /* end stat_rnr */
} /* end if receiver started */
- UTI_596_ASSERT(uti596_softc.scb.status == scbStatus, "****WARNING:scbStatus change!\n");
+ /* UTI_596_ASSERT(uti596_softc.scb.status == scbStatus, "****WARNING:scbStatus change!\n"); */
#ifdef DBG_ISR
printk("X\n");
@@ -2690,7 +2730,7 @@ void uti596_init(void * arg){
ifp->if_flags |= IFF_RUNNING;
}
-void dump_scb(){
+void dump_scb(void){
printk("status 0x%x\n",uti596_softc.scb.status);
printk("command 0x%x\n",uti596_softc.scb.command);
printk("cmd 0x%x\n",(int)uti596_softc.scb.pCmd);
@@ -2705,3 +2745,9 @@ void dump_scb(){
printk("t_off 0x%x\n",uti596_softc.scb.t_off);
}
+void printk_time(void){
+ rtems_time_of_day tm_struct;
+
+ rtems_clock_get(RTEMS_CLOCK_GET_TOD, &tm_struct);
+ printk("Current time: %d:%d:%d \n", tm_struct.hour, tm_struct.minute, tm_struct.second);
+}