if_rhine.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,320 行 · 第 1/3 页

C
1,320
字号
                // Reload ESA from EEPROM                {                    cyg_uint8 tmp;                    int i;#if DEBUG & 8                    diag_printf("Reload ESA from EEPROM...");#endif                    HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_EECSR, 0x20);                    for (i = 0; i < 150; i++) {                        HAL_PCI_IO_READ_UINT8(cpd->base+RHINE_EECSR, tmp);                        if (!(tmp & 0x20)) {                            break;                        }                    }#if DEBUG & 8                    if (tmp & 0x20)                        diag_printf("Timed out\n");                    else                        diag_printf("Done\n");#endif                }                // This is the indicator for "uses an interrupt"                if (cpd->interrupt_handle != 0) {                    cyg_drv_interrupt_acknowledge(cpd->interrupt);                    cyg_drv_interrupt_unmask(cpd->interrupt);#if DEBUG & 8                    diag_printf(" Enabled interrupt %d\n", cpd->interrupt);#endif                }#if DEBUG & 8                diag_printf(" **** Device enabled for I/O and Memory "                            "and Bus Master\n");#endif            }            else {                cpd->found = 0;                cpd->active = 0;#if DEBUG & 8                diag_printf("Failed to configure device %d\n", device_index);#endif            }        }        else {            cpd->found = 0;            cpd->active = 0;#if DEBUG & 8            diag_printf("eth%d not found\n", device_index);#endif        }    }    if (0 == found_devices)        return 0;    return 1;}static bool via_rhine_init(struct cyg_netdevtab_entry *tab){    static int initialized = 0; // only probe PCI et al *once*    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;    struct rhine_priv_data *cpd =        (struct rhine_priv_data *)sc->driver_private;    cyg_uint8 *d, *p, *p_next;    int i;    cyg_addrword_t ba;    DEBUG_FUNCTION();    if ( 0 == initialized++ ) {        // then this is the first time ever:        if ( ! pci_init_find_rhines() ) {#if DEBUG & 8            diag_printf( "pci_init_find_rhines failed" );#endif            return false;        }    }    // If this device is not present, exit    if (0 == cpd->found)        return 0;#if DEBUG & 8    diag_printf( "Rhine device SC %08x CPD %08x\n", sc, cpd);#endif    // Look for physical MII device    for (i = 0; i < 32; i++) {        cyg_uint16 mii_status = rhine_read_MII(cpd, i, MII_BMSR);        if (mii_status != 0x0000 && mii_status != 0xffff) {            cpd->phys_id = i;#if DEBUG & 8            diag_printf("Found MII interface at id %d, status %04x, adv 0x%04x, link 0x%04x\n",                        cpd->phys_id, mii_status, rhine_read_MII(cpd,i,4), rhine_read_MII(cpd,i,5));#endif            break;        }    }#if DEBUG & 8    if (i == 32)        diag_printf("No MII interface found!");#endif    // Prepare ESA    if (cpd->hardwired_esa) {        // Force the NIC to use the specified ESA        p = cpd->base + RHINE_PAR0;        for (i = 0; i < 6; i++)            *p++ = cpd->esa[i];    } else {        // Use the address from the serial EEPROM        p = cpd->base + RHINE_PAR0;        for (i = 0; i < 6; i++)            cpd->esa[i] = *p++;    }#if DEBUG & 8    diag_printf("RHINE - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",                (cpd->hardwired_esa) ? "static" : "eeprom",                cpd->esa[0],                cpd->esa[1],                cpd->esa[2],                cpd->esa[3],                cpd->esa[4],                cpd->esa[5] );#endif    // Prepare RX and TX rings    p = cpd->rx_ring = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc((1<<cpd->rx_ring_log_cnt)*RHINE_RD_SIZE));    d = cpd->rx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc(_BUF_SIZE*cpd->rx_ring_cnt));    for (i = 0; i < cpd->rx_ring_cnt; i++) {        p_next = p + RHINE_RD_SIZE;        HAL_PCI_CPU_TO_BUS((cyg_uint32)d, ba);        _SU32(p, RHINE_RDES2) = ba;        _SU32(p, RHINE_RDES1) = _BUF_SIZE;        HAL_PCI_CPU_TO_BUS((cyg_uint32)p_next, ba);        _SU32(p, RHINE_RDES3) = ba;        _SU32(p, RHINE_RDES0) = RHINE_RDES0_OWN;#if DEBUG & 8        diag_printf("Set RDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",                    (unsigned long)p,                    _SU32(p, RHINE_RDES0), _SU32(p, RHINE_RDES1),                    _SU32(p, RHINE_RDES2), _SU32(p, RHINE_RDES3));#endif        p = p_next;        d += _BUF_SIZE;    }    // last entry wraps to the first    p -= RHINE_RD_SIZE;    HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->rx_ring, ba);    _SU32(p, RHINE_RDES3) = ba;#if DEBUG & 8    diag_printf("Set RDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",                (unsigned long)p,                _SU32(p, RHINE_RDES0), _SU32(p, RHINE_RDES1),                _SU32(p, RHINE_RDES2), _SU32(p, RHINE_RDES3));#endif    cpd->rx_ring_next = 0;    // CPU to PCI space translation    HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->rx_ring, ba);    HAL_PCI_IO_WRITE_UINT32(cpd->base + RHINE_CUR_RX, ba);    p = cpd->tx_ring = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc((1<<cpd->tx_ring_log_cnt)*RHINE_TD_SIZE));    d = cpd->tx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS(pciwindow_mem_alloc(_BUF_SIZE*cpd->tx_ring_cnt));    for (i = 0; i < cpd->tx_ring_cnt; i++) {        _SU32(p, RHINE_TDES0) = 0;        _SU32(p, RHINE_TDES1) = (RHINE_TDES1_IC|RHINE_TDES1_EDP|RHINE_TDES1_STP|RHINE_TDES1_C);        HAL_PCI_CPU_TO_BUS((cyg_uint32)d, ba);        _SU32(p, RHINE_TDES2) = ba;        HAL_PCI_CPU_TO_BUS((cyg_uint32)(p + RHINE_TD_SIZE), ba);        _SU32(p, RHINE_TDES3) = ba;#if DEBUG & 8        diag_printf("Set TDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",                    (unsigned long)p,                    _SU32(p, RHINE_TDES0), _SU32(p, RHINE_TDES1),                    _SU32(p, RHINE_TDES2), _SU32(p, RHINE_TDES3));#endif        p += RHINE_TD_SIZE;        d += _BUF_SIZE;    }    // last entry wraps to the first    p -= RHINE_TD_SIZE;    HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->tx_ring, ba);    _SU32(p, RHINE_TDES3) = ba;#if DEBUG & 8    diag_printf("Set TDES at 0x%08lx to 0x%08x 0x%08x 0x%08x 0x%08x\n",                (unsigned long)p,                _SU32(p, RHINE_TDES0), _SU32(p, RHINE_TDES1),                _SU32(p, RHINE_TDES2), _SU32(p, RHINE_TDES3));#endif    cpd->tx_ring_free = cpd->tx_ring_alloc = cpd->tx_ring_owned = 0;    HAL_PCI_CPU_TO_BUS((cyg_uint32)cpd->tx_ring, ba);    HAL_PCI_IO_WRITE_UINT32(cpd->base + RHINE_CUR_TX, ba);    cpd->txbusy = 0;#if DEBUG & 9    {        cyg_uint8 tmp1, tmp2;        HAL_PCI_IO_READ_UINT8(cpd->base+RHINE_CR0, tmp1);         HAL_PCI_IO_READ_UINT8(cpd->base+RHINE_CR1, tmp2);        diag_printf("CR0: %02x  CR1: %02x\n", tmp1, tmp2);    }#endif    // and record the net dev pointer    cpd->ndp = (void *)tab;    // Initialize upper level driver    (sc->funs->eth_drv->init)(sc, cpd->esa);#if DEBUG & 9    diag_printf("Done\n");#endif    return true;}static voidrhine_stop(struct eth_drv_sc *sc){    struct rhine_priv_data *cpd =        (struct rhine_priv_data *)sc->driver_private;    DEBUG_FUNCTION();    // Stop chip    HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_CR0, RHINE_CR0_STOP);}//// 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 voidrhine_start(struct eth_drv_sc *sc, unsigned char *esa, int flags){#ifdef CYGPKG_NET    struct ifnet *ifp = &sc->sc_arpcom.ac_if;#endif    struct rhine_priv_data *cpd =        (struct rhine_priv_data *)sc->driver_private;    DEBUG_FUNCTION();    // Disable device    HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, RHINE_CR0_STOP);    // Ack old interrupts    HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_ISR, 0xffff);    // Enable interrupts    HAL_PCI_IO_WRITE_UINT16(cpd->base + RHINE_IMR, RHINE_IMR_INIT);    // Enable duplex    HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_CR1, RHINE_CR1_DPOLL /* | RHINE_CR1_FDX*/);    // Accept broadcast, multicast and small packets    HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_RCR, RHINE_RCR_AB | RHINE_RCR_AM | RHINE_RCR_AR);    // Tweak some magic (undocumented) parameters    HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_BCR0, RHINE_BCR0_MAGIC_INIT);    HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_BCR1, RHINE_BCR1_MAGIC_INIT);#if 1 // FIXME    HAL_PCI_IO_WRITE_UINT8(cpd->base+RHINE_TCR, 0x20);#endif#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.        cyg_uint8 rcr;        HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_RCR, rcr);        rcr |= RHINE_RCR_PRO;        HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_RCR, rcr);    }#endif    // Enable device    HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, RHINE_CR0_STRT | RHINE_CR0_RXON | RHINE_CR0_TXON);}//// This routine is called to perform special "control" opertions//static intrhine_control(struct eth_drv_sc *sc, unsigned long key,               void *data, int data_length){    cyg_uint8 *esa = (cyg_uint8 *)data;    int i, res;    cyg_uint8 reg, old_stat;    struct rhine_priv_data *cpd =        (struct rhine_priv_data *)sc->driver_private;    DEBUG_FUNCTION();    // Stop the controller while accessing (possibly altering) registers    HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_CR0, old_stat);    reg = old_stat;    reg |= RHINE_CR0_STOP;    reg &= ~RHINE_CR0_STRT;    HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, reg);    res = 0;                            // expect success    switch (key) {    case ETH_DRV_SET_MAC_ADDRESS:#if DEBUG & 9        diag_printf("RHINE - set ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",                esa[0],                esa[1],                esa[2],                esa[3],                esa[4],                esa[5] );#endif // DEBUG        for ( i = 0; i < sizeof(cpd->esa);  i++ ) {            cpd->esa[i] = esa[i];            HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_PAR0 + i, esa[i]);        }        break;#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->esa);  i++) {            HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_PAR0 + i, esa[i]);        }        break;#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)    {        cyg_uint8 reg;        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, "VIA Rhine" );        // CYG_ASSERT( 48 > strlen(p->description), "Description too long" );        HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_MIISR, reg);        if (reg & RHINE_MIISR_LNKFL) {            p->operational = 2;         // LINK DOWN            p->duplex = 1;              // UNKNOWN            p->speed = 0;        }        else {            p->operational = 3;         // LINK UP            p->speed = (reg & RHINE_MIISR_SPEED) ? 10 * 1000000 : 100 * 1000000;            HAL_PCI_IO_READ_UINT8(cpd->base + RHINE_CR1, reg);            if (reg & RHINE_CR1_FDX)                p->duplex = 3;              // 3 = DUPLEX            else                p->duplex = 2;              // 2 = SIMPLEX        }#ifdef KEEP_STATISTICS        {            struct via_rhine_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        p->tx_queue_len = 1;        break;    }#endif    default:        res = 1;        break;    }    // Restore controller state    HAL_PCI_IO_WRITE_UINT8(cpd->base + RHINE_CR0, old_stat);    return res;}//// This routine is called to see if it is possible to send another packet.// It will return non-zero if a transmit is possible, zero otherwise.//static intrhine_can_send(struct eth_drv_sc *sc){    cyg_uint8 stat;    struct rhine_priv_data *cpd =        (struct rhine_priv_data *)sc->driver_private;    DEBUG_FUNCTION();

⌨️ 快捷键说明

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