📄 de2104x.c
字号:
return 0;}static int de_nway_reset(struct net_device *dev){ struct de_private *de = dev->priv; u32 status; if (de->media_type != DE_MEDIA_TP_AUTO) return -EINVAL; if (netif_carrier_ok(de->dev)) de_link_down(de); status = dr32(SIAStatus); dw32(SIAStatus, (status & ~NWayState) | NWayRestart); if (netif_msg_link(de)) printk(KERN_INFO "%s: link nway restart, status %x,%x\n", de->dev->name, status, dr32(SIAStatus)); return 0;}static void de_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *data){ struct de_private *de = dev->priv; regs->version = (DE_REGS_VER << 2) | de->de21040; spin_lock_irq(&de->lock); __de_get_regs(de, data); spin_unlock_irq(&de->lock);}static struct ethtool_ops de_ethtool_ops = { .get_link = ethtool_op_get_link, .get_tx_csum = ethtool_op_get_tx_csum, .get_sg = ethtool_op_get_sg, .get_drvinfo = de_get_drvinfo, .get_regs_len = de_get_regs_len, .get_settings = de_get_settings, .set_settings = de_set_settings, .get_msglevel = de_get_msglevel, .set_msglevel = de_set_msglevel, .get_eeprom = de_get_eeprom, .nway_reset = de_nway_reset, .get_regs = de_get_regs,};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; udelay(1); 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 __iomem *regs, int location, int addr_len){ int i; unsigned retval = 0; void __iomem *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) */#ifndef CONFIG_MIPS_COBALT for (i = 0; i < 8; i ++) if (ee_data[i] != ee_data[16+i]) sa_offset = 20;#endif /* 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 __iomem *regs; unsigned 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); SET_NETDEV_DEV(dev, &pdev->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->ethtool_ops = &de_ethtool_ops; dev->tx_timeout = de_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; 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, pci_name(pdev)); goto err_out_res; } dev->irq = pdev->irq; /* 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", pci_name(pdev)); 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), pci_name(pdev)); 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, pci_name(pdev)); 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", pci_name(pdev)); 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: kfree(de->ee_data); iounmap(regs);err_out_res: pci_release_regions(pdev);err_out_disable: pci_disable_device(pdev);err_out_free: free_netdev(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); kfree(de->ee_data); iounmap(de->regs); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev);}#ifdef CONFIG_PMstatic int de_suspend (struct pci_dev *pdev, pm_message_t 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(dev->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 = __exit_p(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 + -