if_fxp.c
来自「RTEMS (Real-Time Executive for Multiproc」· C语言 代码 · 共 2,315 行 · 第 1/5 页
C
2,315 行
i = pcib_find_by_devid( 0x8086, fxp_ident_table[j].devid, unitNumber-1, &(sc->pci_signature)); DBGLVL_PRINTK(2,"fxp_attach: find_devid returned %d " "and pci signature 0x%x\n", i,sc->pci_signature); if (PCIB_ERR_SUCCESS == i) { if ( UNTESTED == fxp_ident_table[j].warn ) { device_printf(dev,"WARNING: this chip version has NOT been reported to work under RTEMS yet.\n"); device_printf(dev," If it works OK, report it as tested in 'c/src/libchip/network/if_fxp.c'\n"); } break; } } } /* * FIXME: add search for more device types... */ if (i != PCIB_ERR_SUCCESS) { device_printf(dev, "could not find 82559ER device\n"); return 0; } /* * Enable bus mastering. Enable memory space too, in case * BIOS/Prom forgot about it. */ pcib_conf_read16(sc->pci_signature, PCI_COMMAND,&val16); val16 |= (PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER); pcib_conf_write16(sc->pci_signature, PCI_COMMAND, val16); DBGLVL_PRINTK(3,"fxp_attach: PCI_COMMAND_write = 0x%x\n",val16); pcib_conf_read16(sc->pci_signature, PCI_COMMAND,&val16); DBGLVL_PRINTK(4,"fxp_attach: PCI_COMMAND_read = 0x%x\n",val16); /* * Figure out which we should try first - memory mapping or i/o mapping? * We default to memory mapping. Then we accept an override from the * command line. Then we check to see which one is enabled. */#ifdef NOTUSED m1 = PCI_COMMAND_MEMORY; m2 = PCI_COMMAND_IO; prefer_iomap = 0; if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_iomap", &prefer_iomap) == 0 && prefer_iomap != 0) { m1 = PCI_COMMAND_IO; m2 = PCI_COMMAND_MEMORY; } if (val & m1) { sc->rtp = ((m1 == PCI_COMMAND_MEMORY) ? SYS_RES_MEMORY : SYS_RES_IOPORT); sc->rgd = ((m1 == PCI_COMMAND_MEMORY) ? FXP_PCI_MMBA : FXP_PCI_IOBA); sc->mem = bus_alloc_resource(dev, sc->rtp, &sc->rgd, 0, ~0, 1, RF_ACTIVE); } if (sc->mem == NULL && (val & m2)) { sc->rtp = ((m2 == PCI_COMMAND_MEMORY) ? SYS_RES_MEMORY : SYS_RES_IOPORT); sc->rgd = ((m2 == PCI_COMMAND_MEMORY) ? FXP_PCI_MMBA : FXP_PCI_IOBA); sc->mem = bus_alloc_resource(dev, sc->rtp, &sc->rgd, 0, ~0, 1, RF_ACTIVE); } if (!sc->mem) { device_printf(dev, "could not map device registers\n"); error = ENXIO; goto fail; } if (fxp_is_verbose) { device_printf(dev, "using %s space register mapping\n", sc->rtp == SYS_RES_MEMORY? "memory" : "I/O"); } sc->sc_st = rman_get_bustag(sc->mem); sc->sc_sh = rman_get_bushandle(sc->mem); /* * Allocate our interrupt. */ rid = 0; sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->irq == NULL) { device_printf(dev, "could not map interrupt\n"); error = ENXIO; goto fail; } error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, fxp_intr, sc, &sc->ih); if (error) { device_printf(dev, "could not setup irq\n"); goto fail; }#endif /* * get mapping and base address of registers */ pcib_conf_read16(sc->pci_signature, PCI_COMMAND,&val16); DBGLVL_PRINTK(4,"fxp_attach: PCI_COMMAND_read = 0x%x\n",val16); if((val16 & PCI_COMMAND_IO) != 0) { sc->pci_regs_are_io = TRUE; pcib_conf_read32(sc->pci_signature, PCI_BASE_ADDRESS_1, &val32); sc->pci_regs_base = val32 & PCI_BASE_ADDRESS_IO_MASK; } else { sc->pci_regs_are_io = FALSE; pcib_conf_read32(sc->pci_signature, PCI_BASE_ADDRESS_0, &val32); sc->pci_regs_base = val32 & PCI_BASE_ADDRESS_MEM_MASK; } DBGLVL_PRINTK(3,"fxp_attach: CSR registers are mapped in %s space" " at address 0x%x\n", sc->pci_regs_are_io ? "I/O" : "MEM", sc->pci_regs_base); /* * get interrupt level to be used */ pcib_conf_read8(sc->pci_signature, 60, &interrupt); DBGLVL_PRINTK(3,"fxp_attach: interrupt = 0x%x\n",interrupt); sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt; /* * Set up interrupts */ sc->irqInfo.hdl = (rtems_irq_hdl)fxp_intr; sc->irqInfo.on = nopOn; sc->irqInfo.off = nopOn; sc->irqInfo.isOn = fxpIsOn; s = BSP_install_rtems_irq_handler (&sc->irqInfo); if (!s) rtems_panic ("Can't attach fxp interrupt handler for irq %d\n", sc->irqInfo.name); /* * Reset to a stable state. CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); */ CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); DELAY(10); sc->cbl_base = malloc(sizeof(struct fxp_cb_tx) * FXP_NTXCB, M_DEVBUF, M_NOWAIT); DBGLVL_PRINTK(3,"fxp_attach: sc->cbl_base = 0x%x\n",sc->cbl_base); if (sc->cbl_base == NULL) goto failmem; else bzero(sc->cbl_base,sizeof(struct fxp_cb_tx) * FXP_NTXCB); sc->fxp_stats = malloc(sizeof(struct fxp_stats), M_DEVBUF, M_NOWAIT); DBGLVL_PRINTK(3,"fxp_attach: sc->fxp_stats = 0x%x\n",sc->fxp_stats); if (sc->fxp_stats == NULL) goto failmem; else bzero(sc->fxp_stats,sizeof(struct fxp_stats)); sc->mcsp = malloc(sizeof(struct fxp_cb_mcs), M_DEVBUF, M_NOWAIT); DBGLVL_PRINTK(3,"fxp_attach: sc->mcsp = 0x%x\n",sc->mcsp); if (sc->mcsp == NULL) goto failmem; /* * Pre-allocate our receive buffers. */ for (i = 0; i < FXP_NRFABUFS; i++) { if (fxp_add_rfabuf(sc, NULL) != 0) { goto failmem; } } /* * Find out how large of an SEEPROM we have. */ DBGLVL_PRINTK(3,"fxp_attach: calling fxp_autosize_eeprom\n"); fxp_autosize_eeprom(sc); /* * Determine whether we must use the 503 serial interface. */ fxp_read_eeprom(sc, &data, 6, 1); if ((data & FXP_PHY_DEVICE_MASK) != 0 && (data & FXP_PHY_SERIAL_ONLY)) sc->flags |= FXP_FLAG_SERIAL_MEDIA; /* * Find out the basic controller type; we currently only * differentiate between a 82557 and greater. */ fxp_read_eeprom(sc, &data, 5, 1); if ((data >> 8) == 1) sc->chip = FXP_CHIP_82557; DBGLVL_PRINTK(3,"fxp_attach: sc->chip = %d\n",sc->chip); /* * Enable workarounds for certain chip revision deficiencies. * * Systems based on the ICH2/ICH2-M chip from Intel have a defect * where the chip can cause a PCI protocol violation if it receives * a CU_RESUME command when it is entering the IDLE state. The * workaround is to disable Dynamic Standby Mode, so the chip never * deasserts CLKRUN#, and always remains in an active state. * * See Intel 82801BA/82801BAM Specification Update, Errata #30. */#ifdef NOTUSED i = pci_get_device(dev);#else pcib_conf_read16(sc->pci_signature,2,&dev_id); DBGLVL_PRINTK(3,"fxp_attach: device id = 0x%x\n",dev_id);#endif if (dev_id == 0x2449 || (dev_id > 0x1030 && dev_id < 0x1039)) { device_printf(dev, "*** See Intel 82801BA/82801BAM Specification Update, Errata #30. ***\n"); fxp_read_eeprom(sc, &data, 10, 1); if (data & 0x02) { /* STB enable */ u_int16_t cksum; int i; device_printf(dev, "*** DISABLING DYNAMIC STANDBY MODE IN EEPROM ***\n"); data &= ~0x02; fxp_write_eeprom(sc, &data, 10, 1); device_printf(dev, "New EEPROM ID: 0x%x\n", data); cksum = 0; for (i = 0; i < (1 << sc->eeprom_size) - 1; i++) { fxp_read_eeprom(sc, &data, i, 1); cksum += data; } i = (1 << sc->eeprom_size) - 1; cksum = 0xBABA - cksum; fxp_read_eeprom(sc, &data, i, 1); fxp_write_eeprom(sc, &cksum, i, 1); device_printf(dev, "EEPROM checksum @ 0x%x: 0x%x -> 0x%x\n", i, data, cksum); /* * We need to do a full PCI reset here. A software * reset to the port doesn't cut it, but let's try * anyway. */ CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); DELAY(50); device_printf(dev, "*** PLEASE REBOOT THE SYSTEM NOW FOR CORRECT OPERATION ***\n");#if 1 /* * If the user elects to continue, try the software * workaround, as it is better than nothing. */ sc->flags |= FXP_FLAG_CU_RESUME_BUG;#endif } } /* * If we are not a 82557 chip, we can enable extended features. */ if (sc->chip != FXP_CHIP_82557) { u_int8_t tmp_val; /* * If MWI is enabled in the PCI configuration, and there * is a valid cacheline size (8 or 16 dwords), then tell * the board to turn on MWI. */ pcib_conf_read8(sc->pci_signature, PCI_CACHE_LINE_SIZE,&tmp_val); DBGLVL_PRINTK(3,"fxp_attach: CACHE_LINE_SIZE = %d\n",tmp_val); if (val16 & PCI_COMMAND_MEMORY && tmp_val != 0) sc->flags |= FXP_FLAG_MWI_ENABLE; /* turn on the extended TxCB feature */ sc->flags |= FXP_FLAG_EXT_TXCB; /* enable reception of long frames for VLAN */ sc->flags |= FXP_FLAG_LONG_PKT_EN; DBGLVL_PRINTK(3,"fxp_attach: sc->flags = 0x%x\n", sc->flags); } /* * Read MAC address. */ fxp_read_eeprom(sc, (u_int16_t *)sc->arpcom.ac_enaddr, 0, 3); if (fxp_is_verbose) { device_printf(dev, "Ethernet address %x:%x:%x:%x:%x:%x %s \n", ((u_int8_t *)sc->arpcom.ac_enaddr)[0], ((u_int8_t *)sc->arpcom.ac_enaddr)[1], ((u_int8_t *)sc->arpcom.ac_enaddr)[2], ((u_int8_t *)sc->arpcom.ac_enaddr)[3], ((u_int8_t *)sc->arpcom.ac_enaddr)[4], ((u_int8_t *)sc->arpcom.ac_enaddr)[5], sc->flags & FXP_FLAG_SERIAL_MEDIA ? ", 10Mbps" : ""); device_printf(dev, "PCI IDs: 0x%x 0x%x 0x%x 0x%x 0x%x\n", pci_get_vendor(sc), pci_get_device(sc), pci_get_subvendor(sc), pci_get_subdevice(sc), pci_get_revid(sc)); device_printf(dev, "Chip Type: %d\n", sc->chip); }#ifdef NOTUSED /* do not set up interface at all... */ /* * If this is only a 10Mbps device, then there is no MII, and * the PHY will use a serial interface instead. * * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter * doesn't have a programming interface of any sort. The * media is sensed automatically based on how the link partner * is configured. This is, in essence, manual configuration. */ if (sc->flags & FXP_FLAG_SERIAL_MEDIA) { ifmedia_init(&sc->sc_media, 0, fxp_serial_ifmedia_upd, fxp_serial_ifmedia_sts); ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); } else { if (mii_phy_probe(dev, &sc->miibus, fxp_ifmedia_upd, fxp_ifmedia_sts)) { device_printf(dev, "MII without any PHY!\n"); error = ENXIO; goto fail; } }#endif if (config->mtu) mtu = config->mtu; else mtu = ETHERMTU; ifp->if_softc = sc; ifp->if_unit = unitNumber; ifp->if_name = unitName; ifp->if_mtu = mtu; ifp->if_baudrate = 100000000; ifp->if_init = fxp_init; ifp->if_ioctl = fxp_ioctl; ifp->if_start = fxp_start; ifp->if_output = ether_output; ifp->if_watchdog = fxp_watchdog; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX /*| IFF_MULTICAST*/; if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; /* * Attach the interface. */ DBGLVL_PRINTK(3,"fxp_attach: calling if_attach\n"); if_attach (ifp); DBGLVL_PRINTK(3,"fxp_attach: calling ether_if_attach\n"); ether_ifattach(ifp); DBGLVL_PRINTK(3,"fxp_attach: return from ether_if_attach\n");#ifdef NOTUSED /* * Tell the upper layer(s) we support long frames. */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);#endif /* * Let the system queue as many packets as we have available * TX descriptors. */ ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1; splx(s); return (0);failmem: device_printf(dev, "Failed to malloc memory\n"); error = ENOMEM;#ifdef NOTUSEDfail:#endif splx(s); fxp_release(sc); return (error);}/* * release all resources */static voidfxp_release(struct fxp_softc *sc){#ifdef NOTUSED bus_generic_detach(sc->dev); if (sc->miibus) device_delete_child(sc->dev, sc->miibus);#endif if (sc->cbl_base) free(sc->cbl_base, M_DEVBUF); if (sc->fxp_stats) free(sc->fxp_stats, M_DEVBUF); if (sc->mcsp) free(sc->mcsp, M_DEVBUF); if (sc->rfa_headm) m_freem(sc->rfa_headm);#ifdef NOTUSED if (sc->ih) bus_teardown_intr(sc->dev, sc->irq, sc->ih); if (sc->irq) bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->irq); if (sc->mem) bus_release_resource(sc->dev, sc->rtp, sc->rgd, sc->mem); mtx_destroy(&sc->sc_mtx);#endif}#if NOTUSED/* * Detach interface. */static intfxp_detach(device_t dev){ struct fxp_softc *sc = device_get_softc(dev); int s; /* disable interrupts */ CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE); s = splimp(); /* * Stop DMA and drop transmit queue. */ fxp_stop(sc); /* * Close down routes etc. */ ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED); /* * Free all media structures. */ ifmedia_removeall(&sc->sc_media); splx(s); /* Release our allocated resources. */ fxp_release(sc); return (0);}/* * Device shutdown routine. Called at system shutdown after sync. The * main purpose of this routine is to shut off receiver DMA so that * kernel memory doesn't get clobbered during warmboot. */static int
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?