patch-2.1.105 linux/drivers/net/ac3200.c
Next file: linux/drivers/net/arcnet.c
Previous file: linux/drivers/net/Space.c
Back to the patch index
Back to the overall index
- Lines: 254
- Date:
Sun Jun 7 10:37:41 1998
- Orig file:
v2.1.104/linux/drivers/net/ac3200.c
- Orig date:
Mon Feb 23 18:12:05 1998
diff -u --recursive --new-file v2.1.104/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
@@ -7,11 +7,16 @@
incorporated herein by reference.
The author may be reached as becker@cesdis.gsfc.nasa.gov, or
- C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+ C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
Adapter. The programming information is from the users manual, as related
by glee@ardnassak.math.clemson.edu.
+
+ Changelog:
+
+ Paul Gortmaker 05/98 : add support for shared mem above 1MB.
+
*/
static const char *version =
@@ -29,23 +34,24 @@
#include <asm/system.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include "8390.h"
/* Offsets from the base address. */
-#define AC_NIC_BASE 0x00
-#define AC_SA_PROM 0x16 /* The station address PROM. */
-#define AC_ADDR0 0x00 /* Prefix station address values. */
-#define AC_ADDR1 0x40 /* !!!!These are just guesses!!!! */
-#define AC_ADDR2 0x90
-#define AC_ID_PORT 0xC80
-#define AC_EISA_ID 0x0110d305
+#define AC_NIC_BASE 0x00
+#define AC_SA_PROM 0x16 /* The station address PROM. */
+#define AC_ADDR0 0x00 /* Prefix station address values. */
+#define AC_ADDR1 0x40
+#define AC_ADDR2 0x90
+#define AC_ID_PORT 0xC80
+#define AC_EISA_ID 0x0110d305
#define AC_RESET_PORT 0xC84
-#define AC_RESET 0x00
-#define AC_ENABLE 0x01
-#define AC_CONFIG 0xC90 /* The configuration port. */
+#define AC_RESET 0x00
+#define AC_ENABLE 0x01
+#define AC_CONFIG 0xC90 /* The configuration port. */
-#define AC_IO_EXTENT 0x10 /* IS THIS REALLY TRUE ??? */
+#define AC_IO_EXTENT 0x20
/* Actually accessed is:
* AC_NIC_BASE (0-15)
* AC_SA_PROM (0-5)
@@ -98,7 +104,6 @@
else if (ioaddr > 0) /* Don't probe at all. */
return ENXIO;
- /* If you have a pre 0.99pl15 machine you should delete this line. */
if ( ! EISA_bus)
return ENXIO;
@@ -116,32 +121,19 @@
{
int i;
-#ifndef final_version
- printk("AC3200 ethercard probe at %#3x:", ioaddr);
+ if (inb_p(ioaddr + AC_ID_PORT) == 0xff)
+ return -ENODEV;
+
+ if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID)
+ return -ENODEV;
- for(i = 0; i < 6; i++)
- printk(" %02x", inb(ioaddr + AC_SA_PROM + i));
-#endif
- /* !!!!The values of AC_ADDRn (see above) should be corrected when we
- find out the correct station address prefix!!!! */
- if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
- || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
- || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
#ifndef final_version
- printk(" not found (invalid prefix).\n");
+ printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
+ " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
+ inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
+ inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
#endif
- return ENODEV;
- }
-
- /* The correct probe method is to check the EISA ID. */
- for (i = 0; i < 4; i++)
- if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
- printk("EISA ID mismatch, %8x vs %8x.\n",
- inl(ioaddr + AC_ID_PORT), AC_EISA_ID);
- return ENODEV;
- }
-
/* We should have a "dev" from Space.c or the static module table. */
if (dev == NULL) {
@@ -149,33 +141,43 @@
dev = init_etherdev(0, 0);
}
- for(i = 0; i < ETHER_ADDR_LEN; i++)
- dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
+ printk("AC3200 in EISA slot %d, node", ioaddr/0x1000);
+ for(i = 0; i < 6; i++)
+ printk(" %02x", dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i));
-#ifndef final_version
- printk("\nAC3200 ethercard configuration register is %#02x,"
- " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
- inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
- inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
+#if 0
+ /* Check the vendor ID/prefix. Redundant after checking the EISA ID */
+ if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
+ || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
+ || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
+ printk(", not found (invalid prefix).\n");
+ return ENODEV;
+ }
#endif
+ /* Allocate dev->priv and fill in 8390 specific dev fields. */
+ if (ethdev_init(dev)) {
+ printk (", unable to allocate memory for dev->priv.\n");
+ return -ENOMEM;
+ }
+
/* Assign and allocate the interrupt now. */
- if (dev->irq == 0)
+ if (dev->irq == 0) {
dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
- else if (dev->irq == 2)
- dev->irq = 9;
+ printk(", using");
+ } else {
+ dev->irq = irq_cannonicalize(dev->irq);
+ printk(", assigning");
+ }
if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", dev)) {
- printk (" unable to get IRQ %d.\n", dev->irq);
+ printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
+ kfree(dev->priv);
+ dev->priv = NULL;
return EAGAIN;
}
- /* Allocate dev->priv and fill in 8390 specific dev fields. */
- if (ethdev_init(dev)) {
- printk (" unable to allocate memory for dev->priv.\n");
- free_irq(dev->irq, dev);
- return -ENOMEM;
- }
+ printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
request_region(ioaddr, AC_IO_EXTENT, "ac3200");
@@ -194,6 +196,39 @@
dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
+
+ printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
+ dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
+
+ /*
+ * BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+ * the card mem within the region covered by `normal' RAM !!!
+ */
+ if (dev->mem_start > 1024*1024) { /* phys addr > 1MB */
+ if (dev->mem_start < (unsigned long)high_memory) {
+ printk(KERN_CRIT "ac3200.c: Card RAM overlaps with normal memory!!!\n");
+ printk(KERN_CRIT "ac3200.c: Use EISA SCU to set card memory below 1MB,\n");
+ printk(KERN_CRIT "ac3200.c: or to an address above %p.\n", high_memory);
+ printk(KERN_CRIT "ac3200.c: Driver NOT installed.\n");
+ free_irq(dev->irq, dev);
+ kfree(dev->priv);
+ dev->priv = NULL;
+ return EINVAL;
+ }
+ dev->mem_start = (unsigned long)ioremap(dev->mem_start, AC_STOP_PG*0x100);
+ if (dev->mem_start == 0) {
+ printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
+ printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
+ printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
+ free_irq(dev->irq, dev);
+ kfree(dev->priv);
+ dev->priv = NULL;
+ return EAGAIN;
+ }
+ printk("ac3200.c: remapped %dkB card memory to virtual address %#lx\n",
+ AC_STOP_PG/4, dev->mem_start);
+ }
+
dev->rmem_start = dev->mem_start + TX_PAGES*256;
dev->mem_end = dev->rmem_end = dev->mem_start
+ (AC_STOP_PG - AC_START_PG)*256;
@@ -204,10 +239,6 @@
ei_status.stop_page = AC_STOP_PG;
ei_status.word16 = 1;
- printk("\n%s: AC3200 at %#x, IRQ %d, %s port, shared memory %#lx-%#lx.\n",
- dev->name, ioaddr, dev->irq, port_name[dev->if_port],
- dev->mem_start, dev->mem_end-1);
-
if (ei_debug > 0)
printk(version);
@@ -349,12 +380,15 @@
if (io[this_dev] == 0 && this_dev != 0) break;
if (register_netdev(dev) != 0) {
printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
- if (found != 0) return 0; /* Got at least one. */
+ if (found != 0) { /* Got at least one. */
+ lock_8390_module();
+ return 0;
+ }
return -ENXIO;
}
found++;
}
-
+ lock_8390_module();
return 0;
}
@@ -366,14 +400,16 @@
for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
struct device *dev = &dev_ac32[this_dev];
if (dev->priv != NULL) {
- unregister_netdev(dev);
- kfree(dev->priv);
- dev->priv = NULL;
+ void *priv = dev->priv;
/* Someday free_irq may be in ac_close_card() */
free_irq(dev->irq, dev);
release_region(dev->base_addr, AC_IO_EXTENT);
+ dev->priv = NULL;
+ unregister_netdev(dev);
+ kfree(priv);
}
}
+ unlock_8390_module();
}
#endif /* MODULE */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov