📄 sonic.c
字号:
* request an interrupt on every other transmitted packet. * * NOTE: sonic_allocate() zeroes all of the memory allocated. */ sc->tdaTail = sonic_allocate(sc->tdaCount * sizeof *tdp);#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) printf( "tdaTail = %p\n", sc->tdaTail );#endif tdp = sc->tdaTail; for (i = 0 ; i < sc->tdaCount ; i++) { /* * Start off with the table of outstanding mbuf's */ /* * status, pkt_config, pkt_size, and all fragment fields * are set to zero by sonic_allocate. *//* XXX not used by the BSD drivers tdp->frag[0].frag_link = LSW(tdp + 1);*/ if (i & 3) tdp->pkt_config = TDA_CONFIG_PINT; tdp->status = 0; tdp->frag_count = 0; tdp->link_pad = LSW(tdp + 1) | TDA_LINK_EOL; tdp->linkp = &((tdp + 1)->frag[0].frag_link); tdp->next = (TransmitDescriptor_t *)(tdp + 1);#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) sonic_print_tx_descriptor( tdp );#endif tdp++; } tdp--; sc->tdaHead = tdp; tdp->link_pad = LSW(sc->tdaTail) | TDA_LINK_EOL; tdp->next = (TransmitDescriptor_t *)sc->tdaTail; tdp->linkp = &sc->tdaTail->frag[0].frag_link; /* * Set up circular linked list in Receive Descriptor Area. * Leaves sc->rda pointing at the `beginning' of the list. * * NOTE: The RDA and CDP must have the same MSW for their addresses. */ sc->rda = sonic_allocate( (sc->rdaCount * sizeof(ReceiveDescriptor_t)) + sizeof(CamDescriptor_t) ); sc->cdp = (CamDescriptorPointer_t) ((unsigned char *)sc->rda + (sc->rdaCount * sizeof(ReceiveDescriptor_t)));#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) printf( "rda area = %p\n", sc->rda ); printf( "cdp area = %p\n", sc->cdp );#endif ordp = rdp = sc->rda; for (i = 0 ; i < sc->rdaCount ; i++) { /* * status, byte_count, pkt_ptr0, pkt_ptr1, and seq_no are set * to zero by sonic_allocate. */ rdp->link = LSW(rdp + 1); rdp->in_use = RDA_FREE; rdp->next = (ReceiveDescriptor_t *)(rdp + 1); ordp = rdp; rdp++; } /* * Link the last desriptor to the 1st one and mark it as the end * of the list. */ ordp->next = sc->rda; ordp->link = LSW(sc->rda) | RDA_LINK_EOL; sc->rdp_last = ordp; /* * Allocate the receive resource area. * In accordance with National Application Note 746, make the * receive resource area bigger than the receive descriptor area. * This has the useful side effect of making the receive resource * area big enough to hold the CAM descriptor area. */ sc->rsa = sonic_allocate((sc->rdaCount + RRA_EXTRA_COUNT) * sizeof *sc->rsa);#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) printf( "rsa area = %p\n", sc->rsa );#endif /* * Set up list in Receive Resource Area. * Allocate space for incoming packets. */ rwp = sc->rsa; for (i = 0 ; i < (sc->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) { /* * Allocate memory for buffer. * Place a pointer to the mbuf at the beginning of the buffer * so we can find the mbuf when the SONIC returns the buffer * to the driver. */ MGETHDR (m, M_WAIT, MT_DATA); MCLGET (m, M_WAIT); m->m_pkthdr.rcvif = &sc->arpcom.ac_if; sc->rda[i].mbufp = m; p = mtod (m, void *); /* * Set up RRA entry */ rwp->buff_ptr_lsw = LSW(p); rwp->buff_ptr_msw = MSW(p); rwp->buff_wc_lsw = RBUF_WC; rwp->buff_wc_msw = 0;#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) sonic_print_rx_descriptor( &sc->rda[i] );#endif } sc->rea = rwp;#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) printf( "rea area = %p\n", sc->rea );#endif /* * Issue a software reset. */ (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX ); /* * Set up data configuration registers. */ (*sc->write_register)( rp, SONIC_REG_DCR, sc->dcr_value ); (*sc->write_register)( rp, SONIC_REG_DCR2, sc->dc2_value ); (*sc->write_register)( rp, SONIC_REG_CR, CR_STP | CR_RXDIS | CR_HTX ); /* * Mask all interrupts */ (*sc->write_register)( rp, SONIC_REG_IMR, 0x0 ); /* XXX was backwards */ /* * Clear outstanding interrupts. */ (*sc->write_register)( rp, SONIC_REG_ISR, 0x7FFF ); /* * Clear the tally counters */ (*sc->write_register)( rp, SONIC_REG_CRCT, 0xFFFF ); (*sc->write_register)( rp, SONIC_REG_FAET, 0xFFFF ); (*sc->write_register)( rp, SONIC_REG_MPT, 0xFFFF ); (*sc->write_register)( rp, SONIC_REG_RSC, 0 ); /* * Set the Receiver mode * * Enable/disable reception of broadcast packets */ if (sc->acceptBroadcast) (*sc->write_register)( rp, SONIC_REG_RCR, RCR_BRD ); else (*sc->write_register)( rp, SONIC_REG_RCR, 0 ); /* * Set up Resource Area pointers */ (*sc->write_register)( rp, SONIC_REG_URRA, MSW(sc->rsa) ); (*sc->write_register)( rp, SONIC_REG_RSA, LSW(sc->rsa) ); (*sc->write_register)( rp, SONIC_REG_REA, LSW(sc->rea) ); (*sc->write_register)( rp, SONIC_REG_RRP, LSW(sc->rsa) ); (*sc->write_register)( rp, SONIC_REG_RWP, LSW(sc->rsa) ); /* XXX was rea */ (*sc->write_register)( rp, SONIC_REG_URDA, MSW(sc->rda) ); (*sc->write_register)( rp, SONIC_REG_CRDA, LSW(sc->rda) ); (*sc->write_register)( rp, SONIC_REG_UTDA, MSW(sc->tdaTail) ); (*sc->write_register)( rp, SONIC_REG_CTDA, LSW(sc->tdaTail) ); /* * Set End Of Buffer Count register to the value recommended * in Note 1 of Section 3.4.4.4 of the SONIC data sheet. */ (*sc->write_register)( rp, SONIC_REG_EOBC, RBUF_WC - 2 ); /* * Issue the load RRA command */ (*sc->write_register)( rp, SONIC_REG_CR, CR_RRRA ); while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RRRA) continue; /* * Remove device reset */ (*sc->write_register)( rp, SONIC_REG_CR, 0 ); /* * Set up the SONIC CAM with our hardware address. */ hwaddr = sc->arpcom.ac_enaddr; cdp = sc->cdp;#if (SONIC_DEBUG & SONIC_DEBUG_CAM) printf( "hwaddr: %2x:%2x:%2x:%2x:%2x:%2x\n", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] );#endif cdp->cep = 0; /* Fill first and only entry in CAM */ cdp->cap0 = hwaddr[1] << 8 | hwaddr[0]; cdp->cap1 = hwaddr[3] << 8 | hwaddr[2]; cdp->cap2 = hwaddr[5] << 8 | hwaddr[4]; cdp->ce = 0x0001; /* Enable first entry in CAM */ (*sc->write_register)( rp, SONIC_REG_CDC, 1 ); /* 1 entry in CDA */ (*sc->write_register)( rp, SONIC_REG_CDP, LSW(cdp) ); (*sc->write_register)( rp, SONIC_REG_CR, CR_LCAM ); /* Load the CAM */ while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_LCAM) continue; /* * Verify that CAM was properly loaded. */ (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );#if (SONIC_DEBUG & SONIC_DEBUG_CAM) (*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */ printf ("Loaded Ethernet address into SONIC CAM.\n" " Wrote %04x%04x%04x - %#x\n" " Read %04x%04x%04x - %#x\n", cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce, (*sc->read_register)( rp, SONIC_REG_CAP2 ), (*sc->read_register)( rp, SONIC_REG_CAP1 ), (*sc->read_register)( rp, SONIC_REG_CAP0 ), (*sc->read_register)( rp, SONIC_REG_CE )); (*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */ if (((*sc->read_register)( rp, SONIC_REG_CAP2 ) != cdp->cap2) || ((*sc->read_register)( rp, SONIC_REG_CAP1 ) != cdp->cap1) || ((*sc->read_register)( rp, SONIC_REG_CAP0 ) != cdp->cap0) || ((*sc->read_register)( rp, SONIC_REG_CE ) != cdp->ce)) { printf ("Failed to load Ethernet address into SONIC CAM.\n" " Wrote %04x%04x%04x - %#x\n" " Read %04x%04x%04x - %#x\n", cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce, (*sc->read_register)( rp, SONIC_REG_CAP2 ), (*sc->read_register)( rp, SONIC_REG_CAP1 ), (*sc->read_register)( rp, SONIC_REG_CAP0 ), (*sc->read_register)( rp, SONIC_REG_CE )); rtems_panic ("SONIC LCAM"); }#endif (*sc->write_register)(rp, SONIC_REG_CR, /* CR_TXP | */CR_RXEN | CR_STP); /* * Attach SONIC interrupt handler *//* XXX (*sc->write_register)( rp, SONIC_REG_IMR, 0 );*/ old_handler = set_vector(sonic_interrupt_handler, sc->vector, 1); /* * Remainder of hardware initialization is * done by the receive and transmit daemons. */}/* * Send packet (caller provides header). */SONIC_STATIC void sonic_start(struct ifnet *ifp){ struct sonic_softc *sc = ifp->if_softc; rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); ifp->if_flags |= IFF_OACTIVE;}/* * Initialize and start the device */SONIC_STATIC void sonic_init (void *arg){ struct sonic_softc *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; void *rp = sc->sonic; int rcr; if (sc->txDaemonTid == 0) { /* * Set up SONIC hardware */ sonic_initialize_hardware (sc); /* * Start driver tasks */ sc->rxDaemonTid = rtems_bsdnet_newproc ("SNrx", 4096, sonic_rxDaemon, sc); sc->txDaemonTid = rtems_bsdnet_newproc ("SNtx", 4096, sonic_txDaemon, sc); } /* * Set flags appropriately */ rcr = (*sc->read_register)( rp, SONIC_REG_RCR ); if (ifp->if_flags & IFF_PROMISC) rcr |= RCR_PRO; else rcr &= ~RCR_PRO; (*sc->write_register)( rp, SONIC_REG_RCR, rcr); /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING; /* * Enable receiver and transmitter */ sonic_enable_interrupts( sc, IMR_TXEREN | (IMR_PRXEN | IMR_RBAEEN) ); sonic_command( sc, CR_RXEN );}/* * Driver ioctl handler */static intsonic_ioctl (struct ifnet *ifp, int command, caddr_t data){ struct sonic_softc *sc = ifp->if_softc; int error = 0; switch (command) { case SIOCGIFADDR: case SIOCSIFADDR: ether_ioctl (ifp, command, data); break; case SIOCSIFFLAGS: switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { case IFF_RUNNING: sonic_stop (sc); break; case IFF_UP: sonic_init (sc); break; case IFF_UP | IFF_RUNNING: sonic_stop (sc); sonic_init (sc); break; default: break; } break; case SIO_RTEMS_SHOW_STATS: sonic_stats (sc); break; /* * FIXME: All sorts of multicast commands need to be added here! */ default: error = EINVAL; break; } return error;}/* * Attach an SONIC driver to the system * This is the only `extern' function in the driver. */intrtems_sonic_driver_attach ( struct rtems_bsdnet_ifconfig *config, sonic_configuration_t *chip){ struct sonic_softc *sc; struct ifnet *ifp; int mtu; int unitNumber; char *unitName; /* * Parse driver name */ if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) return 0; /* * Is driver free? */ if ((unitNumber <= 0) || (unitNumber > NSONIC)) { printf ("Bad SONIC unit number.\n"); return 0; } sc = &sonic_softc[unitNumber - 1]; ifp = &sc->arpcom.ac_if; if (ifp->if_softc != NULL) { printf ("Driver already in use.\n"); return 0; } /* * zero out the control structure */ memset( sc, 0, sizeof(*sc) ); /* * Process options */ if (config->hardware_address) { memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); } else { memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN); } if (config->mtu) mtu = config->mtu; else mtu = ETHERMTU; if (config->rbuf_count) sc->rdaCount = config->rbuf_count; else sc->rdaCount = chip->rda_count; if (config->xbuf_count) sc->tdaCount = config->xbuf_count; else sc->tdaCount = chip->tda_count; sc->acceptBroadcast = !config->ignore_broadcast; sc->sonic = (void *) chip->base_address; sc->vector = chip->vector; sc->dcr_value = chip->dcr_value; sc->dc2_value = chip->dc2_value; sc->write_register = chip->write_register; sc->read_register = chip->read_register; /* * Set up network interface values */ ifp->if_softc = sc; ifp->if_unit = unitNumber; ifp->if_name = unitName; ifp->if_mtu = mtu; ifp->if_init = sonic_init; ifp->if_ioctl = sonic_ioctl; ifp->if_start = sonic_start; ifp->if_output = ether_output; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; /* * Attach the interface */ if_attach (ifp); ether_ifattach (ifp); return 1;}#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS)#include <stdio.h>char SONIC_Reg_name[64][6]= { "CR", /* 0x00 */ "DCR", /* 0x01 */ "RCR", /* 0x02 */ "TCR", /* 0x03 */ "IMR", /* 0x04 */ "ISR", /* 0x05 */ "UTDA", /* 0x06 */ "CTDA", /* 0x07 */ "0x08", /* 0x08 */ "0x09", /* 0x09 */ "0x0A", /* 0x0A */ "0x0B", /* 0x0B */ "0x0C", /* 0x0C */ "URDA", /* 0x0D */ "CRDA", /* 0x0E */ "0x0F", /* 0x0F */ "0x10", /* 0x10 */ "0x11", /* 0x11 */ "0x12", /* 0x12 */ "EOBC", /* 0x13 */ "URRA", /* 0x14 */ "RSA", /* 0x15 */ "REA", /* 0x16 */ "RRP", /* 0x17 */ "RWP", /* 0x18 */ "0x19", /* 0x19 */ "0x1A", /* 0x1A */ "0x1B", /* 0x1B */ "0x1C", /* 0x1C */ "0x0D", /* 0x1D */ "0x1E", /* 0x1E */ "0x1F", /* 0x1F */ "0x20", /* 0x20 */ "CEP", /* 0x21 */ "CAP2", /* 0x22 */ "CAP1", /* 0x23 */ "CAP0", /* 0x24 */ "CE", /* 0x25 */ "CDP", /* 0x26 */ "CDC", /* 0x27 */ "SR", /* 0x28 */ "WT0", /* 0x29 */ "WT1", /* 0x2A */ "RSC", /* 0x2B */ "CRCT", /* 0x2C */ "FAET", /* 0x2D */ "MPT", /* 0x2E */ "MDT", /* 0x2F */ "0x30", /* 0x30 */ "0x31", /* 0x31 */ "0x32", /* 0x32 */ "0x33", /* 0x33 */ "0x34", /* 0x34 */ "0x35", /* 0x35 */ "0x36", /* 0x36 */ "0x37", /* 0x37 */ "0x38", /* 0x38 */ "0x39", /* 0x39 */ "0x3A", /* 0x3A */ "0x3B", /* 0x3B */ "0x3C", /* 0x3C */ "0x3D", /* 0x3D */ "0x3E", /* 0x3E */ "DCR2" /* 0x3F */};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -