📄 acenic.c
字号:
"acenic.c: v0.49 12/13/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n";static struct net_device *root_dev = NULL;static int probed __initdata = 0;int __init acenic_probe (ACE_PROBE_ARG){#ifdef NEW_NETINIT struct net_device *dev;#endif struct ace_private *ap; struct pci_dev *pdev = NULL; int boards_found = 0; int version_disp; if (probed) return -ENODEV; probed++; if (!pci_present()) /* is PCI support present? */ return -ENODEV; version_disp = 0; while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) { if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) && ((pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE) || (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_COPPER)))&& !((pdev->vendor == PCI_VENDOR_ID_3COM) && (pdev->device == PCI_DEVICE_ID_3COM_3C985)) && !((pdev->vendor == PCI_VENDOR_ID_NETGEAR) && ((pdev->device == PCI_DEVICE_ID_NETGEAR_GA620) || (pdev->device == PCI_DEVICE_ID_NETGEAR_GA620T))) && /* * Farallon used the DEC vendor ID on their cards by * mistake for a while */ !((pdev->vendor == PCI_VENDOR_ID_DEC) && (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX)) && !((pdev->vendor == PCI_VENDOR_ID_SGI) && (pdev->device == PCI_DEVICE_ID_SGI_ACENIC))) continue; dev = init_etherdev(NULL, sizeof(struct ace_private)); if (dev == NULL) { printk(KERN_ERR "acenic: Unable to allocate " "net_device structure!\n"); break; } SET_MODULE_OWNER(dev); if (!dev->priv) dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL); if (!dev->priv) { printk(KERN_ERR "acenic: Unable to allocate memory\n"); return -ENOMEM; } ap = dev->priv; ap->pdev = pdev; dev->irq = pdev->irq; dev->open = &ace_open; dev->hard_start_xmit = &ace_start_xmit; dev->stop = &ace_close; dev->get_stats = &ace_get_stats; dev->set_multicast_list = &ace_set_multicast_list; dev->do_ioctl = &ace_ioctl; dev->set_mac_address = &ace_set_mac_addr; dev->change_mtu = &ace_change_mtu; /* display version info if adapter is found */ if (!version_disp) { /* set display flag to TRUE so that */ /* we only display this string ONCE */ version_disp = 1; printk(version); } /* * Enable master mode before we start playing with the * pci_command word since pci_set_master() will modify * it. */ pci_set_master(pdev); pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command); /* OpenFirmware on Mac's does not set this - DOH.. */ if (!(ap->pci_command & PCI_COMMAND_MEMORY)) { printk(KERN_INFO "%s: Enabling PCI Memory Mapped " "access - was not enabled by BIOS/Firmware\n", dev->name); ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY; pci_write_config_word(ap->pdev, PCI_COMMAND, ap->pci_command); wmb(); } pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ap->pci_latency); if (ap->pci_latency <= 0x40) { ap->pci_latency = 0x40; pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ap->pci_latency); } /* * Remap the regs into kernel space - this is abuse of * dev->base_addr since it was means for I/O port * addresses but who gives a damn. */ dev->base_addr = pci_resource_start(pdev, 0); ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); if (!ap->regs) { printk(KERN_ERR "%s: Unable to map I/O register, " "AceNIC %i will be disabled.\n", dev->name, boards_found); break; } switch(pdev->vendor) { case PCI_VENDOR_ID_ALTEON: strncpy(ap->name, "AceNIC Gigabit Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: Alteon AceNIC ", dev->name); break; case PCI_VENDOR_ID_3COM: strncpy(ap->name, "3Com 3C985 Gigabit Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: 3Com 3C985 ", dev->name); break; case PCI_VENDOR_ID_NETGEAR: strncpy(ap->name, "NetGear GA620 Gigabit Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: NetGear GA620 ", dev->name); break; case PCI_VENDOR_ID_DEC: if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) { strncpy(ap->name, "Farallon PN9000-SX " "Gigabit Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: Farallon PN9000-SX ", dev->name); break; } case PCI_VENDOR_ID_SGI: strncpy(ap->name, "SGI AceNIC Gigabit Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: SGI AceNIC ", dev->name); break; default: strncpy(ap->name, "Unknown AceNIC based Gigabit " "Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: Unknown AceNIC ", dev->name); break; } ap->name [sizeof (ap->name) - 1] = '\0'; printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);#ifdef __sparc__ printk("irq %s\n", __irq_itoa(dev->irq));#else printk("irq %i\n", dev->irq);#endif#ifdef CONFIG_ACENIC_OMIT_TIGON_I if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { printk(KERN_ERR "%s: Driver compiled without Tigon I" " support - NIC disabled\n", dev->name); ace_init_cleanup(dev); continue; }#endif if (ace_allocate_descriptors(dev)) continue;#ifdef MODULE if (boards_found >= ACE_MAX_MOD_PARMS) ap->board_idx = BOARD_IDX_OVERFLOW; else ap->board_idx = boards_found;#else ap->board_idx = BOARD_IDX_STATIC;#endif if (ace_init(dev)) continue; boards_found++; } /* * If we're at this point we're going through ace_probe() for * the first time. Return success (0) if we've initialized 1 * or more boards. Otherwise, return failure (-ENODEV). */ if (boards_found > 0) return 0; else return -ENODEV;}#ifdef MODULEMODULE_AUTHOR("Jes Sorensen <jes@linuxcare.com>");MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i");MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i");MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");#endifvoid __exit ace_module_cleanup(void){ struct ace_private *ap; struct ace_regs *regs; struct net_device *next; short i; while (root_dev) { ap = root_dev->priv; next = ap->next; regs = ap->regs; writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); if (ap->version >= 2) writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); /* * This clears any pending interrupts */ writel(1, ®s->Mb0Lo); /* * Make sure no other CPUs are processing interrupts * on the card before the buffers are being released. * Otherwise one might experience some `interesting' * effects. * * Then release the RX buffers - jumbo buffers were * already released in ace_close(). */ synchronize_irq(); for (i = 0; i < RX_STD_RING_ENTRIES; i++) { struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb; if (skb) { dma_addr_t mapping; mapping = ap->skb->rx_std_skbuff[i].mapping; ap->rx_std_ring[i].size = 0; ap->skb->rx_std_skbuff[i].skb = NULL; pci_unmap_single(ap->pdev, mapping, ACE_STD_BUFSIZE - (2 + 16), PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); } } if (ap->version >= 2) { for (i = 0; i < RX_MINI_RING_ENTRIES; i++) { struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb; if (skb) { dma_addr_t mapping; mapping = ap->skb->rx_mini_skbuff[i].mapping; ap->rx_mini_ring[i].size = 0; ap->skb->rx_mini_skbuff[i].skb = NULL; pci_unmap_single(ap->pdev, mapping, ACE_MINI_BUFSIZE - (2 + 16), PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); } } } for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) { struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb; if (skb) { dma_addr_t mapping; mapping = ap->skb->rx_jumbo_skbuff[i].mapping; ap->rx_jumbo_ring[i].size = 0; ap->skb->rx_jumbo_skbuff[i].skb = NULL; pci_unmap_single(ap->pdev, mapping, ACE_JUMBO_BUFSIZE - (2 + 16), PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); } } ace_init_cleanup(root_dev); kfree(root_dev); root_dev = next; }}int __init ace_module_init(void){ int status; root_dev = NULL;#ifdef NEW_NETINIT status = acenic_probe();#else status = acenic_probe(NULL);#endif return status;}#if (LINUX_VERSION_CODE < 0x02032a)#ifdef MODULEint init_module(void){ return ace_module_init();}void cleanup_module(void){ ace_module_cleanup();}#endif#elsemodule_init(ace_module_init);module_exit(ace_module_cleanup);#endifstatic void ace_free_descriptors(struct net_device *dev){ struct ace_private *ap = dev->priv; int size; if (ap->rx_std_ring != NULL) { size = (sizeof(struct rx_desc) * (RX_STD_RING_ENTRIES + RX_JUMBO_RING_ENTRIES + RX_MINI_RING_ENTRIES + RX_RETURN_RING_ENTRIES)); pci_free_consistent(ap->pdev, size, ap->rx_std_ring, ap->rx_ring_base_dma); ap->rx_std_ring = NULL; ap->rx_jumbo_ring = NULL; ap->rx_mini_ring = NULL; ap->rx_return_ring = NULL; } if (ap->evt_ring != NULL) { size = (sizeof(struct event) * EVT_RING_ENTRIES); pci_free_consistent(ap->pdev, size, ap->evt_ring, ap->evt_ring_dma); ap->evt_ring = NULL; } if (ap->evt_prd != NULL) { pci_free_consistent(ap->pdev, sizeof(u32), (void *)ap->evt_prd, ap->evt_prd_dma); ap->evt_prd = NULL; } if (ap->rx_ret_prd != NULL) { pci_free_consistent(ap->pdev, sizeof(u32), (void *)ap->rx_ret_prd, ap->rx_ret_prd_dma); ap->rx_ret_prd = NULL; } if (ap->tx_csm != NULL) { pci_free_consistent(ap->pdev, sizeof(u32), (void *)ap->tx_csm, ap->tx_csm_dma); ap->tx_csm = NULL; }}static int ace_allocate_descriptors(struct net_device *dev){ struct ace_private *ap = dev->priv; int size; size = (sizeof(struct rx_desc) * (RX_STD_RING_ENTRIES + RX_JUMBO_RING_ENTRIES + RX_MINI_RING_ENTRIES + RX_RETURN_RING_ENTRIES)); ap->rx_std_ring = pci_alloc_consistent(ap->pdev, size, &ap->rx_ring_base_dma); if (ap->rx_std_ring == NULL) goto fail; ap->rx_jumbo_ring = ap->rx_std_ring + RX_STD_RING_ENTRIES; ap->rx_mini_ring = ap->rx_jumbo_ring + RX_JUMBO_RING_ENTRIES; ap->rx_return_ring = ap->rx_mini_ring + RX_MINI_RING_ENTRIES; size = (sizeof(struct event) * EVT_RING_ENTRIES); ap->evt_ring = pci_alloc_consistent(ap->pdev, size, &ap->evt_ring_dma); if (ap->evt_ring == NULL) goto fail; size = (sizeof(struct tx_desc) * TX_RING_ENTRIES); ap->tx_ring = pci_alloc_consistent(ap->pdev, size, &ap->tx_ring_dma); if (ap->tx_ring == NULL) goto fail; ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32), &ap->evt_prd_dma); if (ap->evt_prd == NULL) goto fail; ap->rx_ret_prd = pci_alloc_consistent(ap->pdev, sizeof(u32), &ap->rx_ret_prd_dma); if (ap->rx_ret_prd == NULL) goto fail; ap->tx_csm = pci_alloc_consistent(ap->pdev, sizeof(u32), &ap->tx_csm_dma); if (ap->tx_csm == NULL) goto fail; return 0;fail: /* Clean up. */ ace_init_cleanup(dev); return 1;}/* * Generic cleanup handling data allocated during init. Used when the * module is unloaded or if an error occurs during initialization */static void ace_init_cleanup(struct net_device *dev){ struct ace_private *ap; ap = dev->priv; ace_free_descriptors(dev); if (ap->info) pci_free_consistent(ap->pdev, sizeof(struct ace_info), ap->info, ap->info_dma); if (ap->skb) kfree(ap->skb); if (ap->trace_buf) kfree(ap->trace_buf); if (dev->irq) free_irq(dev->irq, dev); unregister_netdev(dev); iounmap(ap->regs);}/* * Commands are considered to be slow. */static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd){ u32 idx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -