Exemplo n.º 1
0
/*  Block input and output are easy on shared memory ethercards.
	The E21xx makes block_input() especially easy by wrapping the top
	ring buffer to the bottom automatically. */
static void
e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
	short ioaddr = dev->base_addr;
	char __iomem *shared_mem = ei_status.mem;

	mem_on(ioaddr, shared_mem, (ring_offset>>8));

	/* Packet is always in one chunk -- we can copy + cksum. */
	eth_io_copy_and_sum(skb, ei_status.mem + (ring_offset & 0xff), count, 0);

	mem_off(ioaddr);
}
Exemplo n.º 2
0
static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
                           int ring_offset)
{
    void __iomem *xfer_start = ei_status.mem + ring_offset - ES_START_PG*256;

    if (ring_offset + count > ES_STOP_PG*256) {
        /* Packet wraps over end of ring buffer. */
        int semi_count = ES_STOP_PG*256 - ring_offset;
        memcpy_fromio(skb->data, xfer_start, semi_count);
        count -= semi_count;
        memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
    } else {
        /* Packet is in one chunk. */
        eth_io_copy_and_sum(skb, xfer_start, count, 0);
    }
}
Exemplo n.º 3
0
static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
						  int ring_offset)
{
	void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;

	if (ring_offset + count > AC_STOP_PG*256) {
		/* We must wrap the input move. */
		int semi_count = AC_STOP_PG*256 - ring_offset;
		memcpy_fromio(skb->data, start, semi_count);
		count -= semi_count;
		memcpy_fromio(skb->data + semi_count,
				ei_status.mem + TX_PAGES*256, count);
	} else {
		/* Packet is in one chunk -- we can copy + cksum. */
		eth_io_copy_and_sum(skb, start, count, 0);
	}
}
Exemplo n.º 4
0
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 {
            /* Packet is in one chunk -- we can copy + cksum. */
            eth_io_copy_and_sum(skb, base + 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;
}