if_i21143.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,882 行 · 第 1/5 页

C
1,882
字号
    static int initialized = 0; // only probe PCI et al *once*

    struct eth_drv_sc *sc;
    struct i21143 *p_i21143;
    cyg_uint8 mac_address[ETHER_ADDR_LEN];

#ifdef DEBUG
    diag_printf("intel_i21143_init\n");
#endif

    sc = (struct eth_drv_sc *)(ndp->device_instance);
    p_i21143 = (struct i21143 *)(sc->driver_private);

    IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
        diag_printf( "Bad device private pointer %x\n", sc->driver_private );
#endif
        return 0;
    }

    CHECK_NDP_SC_LINK();

    p_i21143->ndp = (void *)ndp;

    if ( 0 == initialized++ ) {
        // then this is the first time ever:
        if ( ! pci_init_find_21143s() ) {
#ifdef DEBUG
            diag_printf( "pci_init_find_21143s failed" );
#endif
            return 0;
        }
    }

    // If this device is not present, exit
    if (0 == p_i21143->found)
        return 0;

    p_i21143->mac_addr_ok = 0;

    if ( p_i21143->hardwired_esa )
        eth_set_mac_address( p_i21143, NULL ); // use that already there
                                        // (actually a NOP because !active)
    else {
        int ee_addrbits;
        int val[3];
        int good = 0;

        ee_addrbits = get_eeprom_size( p_i21143->io_address );
#ifdef DEBUG_EE
        diag_printf( "EEPROM size = %d\n", ee_addrbits );
#endif
        if ( 6 == ee_addrbits || 8 == ee_addrbits ) {
            int i;
            for ( i = 0; i < 3; i++ ) {
                val[i] = read_eeprom_word( p_i21143->io_address,
                                           ee_addrbits,
                                           i );
#ifdef DEBUG_EE
                diag_printf( "EEPROM: word at %04x = %04x\n", i, val[i] );
#endif
            }
            if ( 0x0000 != (val[0] | val[1] | val[2] ) && // some nonzero bits
                 0xffff != (val[0] & val[1] & val[2] ) && // not all ones
                 0x0000 == (val[0] & 0x80) ) {            // not multicast
                mac_address[0] = val[0] & 0xff;
                mac_address[1] = val[0] >> 8;
                mac_address[2] = val[1] & 0xff;
                mac_address[3] = val[1] >> 8;
                mac_address[4] = val[2] & 0xff;
                mac_address[5] = val[2] >> 8;
                good = 1;
#ifdef DEBUG_MAC
                diag_printf( "EEPROM ESA OK: %04x %04x %04x\n",
                             val[0], val[1], val[2] );
#endif
            }
        }                
        if ( !good ) {
            // Invent one
            mac_address[0] = 0x01;
            mac_address[1] = 0x23;
            mac_address[2] = 0x45;
            mac_address[3] = 0x67;
            mac_address[4] = 0x98;
            mac_address[5] = 0x76;
        }
        // Just copy into the structure - not into hardware 'cos !active
        eth_set_mac_address( p_i21143, &mac_address[0] );
    }

#if defined( DEBUG ) || defined( DEBUG_MAC )
    diag_printf("MAC Address %s, ESA = %02X %02X %02X %02X %02X %02X\n",
                p_i21143->mac_addr_ok ? "OK" : "**BAD**", 
                p_i21143->mac_address[0],
                p_i21143->mac_address[1],
                p_i21143->mac_address[2],
                p_i21143->mac_address[3],
                p_i21143->mac_address[4],
                p_i21143->mac_address[5]);
#endif

    // Initialize upper level driver
    if ( p_i21143->mac_addr_ok )
        (sc->funs->eth_drv->init)(sc, &(p_i21143->mac_address[0]) );
    else
        (sc->funs->eth_drv->init)(sc, NULL );

    return (1);
}

// ------------------------------------------------------------------------
//
//  Function : i21143_start
//
// ------------------------------------------------------------------------
static void 
i21143_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags )
{
    struct i21143 *p_i21143;
    cyg_uint32 ioaddr;
    cyg_uint32 l;
#ifdef CYGPKG_NET
    struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#endif

    p_i21143 = (struct i21143 *)sc->driver_private;
    ioaddr = p_i21143->io_address; // get 21143's I/O address
    
    IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
        diag_printf( "i21143_start: Bad device pointer %x\n", p_i21143 );
#endif
        return;
    }

    if ( ! p_i21143->mac_addr_ok ) {
#ifdef DEBUG
        diag_printf("i21143_start %d: invalid MAC address, "
                  "can't bring up interface\n",
                  p_i21143->index );
#endif
        return;
    }

#ifdef DEBUG
    diag_printf( "i21143_start: enters\n" );
#endif

    if ( p_i21143->active )
        i21143_stop( sc );

    // Update the cached copy of the status reg just in case
    l = i21143_status( p_i21143 );
    if ( l != p_i21143->line_status ) {
        // It has changed!
        i21143_reset(p_i21143);             // sets line_status itself
    }

    // Enable device
    p_i21143->active = 1;

    // Initialize tx status
    p_i21143->tx_endbuf = NO_TX_IN_PROGRESS;

    eth_set_mac_address( p_i21143, NULL ); // to put it in the device

    // After eth_set_mac_address() initialize the data structs for use:
    InitRxRing( p_i21143 );
    InitTxRing( p_i21143 );

    // Enable promiscuous mode if requested.
    i21143_configure(p_i21143, 0
#ifdef CYGPKG_NET
                     || !!(ifp->if_flags & IFF_PROMISC)
#endif
#ifdef ETH_DRV_FLAGS_PROMISC_MODE
                     || !!(flags & ETH_DRV_FLAGS_PROMISC_MODE)
#endif

                     );
#ifdef DEBUG
    {
        int status = p_i21143->line_status;
        diag_printf("i21143_start %d flg %x Link = %s, %s Mbps, %s Duplex\n",
                    p_i21143->index,
                    *(int *)p_i21143,
                    (GEN_STATUS_LINK    & status) ?   "Up" : "Down",
                    (GEN_STATUS_100MBPS & status) ?  "100" : "10",
                    (GEN_STATUS_FDX     & status) ? "Full" : "Half");
    }
#endif

    // Load pointer to Rx Ring and enable receiver
    OUTL( CYGHWR_PCI_VIRT_TO_BUS( (cyg_uint32)p_i21143->rx_ring ), CSR_RXBASE );
    // Enable receive interrupts
    l = INL( CSR_INTR_ENABLE );
    l |= 0
     | CSR_STATUS_NIS      
     | CSR_STATUS_AIS      
     // CSR_STATUS_ERI      
     // CSR_STATUS_FBE      
     // CSR_STATUS_LNF      
     // CSR_STATUS_GTE      
     // CSR_STATUS_ETI      
     // CSR_STATUS_RWT      
     | CSR_STATUS_RX_STOPPED
     | CSR_STATUS_RBU      
     | CSR_STATUS_RX_INTR  
     // CSR_STATUS_UNF      
     // CSR_STATUS_LNP_ANC  
     // CSR_STATUS_TJT      
     | CSR_STATUS_TBU      
     | CSR_STATUS_TX_STOPPED
     | CSR_STATUS_TX_INTR  
        ;
    OUTL( l, CSR_INTR_ENABLE );
    // and start the receiver
    l = INL( CSR_OPMODE );
    l |= (CSR_OPMODE_RX_START);
    OUTL( l, CSR_OPMODE );
    INCR_STAT( rx_restart );
#ifdef DEBUG_DUMP_REGS
    debug_dump_regs( ioaddr, BOTH );
#endif
}

// ------------------------------------------------------------------------
//
//  Function : i21143_status
//
// ------------------------------------------------------------------------
int
i21143_status( struct i21143* p_i21143 )
{
    int status;
    int i, j;
    cyg_uint32 ioaddr;
    
    IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
        diag_printf( "i21143_status: Bad device pointer %x\n", p_i21143 );
#endif
        return 0;
    }

    ioaddr = p_i21143->io_address; // get 21143's I/O address

    // Some of these bits latch and only reflect "the truth" on a 2nd reading.
    // So read and discard.
    status = mii_read_register( ioaddr, PHY_CONTROL_REG );
    status = mii_read_register( ioaddr, PHY_STATUS_REG  );
    // Use the "and" of the local and remote capabilities words to infer
    // what is selected:
    status = 0;
    i = mii_read_register( ioaddr, PHY_STATUS_REG );
    if ( PHY_STATUS_LINK_OK & i )
        status |= GEN_STATUS_LINK;

    i = mii_read_register( ioaddr, PHY_AUTONEG_ADVERT );
    j = mii_read_register( ioaddr, PHY_AUTONEG_REMOTE );
    p_i21143->phy_autoneg_remote = j;
#if defined( DEBUG_TRAFFIC ) || defined( DEBUG_IOCTL )
    diag_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 |= GEN_STATUS_100MBPS;
    if ( (PHY_AUTONEG_100BASETX_FDX | PHY_AUTONEG_10BASET_FDX) & j )
        status |= GEN_STATUS_FDX;

    return status;
}

int
i21143_status_changed( struct i21143* p_i21143 )
{
    cyg_uint32 ioaddr;
    int j;
    ioaddr = p_i21143->io_address; // get 21143's I/O address

    j = mii_read_register( ioaddr, PHY_AUTONEG_REMOTE );
    return ( j != p_i21143->phy_autoneg_remote );
}

// ------------------------------------------------------------------------
//
//  Function : i21143_stop
//
// ------------------------------------------------------------------------

static void
i21143_stop( struct eth_drv_sc *sc )
{
    struct i21143 *p_i21143;

    p_i21143 = (struct i21143 *)sc->driver_private;

    IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
        diag_printf( "i21143_stop: Bad device pointer %x\n", p_i21143 );
#endif
        return;
    }
   
#ifdef DEBUG_STARTSTOPRESET
    diag_printf("i21143_stop %d flg %x\n", p_i21143->index, *(int *)p_i21143 );
#endif

    p_i21143->active = 0;               // stop people tormenting it

    if ( NO_TX_IN_PROGRESS != p_i21143->tx_endbuf) {
        cyg_uint32 key;
        
        CYG_ASSERT( TX_DESCRIPTORS > p_i21143->tx_endbuf, "tx_endbuf range" );

        key = p_i21143->tx_keys[ 0 ];
        // Common "done" code - key nonzero => report done
        if (key) {
            p_i21143->tx_keys[ 0 ] = 0;
            p_i21143->tx_endbuf = NO_TX_IN_PROGRESS;
            // Then tell the stack we are done:
            INCR_STAT( tx_complete );
            (sc->funs->eth_drv->tx_done)( sc, key, 0 );
        }
    }

    i21143_reset(p_i21143);             // that should stop it
}


// ------------------------------------------------------------------------
//
//  Function : InitRxRing
//
// ------------------------------------------------------------------------
static void
InitRxRing(struct i21143* p_i21143)
{
    int i;
    volatile BUFDES *bp;

    p_i21143->rx_ring =
        (BUFDES *)CYGHWR_CACHED_TO_UNCACHED( &(p_i21143->_rx[0]) );

    bp = p_i21143->rx_ring;
    for ( i = 0 ; i < RX_DESCRIPTORS; i++ ) {
        bp->des0 = DES0_STATUS_OWN_OPEN; // NIC owns it, not the CPU
        bp->des1 = (MAX_RX_PACKET_SIZE << DES1_B1SIZE_SHIFT);
        bp->buf1 = CYGHWR_PCI_VIRT_TO_BUS( &( p_i21143->_rxbufs[i][0] ) );
        bp->buf2 = 0;
        bp++;
    }
    bp--; // last one
    bp->des1 |= DES1_ENDRING;

    p_i21143->next_rx_descriptor = 0;
}

// ------------------------------------------------------------------------
//
//  Function : PacketRxReady     (Called from delivery thread & foreground)
//
// ------------------------------------------------------------------------
static void
PacketRxReady(struct i21143* p_i21143)
{
    volatile BUFDES *bp;
    int index;
    struct eth_drv_sc *sc;
    int count;
    {
        struct cyg_netdevtab_entry *ndp;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?