欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

if_lan91cxx.c

eCos操作系统源码
C
第 1 页 / 共 4 页
字号:
                cpd->enaddr[1],                cpd->enaddr[2],                cpd->enaddr[3],                cpd->enaddr[4],                cpd->enaddr[5] );#endif // DEBUG    // Set up hardware address    for (i = 0;  i < sizeof(cpd->enaddr);  i += 2)        put_reg(sc, LAN91CXX_IA01+i/2,                cpd->enaddr[i] | (cpd->enaddr[i+1] << 8));#else // not CYGINT_DEVS_ETH_SMSC_LAN91CXX_STATIC_ESA    // Find ESA - check possible sources in sequence and stop when    // one provides the ESA:    //   RedBoot option (via provide_esa)    //   Compile-time configuration    //   EEPROM    if (NULL != cpd->provide_esa) {        esa_configured = cpd->provide_esa(cpd);# if DEBUG & 8        if (esa_configured)            db_printf("Got ESA from RedBoot option\n");# endif    }    if (!esa_configured && cpd->hardwired_esa) {        // ESA is already set in cpd->esa[]        esa_configured = true;# if DEBUG & 8        db_printf("Got ESA from cpd\n");# endif    }    if (esa_configured) {        // Set up hardware address        for (i = 0;  i < sizeof(cpd->enaddr);  i += 2)            put_reg(sc, LAN91CXX_IA01+i/2,                    cpd->enaddr[i] | (cpd->enaddr[i+1] << 8));    } else {        // Use the address from the serial EEPROM        // Read out hardware address        for (i = 0;  i < sizeof(cpd->enaddr);  i += 2) {            unsigned short z = get_reg(sc, LAN91CXX_IA01+i/2 );            cpd->enaddr[i] =   (unsigned char)(0xff & z);            cpd->enaddr[i+1] = (unsigned char)(0xff & (z >> 8));        }        esa_configured = true;# if DEBUG & 8        db_printf("Got ESA from eeprom\n");# endif    }#if DEBUG & 9    db_printf("LAN91CXX - ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",                cpd->enaddr[0],                cpd->enaddr[1],                cpd->enaddr[2],                cpd->enaddr[3],                cpd->enaddr[4],                cpd->enaddr[5] );#endif // DEBUG#endif // !CYGINT_DEVS_ETH_SMSC_LAN91CXX_STATIC_ESA    // Initialize upper level driver    (sc->funs->eth_drv->init)(sc, cpd->enaddr);    return true;}static voidlan91cxx_stop(struct eth_drv_sc *sc){    struct lan91cxx_priv_data *cpd =        (struct lan91cxx_priv_data *)sc->driver_private;    DEBUG_FUNCTION();    CYG_ASSERT( cpd->within_send < 10, "stop: Excess send recursions" );    cpd->within_send++;    // Complete any outstanding activity:    if ( cpd->txbusy ) {        cpd->txbusy = 0;#if DEBUG & 9        db_printf("LAN91CXX - Stopping, cleaning up pending TX\n" );#endif        (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, 0);    }    // Reset chip    put_reg(sc, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST);    put_reg(sc, LAN91CXX_RCR, 0);    cpd->txbusy = cpd->within_send = 0;}//// This function is called to "start up" the interface.  It may be called// multiple times, even when the hardware is already running.  It will be// called whenever something "hardware oriented" changes and should leave// the hardware ready to send/receive packets.//static voidlan91cxx_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags){    cyg_uint16 intr;#ifdef LAN91CXX_IS_LAN91C111    cyg_uint16 phy_ctl;    int delay;#endif#ifdef CYGPKG_NET    struct ifnet *ifp = &sc->sc_arpcom.ac_if;#endif    DEBUG_FUNCTION();#ifdef LAN91CXX_IS_LAN91C111    HAL_DELAY_US(100000);    // 91C111 Errata. Internal PHY comes up disabled. Must enable here.    phy_ctl = lan91cxx_read_phy(sc, 0, LAN91CXX_PHY_CTRL);    phy_ctl &= ~LAN91CXX_PHY_CTRL_MII_DIS;    lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, phy_ctl);    // Start auto-negotiation    put_reg(sc, LAN91CXX_RPCR,	    LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK | LAN91CXX_RPCR_ANEG);    // wait for auto-negotiation to finish.    // give it ~5 seconds before giving up (no cable?)    delay = 50;    while (!(lan91cxx_read_phy(sc, 0, LAN91CXX_PHY_STAT) & 0x20)) {	if (--delay <= 0)	    break;	HAL_DELAY_US(100000);    }#endif    put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu);    put_reg(sc, LAN91CXX_INTERRUPT, 0);   // disable interrupts    intr = get_reg(sc, LAN91CXX_INTERRUPT);    put_reg(sc, LAN91CXX_INTERRUPT, intr &      // ack old interrupts            (LAN91CXX_INTERRUPT_TX_INT | LAN91CXX_INTERRUPT_TX_EMPTY_INT |             LAN91CXX_INTERRUPT_RX_OVRN_INT | LAN91CXX_INTERRUPT_ERCV_INT));    put_reg(sc, LAN91CXX_RCR, #ifdef RCR_HAS_ABORT_ENB // 91C96 does not - page 46.            LAN91CXX_RCR_ABORT_ENB |#endif            LAN91CXX_RCR_STRIP_CRC |            LAN91CXX_RCR_RXEN | LAN91CXX_RCR_ALMUL);    put_reg(sc, LAN91CXX_TCR, LAN91CXX_TCR_TXENA | LAN91CXX_TCR_PAD_EN);    put_reg(sc, LAN91CXX_CONTROL, 0);    put_reg(sc, LAN91CXX_INTERRUPT,       // enable interrupts            LAN91CXX_INTERRUPT_RCV_INT_M);#ifdef CYGPKG_NET    if (( 0#ifdef ETH_DRV_FLAGS_PROMISC_MODE         != (flags & ETH_DRV_FLAGS_PROMISC_MODE)#endif        ) || (ifp->if_flags & IFF_PROMISC)        ) {        // Then we select promiscuous mode.        unsigned short rcr;        rcr = get_reg(sc, LAN91CXX_RCR );        rcr |= LAN91CXX_RCR_PRMS;        put_reg(sc, LAN91CXX_RCR, rcr );    }#endif}//// This routine is called to perform special "control" opertions//static intlan91cxx_control(struct eth_drv_sc *sc, unsigned long key,               void *data, int data_length){    unsigned char *esa = (unsigned char *)data;    int i;    unsigned short reg;    struct lan91cxx_priv_data *cpd =        (struct lan91cxx_priv_data *)sc->driver_private;    DEBUG_FUNCTION();    switch (key) {    case ETH_DRV_SET_MAC_ADDRESS:#if 9 & DEBUG        db_printf("LAN91CXX - set ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",                esa[0],                esa[1],                esa[2],                esa[3],                esa[4],                esa[5] );#ifndef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_WRITE_EEPROM        db_printf("*** PERMANENT EEPROM WRITE NOT ENABLED ***\n");#endif#endif // DEBUG#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_WRITE_EEPROM        // Only now can we command the chip to perform EEPROM writes:        // select arbitrary writing to the EEPROM        reg = get_reg(sc, LAN91CXX_CONTROL);        reg |= LAN91CXX_CONTROL_EEPROM_SELECT;        put_reg(sc, LAN91CXX_CONTROL, reg );        for (i = 0;  i < sizeof(cpd->enaddr);  i += 2) {            int j;            // Set the address register            put_reg(sc, LAN91CXX_POINTER, LAN91CXX_ESA_EEPROM_OFFSET + i/2);            // Poke the data            put_reg(sc, LAN91CXX_GENERAL, esa[i] | (esa[i+1] << 8));            // Command the store            reg = get_reg(sc, LAN91CXX_CONTROL);            reg |= LAN91CXX_CONTROL_STORE;            put_reg(sc, LAN91CXX_CONTROL, reg );            // and poll for completion            for ( j = 1024 * 1024; 0 < j ; j-- ) {                reg = get_reg(sc, LAN91CXX_CONTROL);                if ( 0 == (reg & LAN91CXX_CONTROL_EEPROM_BUSY) )                    break;            }            CYG_ASSERT( 0 < j, "EEPROM write timout!" );        }        reg = get_reg(sc, LAN91CXX_CONTROL);        CYG_ASSERT( 0 == (reg & LAN91CXX_CONTROL_EEPROM_BUSY),                    "EEPROM still busy!" );        // Clear the EEPROM selection bit        reg &=~LAN91CXX_CONTROL_EEPROM_SELECT;        put_reg(sc, LAN91CXX_CONTROL, reg );        // and check it "took"        reg = get_reg(sc, LAN91CXX_CONTROL);        CYG_ASSERT( 0 == (reg & LAN91CXX_CONTROL_EEPROM_SELECT),                    "EEPROM still selected!" );        // and command a complete reload        reg |= LAN91CXX_CONTROL_RELOAD;        put_reg(sc, LAN91CXX_CONTROL, reg );        for ( i = 1024 * 1024; 0 < i ; i-- ) {            reg = get_reg(sc, LAN91CXX_CONTROL);            if ( 0 == (reg & LAN91CXX_CONTROL_EEPROM_BUSY) )                break;        }        CYG_ASSERT( 0 < i, "EEPROM reload timout!" );        // Now extract the MAC address that is in the chip, and tell the        // system about it.        for (i = 0;  i < sizeof(cpd->enaddr);  i += 2) {            unsigned short z = get_reg(sc, LAN91CXX_IA01+i/2 );            cpd->enaddr[i] =   (unsigned char)(0xff & z);            cpd->enaddr[i+1] = (unsigned char)(0xff & (z >> 8));        }#if DEBUG & 9        db_printf("LAN91CXX - eeprom new ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",                    cpd->enaddr[0],                    cpd->enaddr[1],                    cpd->enaddr[2],                    cpd->enaddr[3],                    cpd->enaddr[4],                    cpd->enaddr[5] );#endif // DEBUG        for (i = 0;  i < sizeof(cpd->enaddr);  i++ ) {            CYG_ASSERT( esa[i] == cpd->enaddr[i], "ESA not written correctly" );            if ( esa[i] != cpd->enaddr[i] )                return 1; // the operation failed.        }#else // not CYGSEM_DEVS_ETH_SMSC_LAN91CXX_WRITE_EEPROM        // Whatever, we can write the MAC address into the interface info,        // and the chip registers no problem.        for ( i = 0; i < sizeof(cpd->enaddr);  i++ )            cpd->enaddr[i] = esa[i];        for (i = 0;  i < sizeof(cpd->enaddr);  i += 2) {            reg = cpd->enaddr[i] | (cpd->enaddr[i+1] << 8);            put_reg(sc, LAN91CXX_IA01+i/2, reg );        }#endif // !CYGSEM_DEVS_ETH_SMSC_LAN91CXX_WRITE_EEPROM        return 0;#ifdef ETH_DRV_GET_MAC_ADDRESS    case ETH_DRV_GET_MAC_ADDRESS:        // Extract the MAC address that is in the chip, and tell the        // system about it.        for (i = 0;  i < sizeof(cpd->enaddr);  i += 2) {            unsigned short z = get_reg(sc, LAN91CXX_IA01+i/2 );            esa[i] =   (unsigned char)(0xff & z);            esa[i+1] = (unsigned char)(0xff & (z >> 8));        }        return 0;#endif#ifdef ETH_DRV_GET_IF_STATS_UD    case ETH_DRV_GET_IF_STATS_UD: // UD == UPDATE#endif        // drop through#ifdef ETH_DRV_GET_IF_STATS    case ETH_DRV_GET_IF_STATS:#endif#if defined(ETH_DRV_GET_IF_STATS) || defined (ETH_DRV_GET_IF_STATS_UD)    {        struct ether_drv_stats *p = (struct ether_drv_stats *)data;        // Chipset entry is no longer supported; RFC1573.        for ( i = 0; i < SNMP_CHIPSET_LEN; i++ )            p->snmp_chipset[i] = 0;        // This perhaps should be a config opt, so you can make up your own        // description, or supply it from the instantiation.        strcpy( p->description, "SMSC LAN91Cxx" );        // CYG_ASSERT( 48 > strlen(p->description), "Description too long" );        reg = get_reg(sc, LAN91CXX_EPH_STATUS);        if ((reg & LAN91CXX_STATUS_LINK_OK) == 0) {            p->operational = 2;         // LINK DOWN            p->duplex = 1;              // UNKNOWN            p->speed = 0;        }        else {            p->operational = 3;         // LINK UP            p->duplex = 2;              // 2 = SIMPLEX, 3 = DUPLEX            p->speed = 10 * 1000000;    // it's only a 10Mbit device        }#ifdef KEEP_STATISTICS        {            struct smsc_lan91cxx_stats *ps = &(cpd->stats);            // Admit to it...            p->supports_dot3        = true;            p->tx_good              = ps->tx_good             ;            p->tx_max_collisions    = ps->tx_max_collisions   ;            p->tx_late_collisions   = ps->tx_late_collisions  ;            p->tx_underrun          = ps->tx_underrun         ;            p->tx_carrier_loss      = ps->tx_carrier_loss     ;            p->tx_deferred          = ps->tx_deferred         ;            p->tx_sqetesterrors     = ps->tx_sqetesterrors    ;            p->tx_single_collisions = ps->tx_single_collisions;            p->tx_mult_collisions   = ps->tx_mult_collisions  ;            p->tx_total_collisions  = ps->tx_total_collisions ;            p->rx_good              = ps->rx_good             ;            p->rx_crc_errors        = ps->rx_crc_errors       ;            p->rx_align_errors      = ps->rx_align_errors     ;            p->rx_resource_errors   = ps->rx_resource_errors  ;            p->rx_overrun_errors    = ps->rx_overrun_errors   ;            p->rx_collisions        = ps->rx_collisions       ;            p->rx_short_frames      = ps->rx_short_frames     ;            p->rx_too_long_frames   = ps->rx_too_long_frames  ;            p->rx_symbol_errors     = ps->rx_symbol_errors    ;                    p->interrupts           = ps->interrupts          ;            p->rx_count             = ps->rx_count            ;            p->rx_deliver           = ps->rx_deliver          ;            p->rx_resource          = ps->rx_resource         ;            p->rx_restart           = ps->rx_restart          ;            p->tx_count             = ps->tx_count            ;            p->tx_complete          = ps->tx_complete         ;            p->tx_dropped           = ps->tx_dropped          ;        }#endif // KEEP_STATISTICS

⌨️ 快捷键说明

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