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

📄 3c503.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		    && request_irq (dev->irq = *irqp, ei_interrupt, 0, ei_status.name, dev) == 0)		    break;	    }	} while (*++irqp);	if (*irqp == 0) {	    outb(EGACFR_IRQOFF, E33G_GACFR);	/* disable interrupts. */	    return -EAGAIN;	}    } else {	if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev)) {	    return -EAGAIN;	}    }    el2_init_card(dev);    ei_open(dev);    MOD_INC_USE_COUNT;    return 0;}static intel2_close(struct device *dev){    free_irq(dev->irq, dev);    dev->irq = ei_status.saved_irq;    outb(EGACFR_IRQOFF, E33G_GACFR);	/* disable interrupts. */    ei_close(dev);    MOD_DEC_USE_COUNT;    return 0;}/* This is called whenever we have a unrecoverable failure:       transmit timeout       Bad ring buffer packet header */static voidel2_reset_8390(struct device *dev){    if (ei_debug > 1) {	printk("%s: Resetting the 3c503 board...", dev->name);	printk("%#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),	       E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));    }    outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);    ei_status.txing = 0;    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);    el2_init_card(dev);    if (ei_debug > 1) printk("done\n");}/* Initialize the 3c503 GA registers after a reset. */static voidel2_init_card(struct device *dev){    /* Unmap the station PROM and select the DIX or BNC connector. */    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);    /* Set ASIC copy of rx's first and last+1 buffer pages */    /* These must be the same as in the 8390. */    outb(ei_status.rx_start_page, E33G_STARTPG);    outb(ei_status.stop_page,  E33G_STOPPG);    /* Point the vector pointer registers somewhere ?harmless?. */    outb(0xff, E33G_VP2);	/* Point at the ROM restart location 0xffff0 */    outb(0xff, E33G_VP1);    outb(0x00, E33G_VP0);    /* Turn off all interrupts until we're opened. */    outb_p(0x00,  dev->base_addr + EN0_IMR);    /* Enable IRQs iff started. */    outb(EGACFR_NORM, E33G_GACFR);    /* Set the interrupt line. */    outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR);    outb_p((WRD_COUNT << 1), E33G_DRQCNT);	/* Set burst size to 8 */    outb_p(0x20, E33G_DMAAH);	/* Put a valid addr in the GA DMA */    outb_p(0x00, E33G_DMAAL);    return;			/* We always succeed */}/* * Either use the shared memory (if enabled on the board) or put the packet * out through the ASIC FIFO. */static voidel2_block_output(struct device *dev, int count,		 const unsigned char *buf, int start_page){    unsigned short int *wrd;    int boguscount;		/* timeout counter */    unsigned short word;	/* temporary for better machine code */    if (ei_status.word16)      /* Tx packets go into bank 0 on EL2/16 card */	outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);    else	outb(EGACFR_NORM, E33G_GACFR);    if (dev->mem_start) {	/* Shared memory transfer */	unsigned long dest_addr = dev->mem_start +	    ((start_page - ei_status.tx_start_page) << 8);	memcpy_toio(dest_addr, buf, count);	outb(EGACFR_NORM, E33G_GACFR);	/* Back to bank1 in case on bank0 */	return;    }/* *  No shared memory, put the packet out the other way. *  Set up then start the internal memory transfer to Tx Start Page */    word = (unsigned short)start_page;    outb(word&0xFF, E33G_DMAAH);    outb(word>>8, E33G_DMAAL);    outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT	   | ECNTRL_START, E33G_CNTRL);/* *  Here I am going to write data to the FIFO as quickly as possible. *  Note that E33G_FIFOH is defined incorrectly. It is really *  E33G_FIFOL, the lowest port address for both the byte and *  word write. Variable 'count' is NOT checked. Caller must supply a *  valid count. Note that I may write a harmless extra byte to the *  8390 if the byte-count was not even. */    wrd = (unsigned short int *) buf;    count  = (count + 1) >> 1;    for(;;)    {        boguscount = 0x1000;        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)        {            if(!boguscount--)            {                printk("%s: FIFO blocked in el2_block_output.\n", dev->name);                el2_reset_8390(dev);                goto blocked;            }        }        if(count > WRD_COUNT)        {            outsw(E33G_FIFOH, wrd, WRD_COUNT);            wrd   += WRD_COUNT;            count -= WRD_COUNT;        }        else        {            outsw(E33G_FIFOH, wrd, count);            break;        }    }    blocked:;    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);    return;}/* Read the 4 byte, page aligned 8390 specific header. */static voidel2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page){    int boguscount;    unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8);    unsigned short word;    if (dev->mem_start) {       /* Use the shared memory. */	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));	return;    }/* *  No shared memory, use programmed I/O. */    word = (unsigned short)ring_page;    outb(word&0xFF, E33G_DMAAH);    outb(word>>8, E33G_DMAAL);    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT	   | ECNTRL_START, E33G_CNTRL);    boguscount = 0x1000;    while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)    {        if(!boguscount--)        {            printk("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);            memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr));            el2_reset_8390(dev);            goto blocked;        }    }    insw(E33G_FIFOH, hdr, (sizeof(struct e8390_pkt_hdr))>> 1);    blocked:;    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);}static voidel2_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset){    int boguscount = 0;    unsigned short int *buf;    unsigned short word;    int end_of_ring = dev->rmem_end;    /* Maybe enable shared memory just be to be safe... nahh.*/    if (dev->mem_start) {	/* Use the shared memory. */	ring_offset -= (EL2_MB1_START_PG<<8);	if (dev->mem_start + ring_offset + count > end_of_ring) {	    /* We must wrap the input move. */	    int semi_count = end_of_ring - (dev->mem_start + ring_offset);	    memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);	    count -= semi_count;	    memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);	} else {		/* Packet is in one chunk -- we can copy + cksum. */		eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);	}	return;    }/* *  No shared memory, use programmed I/O. */    word = (unsigned short) ring_offset;    outb(word>>8, E33G_DMAAH);    outb(word&0xFF, E33G_DMAAL);    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT	   | ECNTRL_START, E33G_CNTRL);/* *  Here I also try to get data as fast as possible. I am betting that I *  can read one extra byte without clobbering anything in the kernel because *  this would only occur on an odd byte-count and allocation of skb->data *  is word-aligned. Variable 'count' is NOT checked. Caller must check *  for a valid count. *  [This is currently quite safe.... but if one day the 3c503 explodes *   you know where to come looking ;)] */    buf =  (unsigned short int *) skb->data;    count =  (count + 1) >> 1;    for(;;)    {        boguscount = 0x1000;        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)        {            if(!boguscount--)            {                printk("%s: FIFO blocked in el2_block_input.\n", dev->name);                el2_reset_8390(dev);                goto blocked;            }        }        if(count > WRD_COUNT)        {            insw(E33G_FIFOH, buf, WRD_COUNT);            buf   += WRD_COUNT;            count -= WRD_COUNT;        }        else        {            insw(E33G_FIFOH, buf, count);            break;        }    }    blocked:;    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);    return;}#ifdef MODULE#define MAX_EL2_CARDS	4	/* Max number of EL2 cards per module */#define NAMELEN 	8	/* #of chars for storing dev->name */static char namelist[NAMELEN * MAX_EL2_CARDS] = { 0, };static struct device dev_el2[MAX_EL2_CARDS] = {	{		NULL,		/* assign a chunk of namelist[] below */		0, 0, 0, 0,		0, 0,		0, 0, 0, NULL, NULL	},};static int io[MAX_EL2_CARDS] = { 0, };static int irq[MAX_EL2_CARDS]  = { 0, };static int xcvr[MAX_EL2_CARDS] = { 0, };	/* choose int. or ext. xcvr */MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i");MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i");MODULE_PARM(xcvr, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i");/* This is set up so that only a single autoprobe takes place per call.ISA device autoprobes on a running machine are not recommended. */intinit_module(void){	int this_dev, found = 0;	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {		struct device *dev = &dev_el2[this_dev];		dev->name = namelist+(NAMELEN*this_dev);		dev->irq = irq[this_dev];		dev->base_addr = io[this_dev];		dev->mem_end = xcvr[this_dev];	/* low 4bits = xcvr sel. */		dev->init = el2_probe;		if (io[this_dev] == 0)  {			if (this_dev != 0) break; /* only autoprobe 1st one */			printk(KERN_NOTICE "3c503.c: Presently autoprobing (not recommended) for a single card.\n");		}		if (register_netdev(dev) != 0) {			printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);			if (found != 0) {	/* Got at least one. */				lock_8390_module();				return 0;			}			return -ENXIO;		}		found++;	}	lock_8390_module();	return 0;}voidcleanup_module(void){	int this_dev;	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {		struct device *dev = &dev_el2[this_dev];		if (dev->priv != NULL) {			void *priv = dev->priv;			/* NB: el2_close() handles free_irq */			release_region(dev->base_addr, EL2_IO_EXTENT);			unregister_netdev(dev);			kfree(priv);		}	}	unlock_8390_module();}#endif /* MODULE *//* * Local variables: *  version-control: t *  kept-new-versions: 5 *  c-indent-level: 4 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -