📄 network.c
字号:
voiduti596clearListStatus(struct i596_rfd *pRfd){ while ( pRfd != I596_NULL ) { pRfd -> stat = 0; /* clear the status field */ pRfd = pRfd-> next; }}void uti596reset(void) { int i,count; struct uti596_softc *sc = &uti596_softc; /* struct i596_rfd * pRfd; */#ifdef DBG_RESET printf ("reset: begins\n");#endif 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 */ /* 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 */#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 ****/ count = 2000; while( !( sc->set_conf.cmd.status & STAT_C ) && --count ) printf("."); 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 sc->set_add.cmd.command = CmdSASetup; for ( i=0; i<6; i++) sc->set_add.data[i]=sc->arpcom.ac_enaddr[i]; 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"); /*******/ 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); #endif /* restore the RFA */ /*dumpQ();*/ if ( sc->pLastUnkRFD != I596_NULL ) { sc-> pEndRFA = sc->pLastUnkRFD; /* The end position can be updated */ sc-> pLastUnkRFD = I596_NULL; } 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();*/ 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. */ /* uti596addCmd(&uti506_softc.nop); */ /* just for fun */ #ifdef DBG_RESET printf("reset: complete\n");#endif } /*********************************************************************** * Function: uti596addCmd * * Description: * This routine adds a command onto the end of the * command chain * * Algorithm: * Add the command to the end of and existing chain, * or start the chain and issue a CUC_START * * ***********************************************************************/ /* static */ void uti596addCmd(struct i596_cmd *pCmd) { ISR_Level level; #ifdef DBG_596 printf("Adding command 0x%x\n", pCmd -> command ); #endif#ifdef DEBUG_ADD switch ( pCmd -> command & 0x7 ){ /* check bottom 7 bits */ case CmdConfigure: printf("ADD: Configure Command 0x%x\n", pCmd->command); break; case CmdSASetup: printf("ADD: Set Address Command 0x%x\n", pCmd->command); break; case CmdMulticastList: printf("ADD: Multi-cast list 0x%x\n", pCmd->command); break; case CmdNOp: printf("ADD: NO op 0x%x\n", pCmd->command); break; case CmdTDR: printf("ADD: TDR 0x%x\n", pCmd->command); break; case CmdDump: printf("ADD: Dump 0x%x\n", pCmd->command); break; case CmdDiagnose: printf("ADD: Diagnose 0x%x\n", pCmd->command); break; case CmdTx: break; default: printf("****Unknown Command encountered 0x%x\n", pCmd->command); break; } /* end switch */ #endif pCmd->status = 0; pCmd->command |= (CMD_EOL | CMD_INTR ); /* all commands last in list & return an interrupt */ pCmd->next = I596_NULL; _ISR_Disable(level); if (uti596_softc.pCmdHead == I596_NULL) { uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd;#ifdef DBG_596 printf("First Cmd\n");#endif UTI_WAIT_COMMAND_ACCEPTED(10000,"add command"); /* wait for acceptance of previous command */ /* CHANGED TO |= Mar. 27 4:20 pm, was just =. changed back jun 18 1998. The wait assures command = 0 */ uti596_softc.scb.command = CUC_START; outport_word (CHAN_ATTN,0); _ISR_Enable(level); } else {#ifdef DBG_596 printf("Chained Cmd\n");#endif uti596_softc.pCmdTail->next = pCmd; uti596_softc.pCmdTail = pCmd; /* added Jan 30 */ _ISR_Enable(level); }#ifdef DBG_596 printf("Scb status & command 0x%x 0x%x\n", uti596_softc.scb.status, uti596_softc.scb.command );#endif } /*********************************************************************** * Function: uti596addPolledCmd * * Description: * This routine issues a single command then polls for it's * completion. TO BE CALLED FROM ISR ONLY * * Algorithm: * Give the command to the driver. ( CUC_START is ALWAYS required ) * Poll for completion. * ***********************************************************************/void uti596addPolledCmd(struct i596_cmd *pCmd) { #ifdef DBG_596 printf("Adding command 0x%x\n", pCmd -> command ); #endif#ifdef DBG_POLLED_CMD switch ( pCmd -> command & 0x7 ){ /* check bottom 7 bits */ case CmdConfigure: printf("PolledCMD: Configure Command 0x%x\n", pCmd->command); break; case CmdSASetup: printf("PolledCMD: Set CMDress Command 0x%x\n", pCmd->command); break; case CmdMulticastList: printf("PolledCMD: Multi-cast list 0x%x\n", pCmd->command); break; case CmdNOp: printf("PolledCMD: NO op 0x%x\n", pCmd->command); break; case CmdTDR: printf("PolledCMD: TDR 0x%x\n", pCmd->command); break; case CmdDump: printf("PolledCMD: Dump 0x%x\n", pCmd->command); break; case CmdDiagnose: printf("PolledCMD: Diagnose 0x%x\n", pCmd->command); break; case CmdTx: break; default: printf("PolledCMD: ****Unknown Command encountered 0x%x\n", pCmd->command); break; } /* end switch */ #endif pCmd->status = 0; pCmd->command |= CMD_EOL ; /* only command in list*/ pCmd->next = I596_NULL; UTI_WAIT_COMMAND_ACCEPTED(10000,"Add Polled command: wait prev"); uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd; uti596_softc.scb.command = CUC_START; outport_word (CHAN_ATTN,0); UTI_WAIT_COMMAND_ACCEPTED(10000,"Add Polled command: start"); uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = I596_NULL;#ifdef DBG_POLLED_CMD printf("Scb status & command 0x%x 0x%x\n", uti596_softc.scb.status, uti596_softc.scb.command );#endif }/* * Driver transmit daemon */voiduti596_txDaemon (void *arg){ struct uti596_softc *sc = (struct uti596_softc *)arg; struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m; rtems_event_set events; for (;;) { /* * Wait for packet from stack */ rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); /* * Send packets till queue is empty. * Ensure that irq is on before sending. */ for (;;) { /* 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 */ }} /* * NIC reset daemon. */voiduti596_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 (;;) { /* * Wait for reset event from ISR */ rtems_bsdnet_event_receive (NIC_RESET_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); 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++; /* * Reinitialize the network card */ rtems_bsdnet_semaphore_obtain (); uti596reset(); rtems_bsdnet_semaphore_release (); }} /*********************************************************************** * Function: send_packet * * Description: Send a raw ethernet packet * * Algorithm: * increment some stats counters, * create the transmit command, * add the command to the CBL, * wait for event * ***********************************************************************/void send_packet(struct ifnet *ifp, struct mbuf *m){ struct i596_tbd *pPrev = I596_NULL, *pRemainingTbdList, *pTbd; struct mbuf *n, *input_m = m; struct uti596_softc *sc = ifp->if_softc; /* is this available from ifp ?*/ struct mbuf *l = NULL; unsigned int length = 0; rtems_status_code status; int bd_count = 0; rtems_event_set events; /* * For all mbufs in the chain, * fill a transmit buffer descriptor */ pTbd = sc->pTxCmd->pTbd; do { if (m->m_len) { /* * Fill in the buffer descriptor */ length += m->m_len; pTbd->data = mtod (m, void *); pTbd->size = m->m_len; pPrev = pTbd; pTbd = pTbd -> next; l = m; m = m->m_next; } else { /* * Just toss empty mbufs */ MFREE (m, n); m = n; if (l != NULL) l->m_next = m; } } while( m != NULL && ++bd_count < 16 ); /* This should never happen */ if ( bd_count == 16 ) { printf("TX ERROR:Too many mbufs in the packet!!!\n"); printf("Must coalesce!\n"); } if ( length < UTI_596_ETH_MIN_SIZE ) { pTbd->data = sc->zeroes; /* add padding to pTbd */ pTbd->size = UTI_596_ETH_MIN_SIZE - length; /* zeroes have no effect on the CRC */ } else pTbd = pPrev; /* Don't use pTbd in the send routine */ /* Disconnect the packet from the list of Tbd's */ pRemainingTbdList = pTbd->next; pTbd->next = I596_NULL; pTbd->size |= UTI_596_END_OF_FRAME; #ifdef DBG_RAW printf("RAW:Add cmd and sleep\n");#endif sc->rawsndcnt++; #ifdef DBG_RAW printf ("sending packet\n");#endif /* Sending Zero length packet: shouldn't happen */ if (pTbd->size <= 0) return ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -