fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / wireless / prism54 / islpci_hotplug.c
index 5cd7da4..58257b4 100644 (file)
@@ -1,5 +1,4 @@
-/*  $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_hotplug.c,v 1.56 2004/02/26 23:33:02 mcgrof Exp $
- *  
+/*
  *  Copyright (C) 2002 Intersil Americas Inc.
  *  Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
  *
  *
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h> /* For __init, __exit */
+#include <linux/dma-mapping.h>
 
+#include "prismcompat.h"
 #include "islpci_dev.h"
 #include "islpci_mgt.h"                /* for pc_debug */
 #include "isl_oid.h"
 
 #define DRV_NAME       "prism54"
-#define DRV_VERSION    "1.1"
+#define DRV_VERSION    "1.2"
 
 MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team <prism54-devel@prism54.org>");
 MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter");
 MODULE_LICENSE("GPL");
 
+static int     init_pcitm = 0;
+module_param(init_pcitm, int, 0);
+
 /* In this order: vendor, device, subvendor, subdevice, class, class_mask,
- * driver_data 
- * Note: for driver_data we put the device's name 
- * If you have an update for this please contact prism54-devel@prism54.org 
+ * driver_data
+ * If you have an update for this please contact prism54-devel@prism54.org
  * The latest list can be found at http://prism54.org/supported_cards.php */
 static const struct pci_device_id prism54_id_tbl[] = {
+       /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
        {
-        PCIVENDOR_3COM, PCIDEVICE_3COM6001,
-        PCIVENDOR_3COM, PCIDEVICE_3COM6001,
-        0, 0,
-        (unsigned long) "3COM 3CRWE154G72 Wireless LAN adapter"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_DLINK, 0x3202UL, 
-        0, 0,
-        (unsigned long) "D-Link Air Plus Xtreme G A1 - DWL-g650 A1"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_IODATA, 0xd019UL, 
-        0, 0,
-        (unsigned long) "I-O Data WN-G54/CB - WN-G54/CB"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_NETGEAR, 0x4800UL,
-        0, 0,
-        (unsigned long) "Netgear WG511"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_I4, 0x0020UL,
-        0, 0,
-        (unsigned long) "PLANEX GW-DS54G"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_SMC, 0x2802UL,
-        0, 0,
-        (unsigned long) "EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card - SMC2802W"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_SMC, 0x2835UL,
-        0, 0,
-        (unsigned long) "EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Adapter - SMC2835W"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_INTERSIL, 0x0000UL, /* This was probably a bogus reading... */
-        0, 0,
-        (unsigned long) "SparkLAN WL-850F"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_I4, 0x0014UL,
-        0, 0,
-        (unsigned long) "I4 Z-Com XG-600"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_I4, 0x0020UL,
-        0, 0,
-        (unsigned long) "I4 Z-Com XG-900/PLANEX GW-DS54G"},
-       {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_ACCTON, 0xee03UL,
-        0, 0,
-        (unsigned long) "SMC 2802Wv2"},
+        0x1260, 0x3890,
+        PCI_ANY_ID, PCI_ANY_ID,
+        0, 0, 0
+       },
+
+       /* 3COM 3CRWE154G72 Wireless LAN adapter */
        {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
-        PCIVENDOR_SMC, 0xa835UL,
-        0, 0,
-        (unsigned long) "SMC 2835Wv2"},
+        0x10b7, 0x6001,
+        PCI_ANY_ID, PCI_ANY_ID,
+        0, 0, 0
+       },
+
+       /* Intersil PRISM Indigo Wireless LAN adapter */
        {
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3877,
+        0x1260, 0x3877,
         PCI_ANY_ID, PCI_ANY_ID,
-        0, 0,
-        (unsigned long) "Intersil PRISM Indigo Wireless LAN adapter"},
-       { /* Default */
-        PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
+        0, 0, 0
+       },
+
+       /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
+       {
+        0x1260, 0x3886,
         PCI_ANY_ID, PCI_ANY_ID,
-        0, 0,
-        (unsigned long) "Intersil PRISM Duette/Prism GT Wireless LAN adapter"},
-       {0,}
+        0, 0, 0
+       },
+
+       /* End of list */
+       {0,0,0,0,0,0,0}
 };
 
 /* register the device with the Hotplug facilities of the kernel */
@@ -119,7 +80,7 @@ MODULE_DEVICE_TABLE(pci, prism54_id_tbl);
 
 static int prism54_probe(struct pci_dev *, const struct pci_device_id *);
 static void prism54_remove(struct pci_dev *);
