📄 3c503.c
字号:
&& 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 + -