📄 network.c
字号:
uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL; UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n") UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n") UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n") #ifdef DBG_MEM printk(("uti596_supplyFD: starting receiver")) #endif /* start the receiver */ UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n") uti596_softc.scb.pRfd = uti596_softc.pBeginRFA; uti596_softc.scb.rfd_pointer = word_swap ((unsigned long) uti596_softc.pBeginRFA); /* Don't ack RNR! The receiver should be stopped in this case */ uti596_softc.scb.command = RX_START | SCB_STAT_RNR; UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n") /* send CA signal */ uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); } } return; } } else { /* * too late , pLastRfd in use ( or NULL ), * in either case, EL bit has been read, and RNR condition will occur */ uti596_append( (i596_rfd **)&uti596_softc.pSavedRfdQueue, pRfd); /* save it for RNR */ uti596_softc.pEndSavedQueue = pRfd; /* reset end of saved queue */ uti596_softc.savedCount++; return; }}/* * send_packet * * Send a raw ethernet packet, add a * transmit command to the CBL * * Input parameters: * ifp - a pointer to the ifnet structure * m - a pointer to the mbuf being sent * * Output parameters: NONE * * Return value: NONE */void send_packet( struct ifnet *ifp, struct mbuf *m){ i596_tbd *pPrev = I596_NULL; i596_tbd *pRemainingTbdList; i596_tbd *pTbd; struct mbuf *n, *input_m = m; uti596_softc_ *sc = ifp->if_softc; 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 for each */ pTbd = (i596_tbd*) word_swap ((unsigned long)sc->pTxCmd->pTbd); do { if (m->m_len) { /* * Fill in the buffer descriptor */ length += m->m_len; pTbd->data = (char *) word_swap ((unsigned long) mtod (m, void *)); pTbd->size = m->m_len; pPrev = pTbd; pTbd = (i596_tbd *) word_swap ((unsigned long) 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 ); if ( length < UTI_596_ETH_MIN_SIZE ) { pTbd->data = (char *) word_swap ((unsigned long) sc->zeroes); /* add padding to pTbd */ pTbd->size = UTI_596_ETH_MIN_SIZE - length; /* zeroes have no effect on the CRC */ } else /* Don't use pTbd in the send routine */ pTbd = pPrev; /* Disconnect the packet from the list of Tbd's */ pRemainingTbdList = (i596_tbd *) word_swap ((unsigned long)pTbd->next); pTbd->next = I596_NULL; pTbd->size |= UTI_596_END_OF_FRAME; sc->rawsndcnt++; #ifdef DBG_SEND printk(("send_packet: sending packet\n")) #endif /* Sending Zero length packet: shouldn't happen */ if (pTbd->size <= 0) return; #ifdef DBG_PACKETS printk (("\nsend_packet: Transmitter adds packet\n")) print_hdr ( sc->pTxCmd->pTbd->data ); /* print the first part */ print_pkt ( sc->pTxCmd->pTbd->next->data ); /* print the first part */ print_echo (sc->pTxCmd->pTbd->data); #endif /* add the command to the output command queue */ uti596_addCmd ( (i596_cmd *) sc->pTxCmd ); /* sleep until the command has been processed or Timeout encountered. */ status= rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); if ( status != RTEMS_SUCCESSFUL ) { printk(("Could not sleep %s\n", rtems_status_text(status))) } #ifdef DBG_SEND printk(("send_packet: RAW - wake\n")) #endif sc->txInterrupts++; if ( sc->pTxCmd -> cmd.status & STAT_OK ) { sc->stats.tx_packets++; } else { printk(("*** send_packet: Driver Error 0x%x\n", sc->pTxCmd -> cmd.status )) sc->stats.tx_errors++; if ( sc->pTxCmd->cmd.status & 0x0020 ) sc->stats.tx_retries_exceeded++; if (!(sc->pTxCmd->cmd.status & 0x0040)) sc->stats.tx_heartbeat_errors++; if ( sc->pTxCmd->cmd.status & 0x0400 ) sc->stats.tx_carrier_errors++; if ( sc->pTxCmd->cmd.status & 0x0800 ) sc->stats.collisions++; if ( sc->pTxCmd->cmd.status & 0x1000 ) sc->stats.tx_aborted_errors++; } /* end if stat_ok */ /* * Restore the transmitted buffer descriptor chain. */ pTbd -> next = (i596_tbd *) word_swap ((unsigned long)pRemainingTbdList); /* * Free the mbufs used by the sender. */ m = input_m; while ( m != NULL ) { MFREE(m,n); m = n; }}/*********************************************************************** * Function: uti596_attach * * Description: * Configure the driver, and connect to the network stack * * Algorithm: * * Check parameters in the ifconfig structure, and * set driver parameters accordingly. * Initialize required rx and tx buffers. * Link driver data structure onto device list. * Return 1 on successful completion. * ***********************************************************************/int uti596_attach( struct rtems_bsdnet_ifconfig * pConfig, int attaching){ uti596_softc_ *sc = &uti596_softc; /* device dependent data structure */ struct ifnet * ifp = (struct ifnet *)&sc->arpcom.ac_if; /* ifnet structure */ unsigned char j1; /* State of J1 jumpers */ int unitNumber; char *unitName;#if defined(mvme167) char *pAddr; int addr;#endif #ifdef DBG_ATTACH printk(("uti596_attach: begins\n")) #endif /* The NIC is not started yet */ sc->started = 0; /* Indicate to ULCS that this is initialized */ ifp->if_softc = (void *)sc; sc->pScp = NULL; /* Parse driver name */ if ((unitNumber = rtems_bsdnet_parse_driver_name (pConfig, &unitName)) < 0) return 0; ifp->if_name = unitName; ifp->if_unit = unitNumber; /* Assign mtu */ if ( pConfig -> mtu ) ifp->if_mtu = pConfig -> mtu; else ifp->if_mtu = ETHERMTU; /* * Check whether parameters should be obtained from NVRAM. If * yes, and if an IP address, netmask, or ethernet address are * provided in NVRAM, cheat, and stuff them into the ifconfig * structure, OVERRIDING and existing or NULL values. * * Warning: If values are provided in NVRAM, the ifconfig entries * must be NULL because buffer memory allocated to hold the * structure values is unrecoverable and would be lost here. */ /* Read the J1 header */ j1 = (unsigned char)(lcsr->vector_base & 0xFF);#if defined(mvme167) if ( !(j1 & 0x10) ) { /* Jumper J1-4 is on, configure from NVRAM */ if ( (addr = nvram->ipaddr) ) { /* We have a non-zero entry, copy the value */ if ( (pAddr = malloc ( INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT )) ) pConfig->ip_address = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1 ); else rtems_panic("Can't allocate ip_address buffer!\n"); } if ( (addr = nvram->netmask) ) { /* We have a non-zero entry, copy the value */ if ( (pAddr = malloc ( INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT )) ) pConfig->ip_netmask = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1 ); else rtems_panic("Can't allocate ip_netmask buffer!\n"); } /* Ethernet address requires special handling -- it must be copied into * the arpcom struct. The following if construct serves only to give the * NVRAM parameter the highest priority if J1-4 indicates we are configuring * from NVRAM. * * If the ethernet address is specified in NVRAM, go ahead and copy it. * (ETHER_ADDR_LEN = 6 bytes). */ if ( nvram->enaddr[0] || nvram->enaddr[1] || nvram->enaddr[2] ) { /* Anything in the first three bytes indicates a non-zero entry, copy value */ memcpy ((void *)sc->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN); } else if ( pConfig->hardware_address) { /* There is no entry in NVRAM, but there is in the ifconfig struct, so use it. */ memcpy ((void *)sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN); } else { /* There is no ethernet address provided, so it will be read * from BBRAM at $FFFC1F2C by default. [mvme167 manual p. 1-47] */ memcpy ((void *)sc->arpcom.ac_enaddr, (char *)0xFFFC1F2C, ETHER_ADDR_LEN); } } else if ( pConfig->hardware_address) { /* We are not configuring from NVRAM (J1-4 is off), and the ethernet address * is given in the ifconfig structure. Copy it. */ memcpy ((void *)sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN); } else#endif { /* We are not configuring from NVRAM (J1-4 is off), and there is no ethernet * address provided in the ifconfig struct, so it will be read from BBRAM at * $FFFC1F2C by default. [mvme167 manual p. 1-47] */ memcpy ((void *)sc->arpcom.ac_enaddr, (char *)0xFFFC1F2C, ETHER_ADDR_LEN); } /* Possibly override default acceptance of broadcast packets */ if (pConfig->ignore_broadcast) uti596initSetup[8] |= 0x02; /* Assign requested receive buffer descriptor count */ if (pConfig->rbuf_count) sc->rxBdCount = pConfig->rbuf_count; else sc->rxBdCount = RX_BUF_COUNT; /* Assign requested tx buffer descriptor count */ if (pConfig->xbuf_count) sc->txBdCount = pConfig->xbuf_count; else sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; /* Set up fields in the ifnet structure*/ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_init = uti596_init; ifp->if_ioctl = uti596_ioctl; ifp->if_start = uti596_start; ifp->if_output = ether_output; /* uti596_softc housekeeping */ sc->started = 1; sc->pInboundFrameQueue = I596_NULL; sc->scb.command = 0; /* * Attach the interface */ if_attach (ifp); ether_ifattach (ifp); return 1;}/*********************************************************************** * Function: uti596_start * * Description: * start the driver * * Algorithm: * send an event to the tx task * set the if_flags * ***********************************************************************/static void uti596_start( struct ifnet *ifp){ uti596_softc_ *sc = ifp->if_softc; #ifdef DBG_START printk(("uti596_start: begins\n")) #endif rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); ifp->if_flags |= IFF_OACTIVE;}/*********************************************************************** * Function: uti596_init * * Description: * driver initialization * * Algorithm: * initialize the 82596 * start driver tx and rx tasks, and reset task * send the RX_START command the the RU * set if_flags * * ***********************************************************************/void uti596_init( void * arg){ uti596_softc_ *sc = arg; struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; if (sc->txDaemonTid == 0) { /* * Initialize the 82596 */ #ifdef DBG_INIT printk(("uti596_init: begins\nuti596_init: initializing the 82596...\n")) #endif uti596_initialize_hardware(sc); /* * Start driver tasks */ #ifdef DBG_INIT printk(("uti596_init: starting driver tasks...\n")) #endif sc->txDaemonTid = rtems_bsdnet_newproc ("UTtx", 2*4096, uti596_txDaemon, (void *)sc); sc->rxDaemonTid = rtems_bsdnet_newproc ("UTrx", 2*4096, uti596_rxDaemon, (void *)sc); sc->resetDaemonTid = rtems_bsdnet_newproc ("UTrt", 2*4096, uti596_resetDaemon, (void *)sc); #ifdef DBG_INIT printk(("uti596_init: After attach, status of board = 0x%x\n", sc->scb.status )) #endif } /* * Enable receiver */ #ifdef DBG_INIT printk(("uti596_init: enabling the reciever...\n" )) #endif sc->scb.command = RX_START; uti596_issueCA ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING; #ifdef DBG_INIT printk(("uti596_init: completed.\n")) #endif }/*********************************************************************** * Function: uti596stop * * Description: * stop the driver * * Algorithm: * mark driver as not started, * mark transmitter as busy * abort any transmissions/receptions * clean-up all buffers ( RFD's et. al. ) * * ***********************************************************************//* static */ void uti596_stop( uti596_softc_ *sc){ struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; ifp->if_flags &= ~IFF_RUNNING; sc->started = 0; #ifdef DBG_STOP printk(("uti596stop: %s: Shutting down ethercard, status was %4.4x.\n", uti596_softc.arpcom.ac_if.if_name, uti596_softc.scb.status)) #endif printk(("Stopping interface\n")) sc->scb.command = CUC_ABORT | RX_ABORT; i82596->chan_attn = 0x00000000;}/*********************************************************************** * Function: void uti596_txDaemon * * Description: Transmit task * * Algorithm: Get mbufs to be transmitted, stuff into RFDs, send * ***********************************************************************/void uti596_txDaemon(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -