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 + -
显示快捷键?