-static int prism54_suspend(struct pci_dev *, u32 state);
+static int prism54_suspend(struct pci_dev *, pm_message_t state);
 static int prism54_resume(struct pci_dev *);
 
 static struct pci_driver prism54_driver = {
@@ -132,69 +93,6 @@ static struct pci_driver prism54_driver = {
        /* .enable_wake ; we don't support this yet */
 };
 
-static void
-prism54_get_card_model(struct net_device *ndev)
-{
-       islpci_private  *priv;
-       char            *modelp;
-
-       priv = netdev_priv(ndev);
-       switch (priv->pdev->subsystem_device) {
-       case PCIDEVICE_ISL3877:
-               modelp = "PRISM Indigo";
-               break;
-       case PCIDEVICE_3COM6001:
-               modelp = "3COM 3CRWE154G72";
-               break;
-       case 0x3202UL:
-               modelp = "D-Link DWL-g650 A1";
-               break;
-       case 0xd019UL:
-               modelp = "WN-G54/CB";
-               break;
-       case 0x4800UL:
-               modelp = "Netgear WG511";
-               break;
-       case 0x2802UL:
-               modelp = "SMC2802W";
-               break;
-       case 0xee03UL:
-               modelp = "SMC2802W V2";
-               break;
-       case 0x2835UL:
-               modelp = "SMC2835W";
-               break;
-       case 0xa835UL:
-               modelp = "SMC2835W V2";
-               break;
-       /* Let's leave this one out for now since it seems bogus/wrong 
-        * Even if the manufacturer did use 0x0000UL it may not be correct
-        * by their part, therefore deserving no name ;) */
-       /*      case 0x0000UL: 
-        *              modelp = "SparkLAN WL-850F";
-        *              break;*/
-
-       /* We have two reported for the one below :( */
-       case 0x0014UL:
-               modelp = "XG-600";
-               break;
-       case 0x0020UL:
-               modelp = "XG-900/GW-DS54G";
-               break;
-/* Default it */
-/*
-       case PCIDEVICE_ISL3890:
-               modelp = "PRISM Duette/GT";
-               break;
-*/
-       default:
-               modelp = "PRISM Duette/GT";
-       }
-       printk(KERN_DEBUG "%s: %s driver detected card model: %s\n",
-                       ndev->name, DRV_NAME, modelp);
-       return;
-}
-
 /******************************************************************************
     Module initialization functions
 ******************************************************************************/
@@ -208,9 +106,6 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        islpci_private *priv;
        int rvalue;
 
-       /* TRACE(DRV_NAME); */
-       
-       
        /* Enable the pci device */
        if (pci_enable_device(pdev)) {
                printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME);
@@ -229,25 +124,30 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* enable PCI DMA */
-       if (pci_set_dma_mask(pdev, 0xffffffff)) {
+       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME);
                goto do_pci_disable_device;
         }
 
        /* 0x40 is the programmable timer to configure the response timeout (TRDY_TIMEOUT)
         * 0x41 is the programmable timer to configure the retry timeout (RETRY_TIMEOUT)
-        *      The RETRY_TIMEOUT is used to set the number of retries that the core, as a
-        *      Master, will perform before abandoning a cycle. The default value for
-        *      RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new
-        *      devices. A write of zero to the RETRY_TIMEOUT register disables this
-        *      function to allow use with any non-compliant legacy devices that may
-        *      execute more retries.
+        *      The RETRY_TIMEOUT is used to set the number of retries that the core, as a
+        *      Master, will perform before abandoning a cycle. The default value for
+        *      RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new
+        *      devices. A write of zero to the RETRY_TIMEOUT register disables this
+        *      function to allow use with any non-compliant legacy devices that may
+        *      execute more retries.
         *
-        *      Writing zero to both these two registers will disable both timeouts and
-        *      *can* solve problems caused by devices that are slow to respond.
+        *      Writing zero to both these two registers will disable both timeouts and
+        *      *can* solve problems caused by devices that are slow to respond.
+        *      Make this configurable - MSW
         */
-       pci_write_config_byte(pdev, 0x40, 0);
-       pci_write_config_byte(pdev, 0x41, 0);
+       if ( init_pcitm >= 0 ) {
+               pci_write_config_byte(pdev, 0x40, (u8)init_pcitm);
+               pci_write_config_byte(pdev, 0x41, (u8)init_pcitm);
+       } else {
+               printk(KERN_INFO "PCI TRDY/RETRY unchanged\n");
+       }
 
        /* request the pci device I/O regions */
        rvalue = pci_request_regions(pdev, DRV_NAME);
