sk_g16.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,067 行 · 第 1/4 页
C
2,067 行
* all Network devices. * * Parameters : I : struct net_device *dev - structure preconfigured * from Space.c * Return Value : 0 = Driver Found and initialized * Errors : ENODEV - no device found * ENXIO - not probed * Globals : None * Update History : * YY/MM/DD uid Description-*/static int io; /* 0 == probe *//* * Check for a network adaptor of this type, and return '0' if one exists. * If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 1, always return failure. */struct net_device * __init SK_init(int unit){ int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ static unsigned version_printed; struct net_device *dev = alloc_etherdev(sizeof(struct priv)); int err = -ENODEV; if (!dev) return ERR_PTR(-ENOMEM); if (unit >= 0) { sprintf(dev->name, "eth%d", unit); netdev_boot_setup_check(dev); io = dev->base_addr; } if (version_printed++ == 0) PRINTK(("%s: %s", SK_NAME, rcsid)); if (io > 0xff) { /* Check a single specified address */ err = -EBUSY; /* Check if on specified address is a SK_G16 */ if (request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) { err = SK_probe(dev, io); if (!err) goto got_it; release_region(io, ETHERCARD_TOTAL_SIZE); } } else if (io > 0) { /* Don't probe at all */ err = -ENXIO; } else { /* Autoprobe base_addr */ for (port = &ports[0]; *port; port++) { io = *port; /* Check if I/O Port region is used by another board */ if (!request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) continue; /* Try next Port address */ /* Check if at ioaddr is a SK_G16 */ if (SK_probe(dev, io) == 0) goto got_it; release_region(io, ETHERCARD_TOTAL_SIZE); } }err_out: free_netdev(dev); return ERR_PTR(err);got_it: err = register_netdev(dev); if (err) { release_region(dev->base_addr, ETHERCARD_TOTAL_SIZE); goto err_out; } return dev;} /* End of SK_init */MODULE_AUTHOR("Patrick J.D. Weichmann");MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver");MODULE_LICENSE("GPL");MODULE_PARM(io, "i");MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board");#ifdef MODULEstatic struct net_device *SK_dev;static int __init SK_init_module (void){ SK_dev = SK_init(-1); return IS_ERR(SK_dev) ? PTR_ERR(SK_dev) : 0;}static void __exit SK_cleanup_module (void){ unregister_netdev(SK_dev); release_region(SK_dev->base_addr, ETHERCARD_TOTAL_SIZE); free_netdev(SK_dev);}module_init(SK_init_module);module_exit(SK_cleanup_module);#endif/*- * Function : SK_probe * Author : Patrick J.D. Weichmann * Date Created : 94/05/26 * * Description : This function is called by SK_init and * does the main part of initialization. * * Parameters : I : struct net_device *dev - SK_G16 device structure * I : short ioaddr - I/O Port address where POS is. * Return Value : 0 = Initialization done * Errors : ENODEV - No SK_G16 found * -1 - Configuration problem * Globals : board - pointer to SK_RAM * Update History : * YY/MM/DD uid Description * 94/06/30 pwe SK_ADDR now checked and at the correct place-*/int __init SK_probe(struct net_device *dev, short ioaddr){ int i,j; /* Counters */ int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */ unsigned int rom_addr; /* used to store RAM address used for POS_ADDR */ struct priv *p = netdev_priv(dev); /* SK_G16 private structure */ if (inb(SK_POS0) != SK_IDLOW || inb(SK_POS1) != SK_IDHIGH) return -ENODEV; dev->base_addr = ioaddr; if (SK_ADDR & 0x3fff || SK_ADDR < 0xa0000) { sk_addr_flag = 1; /* * Now here we could use a routine which searches for a free * place in the ram and set SK_ADDR if found. TODO. */ } if (SK_BOOT_ROM) /* Shall we keep Boot_ROM on ? */ { PRINTK(("## %s: SK_BOOT_ROM is set.\n", SK_NAME)); rom_addr = SK_rom_addr(); if (rom_addr == 0) /* No Boot_ROM found */ { if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ { printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", dev->name, SK_ADDR); return -1; } rom_addr = SK_ADDR; /* assign predefined address */ PRINTK(("## %s: NO Bootrom found \n", SK_NAME)); outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ outb(POS_ADDR, SK_POS3); /* Set RAM address */ outb(SK_RAM_ON, SK_POS2); /* enable RAM */ } else if (rom_addr == SK_ADDR) { printk("%s: RAM + ROM are set to the same address %#08x\n" " Check configuration. Now switching off Boot_ROM\n", SK_NAME, rom_addr); outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off*/ outb(POS_ADDR, SK_POS3); /* Set RAM address */ outb(SK_RAM_ON, SK_POS2); /* enable RAM */ } else { PRINTK(("## %s: Found ROM at %#08x\n", SK_NAME, rom_addr)); PRINTK(("## %s: Keeping Boot_ROM on\n", SK_NAME)); if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ { printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", dev->name, SK_ADDR); return -1; } rom_addr = SK_ADDR; outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ outb(POS_ADDR, SK_POS3); /* Set RAM address */ outb(SK_ROM_RAM_ON, SK_POS2); /* RAM on, BOOT_ROM on */ } } else /* Don't keep Boot_ROM */ { PRINTK(("## %s: SK_BOOT_ROM is not set.\n", SK_NAME)); if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ { printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", dev->name, SK_ADDR); return -1; } rom_addr = SK_rom_addr(); /* Try to find a Boot_ROM */ /* IF we find a Boot_ROM disable it */ outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ /* We found a Boot_ROM and it's gone. Set RAM address on * Boot_ROM address. */ if (rom_addr) { printk("%s: We found Boot_ROM at %#08x. Now setting RAM on" "that address\n", SK_NAME, rom_addr); outb(POS_ADDR, SK_POS3); /* Set RAM on Boot_ROM address */ } else /* We did not find a Boot_ROM, use predefined SK_ADDR for ram */ { if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ { printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", dev->name, SK_ADDR); return -1; } rom_addr = SK_ADDR; outb(POS_ADDR, SK_POS3); /* Set RAM address */ } outb(SK_RAM_ON, SK_POS2); /* enable RAM */ }#ifdef SK_DEBUG SK_print_pos(dev, "POS registers after ROM, RAM config");#endif board = (SK_RAM *) isa_bus_to_virt(rom_addr); /* Read in station address */ for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2) { dev->dev_addr[i] = readb(board->rom+j); } /* Check for manufacturer code */ if (!(dev->dev_addr[0] == SK_MAC0 && dev->dev_addr[1] == SK_MAC1 && dev->dev_addr[2] == SK_MAC2) ) { PRINTK(("## %s: We did not find SK_G16 at RAM location.\n", SK_NAME)); return -ENODEV; /* NO SK_G16 found */ } printk("%s: %s found at %#3x, HW addr: %#04x:%02x:%02x:%02x:%02x:%02x\n", dev->name, "Schneider & Koch Netcard", (unsigned int) 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]); memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */ /* Assign our Device Driver functions */ dev->open = SK_open; dev->stop = SK_close; dev->hard_start_xmit = SK_send_packet; dev->get_stats = SK_get_stats; dev->set_multicast_list = set_multicast_list; dev->tx_timeout = SK_timeout; dev->watchdog_timeo = HZ/7; dev->flags &= ~IFF_MULTICAST; /* Initialize private structure */ p->ram = (struct SK_ram *) rom_addr; /* Set dual ported RAM addr */ p->tmdhead = &(p->ram)->tmde[0]; /* Set TMD head */ p->rmdhead = &(p->ram)->rmde[0]; /* Set RMD head */ /* Initialize buffer pointers */ for (i = 0; i < TMDNUM; i++) { p->tmdbufs[i] = &(p->ram)->tmdbuf[i]; } for (i = 0; i < RMDNUM; i++) { p->rmdbufs[i] = &(p->ram)->rmdbuf[i]; }#ifdef SK_DEBUG SK_print_pos(dev, "End of SK_probe"); SK_print_ram(dev);#endif return 0; /* Initialization done */} /* End of SK_probe() *//*- * Function : SK_open * Author : Patrick J.D. Weichmann * Date Created : 94/05/26 * * Description : This function is called sometimes after booting * when ifconfig program is run. * * This function requests an IRQ, sets the correct * IRQ in the card. Then calls SK_lance_init() to * init and start the LANCE chip. Then if everything is * ok returns with 0 (OK), which means SK_G16 is now * opened and operational. * * (Called by dev_open() /net/inet/dev.c) * * Parameters : I : struct net_device *dev - SK_G16 device structure * Return Value : 0 - Device opened * Errors : -EAGAIN - Open failed * Side Effects : None * Update History : * YY/MM/DD uid Description-*/static int SK_open(struct net_device *dev){ int i = 0; int irqval = 0; int ioaddr = dev->base_addr; int irqtab[] = SK_IRQS; struct priv *p = netdev_priv(dev); PRINTK(("## %s: At beginning of SK_open(). CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); if (dev->irq == 0) /* Autoirq */ { i = 0; /* * Check if one IRQ out of SK_IRQS is free and install * interrupt handler. * Most done by request_irq(). * irqval: 0 - interrupt handler installed for IRQ irqtab[i] * -EBUSY - interrupt busy * -EINVAL - irq > 15 or handler = NULL */ do { irqval = request_irq(irqtab[i], &SK_interrupt, 0, "sk_g16", dev); i++; } while (irqval && irqtab[i]); if (irqval) /* We tried every possible IRQ but no success */ { printk("%s: unable to get an IRQ\n", dev->name); return -EAGAIN; } dev->irq = irqtab[--i]; outb(i<<2, SK_POS4); /* Set Card on probed IRQ */ } else if (dev->irq == 2) /* IRQ2 is always IRQ9 */ { if (request_irq(9, &SK_interrupt, 0, "sk_g16", dev)) { printk("%s: unable to get IRQ 9\n", dev->name); return -EAGAIN; } dev->irq = 9; /* * Now we set card on IRQ2. * This can be confusing, but remember that IRQ2 on the network * card is in reality IRQ9 */ outb(0x08, SK_POS4); /* set card to IRQ2 */ } else /* Check IRQ as defined in Space.c */ { int i = 0; /* check if IRQ free and valid. Then install Interrupt handler */ if (request_irq(dev->irq, &SK_interrupt, 0, "sk_g16", dev)) { printk("%s: unable to get selected IRQ\n", dev->name); return -EAGAIN; } switch(dev->irq) { case 3: i = 0; break; case 5: i = 1; break; case 2: i = 2; break; case 11:i = 3; break; default: printk("%s: Preselected IRQ %d is invalid for %s boards", dev->name, dev->irq, SK_NAME); return -EAGAIN; } outb(i<<2, SK_POS4); /* Set IRQ on card */ } printk("%s: Schneider & Koch G16 at %#3x, IRQ %d, shared mem at %#08x\n", dev->name, (unsigned int)dev->base_addr, (int) dev->irq, (unsigned int) p->ram); if (!(i = SK_lance_init(dev, 0))) /* LANCE init OK? */ { netif_start_queue(dev);#ifdef SK_DEBUG /* * This debug block tries to stop LANCE, * reinit LANCE with transmitter and receiver disabled, * then stop again and reinit with NORMAL_MODE */ printk("## %s: After lance init. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0)); SK_write_reg(CSR0, CSR0_STOP); printk("## %s: LANCE stopped. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0)); SK_lance_init(dev, MODE_DTX | MODE_DRX); printk("## %s: Reinit with DTX + DRX off. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0)); SK_write_reg(CSR0, CSR0_STOP); printk("## %s: LANCE stopped. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0)); SK_lance_init(dev, MODE_NORMAL); printk("## %s: LANCE back to normal mode. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0)); SK_print_pos(dev, "POS regs before returning OK");#endif /* SK_DEBUG */ return 0; /* SK_open() is successful */ } else /* LANCE init failed */ { PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); return -EAGAIN; }} /* End of SK_open() *//*- * Function : SK_lance_init * Author : Patrick J.D. Weichmann * Date Created : 94/05/26 * * Description : Reset LANCE chip, fill RMD, TMD structures with * start values and Start LANCE. * * Parameters : I : struct net_device *dev - SK_G16 device structure * I : int mode - put LANCE into "mode" see data-sheet for * more info. * Return Value : 0 - Init done * Errors : -1 - Init failed * Update History : * YY/MM/DD uid Description-*/static int SK_lance_init(struct net_device *dev, unsigned short mode){ int i; unsigned long flags; struct priv *p = netdev_priv(dev); struct tmd *tmdp; struct rmd *rmdp; PRINTK(("## %s: At beginning of LANCE init. CSR0: %#06x\n", SK_NAME, SK_read_reg(CSR0))); /* Reset LANCE */ SK_reset_board();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?