if_upd985xx.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,622 行 · 第 1/4 页
C
1,622 行
cyg_drv_interrupt_unmask(p_eth_upd985xx->vector);}// ------------------------------------------------------------------------// Device table entry to operate the chip in a polled mode.// Only diddle the interface we were asked to!STATIC voideth_upd985xx_poll(struct eth_drv_sc *sc){ struct eth_upd985xx *p_eth_upd985xx; p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private; // As it happens, this driver always requests the DSR to be called: (void)eth_isr( p_eth_upd985xx->vector, (cyg_addrword_t)sc ); eth_upd985xx_deliver( sc );}// ------------------------------------------------------------------------// Determine interrupt vector used by a device - for attaching GDB stubs// packet handler.STATIC inteth_upd985xx_int_vector(struct eth_drv_sc *sc){ struct eth_upd985xx *p_eth_upd985xx; p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private; return (p_eth_upd985xx->vector);}// ------------------------------------------------------------------------STATIC inteth_set_mac_address( struct eth_upd985xx *p_eth_upd985xx, void *data ){ cyg_uint8 *p = (cyg_uint8 *)data; cyg_uint8 *mac_address; mac_address = &p_eth_upd985xx->mac_address[0]; mac_address[5] = p[5]; mac_address[4] = p[4]; mac_address[3] = p[3]; mac_address[2] = p[2]; mac_address[1] = p[1]; mac_address[0] = p[0]; p_eth_upd985xx->mac_addr_ok = 1; // Set the ESA in the device regs OUTL( ETH_LSA2, (p_eth_upd985xx->mac_address[1]) | (p_eth_upd985xx->mac_address[0] << 8 ) ); OUTL( ETH_LSA1, (p_eth_upd985xx->mac_address[5]) | (p_eth_upd985xx->mac_address[4] << 8 ) | (p_eth_upd985xx->mac_address[3] << 16 ) | (p_eth_upd985xx->mac_address[2] << 24) ); return 0; // OK}// ------------------------------------------------------------------------STATIC voideth_upd985xx_reset( struct eth_upd985xx *p_eth_upd985xx ){ int i; // Reset whole device: Software Reset (clears automatically) OUTL( ETH_CCR, ETH_CCR_SRT ); for ( i = 0; i < 10000; i++ ) /* nothing */; // Reset internal units OUTL( ETH_MACC2, ETH_MACC2_MCRST | ETH_MACC2_RFRST | ETH_MACC2_TFRST ); for ( i = 0; i < 10000; i++ ) /* nothing */; FLUSH_WRITES(); OUTL( ETH_MACC2, 0 ); // (and release reset) // Enable CRC adding, padding FLUSH_WRITES(); OUTL( ETH_MACC1, ETH_MACC1_CRCEN | ETH_MACC1_PADEN | ETH_MACC1_TXFC | ETH_MACC1_RXFC | ETH_MACC1_PARF ); FLUSH_WRITES(); OUTL( ETH_MACC2, ETH_MACC2_APD ); // Auto VLAN pad FLUSH_WRITES(); OUTL( ETH_HT1, 0 ); FLUSH_WRITES(); OUTL( ETH_HT2, 0 ); // Enable rx of broadcasts, multicasts, but not promiscuous... FLUSH_WRITES();#if defined( CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2 ) && \ !defined( CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E1E2_E2ONLY ) // Unless we are faking it. OUTL( ETH_AFR, ETH_AFR_ABC | ETH_AFR_PRM | ETH_AFR_PRO );#else OUTL( ETH_AFR, ETH_AFR_ABC | ETH_AFR_PRM );#endif FLUSH_WRITES(); OUTL( ETH_IPGT, 0x00000013 ); FLUSH_WRITES(); OUTL( ETH_IPGR, 0x00000e13 ); FLUSH_WRITES(); OUTL( ETH_CLRT, 0x0000380f ); FLUSH_WRITES(); OUTL( ETH_LMAX, MAX_ETHERNET_PACKET_SIZE ); // Select a clock for the MII FLUSH_WRITES(); OUTL( ETH_MIIC, ETH_MIIC_66 ); // Example code sets to 66. // Set VLAN type reg FLUSH_WRITES(); OUTL( ETH_VLTP, ETH_VLTP_VLTP ); // Set the ESA in the device regs if ( p_eth_upd985xx->mac_addr_ok ) { FLUSH_WRITES(); OUTL( ETH_LSA2, (p_eth_upd985xx->mac_address[1]) | (p_eth_upd985xx->mac_address[0] << 8 ) ); FLUSH_WRITES(); OUTL( ETH_LSA1, (p_eth_upd985xx->mac_address[5]) | (p_eth_upd985xx->mac_address[4] << 8 ) | (p_eth_upd985xx->mac_address[3] << 16 ) | (p_eth_upd985xx->mac_address[2] << 24) ); } FLUSH_WRITES(); OUTL( ETH_RXFCR, ETH_RXFCR_UWM_DEFAULT | ETH_RXFCR_LWM_DEFAULT | ETH_RXFCR_DRTH16W ); FLUSH_WRITES(); // Fault E4 - use only 32 for FLTH, not the previously recommended 48 (words) // Tag: CYGOPT_DEVS_ETH_MIPS_UPD985XX_HARDWARE_BUGS_E4 // but no config opt is provided. OUTL( ETH_TXFCR, ETH_TXFCR_TPTV_DEFAULT | ETH_TXFCR_TX_DRTH_DEFAULT | (32 << ETH_TXFCR_TX_FLTH_SHIFT) ); // Transmit and receive config regs we hit when enabling those // functions separately, and the wet string end of the receiver // which is controlled by MACC1 |= ETH_MACC1_SRXEN; // Tx and Rx interrupts enabled internally; // Tx done/aborted, and rx OK. FLUSH_WRITES(); OUTL( ETH_MSR, ETH_ISR_XMTDN | ETH_ISR_TABR | ETH_ISR_RCVDN | ETH_ISR_RBDRS | ETH_ISR_RBDRU ); FLUSH_WRITES();}// ------------------------------------------------------------------------//// NETWORK INTERFACE INITIALIZATION//// ------------------------------------------------------------------------STATIC boolupd985xx_eth_upd985xx_init(struct cyg_netdevtab_entry * ndp){ struct eth_drv_sc *sc; cyg_uint8 *mac_address; struct eth_upd985xx *p_eth_upd985xx;#ifdef DEBUG db_printf("upd985xx_eth_upd985xx_init\n");#endif sc = (struct eth_drv_sc *)(ndp->device_instance); p_eth_upd985xx = (struct eth_upd985xx *)(sc->driver_private); CHECK_NDP_SC_LINK(); p_eth_upd985xx->tx_busy = 0; // record the net dev pointer p_eth_upd985xx->ndp = (void *)ndp; mac_address = &p_eth_upd985xx->mac_address[0];#ifdef CYGSEM_DEVS_ETH_UPD985XX_ETH0_GET_EEPROM_ESA if ( ! p_eth_upd985xx->hardwired_esa ) { cyg_uint8 *p; union macar { struct { cyg_uint32 macar1, macar2, macar3; } integers; cyg_uint8 bytes[12]; } eeprom; eeprom.integers.macar1 = INL( MACAR1 ); // MAC Address Register 1 eeprom.integers.macar2 = INL( MACAR2 ); // MAC Address Register 2 eeprom.integers.macar3 = INL( MACAR3 ); // MAC Address Register 3 if ( (0 != eeprom.integers.macar1 || 0 != eeprom.integers.macar2 || 0 != eeprom.integers.macar3 ) && (0xffffffff != eeprom.integers.macar1 || 0xffffffff != eeprom.integers.macar2 || 0xffffffff != eeprom.integers.macar3 ) ) { // Then we have good data in the EEPROM#ifdef DEBUG os_printf( "EEPROM data %08x %08x %08x\n", eeprom.integers.macar1, eeprom.integers.macar2, eeprom.integers.macar3 );#endif p = &eeprom.bytes[0]; // pick up either set of ESA info if ( 1 == p_eth_upd985xx->index ) p += 6; mac_address[5] = p[5]; mac_address[4] = p[4]; mac_address[3] = p[3]; mac_address[2] = p[2]; mac_address[1] = p[1]; mac_address[0] = p[0]; p_eth_upd985xx->mac_addr_ok = 1; } else { // Fake it so we can get RedBoot going on a board with no EEPROM mac_address[0] = 0; mac_address[1] = 0xBA; mac_address[2] = 0xD0; mac_address[3] = 0xEE; mac_address[4] = 0x00; mac_address[5] = p_eth_upd985xx->index; p_eth_upd985xx->mac_addr_ok = 1; } }#endif // CYGSEM_DEVS_ETH_UPD985XX_ETH0_GET_EEPROM_ESA // Init the underlying hardware and insert the ESA: eth_upd985xx_reset(p_eth_upd985xx);#ifdef DEBUG os_printf("MAC Address %s, ESA = %02X %02X %02X %02X %02X %02X\n", p_eth_upd985xx->mac_addr_ok ? "OK" : "**BAD**", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]);#endif // Set up the pointers to data structures InitTxRing(p_eth_upd985xx); // Construct the interrupt handler p_eth_upd985xx->active = 0; cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector); cyg_drv_interrupt_mask(p_eth_upd985xx->vector); cyg_drv_interrupt_create( p_eth_upd985xx->vector, 0, // Priority - unused (CYG_ADDRWORD)sc, // Data item passed to ISR & DSR eth_isr, // ISR eth_drv_dsr, // DSR (generic) &p_eth_upd985xx->interrupt_handle, // handle to intr obj &p_eth_upd985xx->interrupt_object ); // space for int obj cyg_drv_interrupt_attach(p_eth_upd985xx->interrupt_handle); // Initialize upper level driver if ( p_eth_upd985xx->mac_addr_ok ) (sc->funs->eth_drv->init)(sc, &(p_eth_upd985xx->mac_address[0]) ); else (sc->funs->eth_drv->init)(sc, 0 ); return (1);}// ------------------------------------------------------------------------//// Function : eth_upd985xx_start//// ------------------------------------------------------------------------STATIC voideth_upd985xx_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags ){ struct eth_upd985xx *p_eth_upd985xx; cyg_uint32 ss; #ifdef CYGPKG_NET struct ifnet *ifp = &sc->sc_arpcom.ac_if;#endif p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private;#ifdef DEBUG os_printf("eth_upd985xx_start %d flg %x\n", p_eth_upd985xx->index, *(int *)p_eth_upd985xx );#endif if ( p_eth_upd985xx->active ) eth_upd985xx_stop( sc ); p_eth_upd985xx->active = 1; #ifdef CYGPKG_NET /* Enable promiscuous mode if requested, reception of oversized frames always. * The latter is needed for VLAN support and shouldn't hurt even if we're not * using VLANs. */ eth_upd985xx_configure(p_eth_upd985xx, !!(ifp->if_flags & IFF_PROMISC), 1);#endif // renegotiate link status p_eth_upd985xx->phy_status = eth_upd985xx_status( p_eth_upd985xx ); if ( p_eth_upd985xx->phy_status & PHY_STATUS_FDX ) { cyg_uint32 ss; // then enable full duplex in the MAC ss = INL( ETH_MACC1 ); ss |= ETH_MACC1_FDX; OUTL( ETH_MACC1, ss ); }#ifdef DEBUG { int status = p_eth_upd985xx->phy_status; os_printf("eth_upd985xx_start %d Link = %s, %s Mbps, %s Duplex\n", p_eth_upd985xx->index, status & PHY_STATUS_LINK ? "Up" : "Down", status & PHY_STATUS_100MBPS ? "100" : "10", status & PHY_STATUS_FDX ? "Full" : "Half" ); }#endif // Start the receive engine p_eth_upd985xx->count_rx_restart++; // Initialize all but one buffer: [B0,B1,B2,...Bx,NULL,LINK] InitRxRing( p_eth_upd985xx ); // Point the hardware at the list of buffers OUTL( ETH_RXDPR, (cyg_uint32)p_eth_upd985xx->rxring_active ); // Tell it about the buffers via the rx descriptor count OUTL( ETH_RXPDR, ETH_RXPDR_AL | (NUM_RXBUFS-1) ); // Ack any pending interrupts from the system p_eth_upd985xx->intrs = INL( ETH_ISR ); // Read-clear // Start the rx. OUTL( ETH_RXCR, ETH_RXCR_RXE | ETH_RXCR_DRBS_16 ); // Enable the wet string end of the receiver ss = INL( ETH_MACC1 ); ss |= ETH_MACC1_SRXEN; OUTL( ETH_MACC1, ss ); // And unmask the interrupt cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector); cyg_drv_interrupt_unmask(p_eth_upd985xx->vector);}// ------------------------------------------------------------------------//// Function : eth_upd985xx_status; 10/100 and Full/Half Duplex (FDX/HDX)//// ------------------------------------------------------------------------STATIC int eth_upd985xx_status( struct eth_upd985xx *p_eth_upd985xx ){ int status; int i, j; // Some of these bits latch and only reflect "the truth" on a 2nd reading. // So read and discard. mii_read( PHY_CONTROL_REG, &i, p_eth_upd985xx ); mii_read( PHY_STATUS_REG, &i, p_eth_upd985xx ); // Use the "and" of the local and remote capabilities words to infer // what is selected: status = 0; if ( mii_read( PHY_STATUS_REG, &i, p_eth_upd985xx ) ) { if ( PHY_STATUS_LINK_OK & i ) status |= PHY_STATUS_LINK; } if ( mii_read( PHY_AUTONEG_ADVERT, &j, p_eth_upd985xx ) && mii_read( PHY_AUTONEG_REMOTE, &i, p_eth_upd985xx ) ) {#if defined( DEBUG_TRAFFIC ) || defined( DEBUG_IOCTL ) os_printf( "MII: capabilities are %04x, %04x; common %04x\n", i, j, i & j );#endif j &= i; // select only common capabilities if ( (PHY_AUTONEG_100BASET4 | PHY_AUTONEG_100BASETX_FDX | PHY_AUTONEG_100BASETX_HDX) & j ) status |= PHY_STATUS_100MBPS; if ( (PHY_AUTONEG_100BASETX_FDX | PHY_AUTONEG_10BASET_FDX) & j ) status |= PHY_STATUS_FDX; } return status;}// ------------------------------------------------------------------------//// Function : eth_upd985xx_stop//// ------------------------------------------------------------------------STATIC void eth_upd985xx_stop( struct eth_drv_sc *sc ){ struct eth_upd985xx *p_eth_upd985xx; p_eth_upd985xx = (struct eth_upd985xx *)sc->driver_private; // No more interrupts cyg_drv_interrupt_acknowledge(p_eth_upd985xx->vector); cyg_drv_interrupt_mask(p_eth_upd985xx->vector);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?