📄 if_lancepci.c
字号:
} else { cpd->found = 0; cpd->active = 0;#if DEBUG & 8 db_printf("eth%d not found\n", device_index);#endif } } if (0 == found_devices) return 0; return 1;}static boolamd_lancepci_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 lancepci_priv_data *cpd = (struct lancepci_priv_data *)sc->driver_private; cyg_uint16 val; cyg_uint32 b; cyg_uint8* p; cyg_uint8* d; int i; DEBUG_FUNCTION(); if ( 0 == initialized++ ) { // then this is the first time ever: if ( ! pci_init_find_lancepci() ) {#if DEBUG & 8 db_printf( "pci_init_find_lancepci failed" );#endif return false; } } // If this device is not present, exit if (0 == cpd->found) return 0;#if DEBUG & 8 db_printf("lancepci at base 0x%08x, EEPROM key 0x%04x\n", cpd->base, _SU16(cpd->base, LANCE_IO_ID));#endif#if 0 // FIXME: Doesn't work with non-conforming EEPROMS if (LANCE_IO_ID_KEY != _SU16(cpd->base, LANCE_IO_ID) ) { db_printf("Lance EPROM key not found\n"); return false; }#endif#if DEBUG & 9 db_printf("pcimem : %08x size: %08x\n", lancepci_heap_base, lancepci_heap_size);#endif // Prepare ESA if (!cpd->hardwired_esa) { // Don't use the address from the EEPROM for VMware // Use the address that VMware prepares in CSR_PAR registers // if You want to be able to use NAT networking. (iz@elsis.si Feb 27 04) // // p = cpd->base + LANCE_IO_EEPROM; // for (i = 0; i < 6; i++) // cpd->esa[i] = *p++; put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP); for (i = 0; i < sizeof(cpd->esa); i += 2) { cyg_uint16 z = get_reg(sc, LANCE_CSR_PAR0+i/2 ); cpd->esa[i] = (cyg_uint8)(0xff & z); cpd->esa[i+1] = (cyg_uint8)(0xff & (z >> 8)); } }#if DEBUG & 9 db_printf("Lance - %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((cyg_uint32)pciwindow_mem_alloc((1<<cpd->rx_ring_log_cnt)*LANCE_RD_SIZE)); memset(cpd->rx_ring,0,(1<<cpd->rx_ring_log_cnt)*LANCE_RD_SIZE); d = cpd->rx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc(_BUF_SIZE*cpd->rx_ring_cnt)); memset(cpd->rx_buffers,0,_BUF_SIZE*cpd->rx_ring_cnt); for (i = 0; i < cpd->rx_ring_cnt; i++) { HAL_PCI_CPU_TO_BUS(d, (cyg_uint8 *)b); _SU32(p, LANCE_RD_PTR) = (b & LANCE_RD_PTR_MASK) | LANCE_RD_PTR_OWN; _SU16(p, LANCE_RD_BLEN) = (-_BUF_SIZE); p += LANCE_RD_SIZE; d += _BUF_SIZE; } cpd->rx_ring_next = 0; p = cpd->tx_ring = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc((1<<cpd->tx_ring_log_cnt)*LANCE_TD_SIZE)); memset(cpd->tx_ring,0,(1<<cpd->tx_ring_log_cnt)*LANCE_TD_SIZE); d = cpd->tx_buffers = (cyg_uint8*) CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc(_BUF_SIZE*cpd->tx_ring_cnt)); for (i = 0; i < cpd->tx_ring_cnt; i++) { HAL_PCI_CPU_TO_BUS(d, (cyg_uint8 *)b); _SU32(p, LANCE_RD_PTR) = b & LANCE_TD_PTR_MASK; p += LANCE_TD_SIZE; d += _BUF_SIZE; } cpd->tx_ring_free = cpd->tx_ring_alloc = cpd->tx_ring_owned = 0; // Initialization table cpd->init_table = (cyg_uint8*)CYGARC_UNCACHED_ADDRESS((cyg_uint32)pciwindow_mem_alloc(LANCE_IB_SIZE)); _SU16(cpd->init_table, LANCE_IB_MODE) = 0x0000; for (i = 0; i < 6; i++) _SU8(cpd->init_table, LANCE_IB_PADR0+i) = cpd->esa[i]; for (i = 0; i < 8; i++) _SU8(cpd->init_table, LANCE_IB_LADRF0+i) = 0; HAL_PCI_CPU_TO_BUS(cpd->rx_ring, (cyg_uint8 *)b); _SU32(cpd->init_table, LANCE_IB_RDRA) = ((b & LANCE_IB_RDRA_PTR_mask) | (cpd->rx_ring_log_cnt << LANCE_IB_RDRA_CNT_shift)); HAL_PCI_CPU_TO_BUS(cpd->tx_ring, (cyg_uint8 *)b); _SU32(cpd->init_table, LANCE_IB_TDRA) = ((b & LANCE_IB_TDRA_PTR_mask) | (cpd->tx_ring_log_cnt << LANCE_IB_TDRA_CNT_shift));#if DEBUG & 9 db_printf("Loading up lance controller from table at 0x%08x\n", cpd->init_table); db_printf(" Mode 0x%04x\n", _SU16(cpd->init_table, LANCE_IB_MODE)); db_printf(" PADR %02x:%02x:%02x:%02x:%02x:%02x ", _SU8(cpd->init_table, LANCE_IB_PADR0+0), _SU8(cpd->init_table, LANCE_IB_PADR0+1), _SU8(cpd->init_table, LANCE_IB_PADR0+2), _SU8(cpd->init_table, LANCE_IB_PADR0+3), _SU8(cpd->init_table, LANCE_IB_PADR0+4), _SU8(cpd->init_table, LANCE_IB_PADR0+5)); db_printf("LADR %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", _SU8(cpd->init_table, LANCE_IB_LADRF0+0), _SU8(cpd->init_table, LANCE_IB_LADRF0+1), _SU8(cpd->init_table, LANCE_IB_LADRF0+2), _SU8(cpd->init_table, LANCE_IB_LADRF0+3), _SU8(cpd->init_table, LANCE_IB_LADRF0+4), _SU8(cpd->init_table, LANCE_IB_LADRF0+5), _SU8(cpd->init_table, LANCE_IB_LADRF0+5), _SU8(cpd->init_table, LANCE_IB_LADRF0+7)); db_printf(" RX 0x%08x (len %d) TX 0x%08x (len %d)\n", _SU32(cpd->init_table, LANCE_IB_RDRA) & 0x1fffffff, (_SU32(cpd->init_table, LANCE_IB_RDRA) >> LANCE_IB_RDRA_CNT_shift) & 7, _SU32(cpd->init_table, LANCE_IB_TDRA) & 0x1fffffff, (_SU32(cpd->init_table, LANCE_IB_TDRA) >> LANCE_IB_TDRA_CNT_shift) & 7);#endif // Reset chip HAL_PCI_IO_READ_UINT16(cpd->base+LANCE_IO_RESET, val); // Load up chip with buffers. // Note: There is a 16M limit on the addresses used by the driver // since the top 8 bits of the init_table address is appended to // all other addresses used by the controller. HAL_PCI_CPU_TO_BUS(cpd->init_table, (cyg_uint8 *)b); put_reg(sc, LANCE_CSR_IBA0, (b >> 0) & 0xffff); put_reg(sc, LANCE_CSR_IBA1, (b >> 16) & 0xffff); // Disable automatic TX polling (_send will force a poll), pad // XT frames to legal length, mask status interrupts. put_reg(sc, LANCE_CSR_TFC, (LANCE_CSR_TFC_TXDPOLL | LANCE_CSR_TFC_APAD_XMT | LANCE_CSR_TFC_MFCOM | LANCE_CSR_TFC_RCVCCOM | LANCE_CSR_TFC_TXSTRTM)); // Recover after TX FIFO underflow put_reg(sc, LANCE_CSR_IM, LANCE_CSR_IM_DXSUFLO); // Initialize controller - load up init_table put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_INIT); while (0 == (get_reg(sc, LANCE_CSR_CSCR) & LANCE_CSR_CSCR_IDON)); // Stop controller put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP);#if DEBUG & 9 db_printf("lancepci controller state is now:\n"); db_printf(" Mode 0x%04x TFC 0x%04x\n", _SU16(cpd->init_table, LANCE_IB_MODE), get_reg(sc, LANCE_CSR_TFC)); db_printf(" PADR %04x:%04x:%04x ", get_reg(sc, LANCE_CSR_PAR0), get_reg(sc, LANCE_CSR_PAR1), get_reg(sc, LANCE_CSR_PAR2)); db_printf("LADR %04x:%04x:%04x:%04x\n", get_reg(sc, LANCE_CSR_LAR0), get_reg(sc, LANCE_CSR_LAR1), get_reg(sc, LANCE_CSR_LAR2), get_reg(sc, LANCE_CSR_LAR3)); db_printf(" RX 0x%04x%04x (len 0x%04x) TX 0x%04x%04x (len 0x%04x)\n", get_reg(sc, LANCE_CSR_BARRU), get_reg(sc, LANCE_CSR_BARRL), get_reg(sc, LANCE_CSR_RRLEN), get_reg(sc, LANCE_CSR_BATRU), get_reg(sc, LANCE_CSR_BATRL), get_reg(sc, LANCE_CSR_TRLEN)); val = get_reg(sc, LANCE_CSR_ID_LO); db_printf("lancepci ID 0x%04x (%s) ", val, (0x5003 == val) ? "Am79C973" : (0x7003 == val) ? "Am79C975" : (0x1003 == val) ? "Am79C900 or wmWare VLANCE" : "Unknown"); val = get_reg(sc, LANCE_CSR_ID_HI); db_printf("Part IDU 0x%03x Silicon rev %d\n", val & 0x0fff, (val >> 12) & 0xf);#endif // and record the net dev pointer cpd->ndp = (void *)tab; cpd->active = 0; oursc=sc; // Initialize upper level driver (sc->funs->eth_drv->init)(sc, cpd->esa); cpd->txbusyh=cpd->txbusy=0; cpd->event=0; db_printf("Lancepci driver loaded and Init Done\n"); return true;}static voidlancepci_stop(struct eth_drv_sc *sc){ cyg_uint32 b; struct lancepci_priv_data *cpd = (struct lancepci_priv_data *)sc->driver_private; DEBUG_FUNCTION(); if (!cpd->active) return; if (cpd->txbusyh) {#if DEBUG & 9 db_printf("Lancepci-stop:waiting for tx empty\n");#endif b=100; while (cpd->txbusyh && b) { CYGACC_CALL_IF_DELAY_US(200); b--; } } put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP); cpd->active = 0;#if DEBUG & 9 db_printf("Lancepci-stop:done\n");#endif}//// 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 voidlancepci_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags){ cyg_uint16 reg; cyg_uint32 b; struct lancepci_priv_data *cpd = (struct lancepci_priv_data *)sc->driver_private;#ifdef CYGPKG_NET struct ifnet *ifp = &sc->sc_arpcom.ac_if;#endif DEBUG_FUNCTION(); // If device is already active, stop it#if DEBUG & 9 db_printf("Lancepci-start:entered\n");#endif if (cpd->active) { if (cpd->txbusyh) {#if DEBUG & 9 db_printf("Lancepci-start:waiting for tx empty\n");#endif b=100; while (cpd->txbusyh && b) { CYGACC_CALL_IF_DELAY_US(200); b--; } } put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_STOP); cpd->active = 0;#if DEBUG & 9 db_printf("Lancepci-start:stopped\n");#endif } CYGACC_CALL_IF_DELAY_US(200);#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. _SU16(cpd->init_table, LANCE_IB_MODE) = 0x0000|LANCE_CSR_MODE_PROM;#if DEBUG & 9 db_printf("Promisc MODE!");#endif } else _SU16(cpd->init_table, LANCE_IB_MODE) = 0x0000;#endif cpd->rx_ring_next = 0; cpd->tx_ring_free = cpd->tx_ring_alloc = cpd->tx_ring_owned = 0; // Init the chip again HAL_PCI_CPU_TO_BUS(cpd->init_table, (cyg_uint8 *)b); put_reg(sc, LANCE_CSR_IBA0, (b >> 0) & 0xffff); put_reg(sc, LANCE_CSR_IBA1, (b >> 16) & 0xffff); // Disable automatic TX polling (_send will force a poll), pad // XT frames to legal length, mask status interrupts. put_reg(sc, LANCE_CSR_TFC, (LANCE_CSR_TFC_TXDPOLL | LANCE_CSR_TFC_APAD_XMT | LANCE_CSR_TFC_MFCOM | LANCE_CSR_TFC_RCVCCOM | LANCE_CSR_TFC_TXSTRTM)); // Recover after TX FIFO underflow put_reg(sc, LANCE_CSR_IM, LANCE_CSR_IM_DXSUFLO); // Initialize controller - load up init_table put_reg(sc, LANCE_CSR_CSCR, LANCE_CSR_CSCR_INIT); while (0 == (get_reg(sc, LANCE_CSR_CSCR) & LANCE_CSR_CSCR_IDON)); reg=get_reg(sc,LANCE_CSR_CSCR); put_reg(sc, LANCE_CSR_CSCR, (reg|(LANCE_CSR_CSCR_IENA | LANCE_CSR_CSCR_STRT))&~LANCE_CSR_CSCR_INIT);#if DEBUG & 9 reg=get_reg(sc,LANCE_CSR_CSCR); db_printf("CSR after start = %4x\n",reg);#endif cpd->active = 1; cpd->txbusy=0; cpd->txbusyh=0; // delay is necessary for Vmware to get a tick !!! CYGACC_CALL_IF_DELAY_US(50000);}//// This routine is called to perform special "control" opertions//static intlancepci_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length){ cyg_uint8 *esa = (cyg_uint8 *)data; int i, res; cyg_uint16 reg; struct lancepci_priv_data *cpd = (struct lancepci_priv_data *)sc->driver_private; DEBUG_FUNCTION();#if DEBUG & 9 db_printf("Lancepci-control:entered\n");#endif res = 0; // expect success switch (key) { case ETH_DRV_SET_MAC_ADDRESS:#if 9 & DEBUG db_printf("PCNET - 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]; for (i = 0; i < sizeof(cpd->esa); i += 2) { reg = cpd->esa[i] | (cpd->esa[i+1] << 8); put_reg(sc, LANCE_CSR_PAR0+i/2, reg ); } for (i = 0; i < 6; i++) // in case of later restart _SU8(cpd->init_table, LANCE_IB_PADR0+i) = cpd->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 += 2) { cyg_uint16 z = get_reg(sc, LANCE_CSR_PAR0+i/2 ); esa[i] = (cyg_uint8)(0xff & z); esa[i+1] = (cyg_uint8)(0xff & (z >> 8)); } 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) { 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, "AMD LancePCI" ); // CYG_ASSERT( 48 > strlen(p->description), "Description too long" ); p->operational = 3; // LINK UP p->duplex = 2; // 2 = SIMPLEX p->speed = 10 * 1000000;#if FIXME#ifdef KEEP_STATISTICS { struct amd_lancepci_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#endif // FIXME p->tx_queue_len = 1; break; }#endif default: res = 1; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -