diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
commit | 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch) | |
tree | 2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /drivers/net/sb1000.c | |
parent | 216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff) |
Merge with Linux 2.3.32.
Diffstat (limited to 'drivers/net/sb1000.c')
-rw-r--r-- | drivers/net/sb1000.c | 252 |
1 files changed, 113 insertions, 139 deletions
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index b0d8a9ad4..ad425f91b 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -56,8 +56,10 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n"; #include <asm/io.h> #include <asm/uaccess.h> #include <linux/etherdevice.h> +#include <linux/isapnp.h> /* for SIOGCM/SIOSCM stuff */ + #include <linux/if_cablemodem.h> #ifdef SB1000_DEBUG @@ -93,8 +95,6 @@ static void sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct enet_statistics *sb1000_stats(struct net_device *dev); static int sb1000_close(struct net_device *dev); -/* Plug-n-Play routine */ -static inline unsigned char read_resource_data(void); /* SB1000 hardware routines to be used during open/configuration phases */ static inline void nicedelay(unsigned long usecs); @@ -138,160 +138,132 @@ static inline int sb1000_set_PIDs(const int ioaddr[], const char* name, static inline int sb1000_rx(struct net_device *dev); static inline void sb1000_error_dpc(struct net_device *dev); - -/* Plug-n-Play constants */ -static const int READ_DATA_PORT = 0x203; /* This port number may change!!! */ -static const int ADDRESS_PORT = 0x279; -static const int WRITE_DATA_PORT = 0xa79; - -/* Plug-n-Play read resource mechanism */ -static inline unsigned char -read_resource_data(void) { - /* poll */ - outb(0x05, ADDRESS_PORT); /* Select PnP status register. */ - while (!(inb(READ_DATA_PORT) & 0x1)) ; - /* read resource data */ - outb(0x04, ADDRESS_PORT); /* Select PnP resource data register. */ - return inb(READ_DATA_PORT); -} - /* probe for SB1000 using Plug-n-Play mechanism */ int sb1000_probe(struct net_device *dev) { unsigned short ioaddr[2], irq; - short i, csn; + struct pci_dev *idev=NULL; unsigned int serial_number; + + while(1) + { + /* + * Find the card + */ + + idev=isapnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'), + ISAPNP_FUNCTION(0x1000), idev); + + /* + * No card + */ + + if(idev==NULL) + return -ENODEV; + + /* + * Bring it online + */ + + idev->prepare(idev); + idev->activate(idev); + + /* + * Ports free ? + */ + + if(!idev->resource[0].start || check_region(idev->resource[0].start, 16)) + continue; + if(!idev->resource[1].start || check_region(idev->resource[1].start, 16)) + continue; + + serial_number = idev->bus->serial; + + ioaddr[0]=idev->resource[0].start; + ioaddr[1]=idev->resource[1].start; + + irq = idev->irq; + + /* check I/O base and IRQ */ + if (dev->base_addr != 0 && dev->base_addr != ioaddr[0]) + continue; + if (dev->rmem_end != 0 && dev->rmem_end != ioaddr[1]) + continue; + if (dev->irq != 0 && dev->irq != irq) + continue; + + /* + * Ok set it up. + */ + + + dev->base_addr = ioaddr[0]; + /* rmem_end holds the second I/O address - fv */ + dev->rmem_end = ioaddr[1]; + dev->irq = irq; + + if (sb1000_debug > 0) + printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), " + "S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr, + dev->rmem_end, serial_number, dev->irq); + + dev = init_etherdev(dev, 0); + + /* Make up a SB1000-specific-data structure. */ + dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct sb1000_private)); + + if (sb1000_debug > 0) + printk(KERN_NOTICE "%s", version); + + /* The SB1000-specific entries in the device structure. */ + dev->open = sb1000_open; + dev->do_ioctl = sb1000_dev_ioctl; + dev->hard_start_xmit = sb1000_start_xmit; + dev->stop = sb1000_close; + dev->get_stats = sb1000_stats; + + /* Fill in the generic fields of the device structure. */ + dev->change_mtu = NULL; + dev->hard_header = NULL; + dev->rebuild_header = NULL; + dev->set_mac_address = NULL; + dev->header_cache_update= NULL; + + dev->type = ARPHRD_ETHER; + dev->hard_header_len = 0; + dev->mtu = 1500; + dev->addr_len = ETH_ALEN; + /* hardware address is 0:0:serial_number */ + dev->dev_addr[0] = 0; + dev->dev_addr[1] = 0; + dev->dev_addr[2] = serial_number >> 24 & 0xff; + dev->dev_addr[3] = serial_number >> 16 & 0xff; + dev->dev_addr[4] = serial_number >> 8 & 0xff; + dev->dev_addr[5] = serial_number >> 0 & 0xff; + dev->tx_queue_len = 0; + + /* New-style flags. */ + dev->flags = IFF_POINTOPOINT|IFF_NOARP; - const unsigned char initiation_key[] = { 0x00, 0x00, 0x6a, 0xb5, 0xda, - 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, - 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, - 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 }; - const unsigned char sb1000_vendor_ID[] = { - 0x1d, 0x23, 0x10, 0x00 }; /* "GIC1000" */ - - /* Reset the ISA PnP mechanism */ - outb(0x02, ADDRESS_PORT); /* Select PnP config control register. */ - outb(0x02, WRITE_DATA_PORT); /* Return to WaitForKey state. */ - - /* send initiation key */ - for (i = 0; i < sizeof(initiation_key) / sizeof(initiation_key[0]); i++) { - outb(initiation_key[i], ADDRESS_PORT); - } - - /* set card CSN into configuration mode */ - for (csn = 1; csn <= 255; csn++) { - outb(0x03, ADDRESS_PORT); /* Select PnP wake[CSN] register. */ - outb(csn, WRITE_DATA_PORT); /* Wake[CSN] */ - /* check card ID */ - for (i = 0; i < 4; i++) { - if (read_resource_data() != sb1000_vendor_ID[i]) break; - } - if (i == 4) break; - } + /* Lock resources */ - /* SB1000 not found */ - if (csn > 255) { - /* return to WaitForKey state */ - outb(0x02, ADDRESS_PORT); /* Select PnP config control register. */ - outb(0x02, WRITE_DATA_PORT);/* Return to WaitForKey state. */ - return -ENODEV; - } + request_region(ioaddr[0], 16, dev->name); + request_region(ioaddr[1], 16, dev->name); - /* found: get serial number and skip checksum */ - serial_number = 0; - for (i = 0; i < 4; i++) { - serial_number |= read_resource_data() << (8 * i); - } - read_resource_data(); - - /* get I/O port base address */ - outb(0x60, ADDRESS_PORT); /* Select PnP I/O port base address 0. */ - ioaddr[0] = inb(READ_DATA_PORT) << 8; - outb(0x61, ADDRESS_PORT); - ioaddr[0] |= inb(READ_DATA_PORT); - outb(0x62, ADDRESS_PORT); /* Select PnP I/O port base address 1. */ - ioaddr[1] = inb(READ_DATA_PORT) << 8; - outb(0x63, ADDRESS_PORT); - ioaddr[1] |= inb(READ_DATA_PORT); - - /* get IRQ */ - outb(0x70, ADDRESS_PORT); /* Select PnP IRQ level select 0. */ - irq = inb(READ_DATA_PORT); - - /* return to WaitForKey state */ - outb(0x02, ADDRESS_PORT); /* Select PnP config control register. */ - outb(0x02, WRITE_DATA_PORT); /* Return to WaitForKey state. */ - - /* check I/O base and IRQ */ - if (dev->base_addr != 0 && dev->base_addr != ioaddr[0]) { - return -ENODEV; - } - if (dev->rmem_end != 0 && dev->rmem_end != ioaddr[1]) { - return -ENODEV; - } - if (dev->irq != 0 && dev->irq != irq) { - return -ENODEV; + return 0; } - - dev->base_addr = ioaddr[0]; - /* rmem_end holds the second I/O address - fv */ - dev->rmem_end = ioaddr[1]; - dev->irq = irq; - - if (sb1000_debug > 0) - printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), csn %d, " - "S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr, - dev->rmem_end, csn, serial_number, dev->irq); - - dev = init_etherdev(dev, 0); - - /* Make up a SB1000-specific-data structure. */ - dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct sb1000_private)); - - if (sb1000_debug > 0) - printk(KERN_NOTICE "%s", version); - - /* The SB1000-specific entries in the device structure. */ - dev->open = sb1000_open; - dev->do_ioctl = sb1000_dev_ioctl; - dev->hard_start_xmit = sb1000_start_xmit; - dev->stop = sb1000_close; - dev->get_stats = sb1000_stats; - - /* Fill in the generic fields of the device structure. */ - dev->change_mtu = NULL; - dev->hard_header = NULL; - dev->rebuild_header = NULL; - dev->set_mac_address = NULL; - dev->header_cache_update= NULL; - - dev->type = ARPHRD_ETHER; - dev->hard_header_len = 0; - dev->mtu = 1500; - dev->addr_len = ETH_ALEN; - /* hardware address is 0:0:serial_number */ - dev->dev_addr[0] = 0; - dev->dev_addr[1] = 0; - dev->dev_addr[2] = serial_number >> 24 & 0xff; - dev->dev_addr[3] = serial_number >> 16 & 0xff; - dev->dev_addr[4] = serial_number >> 8 & 0xff; - dev->dev_addr[5] = serial_number >> 0 & 0xff; - dev->tx_queue_len = 0; - - /* New-style flags. */ - dev->flags = IFF_POINTOPOINT|IFF_NOARP; - return 0; } /* * SB1000 hardware routines to be used during open/configuration phases */ + const int TimeOutJiffies = (int)(8.75 * HZ); static inline void nicedelay(unsigned long usecs) @@ -1279,6 +1251,8 @@ init_module(void) void cleanup_module(void) { unregister_netdev(&dev_sb1000); + release_region(&dev_sb1000.base_addr, 16); + release_region(&dev_sb1000.rmem_end, 16); kfree_s(dev_sb1000.priv, sizeof(struct sb1000_private)); dev_sb1000.priv = NULL; } |