@@ -262,19 +162,23 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rvalue || !mem_addr) {
                printk(KERN_ERR "%s: PCI device memory region not configured; fix your BIOS or CardBus bridge/drivers\n",
                       DRV_NAME);
-               goto do_pci_disable_device;
+               goto do_pci_release_regions;
        }
 
        /* enable PCI bus-mastering */
        DEBUG(SHOW_TRACING, "%s: pci_set_master(pdev)\n", DRV_NAME);
        pci_set_master(pdev);
 
+       /* enable MWI */
+       if (!pci_set_mwi(pdev))
+               printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME);
+
        /* setup the network device interface and its structure */
        if (!(ndev = islpci_setup(pdev))) {
                /* error configuring the driver as a network device */
                printk(KERN_ERR "%s: could not configure network device\n",
                       DRV_NAME);
-               goto do_pci_release_regions;
+               goto do_pci_clear_mwi;
        }
 
        priv = netdev_priv(ndev);
@@ -285,7 +189,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* request for the interrupt before uploading the firmware */
        rvalue = request_irq(pdev->irq, &islpci_interrupt,
-                            SA_SHIRQ, ndev->name, priv);
+                            IRQF_SHARED, ndev->name, priv);
 
        if (rvalue) {
                /* error, could not hook the handler to the irq */
@@ -296,17 +200,16 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* firmware upload is triggered in islpci_open */
 
-       /* Pretty card model discovery output */
-       prism54_get_card_model(ndev);
-
        return 0;
 
       do_unregister_netdev:
        unregister_netdev(ndev);
        islpci_free_memory(priv);
-       pci_set_drvdata(pdev, 0);
+       pci_set_drvdata(pdev, NULL);
        free_netdev(ndev);
-       priv = 0;
+       priv = NULL;
+      do_pci_clear_mwi:
+       pci_clear_mwi(pdev);
       do_pci_release_regions:
        pci_release_regions(pdev);
       do_pci_disable_device:
@@ -322,7 +225,7 @@ void
 prism54_remove(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
-       islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
+       islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
        BUG_ON(!priv);
 
        if (!__in_cleanup_module) {
@@ -340,7 +243,7 @@ prism54_remove(struct pci_dev *pdev)
                isl38xx_disable_interrupts(priv->device_base);
                islpci_set_state(priv, PRV_STATE_OFF);
                /* This bellow causes a lockup at rmmod time. It might be
-                * because some interrupts still linger after rmmod time, 
+                * because some interrupts still linger after rmmod time,
                 * see bug #17 */
                /* pci_set_power_state(pdev, 3);*/      /* try to power-off */
        }
@@ -350,9 +253,11 @@ prism54_remove(struct pci_dev *pdev)
        /* free the PCI memory and unmap the remapped page */
        islpci_free_memory(priv);
 
-       pci_set_drvdata(pdev, 0);
+       pci_set_drvdata(pdev, NULL);
        free_netdev(ndev);
-       priv = 0;
+       priv = NULL;
+
+       pci_clear_mwi(pdev);
 
        pci_release_regions(pdev);
 
@@ -360,16 +265,14 @@ prism54_remove(struct pci_dev *pdev)
 }
 
 int
-prism54_suspend(struct pci_dev *pdev, u32 state)
+prism54_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
-       islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
+       islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
        BUG_ON(!priv);
 
-       printk(KERN_NOTICE "%s: got suspend request (state %d)\n",
-              ndev->name, state);
 
-       pci_save_state(pdev, priv->pci_state);
+       pci_save_state(pdev);
 
        /* tell the device not to trigger interrupts for now... */
        isl38xx_disable_interrupts(priv->device_base);
@@ -388,12 +291,21 @@ int
 prism54_resume(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
-       islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
+       islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
+       int err;
+
        BUG_ON(!priv);
 
        printk(KERN_NOTICE "%s: got resume request\n", ndev->name);
 
-       pci_restore_state(pdev, priv->pci_state);
+       err = pci_enable_device(pdev);
+       if (err) {
+               printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
+                      ndev->name);
+               return err;
+       }
+
+       pci_restore_state(pdev);
 
        /* alright let's go into the PREBOOT state */
        islpci_reset(priv, 1);
@@ -412,7 +324,7 @@ prism54_module_init(void)
 
        __bug_on_wrong_struct_sizes ();
 
-       return pci_module_init(&prism54_driver);
+       return pci_register_driver(&prism54_driver);
 }
 
 /* by the time prism54_module_exit() terminates, as a postcondition