Merge to Fedora kernel-2.6.7-1.441
[linux-2.6.git] / drivers / net / wireless / prism54 / islpci_hotplug.c
1 /*
2  *  
3  *  Copyright (C) 2002 Intersil Americas Inc.
4  *  Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include <linux/version.h>
22 #include <linux/module.h>
23 #include <linux/pci.h>
24 #include <linux/delay.h>
25 #include <linux/init.h> /* For __init, __exit */
26
27 #include "prismcompat.h"
28 #include "islpci_dev.h"
29 #include "islpci_mgt.h"         /* for pc_debug */
30 #include "isl_oid.h"
31
32 #define DRV_NAME        "prism54"
33 #define DRV_VERSION     "1.2"
34
35 MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team <prism54-devel@prism54.org>");
36 MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter");
37 MODULE_LICENSE("GPL");
38
39 /* In this order: vendor, device, subvendor, subdevice, class, class_mask,
40  * driver_data 
41  * Note: for driver_data we put the device's name 
42  * If you have an update for this please contact prism54-devel@prism54.org 
43  * The latest list can be found at http://prism54.org/supported_cards.php */
44 static const struct pci_device_id prism54_id_tbl[] = {
45         {
46          PCIVENDOR_3COM, PCIDEVICE_3COM6001,
47          PCIVENDOR_3COM, PCIDEVICE_3COM6001,
48          0, 0,
49          (unsigned long) "3COM 3CRWE154G72 Wireless LAN adapter"},
50         {
51          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
52          PCIVENDOR_DLINK, 0x3202UL, 
53          0, 0,
54          (unsigned long) "D-Link Air Plus Xtreme G A1 - DWL-g650 A1"},
55         {
56          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
57          PCIVENDOR_IODATA, 0xd019UL, 
58          0, 0,
59          (unsigned long) "I-O Data WN-G54/CB - WN-G54/CB"},
60         {
61          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
62          PCIVENDOR_NETGEAR, 0x4800UL,
63          0, 0,
64          (unsigned long) "Netgear WG511"},
65         {
66          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
67          PCIVENDOR_I4, 0x0020UL,
68          0, 0,
69          (unsigned long) "PLANEX GW-DS54G"},
70         {
71          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
72          PCIVENDOR_SMC, 0x2802UL,
73          0, 0,
74          (unsigned long) "EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card - SMC2802W"},
75         {
76          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
77          PCIVENDOR_SMC, 0x2835UL,
78          0, 0,
79          (unsigned long) "EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Adapter - SMC2835W"},
80         {
81          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
82          PCIVENDOR_INTERSIL, 0x0000UL, /* This was probably a bogus reading... */
83          0, 0,
84          (unsigned long) "SparkLAN WL-850F"},
85         {
86          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
87          PCIVENDOR_I4, 0x0014UL,
88          0, 0,
89          (unsigned long) "I4 Z-Com XG-600"},
90         {
91          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
92          PCIVENDOR_I4, 0x0020UL,
93          0, 0,
94          (unsigned long) "I4 Z-Com XG-900/PLANEX GW-DS54G"},
95         {
96          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
97          PCIVENDOR_ACCTON, 0xee03UL,
98          0, 0,
99          (unsigned long) "SMC 2802Wv2"},
100         {
101          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
102          PCIVENDOR_SMC, 0xa835UL,
103          0, 0,
104          (unsigned long) "SMC 2835Wv2"},
105         {
106          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3877,
107          PCI_ANY_ID, PCI_ANY_ID,
108          0, 0,
109          (unsigned long) "Intersil PRISM Indigo Wireless LAN adapter"},
110         { /* Default */
111          PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
112          PCI_ANY_ID, PCI_ANY_ID,
113          0, 0,
114          (unsigned long) "Intersil PRISM Duette/Prism GT Wireless LAN adapter"},
115         {0,}
116 };
117
118 /* register the device with the Hotplug facilities of the kernel */
119 MODULE_DEVICE_TABLE(pci, prism54_id_tbl);
120
121 static int prism54_probe(struct pci_dev *, const struct pci_device_id *);
122 static void prism54_remove(struct pci_dev *);
123 static int prism54_suspend(struct pci_dev *, u32 state);
124 static int prism54_resume(struct pci_dev *);
125
126 static struct pci_driver prism54_driver = {
127         .name = DRV_NAME,
128         .id_table = prism54_id_tbl,
129         .probe = prism54_probe,
130         .remove = prism54_remove,
131         .suspend = prism54_suspend,
132         .resume = prism54_resume,
133         /* .enable_wake ; we don't support this yet */
134 };
135
136 static void
137 prism54_get_card_model(struct net_device *ndev)
138 {
139         islpci_private  *priv;
140         char            *modelp;
141
142         priv = netdev_priv(ndev);
143         switch (priv->pdev->subsystem_device) {
144         case PCIDEVICE_ISL3877:
145                 modelp = "PRISM Indigo";
146                 break;
147         case PCIDEVICE_3COM6001:
148                 modelp = "3COM 3CRWE154G72";
149                 break;
150         case 0x3202UL:
151                 modelp = "D-Link DWL-g650 A1";
152                 break;
153         case 0xd019UL:
154                 modelp = "WN-G54/CB";
155                 break;
156         case 0x4800UL:
157                 modelp = "Netgear WG511";
158                 break;
159         case 0x2802UL:
160                 modelp = "SMC2802W";
161                 break;
162         case 0xee03UL:
163                 modelp = "SMC2802W V2";
164                 break;
165         case 0x2835UL:
166                 modelp = "SMC2835W";
167                 break;
168         case 0xa835UL:
169                 modelp = "SMC2835W V2";
170                 break;
171         /* Let's leave this one out for now since it seems bogus/wrong 
172          * Even if the manufacturer did use 0x0000UL it may not be correct
173          * by their part, therefore deserving no name ;) */
174         /*      case 0x0000UL: 
175          *              modelp = "SparkLAN WL-850F";
176          *              break;*/
177
178         /* We have two reported for the one below :( */
179         case 0x0014UL:
180                 modelp = "XG-600";
181                 break;
182         case 0x0020UL:
183                 modelp = "XG-900/GW-DS54G";
184                 break;
185 /* Default it */
186 /*
187         case PCIDEVICE_ISL3890:
188                 modelp = "PRISM Duette/GT";
189                 break;
190 */
191         default:
192                 modelp = "PRISM Duette/GT";
193         }
194         printk(KERN_DEBUG "%s: %s driver detected card model: %s\n",
195                         ndev->name, DRV_NAME, modelp);
196         return;
197 }
198
199 /******************************************************************************
200     Module initialization functions
201 ******************************************************************************/
202
203 int
204 prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
205 {
206         struct net_device *ndev;
207         u8 latency_tmr;
208         u32 mem_addr;
209         islpci_private *priv;
210         int rvalue;
211
212         /* TRACE(DRV_NAME); */
213         
214         
215         /* Enable the pci device */
216         if (pci_enable_device(pdev)) {
217                 printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME);
218                 return -ENODEV;
219         }
220
221         /* check whether the latency timer is set correctly */
222         pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_tmr);
223 #if VERBOSE > SHOW_ERROR_MESSAGES
224         DEBUG(SHOW_TRACING, "latency timer: %x\n", latency_tmr);
225 #endif
226         if (latency_tmr < PCIDEVICE_LATENCY_TIMER_MIN) {
227                 /* set the latency timer */
228                 pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
229                                       PCIDEVICE_LATENCY_TIMER_VAL);
230         }
231
232         /* enable PCI DMA */
233         if (pci_set_dma_mask(pdev, 0xffffffff)) {
234                 printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME);
235                 goto do_pci_disable_device;
236         }
237
238         /* 0x40 is the programmable timer to configure the response timeout (TRDY_TIMEOUT)
239          * 0x41 is the programmable timer to configure the retry timeout (RETRY_TIMEOUT)
240          *      The RETRY_TIMEOUT is used to set the number of retries that the core, as a
241          *      Master, will perform before abandoning a cycle. The default value for
242          *      RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new
243          *      devices. A write of zero to the RETRY_TIMEOUT register disables this
244          *      function to allow use with any non-compliant legacy devices that may
245          *      execute more retries.
246          *
247          *      Writing zero to both these two registers will disable both timeouts and
248          *      *can* solve problems caused by devices that are slow to respond.
249          */
250         pci_write_config_byte(pdev, 0x40, 0);
251         pci_write_config_byte(pdev, 0x41, 0);
252
253         /* request the pci device I/O regions */
254         rvalue = pci_request_regions(pdev, DRV_NAME);
255         if (rvalue) {
256                 printk(KERN_ERR "%s: pci_request_regions failure (rc=%d)\n",
257                        DRV_NAME, rvalue);
258                 goto do_pci_disable_device;
259         }
260
261         /* check if the memory window is indeed set */
262         rvalue = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &mem_addr);
263         if (rvalue || !mem_addr) {
264                 printk(KERN_ERR "%s: PCI device memory region not configured; fix your BIOS or CardBus bridge/drivers\n",
265                        DRV_NAME);
266                 goto do_pci_disable_device;
267         }
268
269         /* enable PCI bus-mastering */
270         DEBUG(SHOW_TRACING, "%s: pci_set_master(pdev)\n", DRV_NAME);
271         pci_set_master(pdev);
272
273         /* setup the network device interface and its structure */
274         if (!(ndev = islpci_setup(pdev))) {
275                 /* error configuring the driver as a network device */
276                 printk(KERN_ERR "%s: could not configure network device\n",
277                        DRV_NAME);
278                 goto do_pci_release_regions;
279         }
280
281         priv = netdev_priv(ndev);
282         islpci_set_state(priv, PRV_STATE_PREBOOT); /* we are attempting to boot */
283
284         /* card is in unknown state yet, might have some interrupts pending */
285         isl38xx_disable_interrupts(priv->device_base);
286
287         /* request for the interrupt before uploading the firmware */
288         rvalue = request_irq(pdev->irq, &islpci_interrupt,
289                              SA_SHIRQ, ndev->name, priv);
290
291         if (rvalue) {
292                 /* error, could not hook the handler to the irq */
293                 printk(KERN_ERR "%s: could not install IRQ handler\n",
294                        ndev->name);
295                 goto do_unregister_netdev;
296         }
297
298         /* firmware upload is triggered in islpci_open */
299
300         /* Pretty card model discovery output */
301         prism54_get_card_model(ndev);
302
303         return 0;
304
305       do_unregister_netdev:
306         unregister_netdev(ndev);
307         islpci_free_memory(priv);
308         pci_set_drvdata(pdev, 0);
309         free_netdev(ndev);
310         priv = 0;
311       do_pci_release_regions:
312         pci_release_regions(pdev);
313       do_pci_disable_device:
314         pci_disable_device(pdev);
315         return -EIO;
316 }
317
318 /* set by cleanup_module */
319 static volatile int __in_cleanup_module = 0;
320
321 /* this one removes one(!!) instance only */
322 void
323 prism54_remove(struct pci_dev *pdev)
324 {
325         struct net_device *ndev = pci_get_drvdata(pdev);
326         islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
327         BUG_ON(!priv);
328
329         if (!__in_cleanup_module) {
330                 printk(KERN_DEBUG "%s: hot unplug detected\n", ndev->name);
331                 islpci_set_state(priv, PRV_STATE_OFF);
332         }
333
334         printk(KERN_DEBUG "%s: removing device\n", ndev->name);
335
336         unregister_netdev(ndev);
337
338         /* free the interrupt request */
339
340         if (islpci_get_state(priv) != PRV_STATE_OFF) {
341                 isl38xx_disable_interrupts(priv->device_base);
342                 islpci_set_state(priv, PRV_STATE_OFF);
343                 /* This bellow causes a lockup at rmmod time. It might be
344                  * because some interrupts still linger after rmmod time, 
345                  * see bug #17 */
346                 /* pci_set_power_state(pdev, 3);*/      /* try to power-off */
347         }
348
349         free_irq(pdev->irq, priv);
350
351         /* free the PCI memory and unmap the remapped page */
352         islpci_free_memory(priv);
353
354         pci_set_drvdata(pdev, 0);
355         free_netdev(ndev);
356         priv = 0;
357
358         pci_release_regions(pdev);
359
360         pci_disable_device(pdev);
361 }
362
363 int
364 prism54_suspend(struct pci_dev *pdev, u32 state)
365 {
366         struct net_device *ndev = pci_get_drvdata(pdev);
367         islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
368         BUG_ON(!priv);
369
370         printk(KERN_NOTICE "%s: got suspend request (state %d)\n",
371                ndev->name, state);
372
373         pci_save_state(pdev, priv->pci_state);
374
375         /* tell the device not to trigger interrupts for now... */
376         isl38xx_disable_interrupts(priv->device_base);
377
378         /* from now on assume the hardware was already powered down
379            and don't touch it anymore */
380         islpci_set_state(priv, PRV_STATE_OFF);
381
382         netif_stop_queue(ndev);
383         netif_device_detach(ndev);
384
385         return 0;
386 }
387
388 int
389 prism54_resume(struct pci_dev *pdev)
390 {
391         struct net_device *ndev = pci_get_drvdata(pdev);
392         islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
393         BUG_ON(!priv);
394
395         printk(KERN_NOTICE "%s: got resume request\n", ndev->name);
396
397         pci_restore_state(pdev, priv->pci_state);
398
399         /* alright let's go into the PREBOOT state */
400         islpci_reset(priv, 1);
401
402         netif_device_attach(ndev);
403         netif_start_queue(ndev);
404
405         return 0;
406 }
407
408 static int __init
409 prism54_module_init(void)
410 {
411         printk(KERN_INFO "Loaded %s driver, version %s\n",
412                DRV_NAME, DRV_VERSION);
413
414         __bug_on_wrong_struct_sizes ();
415
416         return pci_module_init(&prism54_driver);
417 }
418
419 /* by the time prism54_module_exit() terminates, as a postcondition
420  * all instances will have been destroyed by calls to
421  * prism54_remove() */
422 static void __exit
423 prism54_module_exit(void)
424 {
425         __in_cleanup_module = 1;
426
427         pci_unregister_driver(&prism54_driver);
428
429         printk(KERN_INFO "Unloaded %s driver\n", DRV_NAME);
430
431         __in_cleanup_module = 0;
432 }
433
434 /* register entry points */
435 module_init(prism54_module_init);
436 module_exit(prism54_module_exit);
437 /* EOF */