📄 etherh.c
字号:
writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); writeb (sizeof (*hdr), addr + EN0_RCNTLO); writeb (0, addr + EN0_RCNTHI); writeb (0, addr + EN0_RSARLO); writeb (ring_page, addr + EN0_RSARHI); writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); if (ei_local->word16) readsw (dma_base, hdr, sizeof (*hdr) >> 1); else readsb (dma_base, hdr, sizeof (*hdr)); writeb (ENISR_RDC, addr + EN0_ISR); ei_local->dmaing = 0;}/* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */static intetherh_open(struct net_device *dev){ struct ei_device *ei_local = netdev_priv(dev); if (!is_valid_ether_addr(dev->dev_addr)) { printk(KERN_WARNING "%s: invalid ethernet MAC address\n", dev->name); return -EINVAL; } if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)) return -EAGAIN; /* * Make sure that we aren't going to change the * media type on the next reset - we are about to * do automedia manually now. */ ei_local->interface_num = 0; /* * If we are doing automedia detection, do it now. * This is more reliable than the 8390's detection. */ if (dev->flags & IFF_AUTOMEDIA) { dev->if_port = IF_PORT_10BASET; etherh_setif(dev); mdelay(1); if (!etherh_getifstat(dev)) { dev->if_port = IF_PORT_10BASE2; etherh_setif(dev); } } else etherh_setif(dev); etherh_reset(dev); ei_open(dev); return 0;}/* * The inverse routine to etherh_open(). */static intetherh_close(struct net_device *dev){ ei_close (dev); free_irq (dev->irq, dev); return 0;}/* * Initialisation */static void __init etherh_banner(void){ static int version_printed; if (net_debug && version_printed++ == 0) printk(KERN_INFO "%s", version);}/* * Read the ethernet address string from the on board rom. * This is an ascii string... */static int __init etherh_addr(char *addr, struct expansion_card *ec){ struct in_chunk_dir cd; char *s; if (!ecard_readchunk(&cd, ec, 0xf5, 0)) { printk(KERN_ERR "%s: unable to read podule description string\n", ec->dev.bus_id); goto no_addr; } s = strchr(cd.d.string, '('); if (s) { int i; for (i = 0; i < 6; i++) { addr[i] = simple_strtoul(s + 1, &s, 0x10); if (*s != (i == 5? ')' : ':')) break; } if (i == 6) return 0; } printk(KERN_ERR "%s: unable to parse MAC address: %s\n", ec->dev.bus_id, cd.d.string); no_addr: return -ENODEV;}/* * Create an ethernet address from the system serial number. */static int __init etherm_addr(char *addr){ unsigned int serial; if (system_serial_low == 0 && system_serial_high == 0) return -ENODEV; serial = system_serial_low | system_serial_high; addr[0] = 0; addr[1] = 0; addr[2] = 0xa4; addr[3] = 0x10 + (serial >> 24); addr[4] = serial >> 16; addr[5] = serial >> 8; return 0;}static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info){ strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_VERSION, sizeof(info->version)); strlcpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));}static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){ cmd->supported = etherh_priv(dev)->supported; cmd->speed = SPEED_10; cmd->duplex = DUPLEX_HALF; cmd->port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC; cmd->autoneg = dev->flags & IFF_AUTOMEDIA ? AUTONEG_ENABLE : AUTONEG_DISABLE; return 0;}static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){ switch (cmd->autoneg) { case AUTONEG_ENABLE: dev->flags |= IFF_AUTOMEDIA; break; case AUTONEG_DISABLE: switch (cmd->port) { case PORT_TP: dev->if_port = IF_PORT_10BASET; break; case PORT_BNC: dev->if_port = IF_PORT_10BASE2; break; default: return -EINVAL; } dev->flags &= ~IFF_AUTOMEDIA; break; default: return -EINVAL; } etherh_setif(dev); return 0;}static struct ethtool_ops etherh_ethtool_ops = { .get_settings = etherh_get_settings, .set_settings = etherh_set_settings, .get_drvinfo = etherh_get_drvinfo,};static u32 etherh_regoffsets[16];static u32 etherm_regoffsets[16];static int __initetherh_probe(struct expansion_card *ec, const struct ecard_id *id){ const struct etherh_data *data = id->data; struct ei_device *ei_local; struct net_device *dev; struct etherh_priv *eh; int i, ret; etherh_banner(); ret = ecard_request_resources(ec); if (ret) goto out; dev = __alloc_ei_netdev(sizeof(struct etherh_priv)); if (!dev) { ret = -ENOMEM; goto release; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &ec->dev); dev->open = etherh_open; dev->stop = etherh_close; dev->set_config = etherh_set_config; dev->irq = ec->irq; dev->ethtool_ops = ðerh_ethtool_ops; if (data->supported & SUPPORTED_Autoneg) dev->flags |= IFF_AUTOMEDIA; if (data->supported & SUPPORTED_TP) { dev->flags |= IFF_PORTSEL; dev->if_port = IF_PORT_10BASET; } else if (data->supported & SUPPORTED_BNC) { dev->flags |= IFF_PORTSEL; dev->if_port = IF_PORT_10BASE2; } else dev->if_port = IF_PORT_UNKNOWN; eh = etherh_priv(dev); eh->supported = data->supported; eh->ctrl = 0; eh->id = ec->cid.product; eh->memc = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), PAGE_SIZE); if (!eh->memc) { ret = -ENOMEM; goto free; } eh->ctrl_port = eh->memc; if (data->ctrl_ioc) { eh->ioc_fast = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), PAGE_SIZE); if (!eh->ioc_fast) { ret = -ENOMEM; goto free; } eh->ctrl_port = eh->ioc_fast; } dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset; eh->dma_base = eh->memc + data->dataport_offset; eh->ctrl_port += data->ctrlport_offset; /* * IRQ and control port handling - only for non-NIC slot cards. */ if (ec->slot_no != 8) { ec->ops = ðerh_ops; ec->irq_data = eh; } else { /* * If we're in the NIC slot, make sure the IRQ is enabled */ etherh_set_ctrl(eh, ETHERH_CP_IE); } ei_local = netdev_priv(dev); spin_lock_init(&ei_local->page_lock); if (ec->cid.product == PROD_ANT_ETHERM) { etherm_addr(dev->dev_addr); ei_local->reg_offset = etherm_regoffsets; } else { etherh_addr(dev->dev_addr, ec); ei_local->reg_offset = etherh_regoffsets; } ei_local->name = dev->name; ei_local->word16 = 1; ei_local->tx_start_page = data->tx_start_page; ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES; ei_local->stop_page = data->stop_page; ei_local->reset_8390 = etherh_reset; ei_local->block_input = etherh_block_input; ei_local->block_output = etherh_block_output; ei_local->get_8390_hdr = etherh_get_header; ei_local->interface_num = 0; etherh_reset(dev); NS8390_init(dev, 0); ret = register_netdev(dev); if (ret) goto free; printk(KERN_INFO "%s: %s in slot %d, ", dev->name, data->name, ec->slot_no); for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); ecard_set_drvdata(ec, dev); return 0; free: if (eh->ioc_fast) iounmap(eh->ioc_fast); if (eh->memc) iounmap(eh->memc); free_netdev(dev); release: ecard_release_resources(ec); out: return ret;}static void __devexit etherh_remove(struct expansion_card *ec){ struct net_device *dev = ecard_get_drvdata(ec); struct etherh_priv *eh = etherh_priv(dev); ecard_set_drvdata(ec, NULL); unregister_netdev(dev); ec->ops = NULL; if (eh->ioc_fast) iounmap(eh->ioc_fast); iounmap(eh->memc); free_netdev(dev); ecard_release_resources(ec);}static struct etherh_data etherm_data = { .ns8390_offset = ETHERM_NS8390, .dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT, .ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT, .name = "ANT EtherM", .supported = SUPPORTED_10baseT_Half, .tx_start_page = ETHERM_TX_START_PAGE, .stop_page = ETHERM_STOP_PAGE,};static struct etherh_data etherlan500_data = { .ns8390_offset = ETHERH500_NS8390, .dataport_offset = ETHERH500_NS8390 + ETHERH500_DATAPORT, .ctrlport_offset = ETHERH500_CTRLPORT, .ctrl_ioc = 1, .name = "i3 EtherH 500", .supported = SUPPORTED_10baseT_Half, .tx_start_page = ETHERH_TX_START_PAGE, .stop_page = ETHERH_STOP_PAGE,};static struct etherh_data etherlan600_data = { .ns8390_offset = ETHERH600_NS8390, .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, .name = "i3 EtherH 600", .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, .tx_start_page = ETHERH_TX_START_PAGE, .stop_page = ETHERH_STOP_PAGE,};static struct etherh_data etherlan600a_data = { .ns8390_offset = ETHERH600_NS8390, .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, .name = "i3 EtherH 600A", .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, .tx_start_page = ETHERH_TX_START_PAGE, .stop_page = ETHERH_STOP_PAGE,};static const struct ecard_id etherh_ids[] = { { MANU_ANT, PROD_ANT_ETHERM, ðerm_data }, { MANU_I3, PROD_I3_ETHERLAN500, ðerlan500_data }, { MANU_I3, PROD_I3_ETHERLAN600, ðerlan600_data }, { MANU_I3, PROD_I3_ETHERLAN600A, ðerlan600a_data }, { 0xffff, 0xffff }};static struct ecard_driver etherh_driver = { .probe = etherh_probe, .remove = __devexit_p(etherh_remove), .id_table = etherh_ids, .drv = { .name = DRV_NAME, },};static int __init etherh_init(void){ int i; for (i = 0; i < 16; i++) { etherh_regoffsets[i] = i << 2; etherm_regoffsets[i] = i << 5; } return ecard_register_driver(ðerh_driver);}static void __exit etherh_exit(void){ ecard_remove_driver(ðerh_driver);}module_init(etherh_init);module_exit(etherh_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -