📄 sk_g16.c
字号:
* ENXIO - not probed * Globals : None * Update History : * YY/MM/DD uid Description-*//* * 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. * If dev->base_addr == 2, allocate space for the device and return success * (detachable devices only). */__initfunc(int SK_init(struct device *dev)){ int ioaddr = 0; /* I/O port address used for POS regs */ int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ /* get preconfigured base_addr from dev which is done in Space.c */ int base_addr = dev->base_addr; PRINTK(("%s: %s", SK_NAME, rcsid)); rcsid = NULL; /* We do not want to use this further */ if (base_addr > 0x0ff) /* Check a single specified address */ { /* Check if on specified address is a SK_G16 */ if ( (inb(SK_POS0) == SK_IDLOW) || (inb(SK_POS1) == SK_IDHIGH) ) { return SK_probe(dev, base_addr); } return ENODEV; /* Sorry, but on specified address NO SK_G16 */ } else if (base_addr > 0) /* Don't probe at all */ { return ENXIO; } /* Autoprobe base_addr */ for (port = &ports[0]; *port; port++) { ioaddr = *port; /* we need ioaddr for accessing POS regs */ /* Check if I/O Port region is used by another board */ if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE)) { continue; /* Try next Port address */ } /* Check if at ioaddr is a SK_G16 */ if ( !(inb(SK_POS0) == SK_IDLOW) || !(inb(SK_POS1) == SK_IDHIGH) ) { continue; /* Try next Port address */ } dev->base_addr = ioaddr; /* Set I/O Port Address */ if (SK_probe(dev, ioaddr) == 0) { return 0; /* Card found and initialized */ } } dev->base_addr = base_addr; /* Write back original base_addr */ return ENODEV; /* Failed to find or init driver */} /* End of SK_init *//*- * 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 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-*/__initfunc(int SK_probe(struct 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; /* SK_G16 private structure */ 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 *) 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]); /* Allocate memory for private structure */ p = dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL); if (p == NULL) { printk("%s: ERROR - no memory for driver data!\n", dev->name); return -ENOMEM; } memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */ /* Grab the I/O Port region */ request_region(ioaddr, ETHERCARD_TOTAL_SIZE,"sk_g16"); /* 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; /* Set the generic fields of the device structure */ ether_setup(dev); 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 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 device *dev){ int i = 0; int irqval = 0; int ioaddr = dev->base_addr; int irqtab[] = SK_IRQS; struct priv *p = (struct priv *)dev->priv; 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? */ { dev->tbusy = 0; dev->interrupt = 0; dev->start = 1;#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))); dev->start = 0; /* Device not ready */ 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 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 device *dev, unsigned short mode){ int i; unsigned long flags; struct priv *p = (struct priv *) dev->priv; 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(); /* Initialize TMD's with start values */ p->tmdnum = 0; /* First descriptor for transmitting */ p->tmdlast = 0; /* First descriptor for reading stats */ for (i = 0; i < TMDNUM; i++) /* Init all TMD's */ { tmdp = p->tmdhead + i; writel((unsigned long) p->tmdbufs[i], tmdp->u.buffer); /* assign buffer */ /* Mark TMD as start and end of packet */ writeb(TX_STP | TX_ENP, tmdp->u.s.status); } /* Initialize RMD's with start values */ p->rmdnum = 0; /* First RMD which will be used */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -