etherh.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 778 行 · 第 1/2 页
C
778 行
writeb (count >> 8, addr + EN0_RCNTHI); writeb (ring_offset, addr + EN0_RSARLO); writeb (ring_offset >> 8, addr + EN0_RSARHI); writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); if (ei_local->word16) { readsw (dma_addr, buf, count >> 1); if (count & 1) buf[count - 1] = readb (dma_addr); } else readsb (dma_addr, buf, count); writeb (ENISR_RDC, addr + EN0_ISR); ei_local->dmaing = 0;}/* * Read a header from the 8390 */static voidetherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page){ struct ei_device *ei_local = netdev_priv(dev); unsigned int addr, dma_addr; if (ei_local->dmaing) { printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: " " DMAstat %d irqlock %d\n", dev->name, ei_local->dmaing, ei_local->irqlock); return; } ei_local->dmaing = 1; addr = dev->base_addr; dma_addr = dev->mem_start; 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_addr, hdr, sizeof (*hdr) >> 1); else readsb (dma_addr, 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) && (s = strchr(cd.d.string, '('))) { 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; } 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 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->if_port = data->if_port; dev->flags |= data->flags; eh = etherh_priv(dev); 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; dev->mem_start = (unsigned long)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", .if_port = IF_PORT_UNKNOWN, .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", .if_port = IF_PORT_UNKNOWN, .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", .flags = IFF_PORTSEL | IFF_AUTOMEDIA, .if_port = IF_PORT_10BASET, .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", .flags = IFF_PORTSEL | IFF_AUTOMEDIA, .if_port = IF_PORT_10BASET, .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 = "etherh", },};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 + =
减小字号Ctrl + -
显示快捷键?