📄 network.c
字号:
void *arg){ uti596_softc_ *sc = (uti596_softc_ *)arg; struct ifnet *ifp = (struct ifnet *)&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 (;;) { /* Get the next mbuf chain to transmit. */ IF_DEQUEUE(&ifp->if_snd, m); if (!m) break; send_packet (ifp, m); /* blocks */ } ifp->if_flags &= ~IFF_OACTIVE; /* no more to send, mark output inactive */ }}/*********************************************************************** * Function: uti596_rxDaemon * * Description: Receiver task * * Algorithm: Extract the packet from an RFD, and place into an * mbuf chain. Place the mbuf chain in the network task * queue. Assumes that the frame check sequence is removed * by the 82596. * ***********************************************************************//* static */ void uti596_rxDaemon( void *arg){ uti596_softc_ *sc = (uti596_softc_ *)arg; struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; struct mbuf *m; i596_rfd *pRfd; ISR_Level level; int tid; rtems_event_set events; struct ether_header *eh; int frames = 0; #ifdef DBG_RX printk(("uti596_rxDaemon: begin\n")) printk(("&scb = %p, pRfd = %p\n", &sc->scb,sc->scb.pRfd)) #endif rtems_task_ident (0, 0, &tid); for(;;) { /* * Wait for packet. */ #ifdef DBG_RX printk(("uti596_rxDaemon: Receiver sleeps\n")) #endif rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); #ifdef DBG_RX printk(("uti596_rxDaemon: Receiver wakes\n")) #endif /* * While received frames are available. Note that the frame may be * a fragment, so it is NOT a complete packet. */ pRfd = uti596_dequeue( (i596_rfd **)&sc->pInboundFrameQueue); while ( pRfd && pRfd != I596_NULL && pRfd -> stat & STAT_C ) { if ( pRfd->stat & STAT_OK) { /* a good frame */ int pkt_len = pRfd->count & 0x3fff; /* the actual # of bytes received */ #ifdef DBG_RX printk(("uti596_rxDaemon: Good frame, @%p, data @%p length %d\n", pRfd, pRfd -> data , pkt_len)) #endif frames++; /* * Allocate an mbuf to give to the stack * The format of the data portion of the RFD is: * <ethernet header, payload>. * The FRAME CHECK SEQUENCE / CRC is stripped by the uti596. * This is to be optimized later.... should not have to memcopy! */ MGETHDR(m, M_WAIT, MT_DATA); MCLGET(m, M_WAIT); m->m_pkthdr.rcvif = ifp; /* move everything into an mbuf */ memcpy(m->m_data, (const char *)pRfd->data, pkt_len); m->m_len = m->m_pkthdr.len = pkt_len - sizeof(struct ether_header) - 4; /* move the header to an mbuf */ eh = mtod (m, struct ether_header *); m->m_data += sizeof(struct ether_header); #ifdef DBG_PACKETS { int i; printk(("uti596_rxDaemon: mbuf contains:\n")) print_eth( (char *) (((int)m->m_data)-sizeof(struct ether_header))); for ( i = 0; i<20; i++) { printk((".")) } } #endif ether_input (ifp, eh, m); } /* end if STAT_OK */ else { /* * A bad frame is present: Note that this could be the last RFD! */ #ifdef DBG_RX printk(("uti596_rxDaemon: Bad frame\n")) #endif /* * FIX ME: use the statistics from the SCB */ sc->stats.rx_errors++; if ((sc->scb.pRfd->stat) & 0x0001) sc->stats.collisions++; if ((sc->scb.pRfd->stat) & 0x0080) sc->stats.rx_length_errors++; if ((sc->scb.pRfd->stat) & 0x0100) sc->stats.rx_over_errors++; if ((sc->scb.pRfd->stat) & 0x0200) sc->stats.rx_fifo_errors++; if ((sc->scb.pRfd->stat) & 0x0400) sc->stats.rx_frame_errors++; if ((sc->scb.pRfd->stat) & 0x0800) sc->stats.rx_crc_errors++; if ((sc->scb.pRfd->stat) & 0x1000) sc->stats.rx_length_errors++; } UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD\n") _ISR_Disable(level); uti596_supplyFD ( pRfd ); /* Return RFD to RFA. */ _ISR_Enable(level); pRfd = uti596_dequeue( (i596_rfd **)&sc->pInboundFrameQueue); /* grab next frame */ } /* end while */ } /* end for() */ #ifdef DBG_RX printk (("uti596_rxDaemon: frames ... %d\n", frames)) #endif}/*********************************************************************** * Function: void uti596_resetDaemon * * Description: ***********************************************************************/void uti596_resetDaemon( void *arg){ uti596_softc_ *sc = (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); printk(("reset daemon: Resetting NIC @ %d:%d:%d \n", tm_struct.hour, tm_struct.minute, tm_struct.second)) sc->stats.nic_reset_count++; /* Reinitialize the LANC */ rtems_bsdnet_semaphore_obtain (); uti596_reset(); rtems_bsdnet_semaphore_release (); }}/*********************************************************************** * Function: uti596_DynamicInterruptHandler * * Description: * This is the interrupt handler for the uti596 board * ***********************************************************************//* static */ rtems_isr uti596_DynamicInterruptHandler( rtems_vector_number irq){ #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: begins")) #endif uti596_wait (&uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT); scbStatus = uti596_softc.scb.status & 0xf000; if ( scbStatus ) { /* acknowledge interrupts */ /* Write to the ICLR bit in the PCCchip2 control registers to clear * the INT status bit. Clearing INT here *before* sending the CA signal * to the 82596 should ensure that interrupts won't be lost. */ pccchip2->LANC_int_ctl |=0x08; pccchip2->LANC_berr_ctl |=0x08; /* printk(("***INFO: ACK %x\n", scbStatus))*/ /* Send the CA signal to acknowledge interrupt */ uti596_softc.scb.command = scbStatus; uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); if( uti596_softc.resetDone ) { /* stack is attached */ uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); } else { printk(("***INFO: ACK'd w/o processing. status = %x\n", scbStatus)) return; } } else { 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, 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 ) { printk(("\n*****WARNING: RNR %x\n",scbStatus)) if (uti596_softc.pBeginRFA != I596_NULL) { printk(("*****INFO: RFD cmd: %x status:%x\n", uti596_softc.pBeginRFA->cmd, uti596_softc.pBeginRFA->stat)) } else { printk(("*****WARNING: RNR condition with NULL BeginRFA\n")) } } /* * Receive Unit Control * a frame is received */ if ( scbStatus & SCB_STAT_FR ) { uti596_softc.rxInterrupts++; #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: Frame received\n")) #endif if ( uti596_softc.pBeginRFA == I596_NULL || !( uti596_softc.pBeginRFA -> stat & STAT_C)) { uti596_dump_scb(); uti596_softc.nic_reset = 1; } else { while ( uti596_softc.pBeginRFA != I596_NULL && ( uti596_softc.pBeginRFA -> stat & STAT_C)) { #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: pBeginRFA != NULL\n")) #endif count_rx ++; if ( count_rx > 1) { printk(("****WARNING: Received 2 frames on 1 interrupt \n")) } /* Give Received Frame to the ULCS */ uti596_softc.countRFD--; if ( uti596_softc.countRFD < 0 ) { printk(("ISR: Count < 0 !!! count == %d, beginRFA = %p\n", uti596_softc.countRFD, uti596_softc.pBeginRFA)) } uti596_softc.stats.rx_packets++; /* the rfd next link is stored with upper and lower words swapped so read it that way */ pIsrRfd = (i596_rfd *) word_swap ((unsigned long)uti596_softc.pBeginRFA->next); /* the append destroys the link */ uti596_append( (i596_rfd **)&uti596_softc.pInboundFrameQueue , uti596_softc.pBeginRFA ); /* * if we have just received the a frame in the last unknown RFD, * then it is certain that the RFA is empty. */ if ( uti596_softc.pLastUnkRFD == uti596_softc.pBeginRFA ) { UTI_596_ASSERT(uti596_softc.pLastUnkRFD != I596_NULL,"****ERROR:LastUnk is NULL, begin ptr @ end!\n") uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD = I596_NULL; } #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: Wake %#x\n",uti596_softc.rxDaemonTid)) #endif sc = rtems_event_send(uti596_softc.rxDaemonTid, INTERRUPT_EVENT); if ( sc != RTEMS_SUCCESSFUL ) { rtems_panic("Can't notify rxDaemon: %s\n", rtems_status_text (sc)); } #ifdef DBG_ISR else { printk(("uti596_DynamicInterruptHandler: Rx Wake: %#x\n",uti596_softc.rxDaemonTid)) } #endif uti596_softc.pBeginRFA = pIsrRfd; } /* end while */ } /* end if */ if ( uti596_softc.pBeginRFA == I596_NULL ) { /* adjust the pEndRFA to reflect an empty list */ if ( uti596_softc.pLastUnkRFD == I596_NULL && uti596_softc.countRFD != 0 ) { printk(("Last Unk is NULL, BeginRFA is null, and count == %d\n", uti596_softc.countRFD)) } uti596_softc.pEndRFA = I596_NULL; if ( uti596_softc.countRFD != 0 ) { printk(("****ERROR:Count is %d, but begin ptr is NULL\n", uti596_softc.countRFD )) } } } /* end if ( scbStatus & SCB_STAT_FR ) */ /* * Command Unit Control * a command is completed */ if ( scbStatus & SCB_STAT_CX ) { #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: CU\n")) #endif pIsrCmd = uti596_softc.pCmdHead; /* For ALL completed commands */ if ( pIsrCmd != I596_NULL && pIsrCmd->status & STAT_C ) { #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: pIsrCmd != NULL\n")) #endif /* Adjust the command block list */ uti596_softc.pCmdHead = (i596_cmd *) word_swap ((unsigned long)pIsrCmd->next); /* * If there are MORE commands to process, * the serialization in the raw routine has failed. * ( Perhaps AddCmd is bad? ) */ UTI_596_ASSERT(uti596_softc.pCmdHead == I596_NULL, "****ERROR: command serialization failed\n") /* What if the command did not complete OK? */ switch ( pIsrCmd->command & 0x7) { case CmdConfigure: uti596_softc.cmdOk = 1; break; case CmdDump: #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: dump!\n")) #endif uti596_softc.cmdOk = 1; break; case CmdDiagnose: #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: diagnose!\n")) #endif uti596_softc.cmdOk = 1; break; case CmdSASetup: /* printk(("****INFO:Set address interrupt\n")) */ if ( pIsrCmd -> status & STAT_OK ) { uti596_softc.cmdOk = 1; } else { printk(("****ERROR:SET ADD FAILED\n")) } break; case CmdTx: UTI_596_ASSERT(uti596_softc.txDaemonTid, "****ERROR:Null txDaemonTid\n") #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: wake TX:0x%x\n",uti596_softc.txDaemonTid)) #endif if ( uti596_softc.txDaemonTid ) { /* Ensure that the 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_ISR else { printk(("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid)) } #endif } break; case CmdMulticastList: printk(("***ERROR:Multicast?!\n")) pIsrCmd->next = I596_NULL; break; case CmdTDR: { unsigned long status = *( (unsigned long *)pIsrCmd)+1; printk(("****ERROR:TDR?!\n")) if (status & STAT_C) { /* mark the TDR command successful */ uti596_softc.cmdOk = 1; } else { if (status & 0x4000) { printk(("****WARNING:Transceiver problem.\n")) } if (status & 0x2000) { printk(("****WARNING:Termination problem.\n")) } if (status & 0x1000) { printk(("****WARNING:Short circuit.\n")) /* printk(("****INFO:Time %
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -