patch-2.3.99-pre3 linux/drivers/net/pcmcia/3c575_cb.c
Next file: linux/drivers/net/pcmcia/Config.in
Previous file: linux/drivers/net/net_init.c
Back to the patch index
Back to the overall index
- Lines: 931
- Date:
Mon Mar 20 07:53:51 2000
- Orig file:
v2.3.99-pre2/linux/drivers/net/pcmcia/3c575_cb.c
- Orig date:
Sun Feb 20 21:12:39 2000
diff -u --recursive --new-file v2.3.99-pre2/linux/drivers/net/pcmcia/3c575_cb.c linux/drivers/net/pcmcia/3c575_cb.c
@@ -12,10 +12,16 @@
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+ Linux Kernel Additions:
+
+ LK1.1.2 (March 19, 2000)
+ * New PCI interface (jgarzik)
+
*/
static char *version =
-"3c59x.c:v0.99L 5/28/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c575_cb.c:v0.99L+LK1.1.2 3/19/2000 Donald Becker and others http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
@@ -64,6 +70,7 @@
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
@@ -85,9 +92,6 @@
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(compaq_ioaddr, "i");
-MODULE_PARM(compaq_irq, "i");
-MODULE_PARM(compaq_device_id, "i");
/* Operational parameter that usually are not changed. */
@@ -103,6 +107,10 @@
code size of a per-interface flag is not worthwhile. */
static char mii_preamble_required = 0;
+#define PFX "3c575_cb: "
+
+
+
/*
Theory of Operation
@@ -186,76 +194,134 @@
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
};
-struct pci_id_info {
- const char *name;
- u16 vendor_id, device_id, device_id_mask, flags;
- int drv_flags, io_size;
- struct net_device *(*probe1)(struct pci_dev *pdev, struct net_device *dev,
- long ioaddr, int irq, int chip_idx, int fnd_cnt);
-};
enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
-static struct net_device *vortex_probe1(struct pci_dev *pdev,
- struct net_device *dev, long ioaddr,
- int irq, int dev_id, int card_idx);
-static struct pci_id_info pci_tbl[] = {
- {"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
- {"3c595 Vortex 100baseTx", 0x10B7, 0x5950, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
- {"3c595 Vortex 100baseT4", 0x10B7, 0x5951, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
- {"3c595 Vortex 100base-MII", 0x10B7, 0x5952, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
- {"3Com Vortex", 0x10B7, 0x5900, 0xff00,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
- {"3c900 Boomerang 10baseT", 0x10B7, 0x9000, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
- {"3c900 Boomerang 10Mbps Combo", 0x10B7, 0x9001, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
- {"3c900 Cyclone 10Mbps Combo", 0x10B7, 0x9005, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
- {"3c900B-FL Cyclone 10base-FL", 0x10B7, 0x900A, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
- {"3c905 Boomerang 100baseTx", 0x10B7, 0x9050, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
- {"3c905 Boomerang 100baseT4", 0x10B7, 0x9051, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
- {"3c905B Cyclone 100baseTx", 0x10B7, 0x9055, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
- {"3c905B Cyclone 10/100/BNC", 0x10B7, 0x9058, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
- {"3c905B-FX Cyclone 100baseFx", 0x10B7, 0x905A, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
- {"3c905C Tornado", 0x10B7, 0x9200, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
- {"3c980 Cyclone", 0x10B7, 0x9800, 0xfff0,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
- {"3cSOHO100-TX Hurricane", 0x10B7, 0x7646, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
- {"3c555 Laptop Hurricane", 0x10B7, 0x5055, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
- {"3c575 Boomerang CardBus", 0x10B7, 0x5057, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
- {"3CCFE575 Cyclone CardBus", 0x10B7, 0x5157, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
- 128, vortex_probe1},
- {"3CCFE575CT Cyclone CardBus", 0x10B7, 0x5257, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
- 128, vortex_probe1},
- {"3CCFE656 Cyclone CardBus", 0x10B7, 0x6560, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
- 128, vortex_probe1},
- {"3CCFEM656 Cyclone CardBus", 0x10B7, 0x6562, 0xffff,
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
- 128, vortex_probe1},
- {"3c575 series CardBus (unknown version)", 0x10B7, 0x5057, 0xf0ff,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
- {"3Com Boomerang (unknown version)", 0x10B7, 0x9000, 0xff00,
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+
+
+enum vortex_chips {
+ CH_3C590 = 0,
+ CH_3C595_1,
+ CH_3C595_2,
+ CH_3C595_3,
+ CH_VORTEX,
+ CH_3C900_1,
+ CH_3C900_2,
+ CH_3C900_3,
+ CH_3C900B_FL,
+ CH_3C905_1,
+ CH_3C905_2,
+ CH_3C905B_1,
+ CH_3C905B_2,
+ CH_3C905B_FX,
+ CH_3C905C,
+ CH_3C980,
+ CH_3CSOHO100_TX,
+ CH_3C555,
+ CH_3C575_1,
+ CH_3CCFE575,
+ CH_3CCFE575CT,
+ CH_3CCFE656,
+ CH_3CCFEM656,
+ CH_3C575_2,
+ CH_BOOMERANG,
+};
+
+
+/* note: this array directly indexed by above enums, and MUST
+ * be kept in sync with both the enums above, and the PCI device
+ * table below
+ */
+static struct vortex_chip_info {
+ const char *name;
+ int flags;
+ int drv_flags;
+ int io_size;
+} vortex_info_tbl[] = {
+ {"3c590 Vortex 10Mbps",
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+ {"3c595 Vortex 100baseTx",
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+ {"3c595 Vortex 100baseT4",
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+ {"3c595 Vortex 100base-MII",
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+ {"3Com Vortex",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
+ {"3c900 Boomerang 10baseT",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
+ {"3c900 Boomerang 10Mbps Combo",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
+ {"3c900 Cyclone 10Mbps Combo",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c900B-FL Cyclone 10base-FL",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c905 Boomerang 100baseTx",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
+ {"3c905 Boomerang 100baseT4",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
+ {"3c905B Cyclone 100baseTx",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
+ {"3c905B Cyclone 10/100/BNC",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
+ {"3c905B-FX Cyclone 100baseFx",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c905C Tornado",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c980 Cyclone",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3cSOHO100-TX Hurricane",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c555 Laptop Hurricane",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c575 Boomerang CardBus",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
+ {"3CCFE575 Cyclone CardBus",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, 128, },
+ {"3CCFE575CT Cyclone CardBus",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, 128, },
+ {"3CCFE656 Cyclone CardBus",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, 128, },
+ {"3CCFEM656 Cyclone CardBus",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, 128, },
+ {"3c575 series CardBus (unknown version)",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
+ {"3Com Boomerang (unknown version)",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
+ {0,}, /* 0 terminated list. */
+};
+
+
+static struct pci_device_id vortex_pci_tbl[] __devinit = {
+ { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 },
+ { 0x10B7, 0x5950, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_1 },
+ { 0x10B7, 0x5951, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_2 },
+ { 0x10B7, 0x5952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_3 },
+ { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VORTEX },
+ { 0x10B7, 0x9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_1 },
+ { 0x10B7, 0x9001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_2 },
+ { 0x10B7, 0x9005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_3 },
+ { 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL },
+ { 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 },
+ { 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 },
+ { 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 },
+ { 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
+ { 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX },
+ { 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C },
+ { 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 },
+ { 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX },
+ { 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 },
+ { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 },
+ { 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 },
+ { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT },
+ { 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 },
+ { 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 },
+ { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_2 },
+ { 0x10B7, 0x9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_BOOMERANG },
{0,}, /* 0 terminated list. */
};
+MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
+
/* Operational definitions.
These are not used by other compilation units and thus are not
@@ -400,7 +466,7 @@
/* The addresses of transmit- and receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
struct sk_buff* tx_skbuff[TX_RING_SIZE];
- struct net_device *next_module;
+ struct net_device *next_module; /* NULL if PCI device */
void *priv_addr;
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
@@ -463,9 +529,8 @@
{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
};
-#ifndef CARDBUS
-static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]);
-#endif
+static int vortex_probe1(struct pci_dev *pdev, long ioaddr, int irq,
+ int chip_idx, int card_idx);
static void vortex_up(struct net_device *dev);
static void vortex_down(struct net_device *dev);
static int vortex_open(struct net_device *dev);
@@ -484,7 +549,6 @@
static void set_rx_mode(struct net_device *dev);
static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void vortex_tx_timeout(struct net_device *dev);
-static void acpi_wake(struct pci_dev *pdev);
static void acpi_set_WOL(struct net_device *dev);
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
@@ -492,280 +556,181 @@
#define MAX_UNITS 8
static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-/* A list of all installed Vortex devices, for removing the driver module. */
-static struct net_device *root_vortex_dev = NULL;
-#ifdef MODULE
-#ifndef CARDBUS
-/* Variables to work-around the Compaq PCI BIOS32 problem. */
-static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
-#endif
-#ifdef CARDBUS
+/* A list of all installed Vortex EISA devices, for removing the driver module. */
+static struct net_device *root_vortex_eisa_dev = NULL;
-#include <pcmcia/driver_ops.h>
+static int vortex_cards_found = 0;
-static void vortex_reap(void)
-{
- struct net_device **devp, **next;
- printk(KERN_DEBUG "vortex_reap()\n");
- for (devp = &root_vortex_dev; *devp; devp = next) {
- struct vortex_private *vp = (*devp)->priv;
- next = &vp->next_module;
- if (vp->open || !vp->reap) continue;
- unregister_netdev(*devp);
- if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
- kfree(*devp);
- kfree(vp->priv_addr);
- *devp = *next; next = devp;
- }
-}
-static dev_node_t *vortex_attach(dev_locator_t *loc)
-{
- u16 dev_id, vendor_id;
- u32 io;
- u8 irq;
- struct net_device *dev;
- int chip_idx;
- struct pci_dev *pdev;
- vortex_reap();
- if (loc->bus != LOC_PCI) return NULL;
- pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
- if (!pdev) return NULL;
- io = pci_resource_start (pdev, 0);
- irq = pdev->irq;
- vendor_id = pdev->vendor;
- dev_id = pdev->device;
- printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
- pdev->bus->number, pdev->devfn, dev_id);
- if (io == 0 || irq == 0) {
- printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
- "assigned an %s.\n" KERN_ERR " It will not be activated.\n",
- io == 0 ? "I/O address" : "IRQ");
- return NULL;
- }
- for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
- if (vendor_id == pci_tbl[chip_idx].vendor_id
- && (dev_id & pci_tbl[chip_idx].device_id_mask) ==
- pci_tbl[chip_idx].device_id)
- break;
- if (pci_tbl[chip_idx].vendor_id == 0) { /* Compiled out! */
- printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in "
- "vortex_attach().\n", vendor_id, dev_id);
- return NULL;
- }
- dev = vortex_probe1(pdev, NULL, io, irq, chip_idx, MAX_UNITS+1);
- if (dev) {
- dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
- strcpy(node->dev_name, dev->name);
- node->major = node->minor = 0;
- node->next = NULL;
- MOD_INC_USE_COUNT;
- return node;
- }
- return NULL;
-}
-
-static void vortex_detach(dev_node_t *node)
-{
- struct net_device *dev, *next;
- printk(KERN_DEBUG "vortex_detach(%s)\n", node->dev_name);
- for (dev = root_vortex_dev; dev; dev = next) {
- next = ((struct vortex_private *)dev->priv)->next_module;
- if (strcmp(dev->name, node->dev_name) == 0) break;
- }
- if (dev && dev->priv) {
- struct vortex_private *vp = dev->priv;
- if (vp->open) vortex_down(dev);
- vp->reap = 1;
- kfree(node);
- MOD_DEC_USE_COUNT;
- }
-}
-static void vortex_suspend(dev_node_t *node)
+static void vortex_suspend (struct pci_dev *pdev)
{
- struct net_device *dev, *next;
- printk(KERN_DEBUG "vortex_suspend(%s)\n", node->dev_name);
- for (dev = root_vortex_dev; dev; dev = next) {
- next = ((struct vortex_private *)dev->priv)->next_module;
- if (strcmp(dev->name, node->dev_name) == 0) break;
- }
+ struct net_device *dev = pdev->driver_data;
+
+ printk(KERN_DEBUG "vortex_suspend(%s)\n", dev->name);
+
if (dev && dev->priv) {
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- if (vp->open) vortex_down(dev);
+ if (vp->open) {
+ netif_device_detach(dev);
+ vortex_down(dev);
+ }
}
}
-static void vortex_resume(dev_node_t *node)
+
+static void vortex_resume (struct pci_dev *pdev)
{
- struct net_device *dev, *next;
- printk(KERN_DEBUG "vortex_resume(%s)\n", node->dev_name);
- for (dev = root_vortex_dev; dev; dev = next) {
- next = ((struct vortex_private *)dev->priv)->next_module;
- if (strcmp(dev->name, node->dev_name) == 0) break;
- }
+ struct net_device *dev = pdev->driver_data;
+
+ printk(KERN_DEBUG "vortex_resume(%s)\n", dev->name);
+
if (dev && dev->priv) {
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- if (vp->open) vortex_up(dev);
+ if (vp->open) {
+ vortex_up(dev);
+ netif_device_attach(dev);
+ }
}
}
-struct driver_operations vortex_ops = {
- "3c575_cb", vortex_attach, vortex_suspend, vortex_resume, vortex_detach
-};
-
-#endif /* Cardbus support */
-int init_module(void)
-{
- if (vortex_debug)
- printk(KERN_INFO "%s", version);
-#ifdef CARDBUS
- register_driver(&vortex_ops);
- return 0;
-#else
- return vortex_scan(0, pci_tbl);
-#endif
-}
-
-#else
-int tc59x_probe(struct net_device *dev)
+/* returns count found (>= 0), or negative on error */
+static int __init vortex_eisa_init (void)
{
- static int did_version = -1;
- if (++did_version <= 0)
- printk(KERN_INFO "%s", version);
- return vortex_scan(dev, pci_tbl);
-}
-#endif /* not MODULE */
-
-#ifndef CARDBUS
-static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
-{
- int cards_found = 0;
-
- /* Allow an EISA-only driver. */
- struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
- ioaddr = pdev->base_address[0] & ~3;
- irq = pdev->irq;
- }
+ long ioaddr;
+ int rc;
+ int orig_cards_found = vortex_cards_found;
- if (ioaddr == 0) {
- printk(KERN_WARNING " A 3Com network adapter has been found, "
- "however it has not been assigned an I/O address.\n"
- " You may need to power-cycle the machine for this "
- "device to work!\n");
- continue;
- }
+ /* Now check all slots of the EISA bus. */
+ if (!EISA_bus)
+ return 0;
- /* Activate the card. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
- new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled the device "
- "at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
- pci_bus, pci_device_fn, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
- }
+ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+ int device_id;
- dev = vortex_probe1(pci_bus, pci_device_fn, dev, ioaddr, irq,
- chip_idx, cards_found);
+ if (request_region(ioaddr, VORTEX_TOTAL_SIZE, "vortex") == NULL)
+ continue;
- if (dev) {
- /* Get and check the latency values. On the 3c590 series
- the latency timer must be set to the maximum value to avoid
- data corruption that occurs when the timer expires during
- a transfer -- a bug in the Vortex chip only. */
- u8 pci_latency;
- u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
-
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < new_latency) {
- printk(KERN_INFO "%s: Overriding PCI latency"
- " timer (CFLT) setting of %d, new value is %d.\n",
- dev->name, pci_latency, new_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, new_latency);
- }
- dev = 0;
- cards_found++;
- }
+ /* Check the standard EISA ID register for an encoded '3Com'. */
+ if (inw(ioaddr + 0xC80) != 0x6d50) {
+ release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ continue;
}
- }
- /* Now check all slots of the EISA bus. */
- if (EISA_bus) {
- static long ioaddr = 0x1000;
- for ( ; ioaddr < 0x9000; ioaddr += 0x1000) {
- int device_id;
- if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
- continue;
- /* Check the standard EISA ID register for an encoded '3Com'. */
- if (inw(ioaddr + 0xC80) != 0x6d50)
- continue;
- /* Check for a product that we support, 3c59{2,7} any rev. */
- device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
- if ((device_id & 0xFF00) != 0x5900)
- continue;
- vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
- 4, cards_found);
- dev = 0;
- cards_found++;
+ /* Check for a product that we support, 3c59{2,7} any rev. */
+ device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
+ if ((device_id & 0xFF00) != 0x5900) {
+ release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ continue;
}
- }
-#ifdef MODULE
- /* Special code to work-around the Compaq PCI BIOS32 problem. */
- if (compaq_ioaddr) {
- vortex_probe1(0, 0, dev, compaq_ioaddr, compaq_irq,
- compaq_device_id, cards_found++);
- dev = 0;
+ rc = vortex_probe1(NULL, ioaddr, inw(ioaddr + 0xC88) >> 12,
+ 4, /* XXX is 4 correct eisa idx? */
+ vortex_cards_found);
+ if (rc == 0)
+ vortex_cards_found++;
+ else
+ release_region (ioaddr, VORTEX_TOTAL_SIZE);
}
-#endif
- return cards_found ? 0 : -ENODEV;
+ return vortex_cards_found - orig_cards_found;
}
-#endif /* ! Cardbus */
-static struct net_device *vortex_probe1(struct pci_dev *pdev,
- struct net_device *dev, long ioaddr,
- int irq, int chip_idx, int card_idx)
+
+/* returns count (>= 0), or negative on error */
+static int __devinit vortex_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+
+ rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq,
+ ent->driver_data, vortex_cards_found);
+ if (rc == 0)
+ vortex_cards_found++;
+
+ return rc;
+}
+
+
+/* NOTE: pdev can be NULL, for the case of an EISA driver */
+static int __devinit vortex_probe1(struct pci_dev *pdev,
+ long ioaddr, int irq,
+ int chip_idx, int card_idx)
{
struct vortex_private *vp;
int option;
unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
int i;
+ struct net_device *dev;
+ static int printed_version = 0;
+
+ if (!printed_version) {
+ printk (KERN_INFO "%s", version);
+ printed_version = 1;
+ }
- dev = init_etherdev(dev, 0);
-
- printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",
- dev->name, pci_tbl[chip_idx].name, ioaddr);
-
+ dev = init_etherdev(NULL, sizeof(*vp));
+ if (!dev) {
+ printk (KERN_ERR PFX "unable to allocate etherdev, aborting\n");
+ return -ENOMEM;
+ }
+
+ printk(KERN_INFO "%s: 3Com %s %s at 0x%lx, ",
+ dev->name,
+ pdev ? "PCI" : "EISA",
+ vortex_info_tbl[chip_idx].name,
+ ioaddr);
+
+ /* private struct aligned and zeroed by init_etherdev */
+ vp = dev->priv;
+ vp->priv_addr = vp;
dev->base_addr = ioaddr;
dev->irq = irq;
dev->mtu = mtu;
- /* Make certain the descriptor lists are aligned. */
- {
- void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
- vp = (void *)(((long)mem + 15) & ~15);
- memset(vp, 0, sizeof(*vp));
- vp->priv_addr = mem;
+ /* module list only for EISA devices */
+ if (pdev == NULL) {
+ vp->next_module = root_vortex_eisa_dev;
+ root_vortex_eisa_dev = dev;
+ }
+
+ /* PCI-only startup logic */
+ if (pdev) {
+ /* EISA resources already marked, so only PCI needs to do this here */
+ if (!request_region (ioaddr, vortex_info_tbl[chip_idx].io_size,
+ dev->name)) {
+ printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n",
+ dev->name, vortex_info_tbl[chip_idx].io_size, ioaddr);
+ kfree (dev);
+ return -EBUSY;
+ }
+
+ /* wake up and enable device */
+ if (pci_enable_device (pdev)) {
+ printk (KERN_ERR "%s: Cannot enable device, aborting\n", dev->name);
+ release_region (ioaddr, vortex_info_tbl[chip_idx].io_size);
+ kfree (dev);
+ return -EIO;
+ }
+
+ /* enable bus-mastering if necessary */
+ if (vortex_info_tbl[chip_idx].flags & PCI_USES_MASTER)
+ pci_set_master (pdev);
}
- dev->priv = vp;
-
- vp->next_module = root_vortex_dev;
- root_vortex_dev = dev;
vp->lock = SPIN_LOCK_UNLOCKED;
vp->chip_id = chip_idx;
vp->pdev = pdev;
+ /* if we are a PCI driver, we store info in pdev->driver_data
+ * instead of a module list */
+ if (pdev)
+ pdev->driver_data = dev;
+
/* The lower four bits are the media type. */
if (dev->mem_start)
option = dev->mem_start;
@@ -793,7 +758,7 @@
EL3WINDOW(0);
for (i = 0; i < 0x40; i++) {
int timer;
-#ifdef CARDBUS
+#if 1 /* ifdef CARDBUS */
outw(0x230 + i, ioaddr + Wn0EepromCmd);
#else
outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
@@ -835,7 +800,7 @@
dev->irq);
#endif
- if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
+ if (pdev && vortex_info_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
u32 fn_st_addr; /* Cardbus function status space */
fn_st_addr = pci_resource_start (pdev, 2);
if (fn_st_addr)
@@ -922,9 +887,6 @@
vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
}
- /* We do a request_region() to register /proc/ioports info. */
- request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
-
/* The 3c59x-specific entries in the device structure. */
dev->open = &vortex_open;
dev->hard_start_xmit = &vortex_start_xmit;
@@ -932,10 +894,10 @@
dev->get_stats = &vortex_get_stats;
dev->do_ioctl = &vortex_ioctl;
dev->set_multicast_list = &set_rx_mode;
- dev->tx_timeout = vortex_tx_timeout;
+ dev->tx_timeout = &vortex_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- return dev;
+ return 0;
}
static void wait_for_completion(struct net_device *dev, int cmd)
@@ -956,11 +918,13 @@
long ioaddr = dev->base_addr;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
union wn3_config config;
- int i;
-
- /* Should be if(HAS_ACPI) */
- acpi_wake(vp->pdev);
+ int i, device_id;
+ if (vp->pdev)
+ device_id = vp->pdev->device;
+ else
+ device_id = 0x5900; /* EISA */
+
/* Before initializing select the active media port. */
EL3WINDOW(3);
config.i = inl(ioaddr + Wn3_Config);
@@ -972,7 +936,7 @@
media_tbl[vp->media_override].name);
dev->if_port = vp->media_override;
} else if (vp->autoselect) {
- if (pci_tbl[vp->chip_id].drv_flags & HAS_NWAY)
+ if (vortex_info_tbl[vp->chip_id].drv_flags & HAS_NWAY)
dev->if_port = XCVR_NWAY;
else {
/* Find first available media type, starting with 100baseTx. */
@@ -995,7 +959,7 @@
vp->full_duplex = vp->force_fd;
config.u.xcvr = dev->if_port;
- if ( ! (pci_tbl[vp->chip_id].drv_flags & HAS_NWAY))
+ if ( ! (vortex_info_tbl[vp->chip_id].drv_flags & HAS_NWAY))
outl(config.i, ioaddr + Wn3_Config);
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
@@ -1045,12 +1009,11 @@
if (vp->cb_fn_base) {
u_short n = inw(ioaddr + Wn2_ResetOptions);
/* Inverted LED polarity */
- if (pci_tbl[vp->chip_id].device_id != 0x5257)
+ if (device_id != 0x5257)
n |= 0x0010;
/* Inverted polarity of MII power bit */
- if ((pci_tbl[vp->chip_id].device_id == 0x6560) ||
- (pci_tbl[vp->chip_id].device_id == 0x6562) ||
- (pci_tbl[vp->chip_id].device_id == 0x5257))
+ if ((device_id == 0x6560) || (device_id == 0x6562) ||
+ (device_id == 0x5257))
n |= 0x4000;
outw(n, ioaddr + Wn2_ResetOptions);
}
@@ -2088,66 +2051,107 @@
/* Change the power state to D3; RxEnable doesn't take effect. */
pci_write_config_word(vp->pdev, 0xe0, 0x8103);
}
-/* Change from D3 (sleep) to D0 (active).
- Problem: The Cyclone forgets all PCI config info during the transition! */
-static void acpi_wake(struct pci_dev *pdev)
-{
- u32 base0, base1, romaddr;
- u16 pci_command, pwr_command;
- u8 pci_latency, pci_cacheline, irq;
- pci_read_config_word(pdev, 0xe0, &pwr_command);
- if ((pwr_command & 3) == 0)
+
+static void __devexit vortex_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+ struct vortex_private *vp;
+
+ if (!dev)
return;
- pci_read_config_word( pdev, PCI_COMMAND, &pci_command);
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base0);
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, &base1);
- pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &romaddr);
- pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &pci_latency);
- pci_read_config_byte( pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
- pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq);
-
- pci_write_config_word( pdev, 0xe0, 0x0000);
- pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, base0);
- pci_write_config_dword(pdev, PCI_BASE_ADDRESS_1, base1);
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, romaddr);
- pci_write_config_byte( pdev, PCI_INTERRUPT_LINE, irq);
- pci_write_config_byte( pdev, PCI_LATENCY_TIMER, pci_latency);
- pci_write_config_byte( pdev, PCI_CACHE_LINE_SIZE, pci_cacheline);
- pci_write_config_word( pdev, PCI_COMMAND, pci_command | 5);
+
+ vp = (void *)(dev->priv);
+
+ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+ unregister_netdev(dev);
+ outw(TotalReset, dev->base_addr + EL3_CMD);
+ release_region(dev->base_addr, vortex_info_tbl[vp->chip_id].io_size);
+ kfree(dev);
}
-#ifdef MODULE
-void cleanup_module(void)
+
+static struct pci_driver vortex_driver = {
+ name: "3c575_cb",
+ probe: vortex_init_one,
+ remove: vortex_remove_one,
+ suspend: vortex_suspend,
+ resume: vortex_resume,
+ id_table: vortex_pci_tbl,
+};
+
+
+static int vortex_have_pci = 0;
+static int vortex_have_eisa = 0;
+
+
+static int __init vortex_init (void)
{
- struct net_device *next_dev;
+ int rc;
+
+ MOD_INC_USE_COUNT;
+
+ rc = pci_module_init (&vortex_driver);
+ if (rc < 0)
+ goto out;
+ if (rc > 0)
+ vortex_have_pci = 1;
+
+ rc = vortex_eisa_init ();
+ if (rc < 0)
+ goto out;
+ if (rc > 0)
+ vortex_have_eisa = 1;
-#ifdef CARDBUS
- unregister_driver(&vortex_ops);
- vortex_reap();
-#endif
+out:
+ MOD_DEC_USE_COUNT;
+ return rc;
+}
- /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- while (root_vortex_dev) {
- struct vortex_private *vp=(void *)(root_vortex_dev->priv);
- next_dev = vp->next_module;
- unregister_netdev(root_vortex_dev);
- outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
- release_region(root_vortex_dev->base_addr,
- pci_tbl[vp->chip_id].io_size);
- kfree(root_vortex_dev);
- kfree(vp->priv_addr);
- root_vortex_dev = next_dev;
+
+static void __exit vortex_eisa_cleanup (void)
+{
+ struct net_device *dev, *tmp;
+ struct vortex_private *vp;
+ long ioaddr;
+
+ dev = root_vortex_eisa_dev;
+
+ while (dev) {
+ vp = dev->priv;
+ ioaddr = dev->base_addr;
+
+ unregister_netdev (dev);
+ outw (TotalReset, ioaddr + EL3_CMD);
+ release_region (ioaddr, VORTEX_TOTAL_SIZE);
+
+ tmp = dev;
+ dev = vp->next_module;
+
+ kfree (tmp);
}
}
-#endif /* MODULE */
+
+static void __exit vortex_cleanup (void)
+{
+ if (vortex_have_pci)
+ pci_unregister_driver (&vortex_driver);
+ if (vortex_have_eisa)
+ vortex_eisa_cleanup ();
+}
+
+
+module_init(vortex_init);
+module_exit(vortex_cleanup);
+
+
/*
* Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c"
- * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/linux/pcmcia-cs-3.0.9/include/"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c575_cb.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c575_cb.c"
+ * cardbus-compile-command: "gcc -DCONFIG_HOTPLUG -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c575_cb.c -o 3c575_cb.o -I/usr/src/linux/pcmcia-cs-3.0.9/include/"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)