📄 de2104x.c
字号:
if (regs.len > DE_REGS_SIZE) { regs.len = DE_REGS_SIZE; } regs.version = (DE_REGS_VER << 2) | de->de21040; if (copy_to_user(useraddr, ®s, sizeof(regs))) return -EFAULT; useraddr += offsetof(struct ethtool_regs, data); spin_lock_irq(&de->lock); r = de_get_regs(de, regbuf); spin_unlock_irq(&de->lock); if (r) return r; if (copy_to_user(useraddr, regbuf, regs.len)) return -EFAULT; return 0; } /* get SROM dump */ case ETHTOOL_GEEPROM: { struct ethtool_eeprom eeprom; if (!de->ee_data) break; if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) return -EFAULT; if ((eeprom.offset != 0) || (eeprom.magic != 0) || (eeprom.len != DE_EEPROM_SIZE)) return -EINVAL; useraddr += offsetof(struct ethtool_regs, data); if (copy_to_user(useraddr, de->ee_data, DE_EEPROM_SIZE)) return -EFAULT; } default: break; } return -EOPNOTSUPP;}static int de_ioctl (struct net_device *dev, struct ifreq *rq, int cmd){ struct de_private *de = dev->priv; int rc = 0; if (!netif_running(dev)) return -EINVAL; switch (cmd) { case SIOCETHTOOL: return de_ethtool_ioctl(de, (void *) rq->ifr_data); default: rc = -EOPNOTSUPP; break; } return rc;}static void __init de21040_get_mac_address (struct de_private *de){ unsigned i; dw32 (ROMCmd, 0); /* Reset the pointer with a dummy write. */ for (i = 0; i < 6; i++) { int value, boguscnt = 100000; do value = dr32(ROMCmd); while (value < 0 && --boguscnt > 0); de->dev->dev_addr[i] = value; if (boguscnt <= 0) printk(KERN_WARNING PFX "timeout reading 21040 MAC address byte %u\n", i); }}static void __init de21040_get_media_info(struct de_private *de){ unsigned int i; de->media_type = DE_MEDIA_TP; de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half | SUPPORTED_AUI; de->media_advertise = de->media_supported; for (i = 0; i < DE_MAX_MEDIA; i++) { switch (i) { case DE_MEDIA_AUI: case DE_MEDIA_TP: case DE_MEDIA_TP_FD: de->media[i].type = i; de->media[i].csr13 = t21040_csr13[i]; de->media[i].csr14 = t21040_csr14[i]; de->media[i].csr15 = t21040_csr15[i]; break; default: de->media[i].type = DE_MEDIA_INVALID; break; } }}/* Note: this routine returns extra data bits for size detection. */static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len){ int i; unsigned retval = 0; void *ee_addr = regs + ROMCmd; int read_cmd = location | (EE_READ_CMD << addr_len); writel(EE_ENB & ~EE_CS, ee_addr); writel(EE_ENB, ee_addr); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; writel(EE_ENB | dataval, ee_addr); readl(ee_addr); writel(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); readl(ee_addr); retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0); } writel(EE_ENB, ee_addr); readl(ee_addr); for (i = 16; i > 0; i--) { writel(EE_ENB | EE_SHIFT_CLK, ee_addr); readl(ee_addr); retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0); writel(EE_ENB, ee_addr); readl(ee_addr); } /* Terminate the EEPROM access. */ writel(EE_ENB & ~EE_CS, ee_addr); return retval;}static void __init de21041_get_srom_info (struct de_private *de){ unsigned i, sa_offset = 0, ofs; u8 ee_data[DE_EEPROM_SIZE + 6] = {}; unsigned ee_addr_size = tulip_read_eeprom(de->regs, 0xff, 8) & 0x40000 ? 8 : 6; struct de_srom_info_leaf *il; void *bufp; /* download entire eeprom */ for (i = 0; i < DE_EEPROM_WORDS; i++) ((u16 *)ee_data)[i] = le16_to_cpu(tulip_read_eeprom(de->regs, i, ee_addr_size)); /* DEC now has a specification but early board makers just put the address in the first EEPROM locations. */ /* This does memcmp(eedata, eedata+16, 8) */ for (i = 0; i < 8; i ++) if (ee_data[i] != ee_data[16+i]) sa_offset = 20; /* store MAC address */ for (i = 0; i < 6; i ++) de->dev->dev_addr[i] = ee_data[i + sa_offset]; /* get offset of controller 0 info leaf. ignore 2nd byte. */ ofs = ee_data[SROMC0InfoLeaf]; if (ofs >= (sizeof(ee_data) - sizeof(struct de_srom_info_leaf) - sizeof(struct de_srom_media_block))) goto bad_srom; /* get pointer to info leaf */ il = (struct de_srom_info_leaf *) &ee_data[ofs]; /* paranoia checks */ if (il->n_blocks == 0) goto bad_srom; if ((sizeof(ee_data) - ofs) < (sizeof(struct de_srom_info_leaf) + (sizeof(struct de_srom_media_block) * il->n_blocks))) goto bad_srom; /* get default media type */ switch (DE_UNALIGNED_16(&il->default_media)) { case 0x0001: de->media_type = DE_MEDIA_BNC; break; case 0x0002: de->media_type = DE_MEDIA_AUI; break; case 0x0204: de->media_type = DE_MEDIA_TP_FD; break; default: de->media_type = DE_MEDIA_TP_AUTO; break; } if (netif_msg_probe(de)) printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n", de->board_idx, ofs, media_name[de->media_type]); /* init SIA register values to defaults */ for (i = 0; i < DE_MAX_MEDIA; i++) { de->media[i].type = DE_MEDIA_INVALID; de->media[i].csr13 = 0xffff; de->media[i].csr14 = 0xffff; de->media[i].csr15 = 0xffff; } /* parse media blocks to see what medias are supported, * and if any custom CSR values are provided */ bufp = ((void *)il) + sizeof(*il); for (i = 0; i < il->n_blocks; i++) { struct de_srom_media_block *ib = bufp; unsigned idx; /* index based on media type in media block */ switch(ib->opts & MediaBlockMask) { case 0: /* 10baseT */ de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg; idx = DE_MEDIA_TP; de->media[DE_MEDIA_TP_AUTO].type = DE_MEDIA_TP_AUTO; break; case 1: /* BNC */ de->media_supported |= SUPPORTED_BNC; idx = DE_MEDIA_BNC; break; case 2: /* AUI */ de->media_supported |= SUPPORTED_AUI; idx = DE_MEDIA_AUI; break; case 4: /* 10baseT-FD */ de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full | SUPPORTED_Autoneg; idx = DE_MEDIA_TP_FD; de->media[DE_MEDIA_TP_AUTO].type = DE_MEDIA_TP_AUTO; break; default: goto bad_srom; } de->media[idx].type = idx; if (netif_msg_probe(de)) printk(KERN_INFO "de%d: media block #%u: %s", de->board_idx, i, media_name[de->media[idx].type]); bufp += sizeof (ib->opts); if (ib->opts & MediaCustomCSRs) { de->media[idx].csr13 = DE_UNALIGNED_16(&ib->csr13); de->media[idx].csr14 = DE_UNALIGNED_16(&ib->csr14); de->media[idx].csr15 = DE_UNALIGNED_16(&ib->csr15); bufp += sizeof(ib->csr13) + sizeof(ib->csr14) + sizeof(ib->csr15); if (netif_msg_probe(de)) printk(" (%x,%x,%x)\n", de->media[idx].csr13, de->media[idx].csr14, de->media[idx].csr15); } else if (netif_msg_probe(de)) printk("\n"); if (bufp > ((void *)&ee_data[DE_EEPROM_SIZE - 3])) break; } de->media_advertise = de->media_supported;fill_defaults: /* fill in defaults, for cases where custom CSRs not used */ for (i = 0; i < DE_MAX_MEDIA; i++) { if (de->media[i].csr13 == 0xffff) de->media[i].csr13 = t21041_csr13[i]; if (de->media[i].csr14 == 0xffff) de->media[i].csr14 = t21041_csr14[i]; if (de->media[i].csr15 == 0xffff) de->media[i].csr15 = t21041_csr15[i]; } de->ee_data = kmalloc(DE_EEPROM_SIZE, GFP_KERNEL); if (de->ee_data) memcpy(de->ee_data, &ee_data[0], DE_EEPROM_SIZE); return;bad_srom: /* for error cases, it's ok to assume we support all these */ for (i = 0; i < DE_MAX_MEDIA; i++) de->media[i].type = i; de->media_supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_AUI | SUPPORTED_BNC; goto fill_defaults;}static int __init de_init_one (struct pci_dev *pdev, const struct pci_device_id *ent){ struct net_device *dev; struct de_private *de; int rc; void *regs; long pciaddr; static int board_idx = -1; board_idx++;#ifndef MODULE if (board_idx == 0) printk("%s", version);#endif /* allocate a new ethernet device structure, and fill in defaults */ dev = alloc_etherdev(sizeof(struct de_private)); if (!dev) return -ENOMEM; SET_MODULE_OWNER(dev); dev->open = de_open; dev->stop = de_close; dev->set_multicast_list = de_set_rx_mode; dev->hard_start_xmit = de_start_xmit; dev->get_stats = de_get_stats; dev->do_ioctl = de_ioctl; dev->tx_timeout = de_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->irq = pdev->irq; de = dev->priv; de->de21040 = ent->driver_data == 0 ? 1 : 0; de->pdev = pdev; de->dev = dev; de->msg_enable = (debug < 0 ? DE_DEF_MSG_ENABLE : debug); de->board_idx = board_idx; spin_lock_init (&de->lock); init_timer(&de->media_timer); if (de->de21040) de->media_timer.function = de21040_media_timer; else de->media_timer.function = de21041_media_timer; de->media_timer.data = (unsigned long) de; netif_carrier_off(dev); netif_stop_queue(dev); /* wake up device, assign resources */ rc = pci_enable_device(pdev); if (rc) goto err_out_free; /* reserve PCI resources to ensure driver atomicity */ rc = pci_request_regions(pdev, DRV_NAME); if (rc) goto err_out_disable; /* check for invalid IRQ value */ if (pdev->irq < 2) { rc = -EIO; printk(KERN_ERR PFX "invalid irq (%d) for pci dev %s\n", pdev->irq, pdev->slot_name); goto err_out_res; } /* obtain and check validity of PCI I/O address */ pciaddr = pci_resource_start(pdev, 1); if (!pciaddr) { rc = -EIO; printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n", pdev->slot_name); goto err_out_res; } if (pci_resource_len(pdev, 1) < DE_REGS_SIZE) { rc = -EIO; printk(KERN_ERR PFX "MMIO resource (%lx) too small on pci dev %s\n", pci_resource_len(pdev, 1), pdev->slot_name); goto err_out_res; } /* remap CSR registers */ regs = ioremap_nocache(pciaddr, DE_REGS_SIZE); if (!regs) { rc = -EIO; printk(KERN_ERR PFX "Cannot map PCI MMIO (%lx@%lx) on pci dev %s\n", pci_resource_len(pdev, 1), pciaddr, pdev->slot_name); goto err_out_res; } dev->base_addr = (unsigned long) regs; de->regs = regs; de_adapter_wake(de); /* make sure hardware is not running */ rc = de_reset_mac(de); if (rc) { printk(KERN_ERR PFX "Cannot reset MAC, pci dev %s\n", pdev->slot_name); goto err_out_iomap; } /* get MAC address, initialize default media type and * get list of supported media */ if (de->de21040) { de21040_get_mac_address(de); de21040_get_media_info(de); } else { de21041_get_srom_info(de); } /* register new network interface with kernel */ rc = register_netdev(dev); if (rc) goto err_out_iomap; /* print info about board and interface just registered */ printk (KERN_INFO "%s: %s at 0x%lx, " "%02x:%02x:%02x:%02x:%02x:%02x, " "IRQ %d\n", dev->name, de->de21040 ? "21040" : "21041", dev->base_addr, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq); pci_set_drvdata(pdev, dev); /* enable busmastering */ pci_set_master(pdev); /* put adapter to sleep */ de_adapter_sleep(de); return 0;err_out_iomap: if (de->ee_data) kfree(de->ee_data); iounmap(regs);err_out_res: pci_release_regions(pdev);err_out_disable: pci_disable_device(pdev);err_out_free: kfree(dev); return rc;}static void __exit de_remove_one (struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata(pdev); struct de_private *de = dev->priv; if (!dev) BUG(); unregister_netdev(dev); if (de->ee_data) kfree(de->ee_data); iounmap(de->regs); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); kfree(dev);}#ifdef CONFIG_PMstatic int de_suspend (struct pci_dev *pdev, u32 state){ struct net_device *dev = pci_get_drvdata (pdev); struct de_private *de = dev->priv; rtnl_lock(); if (netif_running (dev)) { del_timer_sync(&de->media_timer); disable_irq(dev->irq); spin_lock_irq(&de->lock); de_stop_hw(de); netif_stop_queue(dev); netif_device_detach(dev); netif_carrier_off(dev); spin_unlock_irq(&de->lock); enable_irq(dev->irq); /* Update the error counts. */ __de_get_stats(de); synchronize_irq(); de_clean_rings(de); de_adapter_sleep(de); pci_disable_device(pdev); } else { netif_device_detach(dev); } rtnl_unlock(); return 0;}static int de_resume (struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata (pdev); struct de_private *de = dev->priv; rtnl_lock(); if (netif_device_present(dev)) goto out; if (netif_running(dev)) { pci_enable_device(pdev); de_init_hw(de); netif_device_attach(dev); } else { netif_device_attach(dev); }out: rtnl_unlock(); return 0;}#endif /* CONFIG_PM */static struct pci_driver de_driver = { name: DRV_NAME, id_table: de_pci_tbl, probe: de_init_one, remove: de_remove_one,#ifdef CONFIG_PM suspend: de_suspend, resume: de_resume,#endif};static int __init de_init (void){#ifdef MODULE printk("%s", version);#endif return pci_module_init (&de_driver);}static void __exit de_exit (void){ pci_unregister_driver (&de_driver);}module_init(de_init);module_exit(de_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -