📄 network.c
字号:
{ int i; #ifdef DBG_INIT printk(("uti596_initMem: begins\n")) #endif sc->resetDone = 0; /* * Set up receive frame area (RFA) */ i = uti596_initRFA( sc->rxBdCount ); if ( i < sc->rxBdCount ) { printk(("init_rfd: only able to allocate %d receive frame descriptors\n", i)) } /* * Write the SCB with a pointer to the receive frame area * and keep a pointer for our use. */ sc->scb.rfd_pointer = word_swap((unsigned long)sc->pBeginRFA); sc->scb.pRfd = sc->pBeginRFA; /* * Diagnose the health of the board */ uti596_diagnose(); /* * Configure the 82596 */ uti596_configure( sc ); /* * Set up the Individual (hardware) Address */ uti596_IAsetup ( sc ); /* * Initialize the transmit buffer descriptors */ uti596_initTBD( sc ); /* Padding used to fill short tx frames */ memset ( &sc->zeroes, 0, 64); /* now need ISR */ sc->resetDone = 1;}/* * uti596_initialize * * Reset the 82596 and initialize it with a new SCP. * * Input parameters: * sc - pointer to the uti596_softc * * Output parameters: NONE * * Return value: NONE */void uti596_initialize( uti596_softc_ *sc){ /* Reset the device. Stops it from doing whatever it might be doing. */ uti596_portReset(); /* Get a new System Configuration Pointer */ uti596_scp_alloc( sc ); /* write the SYSBUS: interrupt pin active high, LOCK disabled, * internal triggering, linear mode */ sc->pScp->sysbus = 0x54; /* provide the iscp to the scp, keep a pointer for our use */ sc->pScp->iscp_pointer = word_swap((unsigned long)&sc->iscp); sc->pScp->iscp = &sc->iscp; /* provide the scb to the iscp, keep a pointer for our use */ sc->iscp.scb_pointer = word_swap((unsigned long)&sc->scb); sc->iscp.scb = &sc->scb; #ifdef DBG_INIT printk(("uti596_initialize: Starting i82596.\n")) #endif /* Set up the 82596 */ uti596_setScpAndScb( sc ); /* clear the scb command word */ sc->scb.command = 0;}/* * uti596_initialize_hardware * * Reset the 82596 and initialize it with a new SCP. Enable bus snooping. * Install the interrupt handlers. * * Input parameters: * sc - pointer to the uti596_softc * * Output parameters: NONE * * Return value: NONE */void uti596_initialize_hardware( uti596_softc_ *sc){ rtems_isr_entry dummy; printk(("uti596_initialize_hardware: begins\n")) /* Get the PCCChip2 to assert bus snooping signals on behalf of the i82596 */ pccchip2->LANC_berr_ctl = 0x40; uti596_initialize( sc ); /* * Configure interrupt control in PCCchip2 */ pccchip2->LANC_error = 0xff; /* clear status register */ pccchip2->LANC_int_ctl = 0x5d; /* lvl 5, enabled, edge-sensitive rising */ pccchip2->LANC_berr_ctl = 0x5d; /* bus error: lvl 5, enabled, snoop control * will supply dirty data and leave dirty data * on read access and sink any data on write */ /* * Install the interrupt handler * calls rtems_interrupt_catch */ dummy = (rtems_isr_entry) set_vector( uti596_DynamicInterruptHandler, 0x57, 1 ); /* Initialize the 82596 memory */ uti596_initMem(sc); #ifdef DBG_INIT printk(("uti596_initialize_hardware: After attach, status of board = 0x%x\n", sc->scb.status )) #endif}/* * uti596_reset_hardware * * Reset the 82596 and initialize it with an SCP. * * Input parameters: * sc - pointer to the uti596_softc * * Output parameters: NONE * * Return value: NONE */void uti596_reset_hardware( uti596_softc_ *sc){ rtems_status_code status_code; i596_cmd *pCmd; pCmd = sc->pCmdHead; /* This is a tx command for sure (99.99999%) */ /* the command block list (CBL) is empty */ sc->scb.cmd_pointer = (unsigned long) I596_NULL; /* all 1's */ sc->pCmdHead = sc->scb.pCmd = I596_NULL; /* all 1's */ #ifdef DBG_RESET printk(("uti596_reset_hardware\n")) #endif uti596_initialize( sc ); /* * Wake the transmitter if needed. */ if ( sc->txDaemonTid && pCmd != I596_NULL ) { printk(("****RESET: wakes transmitter!\n")) status_code = rtems_event_send (sc->txDaemonTid, INTERRUPT_EVENT); if ( status_code != RTEMS_SUCCESSFUL ) { printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n", sc->txDaemonTid, rtems_status_text (status_code) )) } } #ifdef DBG_RESET printk(("uti596_reset_hardware: After reset_hardware, status of board = 0x%x\n", sc->scb.status )) #endif}/* * uti596_clearListStatus * * Clear the stat fields for all RFDs * * Input parameters: * pRfd - a pointer to the head of the RFA * * Output parameters: NONE * * Return value: NONE */void uti596_clearListStatus( i596_rfd *pRfd){ while ( pRfd != I596_NULL ) { pRfd -> stat = 0; pRfd = (i596_rfd *) word_swap((unsigned long)pRfd-> next); }}/* * uti596_reset * * Reset the 82596 and reconfigure * * Input parameters: NONE * * Output parameters: NONE * * Return value: NONE */void uti596_reset( void ){ uti596_softc_ *sc = &uti596_softc; #ifdef DBG_RESET printk(("uti596_reset: begin\n")) #endif /* Wait for the CU to be available, then * reset the ethernet hardware. Must re-config. */ sc->resetDone = 0; uti596_wait ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); uti596_reset_hardware ( &uti596_softc ); #ifdef DBG_RESET uti596_diagnose(); #endif /* * Configure the 82596 */ uti596_configure( sc ); /* * Set up the Individual (hardware) Address */ uti596_IAsetup ( sc ); sc->pCmdHead = sc->pCmdTail = sc->scb.pCmd = I596_NULL; /* restore the RFA */ 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 ; } /* Re-address the head of the RFA in the SCB */ sc->scb.pRfd = sc->pBeginRFA; sc->scb.rfd_pointer = word_swap((unsigned long)sc->pBeginRFA); /* Clear the status of all RFDs */ uti596_clearListStatus( sc->pBeginRFA ); printk(("uti596_reset: Starting NIC\n")) /* Start the receiver */ sc->scb.command = RX_START; sc->started = 1; /* assume that the start is accepted */ sc->resetDone = 1; uti596_issueCA ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); UTI_596_ASSERT(sc->pCmdHead == I596_NULL, "Reset: CMD not cleared\n") #ifdef DBG_RESET printk(("uti596_reset: completed\n")) #endif}/* * uti596_dequeue * * Remove an RFD from the received fram queue * * Input parameters: * ppQ - a pointer to a i596_rfd pointer * * Output parameters: NONE * * Return value: * pRfd - a pointer to the dequeued RFD */i596_rfd * uti596_dequeue( i596_rfd ** ppQ){ ISR_Level level; i596_rfd * pRfd; _ISR_Disable(level); /* invalid address, or empty queue or emptied queue */ if( ppQ == NULL || *ppQ == NULL || *ppQ == I596_NULL) { _ISR_Enable(level); return I596_NULL; } /* * Point to the dequeued buffer, then * adjust the queue pointer and detach the buffer */ pRfd = *ppQ; *ppQ = (i596_rfd *) word_swap ((unsigned long) pRfd->next); pRfd->next = I596_NULL; /* unlink the rfd being returned */ _ISR_Enable(level); return pRfd;}/* * uti596_append * * Remove an RFD buffer from the RFA and tack it on to * the received frame queue for processing. * * Input parameters: * ppQ - a pointer to the queue pointer * pRfd - a pointer to the buffer to be returned * * Output parameters: NONE * * Return value: NONE */ void uti596_append( i596_rfd ** ppQ, i596_rfd * pRfd){ i596_rfd *p; if ( pRfd != NULL && pRfd != I596_NULL) { pRfd -> next = I596_NULL; pRfd -> cmd |= CMD_EOL; /* set EL bit */ if ( *ppQ == NULL || *ppQ == I596_NULL ) { /* empty list */ *ppQ = pRfd; } else { /* walk to the end of the list */ for ( p=*ppQ; p->next != I596_NULL; p=(i596_rfd *) word_swap ((unsigned long)p->next) ); /* append the rfd */ p->cmd &= ~CMD_EOL; /* Clear EL bit at end */ p->next = (i596_rfd *) word_swap ((unsigned long)pRfd); } } else { printk(("Illegal attempt to append: %p\n", pRfd)) }}/* * uti596_supplyFD * * Return a buffer (RFD) to the receive frame area (RFA). * Call with interrupts disabled. * * Input parameters: * pRfd - a pointer to the buffer to be returned * * Output parameters: NONE * * Return value: NONE */void uti596_supplyFD ( i596_rfd * pRfd){ i596_rfd *pLastRfd; UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD!\n") pRfd -> cmd = CMD_EOL; pRfd -> pRbd = I596_NULL; pRfd -> next = I596_NULL; pRfd -> stat = 0x0000; /* clear STAT_C and STAT_B bits */ /* * Check if the list is empty: */ if ( uti596_softc.pBeginRFA == I596_NULL ) { /* Start a list with one entry */ uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; UTI_596_ASSERT(uti596_softc.countRFD == 0, "Null begin, but non-zero count\n") if ( uti596_softc.pLastUnkRFD != I596_NULL ) { printk(("LastUnkRFD is NOT NULL!!\n")) } uti596_softc.countRFD = 1; return; } /* * Check if the last RFD is used/read by the 596. */ pLastRfd = uti596_softc.pEndRFA; /* C = complete, B = busy (prefetched) */ if ( pLastRfd != I596_NULL && ! (pLastRfd -> stat & ( STAT_C | STAT_B ) )) { /* * Not yet too late to add it */ pLastRfd -> next = (i596_rfd *) word_swap ((unsigned long)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 !! */ /* * Check if the last RFD was used while appending. */ if ( pLastRfd -> stat & ( STAT_C | STAT_B ) ) { /* completed or was prefetched */ /* * Either the EL bit of the last rfd has been read by the 82596, * and it will stop after reception,( true when RESET_EL not reached ) or * the EL bit was NOT read by the 82596 and it will use the linked * RFD for the next reception. ( true when RESET_EL was reached ) * So, it is unknown whether or not the linked rfd will be used. * Therefore, the end of list CANNOT be updated. */ UTI_596_ASSERT ( uti596_softc.pLastUnkRFD == I596_NULL, "Too many Unk RFD's\n" ) uti596_softc.pLastUnkRFD = pRfd; return; } else { /* * The RFD being added was not touched by the 82596 */ if (uti596_softc.pLastUnkRFD != I596_NULL ) { uti596_append((i596_rfd **)&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */ uti596_softc.pEndSavedQueue = pRfd; uti596_softc.savedCount++; uti596_softc.countRFD--; } else { uti596_softc.pEndRFA = pRfd; /* the RFA has been extended */ if ( ( uti596_softc.scb.status & SCB_STAT_RNR || uti596_softc.scb.status & RU_NO_RESOURCES ) && uti596_softc.countRFD > 1 ) { /* Ensure that beginRFA is not EOL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -