3c59x.c
来自「linux 内核源代码」· C语言 代码 · 共 1,988 行 · 第 1/5 页
C
1,988 行
local_irq_restore(flags);}#endif#ifdef CONFIG_PMstatic int vortex_suspend(struct pci_dev *pdev, pm_message_t state){ struct net_device *dev = pci_get_drvdata(pdev); if (dev && dev->priv) { if (netif_running(dev)) { netif_device_detach(dev); vortex_down(dev, 1); } pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); free_irq(dev->irq, dev); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); } return 0;}static int vortex_resume(struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata(pdev); struct vortex_private *vp = netdev_priv(dev); int err; if (dev && vp) { pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) { printk(KERN_WARNING "%s: Could not enable device \n", dev->name); return err; } pci_set_master(pdev); if (request_irq(dev->irq, vp->full_bus_master_rx ? &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) { printk(KERN_WARNING "%s: Could not reserve IRQ %d\n", dev->name, dev->irq); pci_disable_device(pdev); return -EBUSY; } if (netif_running(dev)) { err = vortex_up(dev); if (err) return err; else netif_device_attach(dev); } } return 0;}#endif /* CONFIG_PM */#ifdef CONFIG_EISAstatic struct eisa_device_id vortex_eisa_ids[] = { { "TCM5920", CH_3C592 }, { "TCM5970", CH_3C597 }, { "" }};MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);static int __init vortex_eisa_probe(struct device *device){ void __iomem *ioaddr; struct eisa_device *edev; edev = to_eisa_device(device); if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME)) return -EBUSY; ioaddr = ioport_map(edev->base_addr, VORTEX_TOTAL_SIZE); if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12, edev->id.driver_data, vortex_cards_found)) { release_region(edev->base_addr, VORTEX_TOTAL_SIZE); return -ENODEV; } vortex_cards_found++; return 0;}static int __devexit vortex_eisa_remove(struct device *device){ struct eisa_device *edev; struct net_device *dev; struct vortex_private *vp; void __iomem *ioaddr; edev = to_eisa_device(device); dev = eisa_get_drvdata(edev); if (!dev) { printk("vortex_eisa_remove called for Compaq device!\n"); BUG(); } vp = netdev_priv(dev); ioaddr = vp->ioaddr; unregister_netdev(dev); iowrite16(TotalReset|0x14, ioaddr + EL3_CMD); release_region(dev->base_addr, VORTEX_TOTAL_SIZE); free_netdev(dev); return 0;}static struct eisa_driver vortex_eisa_driver = { .id_table = vortex_eisa_ids, .driver = { .name = "3c59x", .probe = vortex_eisa_probe, .remove = __devexit_p(vortex_eisa_remove) }};#endif /* CONFIG_EISA *//* returns count found (>= 0), or negative on error */static int __init vortex_eisa_init(void){ int eisa_found = 0; int orig_cards_found = vortex_cards_found;#ifdef CONFIG_EISA int err; err = eisa_driver_register (&vortex_eisa_driver); if (!err) { /* * Because of the way EISA bus is probed, we cannot assume * any device have been found when we exit from * eisa_driver_register (the bus root driver may not be * initialized yet). So we blindly assume something was * found, and let the sysfs magic happend... */ eisa_found = 1; }#endif /* Special code to work-around the Compaq PCI BIOS32 problem. */ if (compaq_ioaddr) { vortex_probe1(NULL, ioport_map(compaq_ioaddr, VORTEX_TOTAL_SIZE), compaq_irq, compaq_device_id, vortex_cards_found++); } return vortex_cards_found - orig_cards_found + eisa_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, unit, pci_bar; struct vortex_chip_info *vci; void __iomem *ioaddr; /* wake up and enable device */ rc = pci_enable_device(pdev); if (rc < 0) goto out; unit = vortex_cards_found; if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) { /* Determine the default if the user didn't override us */ vci = &vortex_info_tbl[ent->driver_data]; pci_bar = vci->drv_flags & (IS_CYCLONE | IS_TORNADO) ? 1 : 0; } else if (unit < MAX_UNITS && use_mmio[unit] >= 0) pci_bar = use_mmio[unit] ? 1 : 0; else pci_bar = global_use_mmio ? 1 : 0; ioaddr = pci_iomap(pdev, pci_bar, 0); if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */ ioaddr = pci_iomap(pdev, 0, 0); rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq, ent->driver_data, unit); if (rc < 0) { pci_disable_device(pdev); goto out; } vortex_cards_found++;out: return rc;}/* * Start up the PCI/EISA device which is described by *gendev. * Return 0 on success. * * NOTE: pdev can be NULL, for the case of a Compaq device */static int __devinit vortex_probe1(struct device *gendev, void __iomem *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, step; struct net_device *dev; static int printed_version; int retval, print_info; struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx]; char *print_name = "3c59x"; struct pci_dev *pdev = NULL; struct eisa_device *edev = NULL; DECLARE_MAC_BUF(mac); if (!printed_version) { printk (version); printed_version = 1; } if (gendev) { if ((pdev = DEVICE_PCI(gendev))) { print_name = pci_name(pdev); } if ((edev = DEVICE_EISA(gendev))) { print_name = edev->dev.bus_id; } } dev = alloc_etherdev(sizeof(*vp)); retval = -ENOMEM; if (!dev) { printk (KERN_ERR PFX "unable to allocate etherdev, aborting\n"); goto out; } SET_NETDEV_DEV(dev, gendev); vp = netdev_priv(dev); option = global_options; /* The lower four bits are the media type. */ if (dev->mem_start) { /* * 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) { if (options[card_idx] >= 0) option = options[card_idx]; } if (option > 0) { if (option & 0x8000) vortex_debug = 7; if (option & 0x4000) vortex_debug = 2; if (option & 0x0400) vp->enable_wol = 1; } print_info = (vortex_debug > 1); if (print_info) printk (KERN_INFO "See Documentation/networking/vortex.txt\n"); printk(KERN_INFO "%s: 3Com %s %s at %p.\n", print_name, pdev ? "PCI" : "EISA", vci->name, ioaddr); dev->base_addr = (unsigned long)ioaddr; dev->irq = irq; dev->mtu = mtu; vp->ioaddr = ioaddr; vp->large_frames = mtu > 1500; vp->drv_flags = vci->drv_flags; vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; vp->io_size = vci->io_size; vp->card_idx = card_idx; /* module list only for Compaq device */ if (gendev == NULL) { compaq_net_device = 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(dev->base_addr, vci->io_size, print_name) != NULL) vp->must_free_region = 1; /* enable bus-mastering if necessary */ if (vci->flags & PCI_USES_MASTER) pci_set_master(pdev); if (vci->drv_flags & IS_VORTEX) { u8 pci_latency; u8 new_latency = 248; /* Check the PCI latency value. On the 3c590 series the latency timer must be set to the maximum value to avoid data corruption that occurs when the timer expires during a transfer. This bug exists the Vortex chip only. */ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < new_latency) { printk(KERN_INFO "%s: Overriding PCI latency" " timer (CFLT) setting of %d, new value is %d.\n", print_name, pci_latency, new_latency); pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency); } } } spin_lock_init(&vp->lock); vp->gendev = gendev; vp->mii.dev = dev; vp->mii.mdio_read = mdio_read; vp->mii.mdio_write = mdio_write; vp->mii.phy_id_mask = 0x1f; vp->mii.reg_num_mask = 0x1f; /* 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); retval = -ENOMEM; if (!vp->rx_ring) 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) pci_set_drvdata(pdev, dev); if (edev) eisa_set_drvdata(edev, dev); vp->media_override = 7; if (option >= 0) { vp->media_override = ((option & 7) == 2) ? 0 : option & 15; if (vp->media_override != 7) vp->medialock = 1; vp->full_duplex = (option & 0x200) ? 1 : 0; vp->bus_master = (option & 16) ? 1 : 0; } if (global_full_duplex > 0) vp->full_duplex = 1; if (global_enable_wol > 0) vp->enable_wol = 1; 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; if (enable_wol[card_idx] > 0) vp->enable_wol = 1; } vp->mii.force_media = 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; iowrite16(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 ((ioread16(ioaddr + Wn0EepromCmd) & 0x8000) == 0) break; } eeprom[i] = ioread16(ioaddr + Wn0EepromData); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?