📄 3c59x.c
字号:
static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};/* #define dev_alloc_skb dev_alloc_skb_debug *//* A list of all installed Vortex EISA devices, for removing the driver module. */static struct net_device *root_vortex_eisa_dev;/* Variables to work-around the Compaq PCI BIOS32 problem. */static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900;static int vortex_cards_found;static void vortex_suspend (struct pci_dev *pdev){ struct net_device *dev = pdev->driver_data; printk(KERN_DEBUG "vortex_suspend(%s)\n", dev->name); if (dev && dev->priv) { struct vortex_private *vp = (struct vortex_private *)dev->priv; if (vp->open) { netif_device_detach(dev); vortex_down(dev); } }}static void vortex_resume (struct pci_dev *pdev){ struct net_device *dev = pdev->driver_data; printk(KERN_DEBUG "vortex_resume(%s)\n", dev->name); if (dev && dev->priv) { struct vortex_private *vp = (struct vortex_private *)dev->priv; if (vp->open) { vortex_up(dev); netif_device_attach(dev); } }}/* returns count found (>= 0), or negative on error */static int __init vortex_eisa_init (void){ long ioaddr; int rc; int orig_cards_found = vortex_cards_found; /* Now check all slots of the EISA bus. */ if (!EISA_bus) return 0; for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { int device_id; if (request_region(ioaddr, VORTEX_TOTAL_SIZE, "3c59x") == NULL) continue; /* Check the standard EISA ID register for an encoded '3Com'. */ if (inw(ioaddr + 0xC80) != 0x6d50) { release_region (ioaddr, VORTEX_TOTAL_SIZE); continue; } /* Check for a product that we support, 3c59{2,7} any rev. */ device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83); if ((device_id & 0xFF00) != 0x5900) { release_region (ioaddr, VORTEX_TOTAL_SIZE); continue; } rc = vortex_probe1(NULL, ioaddr, inw(ioaddr + 0xC88) >> 12, EISA_TBL_OFFSET, vortex_cards_found); if (rc == 0) vortex_cards_found++; else release_region (ioaddr, VORTEX_TOTAL_SIZE); } /* Special code to work-around the Compaq PCI BIOS32 problem. */ if (compaq_ioaddr) { vortex_probe1(NULL, compaq_ioaddr, compaq_irq, compaq_device_id, vortex_cards_found++); } return vortex_cards_found - orig_cards_found;}/* returns count (>= 0), or negative on error */static int __devinit vortex_init_one (struct pci_dev *pdev, const struct pci_device_id *ent){ int rc; rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq, ent->driver_data, vortex_cards_found); if (rc == 0) vortex_cards_found++; return rc;}/* * Start up the PCI device which is described by *pdev. * Return 0 on success. * * NOTE: pdev can be NULL, for the case of an EISA driver */static int __devinit vortex_probe1(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int card_idx){ struct vortex_private *vp; int option; unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ int i; struct net_device *dev; static int printed_version; int retval; struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx]; if (!printed_version) { printk (KERN_INFO "%s", version); printk (KERN_INFO "See Documentation/networking/vortex.txt\n"); printed_version = 1; } dev = init_etherdev(NULL, sizeof(*vp)); if (!dev) { printk (KERN_ERR PFX "unable to allocate etherdev, aborting\n"); retval = -ENOMEM; goto out; } SET_MODULE_OWNER(dev); printk(KERN_INFO "%s: 3Com %s %s at 0x%lx, ", dev->name, pdev ? "PCI" : "EISA", vci->name, ioaddr); /* private struct aligned and zeroed by init_etherdev */ vp = dev->priv; dev->base_addr = ioaddr; dev->irq = irq; dev->mtu = mtu; vp->drv_flags = vci->drv_flags; vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; vp->io_size = vci->io_size; /* module list only for EISA devices */ if (pdev == NULL) { vp->next_module = root_vortex_eisa_dev; root_vortex_eisa_dev = dev; } /* PCI-only startup logic */ if (pdev) { /* EISA resources already marked, so only PCI needs to do this here */ /* Ignore return value, because Cardbus drivers already allocate for us */ if (request_region(ioaddr, vci->io_size, dev->name) != NULL) { vp->must_free_region = 1; } /* wake up and enable device */ if (pci_enable_device (pdev)) { retval = -EIO; goto free_region; } /* enable bus-mastering if necessary */ if (vci->flags & PCI_USES_MASTER) pci_set_master (pdev); } spin_lock_init(&vp->lock); spin_lock_init(&vp->mdio_lock); vp->pdev = pdev; /* Makes sure rings are at least 16 byte aligned. */ vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE + sizeof(struct boom_tx_desc) * TX_RING_SIZE, &vp->rx_ring_dma); if (vp->rx_ring == 0) { retval = -ENOMEM; goto free_region; } vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE); vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE; /* if we are a PCI driver, we store info in pdev->driver_data * instead of a module list */ if (pdev) pdev->driver_data = dev; /* The lower four bits are the media type. */ if (dev->mem_start) { /* * AKPM: ewww.. The 'options' param is passed in as the third arg to the * LILO 'ether=' argument for non-modular use */ option = dev->mem_start; } else if (card_idx < MAX_UNITS) option = options[card_idx]; else option = -1; vp->media_override = 7; if (option >= 0) { vp->media_override = ((option & 7) == 2) ? 0 : option & 15; vp->full_duplex = (option & 0x200) ? 1 : 0; vp->bus_master = (option & 16) ? 1 : 0; } if (card_idx < MAX_UNITS) { if (full_duplex[card_idx] > 0) vp->full_duplex = 1; if (flow_ctrl[card_idx] > 0) vp->flow_ctrl = 1; } vp->force_fd = vp->full_duplex; vp->options = option; /* Read the station address from the EEPROM. */ EL3WINDOW(0); { int base; if (vci->drv_flags & EEPROM_8BIT) base = 0x230; else if (vci->drv_flags & EEPROM_OFFSET) base = EEPROM_Read + 0x30; else base = EEPROM_Read; for (i = 0; i < 0x40; i++) { int timer; outw(base + i, ioaddr + Wn0EepromCmd); /* Pause for at least 162 us. for the read to take place. */ for (timer = 10; timer >= 0; timer--) { udelay(162); if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) break; } eeprom[i] = inw(ioaddr + Wn0EepromData); } } for (i = 0; i < 0x18; i++) checksum ^= eeprom[i]; checksum = (checksum ^ (checksum >> 8)) & 0xff; if (checksum != 0x00) { /* Grrr, needless incompatible change 3Com. */ while (i < 0x21) checksum ^= eeprom[i++]; checksum = (checksum ^ (checksum >> 8)) & 0xff; } if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO)) printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]); for (i = 0; i < 6; i++) printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); EL3WINDOW(2); for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + i);#ifdef __sparc__ printk(", IRQ %s\n", __irq_itoa(dev->irq));#else printk(", IRQ %d\n", dev->irq); /* Tell them about an invalid IRQ. */ if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS)) printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n", dev->irq);#endif if (pdev && vci->drv_flags & HAS_CB_FNS) { unsigned long fn_st_addr; /* Cardbus function status space */ unsigned short n; fn_st_addr = pci_resource_start (pdev, 2); if (fn_st_addr) vp->cb_fn_base = ioremap(fn_st_addr, 128); printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n", dev->name, fn_st_addr, vp->cb_fn_base); EL3WINDOW(2); n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; if (vp->drv_flags & INVERT_LED_PWR) n |= 0x10; if (vp->drv_flags & INVERT_MII_PWR) n |= 0x4000; outw(n, ioaddr + Wn2_ResetOptions); } /* Extract our information from the EEPROM data. */ vp->info1 = eeprom[13]; vp->info2 = eeprom[15]; vp->capabilities = eeprom[16]; if (vp->info1 & 0x8000) { vp->full_duplex = 1; printk(KERN_INFO "Full duplex capable\n"); } { static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; unsigned int config; EL3WINDOW(3); vp->available_media = inw(ioaddr + Wn3_Options); if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ vp->available_media = 0x40; config = inl(ioaddr + Wn3_Config); if (vortex_debug > 1) printk(KERN_DEBUG " Internal config register is %4.4x, " "transceivers %#x.\n", config, inw(ioaddr + Wn3_Options)); printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", 8 << RAM_SIZE(config), RAM_WIDTH(config) ? "word" : "byte", ram_split[RAM_SPLIT(config)], AUTOSELECT(config) ? "autoselect/" : "", XCVR(config) > XCVR_ExtMII ? "<invalid transceiver>" : media_tbl[XCVR(config)].name); vp->default_media = XCVR(config); vp->autoselect = AUTOSELECT(config); } if (vp->media_override != 7) { printk(KERN_INFO " Media override to transceiver type %d (%s).\n", vp->media_override, media_tbl[vp->media_override].name); dev->if_port = vp->media_override; } else dev->if_port = vp->default_media; if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { int phy, phy_idx = 0; EL3WINDOW(4); mii_preamble_required++; mii_preamble_required++; mdio_read(dev, 24, 1); for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) { int mii_status, phyx = phy & 0x1f; mii_status = mdio_read(dev, phyx, 1); if (mii_status && mii_status != 0xffff) { vp->phys[phy_idx++] = phyx; printk(KERN_INFO " MII transceiver found at address %d," " status %4x.\n", phyx, mii_status); if ((mii_status & 0x0040) == 0) mii_preamble_required++; } } mii_preamble_required--; if (phy_idx == 0) { printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n"); vp->phys[0] = 24; } else { vp->advertising = mdio_read(dev, vp->phys[0], 4); if (vp->full_duplex) { /* Only advertise the FD media types. */ vp->advertising &= ~0x02A0; mdio_write(dev, vp->phys[0], 4, vp->advertising); } } } if (vp->capabilities & CapPwrMgmt) acpi_set_WOL(dev); if (vp->capabilities & CapBusMaster) { vp->full_bus_master_tx = 1; printk(KERN_INFO" Enabling bus-master transmits and %s receives.\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -