📄 network.c
字号:
outport_word(CHAN_ATTN,0); while (sc->iscp.stat) if (--boguscnt == 0) { printf("initialize_hardware: timed out with status %4.4lx\n", sc->iscp.stat ); break; } /* clear the command word */ sc->scb.command = 0; /* * Set up interrupts ( NEW irq style ) */ sc->irqInfo.name = UTI_596_IRQ; sc->irqInfo.hdl = ( void * ) uti596DynamicInterruptHandler; sc->irqInfo.on = uti596_maskOn; sc->irqInfo.off = uti596_maskOff; sc->irqInfo.isOn = uti596_isOn; status_code = BSP_install_rtems_irq_handler (&sc->irqInfo); if (!status_code) rtems_panic ("Can't attach uti596 interrupt handler for irq %d\n", sc->irqInfo.name); /* Initialize the 82596 memory ( Transmit buffers ) */ uti596_initMem(sc); #ifdef DBG_INIT printf("After attach, status of board = 0x%x\n", sc->scb.status );#endif outport_word(0x380, 0xf); /* reset the LED's */}voiduti596_reset_hardware(struct uti596_softc *sc){ int boguscnt = 1000; rtems_status_code status_code; struct i596_cmd *pCmd; printf("uti596_reset_hardware\n"); pCmd = sc->pCmdHead; /* This is a tx command for sure (99.99999%) */ /* reset the board */ outport_word( PORT_ADDR, 0 ); outport_word( PORT_ADDR, 0 ); if ( sc->pScp == NULL ) { printf("Calloc scp\n"); uti596_softc.pScp = (struct i596_scp *) calloc(1,sizeof(struct i596_scp) + 0xf); }#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 ); */ outport_word(PORT_ADDR, ((((int)sc->pScp) & 0xffff) | 2 )); outport_word(PORT_ADDR, (( (int)sc->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; /* * 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");#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 * * Description: * creates the necessary descriptors for the * uti596 board, hooks the interrupt, and starts the board. * Assumes that interrupts are hooked. * * Algorithm: * ***********************************************************************/ voiduti596_initMem(struct uti596_softc * sc){ int i,count; struct i596_tbd *pTbd; sc->resetDone = 0; /* ??? */ /* * Set up receive frame area (RFA) */ i = uti596_initRFA( sc->rxBdCount ); if ( i < sc->rxBdCount ) printf("init_rfd: only able to allocate %d receive frame descriptors\n", i); sc->scb.pRfd = sc->pBeginRFA; #ifdef DBG_INIT printf(" IRQ %d.\n", sc->irqInfo.name);#endif /* * Diagnose the health of the board */ uti596Diagnose(1); /* * set up the i596 config command */#ifdef DBG_INIT printf("Configuring\n");#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("***Configure failed\n"); /*******/ /* * Create the IA setup command */#ifdef DBG_INIT printf("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 ("Set Address OK, count= %d\n",count); else printf("Set Address Failed\n"); /*******/#ifdef DBG_INIT printf( "After initialization, status and command: 0x%x, 0x%x\n", sc->scb.status, sc->scb.status); #endif /* initialize transmit buffer descriptors*/ sc->pLastUnkRFD = I596_NULL; sc->pTxCmd = (struct tx_cmd *) calloc (1,sizeof (struct tx_cmd) ); sc->pTbd = (struct i596_tbd *) calloc (1,sizeof (struct i596_tbd) ); sc->pTxCmd -> pTbd = sc->pTbd; sc->pTxCmd->cmd.command = CMD_FLEX|CmdTx; sc->pTxCmd->pad = 0; sc->pTxCmd->size = 0; /* all bytes are in list of TBD's */ pTbd = sc->pTbd; for ( i=0; i<sc->txBdCount; i++) pTbd = pTbd -> next = (struct i596_tbd *) calloc (1,sizeof (struct i596_tbd) ); pTbd -> next = I596_NULL; memset ( &sc->zeroes, 0, 64); #ifdef DBG_596 printf( "After receiver start, status and command: 0x%x, 0x%x\n", sc->scb.status, sc->scb.status);#endif printf("uti596_initMem allows ISR's\n"); sc->resetDone = 1; /* now need ISR */}/*********************************************************************** * Function: uti596dump * * Description: Dump 596 registers * * Algorithm: ***********************************************************************//* static */ intuti596dump(char * pDumpArea){ struct i596_dump dumpCmd; int boguscnt = 25000000; /* over a second! */#ifdef DBG_596 printf("uti596dump:\n");#endif dumpCmd.cmd.command = CmdDump; dumpCmd.cmd.next = I596_NULL; dumpCmd.pData = pDumpArea; uti596_softc.cmdOk = 0; uti596addCmd ( (struct i596_cmd *)&dumpCmd); while (1) if ( --boguscnt == 0){ printf("Dump command was not processed within spin loop delay\n"); return 0; } else { if ( uti596_softc.cmdOk ) return 1; /* successful completion */ } }/*********************************************************************** * 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 */ voiduti596_rxDaemon(void *arg){ struct uti596_softc *sc = (struct uti596_softc *)arg; struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m; struct i596_rfd *pRfd; ISR_Level level; int tid; rtems_event_set events; struct ether_header *eh; int frames = 0; #ifdef DBG_596 printf ("uti596_rxDaemon\n"); printf("&scb = %p, pRfd = %p\n", &sc->scb,sc->scb.pRfd);#endif rtems_task_ident (0, 0, &tid);#ifdef DBG_596 printf("RX tid = 0x%x\n", tid);#endif for(;;) { /* * Wait for packet. */#ifdef DBG_596 printf("Receiver sleeps\n");#endif rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); #ifdef DBG_596 printf("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 = uti596dequeue( &sc->pInboundFrameQueue); while ( pRfd && pRfd != I596_NULL && pRfd -> stat & STAT_C ) {#ifdef DEBUG_INIT printf("\nReceived packet:\n"); print_eth( pRfd->data);#endif if ( pRfd->stat & STAT_OK){ /* a good frame. Allocate an mbuf to take it from the queue */ int pkt_len = pRfd->count & 0x3fff; /* the actual # of bytes received */#ifdef DBG_596 printf("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, 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_596 printf("m->m_ext: %p pRfd -> data: %p\n", m->m_ext, pRfd -> data);#endif#ifdef DEBUG_INIT_2 printf("mbuf contains:\n"); print_eth( (char *) (((int)m->m_data)-sizeof(struct ether_header))); for ( i = 0; i<20; i++) printf(".");#endif#ifdef DBG_VERSION BREAKPOINT();#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_596 printf("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");#ifdef DBG_SUPPLY_FD printf("Supply FD Starting\n");#endif _ISR_Disable(level); uti596supplyFD ( pRfd ); /* Return RFD to RFA. CAN WE REALLY?*/ _ISR_Enable(level);#ifdef DBG_SUPPLY_FD printf("Supply FD Complete\n");#endif#ifdef DBG_VERSION BREAKPOINT();#endif pRfd = uti596dequeue( &sc->pInboundFrameQueue); /* grab next frame */ } /* end while */ } /* end for(;;)*/ #ifdef DBG_596 printf ("frames %d\n", frames);#endif } /*********************************************************************** * Function: uti596clearListStatus * * Description: * Clear the stat fields for all rfd's * Algorithm: * ***********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -