⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sk_g16.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
 *                  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 + -