/* * Either use the shared memory (if enabled on the board) or put the packet * out through the ASIC FIFO. */ static void el2_block_output(struct net_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); isa_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; }
static void el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) { int boguscount = 0; void __iomem *base = ei_status.mem; unsigned short int *buf; unsigned short word; /* Maybe enable shared memory just be to be safe... nahh.*/ if (base) { /* Use the shared memory. */ ring_offset -= (EL2_MB1_START_PG<<8); if (ring_offset + count > EL2_MEMSIZE) { /* We must wrap the input move. */ int semi_count = EL2_MEMSIZE - ring_offset; memcpy_fromio(skb->data, base + ring_offset, semi_count); count -= semi_count; memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count); } else { memcpy_fromio(skb->data, base + ring_offset, count); } 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; }