// SPDX-License-Identifier: GPL-1.0+ /* smc-ultra.c: A SMC Ultra ethernet driver for linux. */ /* This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
Written 1993-1998 by Donald Becker.
Copyright 1993 United States Government as represented by the Director, National Security Agency.
The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 Annapolis MD 21403
This driver uses the cards in the 8390-compatible mode. Most of the run-time complexity is handled by the generic code in 8390.c. The code in this file is responsible for
ultra_probe() Detecting and initializing the card. ultra_probe1() ultra_probe_isapnp()
ultra_open() The card-specific details of starting, stopping ultra_reset_8390() and resetting the 8390 NIC core. ultra_close()
ultra_block_input() Routines for reading and writing blocks of ultra_block_output() packet buffer memory. ultra_pio_input() ultra_pio_output()
This driver enables the shared memory only when doing the actual data transfers to avoid a bug in early version of the card that corrupted data transferred by a AHA1542.
This driver now supports the programmed-I/O (PIO) data transfer mode of the EtherEZ. It does not use the non-8390-compatible "Altego" mode. That support (if available) is in smc-ez.c.
Changelog:
Paul Gortmaker : multiple card support for module users. Donald Becker : 4/17/96 PIO support, minor potential problems avoided. Donald Becker : 6/6/96 correctly set auto-wrap bit. Alexander Sotirov : 1/20/01 Added support for ISAPnP cards
Note about the ISA PnP support:
This driver can not autoprobe for more than one SMC EtherEZ PnP card. You have to configure the second card manually through the /proc/isapnp interface and then load the module with an explicit io=0x___ option.
*/
staticconstchar version[] = "smc-ultra.c:v2.02 2/3/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
/* A zero-terminated list of I/O addresses to be probed. */ staticunsignedint ultra_portlist[] __initdata =
{0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
staticint ultra_probe1(struct net_device *dev, int ioaddr);
#define START_PG 0x00 /* First page of TX buffer */
#define ULTRA_CMDREG 0 /* Offset to ASIC command register. */ #define ULTRA_RESET 0x80 /* Board reset, in ULTRA_CMDREG. */ #define ULTRA_MEMENB 0x40 /* Enable the shared memory. */ #define IOPD 0x02 /* I/O Pipe Data (16 bits), PIO operation. */ #define IOPA 0x07 /* I/O Pipe Address for PIO operation. */ #define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */ #define ULTRA_IO_EXTENT 32 #define EN0_ERWCNT 0x08 /* Early receive warning count. */
#ifdef CONFIG_NET_POLL_CONTROLLER staticvoid ultra_poll(struct net_device *dev)
{
disable_irq(dev->irq);
ei_interrupt(dev->irq, dev);
enable_irq(dev->irq);
} #endif /* Probe for the Ultra. This looks like a 8013 with the station address PROM at I/O ports <base>+8 to <base>+13, with a checksum following.
*/
staticint __init do_ultra_probe(struct net_device *dev)
{ int i; int base_addr = dev->base_addr; int irq = dev->irq;
if (base_addr > 0x1ff) /* Check a single specified location. */ return ultra_probe1(dev, base_addr); elseif (base_addr != 0) /* Don't probe at all. */ return -ENXIO;
#ifdef __ISAPNP__ /* Look for any installed ISAPnP cards */ if (isapnp_present() && (ultra_probe_isapnp(dev) == 0)) return 0; #endif
for (i = 0; ultra_portlist[i]; i++) {
dev->irq = irq; if (ultra_probe1(dev, ultra_portlist[i]) == 0) return 0;
}
outb(0x00, cmd_port); /* Disable shared memory for safety. */
outb(0x80, cmd_port + 5); if (ei_status.block_input == &ultra_pio_input)
outb(0x11, cmd_port + 6); /* Enable interrupts and PIO. */ else
outb(0x01, cmd_port + 6); /* Enable interrupts and memory. */
netif_dbg(ei_local, hw, dev, "reset done\n");
}
/* Grab the 8390 specific header. Similar to the block_input routine, but we don't need to be concerned with ring wrap as the header will be at
the start of a page, so we optimize accordingly. */
outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem on */ #ifdef __BIG_ENDIAN /* Officially this is what we are doing, but the readl() is faster */ /* unfortunately it isn't endian aware of the struct */
memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
hdr->count = le16_to_cpu(hdr->count); #else
((unsignedint*)hdr)[0] = readl(hdr_start); #endif
outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
}
/* Block input and output are easy on shared memory ethercards, the only
complication is when the ring buffer wraps. */
/* The identical operations for programmed I/O cards. The PIO model is trivial to use: the 16 bit start address is written byte-sequentially to IOPA, with no intervening I/O operations, and the data is read or written to the IOPD data port. The only potential complication is that the address register is shared and must be always be rewritten between each read/write direction change. This is no problem for us, as the 8390 code ensures that we are single
threaded. */ staticvoid ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{ int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
outb(0x00, ioaddr + IOPA); /* Set the address, LSB first. */
outb(ring_page, ioaddr + IOPA);
insw(ioaddr + IOPD, hdr, sizeof(struct e8390_pkt_hdr)>>1);
}
staticvoid ultra_pio_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{ int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ char *buf = skb->data;
/* For now set the address again, although it should already be correct. */
outb(ring_offset, ioaddr + IOPA); /* Set the address, LSB first. */
outb(ring_offset >> 8, ioaddr + IOPA); /* We know skbuffs are padded to at least word alignment. */
insw(ioaddr + IOPD, buf, (count+1)>>1);
} staticvoid ultra_pio_output(struct net_device *dev, int count, constunsignedchar *buf, constint start_page)
{ int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
outb(0x00, ioaddr + IOPA); /* Set the address, LSB first. */
outb(start_page, ioaddr + IOPA); /* An extra odd byte is OK here as well. */
outsw(ioaddr + IOPD, buf, (count+1)>>1);
}
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */ staticint __init ultra_init_module(void)
{ struct net_device *dev; int this_dev, found = 0;
for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { if (io[this_dev] == 0) { if (this_dev != 0) break; /* only autoprobe 1st one */
printk(KERN_NOTICE "smc-ultra.c: Presently autoprobing (not recommended) for a single card.\n");
}
dev = alloc_ei_netdev(); if (!dev) break;
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev]; if (do_ultra_probe(dev) == 0) {
dev_ultra[found++] = dev; continue;
}
free_netdev(dev);
printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); break;
} if (found) return 0; return -ENXIO;
}
module_init(ultra_init_module);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.