📄 e100_main.c
字号:
cpu_relax(); udelay(1); } return false;}/** * e100_wait_exec_simple - issue a command * @bdp: atapter's private data struct * @scb_cmd_low: the command that is to be issued * * This general routine will issue a command to the e100 after waiting for * the previous command to finish. * * Returns: * true if the command was issued to the chip successfully * false if the command was not issued to the chip */inline unsigned chare100_wait_exec_simple(struct e100_private *bdp, u8 scb_cmd_low){ if (!e100_wait_scb(bdp)) { printk(KERN_DEBUG "e100: %s: e100_wait_exec_simple: failed\n", bdp->device->name);#ifdef E100_CU_DEBUG printk(KERN_ERR "e100: %s: Last command (%x/%x) " "timeout\n", bdp->device->name, bdp->last_cmd, bdp->last_sub_cmd); printk(KERN_ERR "e100: %s: Current simple command (%x) " "can't be executed\n", bdp->device->name, scb_cmd_low);#endif return false; } e100_exec_cmd(bdp, scb_cmd_low);#ifdef E100_CU_DEBUG bdp->last_cmd = scb_cmd_low; bdp->last_sub_cmd = 0;#endif return true;}voide100_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd){ writel(phys_addr, &(bdp->scb->scb_gen_ptr)); readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ e100_exec_cmd(bdp, cmd);}unsigned chare100_wait_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd, u8 sub_cmd){ if (!e100_wait_scb(bdp)) {#ifdef E100_CU_DEBUG printk(KERN_ERR "e100: %s: Last command (%x/%x) " "timeout\n", bdp->device->name, bdp->last_cmd, bdp->last_sub_cmd); printk(KERN_ERR "e100: %s: Current complex command " "(%x/%x) can't be executed\n", bdp->device->name, cmd, sub_cmd);#endif return false; } e100_exec_cmplx(bdp, phys_addr, cmd);#ifdef E100_CU_DEBUG bdp->last_cmd = cmd; bdp->last_sub_cmd = sub_cmd;#endif return true;}inline u8e100_wait_cus_idle(struct e100_private *bdp){ int i; /* loop on the scb for a few times */ for (i = 0; i < 100; i++) { if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) != SCB_CUS_ACTIVE)) { return true; } cpu_relax(); } for (i = 0; i < E100_MAX_CU_IDLE_WAIT; i++) { if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) != SCB_CUS_ACTIVE)) { return true; } cpu_relax(); udelay(1); } return false;}/** * e100_disable_clear_intr - disable and clear/ack interrupts * @bdp: atapter's private data struct * * This routine disables interrupts at the hardware, by setting * the M (mask) bit in the adapter's CSR SCB command word. * It also clear/ack interrupts. */static inline voide100_disable_clear_intr(struct e100_private *bdp){ u16 intr_status; /* Disable interrupts on our PCI board by setting the mask bit */ writeb(SCB_INT_MASK, &bdp->scb->scb_cmd_hi); intr_status = readw(&bdp->scb->scb_status); /* ack and clear intrs */ writew(intr_status, &bdp->scb->scb_status); readw(&bdp->scb->scb_status);}/** * e100_set_intr_mask - set interrupts * @bdp: atapter's private data struct * * This routine sets interrupts at the hardware, by resetting * the M (mask) bit in the adapter's CSR SCB command word */static inline voide100_set_intr_mask(struct e100_private *bdp){ writeb(bdp->intr_mask, &bdp->scb->scb_cmd_hi); readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */}static inline voide100_trigger_SWI(struct e100_private *bdp){ /* Trigger interrupt on our PCI board by asserting SWI bit */ writeb(SCB_SOFT_INT, &bdp->scb->scb_cmd_hi); readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */}static int __devinite100_found1(struct pci_dev *pcid, const struct pci_device_id *ent){ static int first_time = true; struct net_device *dev = NULL; struct e100_private *bdp = NULL; int rc = 0; u16 cal_checksum, read_checksum;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) dev = init_etherdev(NULL, sizeof (struct e100_private));#else dev = alloc_etherdev(sizeof (struct e100_private));#endif if (dev == NULL) { printk(KERN_ERR "e100: Not able to alloc etherdev struct\n"); rc = -ENODEV; goto out; } SET_MODULE_OWNER(dev); if (first_time) { first_time = false; printk(KERN_NOTICE "%s - version %s\n", e100_full_driver_name, e100_driver_version); printk(KERN_NOTICE "%s\n", e100_copyright); printk(KERN_NOTICE "\n"); } bdp = dev->priv; bdp->pdev = pcid; bdp->device = dev; pci_set_drvdata(pcid, dev); SET_NETDEV_DEV(dev, &pcid->dev); bdp->flags = 0; bdp->ifs_state = 0; bdp->ifs_value = 0; bdp->scb = 0; init_timer(&bdp->nontx_timer_id); bdp->nontx_timer_id.data = (unsigned long) bdp; bdp->nontx_timer_id.function = (void *) &e100_non_tx_background; INIT_LIST_HEAD(&(bdp->non_tx_cmd_list)); bdp->non_tx_command_state = E100_NON_TX_IDLE; init_timer(&bdp->watchdog_timer); bdp->watchdog_timer.data = (unsigned long) dev; bdp->watchdog_timer.function = (void *) &e100_watchdog; if ((rc = e100_pci_setup(pcid, bdp)) != 0) { goto err_dev; } if ((rc = e100_alloc_space(bdp)) != 0) { goto err_pci; } if (((bdp->pdev->device > 0x1030) && (bdp->pdev->device < 0x103F)) || ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1057)) || ((bdp->pdev->device >= 0x1064) && (bdp->pdev->device <= 0x106B)) || (bdp->pdev->device == 0x2449) || (bdp->pdev->device == 0x2459) || (bdp->pdev->device == 0x245D)) { bdp->rev_id = D101MA_REV_ID; /* workaround for ICH3 */ bdp->flags |= IS_ICH; } if (bdp->rev_id == 0xff) bdp->rev_id = 1; if ((u8) bdp->rev_id >= D101A4_REV_ID) bdp->flags |= IS_BACHELOR; if ((u8) bdp->rev_id >= D102_REV_ID) { bdp->flags |= USE_IPCB; bdp->rfd_size = 32; } else { bdp->rfd_size = 16; }#ifdef NETIF_F_HW_VLAN_TX dev->vlan_rx_register = e100_vlan_rx_register; dev->vlan_rx_add_vid = e100_vlan_rx_add_vid; dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid;#endif dev->irq = pcid->irq; dev->open = &e100_open; dev->hard_start_xmit = &e100_xmit_frame; dev->stop = &e100_close; dev->change_mtu = &e100_change_mtu; dev->get_stats = &e100_get_stats; dev->set_multicast_list = &e100_set_multi; dev->set_mac_address = &e100_set_mac; dev->do_ioctl = &e100_ioctl;#ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = e100_netpoll;#endif#ifdef MAX_SKB_FRAGS if (bdp->flags & USE_IPCB)#ifdef NETIF_F_HW_VLAN_TX dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;#else dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;#endif /* NETIF_F_HW_VLAN_TX */#endif /* MAX_SKB_FRAGS */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) if ((rc = register_netdev(dev)) != 0) { goto err_dealloc; }#endif e100_check_options(e100nics, bdp); if (!e100_init(bdp)) { printk(KERN_ERR "e100: Failed to initialize, instance #%d\n", e100nics); rc = -ENODEV; goto err_unregister_netdev; } /* Check if checksum is valid */ cal_checksum = e100_eeprom_calculate_chksum(bdp); read_checksum = e100_eeprom_read(bdp, (bdp->eeprom_size - 1)); if (cal_checksum != read_checksum) { printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n", e100nics); rc = -ENODEV; goto err_unregister_netdev; } e100nics++;#ifdef SIOCETHTOOL e100_get_speed_duplex_caps(bdp);#endif /*SIOCETHTOOL */ printk(KERN_NOTICE "e100: %s: %s\n", bdp->device->name, "Intel(R) PRO/100 Network Connection"); e100_print_brd_conf(bdp); bdp->wolsupported = 0; bdp->wolopts = 0; if (bdp->rev_id >= D101A4_REV_ID) bdp->wolsupported = WAKE_PHY | WAKE_MAGIC; if (bdp->rev_id >= D101MA_REV_ID) bdp->wolsupported |= WAKE_UCAST | WAKE_ARP; /* Check if WoL is enabled on EEPROM */ if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) { /* Magic Packet WoL is enabled on device by default */ /* if EEPROM WoL bit is TRUE */ bdp->wolopts = WAKE_MAGIC; }#ifdef STB_WA if (bdp->rev_id >= D101MA_REV_ID) { u16 id_reg; id_reg = e100_eeprom_read(bdp, EEPROM_ID_WORD); if (id_reg & (0x02)) { id_reg &= ((u16) (~0x02)); e100_eeprom_write_block(bdp, EEPROM_ID_WORD, &id_reg, 1); printk(KERN_NOTICE "e100: %s Changed the eeprom values\n", dev->name); printk(KERN_NOTICE "e100: for sane operation, " "a reboot is required\n"); } }#endif printk(KERN_NOTICE "\n"); goto out;err_unregister_netdev: unregister_netdev(dev);err_dealloc: e100_dealloc_space(bdp);err_pci: iounmap(bdp->scb); pci_release_regions(pcid); pci_disable_device(pcid);err_dev:#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) unregister_netdev(dev);#endif pci_set_drvdata(pcid, NULL); free_netdev(dev);out: return rc;}/** * e100_clear_structs - free resources * @dev: adapter's net_device struct * * Free all device specific structs, unmap i/o address, etc. */static void __devexite100_clear_structs(struct net_device *dev){ struct e100_private *bdp = dev->priv; iounmap(bdp->scb); pci_release_regions(bdp->pdev); pci_disable_device(bdp->pdev); e100_dealloc_space(bdp); pci_set_drvdata(bdp->pdev, NULL); free_netdev(dev);}static void __devexite100_remove1(struct pci_dev *pcid){ struct net_device *dev; struct e100_private *bdp; if (!(dev = (struct net_device *) pci_get_drvdata(pcid))) return; bdp = dev->priv; unregister_netdev(dev); e100_sw_reset(bdp, PORT_SELECTIVE_RESET); if (bdp->non_tx_command_state != E100_NON_TX_IDLE) { del_timer_sync(&bdp->nontx_timer_id); e100_free_nontx_list(bdp); bdp->non_tx_command_state = E100_NON_TX_IDLE; } e100_clear_structs(dev); --e100nics;}static struct pci_device_id e100_id_table[] = { {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1066, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1067, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x1069, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x106A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x106B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, {0,} /* This has to be the last entry*/};MODULE_DEVICE_TABLE(pci, e100_id_table);static struct pci_driver e100_driver = { .name = "e100", .id_table = e100_id_table, .probe = e100_found1, .remove = __devexit_p(e100_remove1),#ifdef CONFIG_PM .suspend = e100_suspend, .resume = e100_resume,#endif};#ifdef E100_IA64_DMA_FIXstatic int non_DMA32_memory_present;#endifstatic int __inite100_init_module(void){ int ret;#ifdef E100_IA64_DMA_FIX struct sysinfo si; si_meminfo(&si); if (si.totalram >= (0x100000000UL) / PAGE_SIZE) { non_DMA32_memory_present = 1; } else { non_DMA32_memory_present = 0; }#endif ret = pci_module_init(&e100_driver);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -