aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorPavel Roskin <proski@gnu.org>2006-04-07 04:10:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-04-24 16:15:52 -0400
commitb884c872fa1917614b42a39020ffcca7fa9302b1 (patch)
tree82f5ba67f6b38c96804fb449e018d83fbdce65a1 /drivers/net/wireless
parentc6fb2e9abef894efc4870e4c1e3aa4365b830a11 (diff)
[PATCH] orinoco: reduce differences between PCI drivers, create orinoco_pci.h
Make all Orinoco PCI drivers (orinoco_pci, orinoco_plx, orinoco_tmd and orinoco_nortel) as similar as possible. Use the best implementation of error handling, the best error messages, the best comments. Put common code to orinoco_pci.h. For now, it's suspend and resume functions and function for registering the network device. Signed-off-by: Pavel Roskin <proski@gnu.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/orinoco_nortel.c240
-rw-r--r--drivers/net/wireless/orinoco_pci.c144
-rw-r--r--drivers/net/wireless/orinoco_pci.h125
-rw-r--r--drivers/net/wireless/orinoco_plx.c259
-rw-r--r--drivers/net/wireless/orinoco_tmd.c165
5 files changed, 368 insertions, 565 deletions
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index 3fff013f6788..deb22fb35515 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -1,5 +1,5 @@
1/* orinoco_nortel.c 1/* orinoco_nortel.c
2 * 2 *
3 * Driver for Prism II devices which would usually be driven by orinoco_cs, 3 * Driver for Prism II devices which would usually be driven by orinoco_cs,
4 * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in 4 * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in
5 * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. 5 * Nortel emobility, Symbol LA-4113 and Symbol LA-4123.
@@ -50,17 +50,12 @@
50#include <pcmcia/cisreg.h> 50#include <pcmcia/cisreg.h>
51 51
52#include "orinoco.h" 52#include "orinoco.h"
53#include "orinoco_pci.h"
53 54
54#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ 55#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
55#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ 56#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
56 57
57 58
58/* Nortel specific data */
59struct nortel_pci_card {
60 unsigned long iobase1;
61 unsigned long iobase2;
62};
63
64/* 59/*
65 * Do a soft reset of the PCI card using the Configuration Option Register 60 * Do a soft reset of the PCI card using the Configuration Option Register
66 * We need this to get going... 61 * We need this to get going...
@@ -69,48 +64,48 @@ struct nortel_pci_card {
69 * Note bis : Don't try to access HERMES_CMD during the reset phase. 64 * Note bis : Don't try to access HERMES_CMD during the reset phase.
70 * It just won't work ! 65 * It just won't work !
71 */ 66 */
72static int nortel_pci_cor_reset(struct orinoco_private *priv) 67static int orinoco_nortel_cor_reset(struct orinoco_private *priv)
73{ 68{
74 struct nortel_pci_card *card = priv->card; 69 struct orinoco_pci_card *card = priv->card;
75 70
76 /* Assert the reset until the card notice */ 71 /* Assert the reset until the card notice */
77 outw_p(8, card->iobase1 + 2); 72 iowrite16(8, card->bridge_io + 2);
78 inw(card->iobase2 + COR_OFFSET); 73 ioread16(card->attr_io + COR_OFFSET);
79 outw_p(0x80, card->iobase2 + COR_OFFSET); 74 iowrite16(0x80, card->attr_io + COR_OFFSET);
80 mdelay(1); 75 mdelay(1);
81 76
82 /* Give time for the card to recover from this hard effort */ 77 /* Give time for the card to recover from this hard effort */
83 outw_p(0, card->iobase2 + COR_OFFSET); 78 iowrite16(0, card->attr_io + COR_OFFSET);
84 outw_p(0, card->iobase2 + COR_OFFSET); 79 iowrite16(0, card->attr_io + COR_OFFSET);
85 mdelay(1); 80 mdelay(1);
86 81
87 /* set COR as usual */ 82 /* Set COR as usual */
88 outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); 83 iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
89 outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); 84 iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
90 mdelay(1); 85 mdelay(1);
91 86
92 outw_p(0x228, card->iobase1 + 2); 87 iowrite16(0x228, card->bridge_io + 2);
93 88
94 return 0; 89 return 0;
95} 90}
96 91
97static int nortel_pci_hw_init(struct nortel_pci_card *card) 92static int orinoco_nortel_hw_init(struct orinoco_pci_card *card)
98{ 93{
99 int i; 94 int i;
100 u32 reg; 95 u32 reg;
101 96
102 /* setup bridge */ 97 /* Setup bridge */
103 if (inw(card->iobase1) & 1) { 98 if (ioread16(card->bridge_io) & 1) {
104 printk(KERN_ERR PFX "brg1 answer1 wrong\n"); 99 printk(KERN_ERR PFX "brg1 answer1 wrong\n");
105 return -EBUSY; 100 return -EBUSY;
106 } 101 }
107 outw_p(0x118, card->iobase1 + 2); 102 iowrite16(0x118, card->bridge_io + 2);
108 outw_p(0x108, card->iobase1 + 2); 103 iowrite16(0x108, card->bridge_io + 2);
109 mdelay(30); 104 mdelay(30);
110 outw_p(0x8, card->iobase1 + 2); 105 iowrite16(0x8, card->bridge_io + 2);
111 for (i = 0; i < 30; i++) { 106 for (i = 0; i < 30; i++) {
112 mdelay(30); 107 mdelay(30);
113 if (inw(card->iobase1) & 0x10) { 108 if (ioread16(card->bridge_io) & 0x10) {
114 break; 109 break;
115 } 110 }
116 } 111 }
@@ -118,42 +113,42 @@ static int nortel_pci_hw_init(struct nortel_pci_card *card)
118 printk(KERN_ERR PFX "brg1 timed out\n"); 113 printk(KERN_ERR PFX "brg1 timed out\n");
119 return -EBUSY; 114 return -EBUSY;
120 } 115 }
121 if (inw(card->iobase2 + 0xe0) & 1) { 116 if (ioread16(card->attr_io + COR_OFFSET) & 1) {
122 printk(KERN_ERR PFX "brg2 answer1 wrong\n"); 117 printk(KERN_ERR PFX "brg2 answer1 wrong\n");
123 return -EBUSY; 118 return -EBUSY;
124 } 119 }
125 if (inw(card->iobase2 + 0xe2) & 1) { 120 if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) {
126 printk(KERN_ERR PFX "brg2 answer2 wrong\n"); 121 printk(KERN_ERR PFX "brg2 answer2 wrong\n");
127 return -EBUSY; 122 return -EBUSY;
128 } 123 }
129 if (inw(card->iobase2 + 0xe4) & 1) { 124 if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) {
130 printk(KERN_ERR PFX "brg2 answer3 wrong\n"); 125 printk(KERN_ERR PFX "brg2 answer3 wrong\n");
131 return -EBUSY; 126 return -EBUSY;
132 } 127 }
133 128
134 /* set the PCMCIA COR-Register */ 129 /* Set the PCMCIA COR-Register */
135 outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); 130 iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
136 mdelay(1); 131 mdelay(1);
137 reg = inw(card->iobase2 + COR_OFFSET); 132 reg = ioread16(card->attr_io + COR_OFFSET);
138 if (reg != COR_VALUE) { 133 if (reg != COR_VALUE) {
139 printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", 134 printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
140 reg); 135 reg);
141 return -EBUSY; 136 return -EBUSY;
142 } 137 }
143 138
144 /* set leds */ 139 /* Set LEDs */
145 outw_p(1, card->iobase1 + 10); 140 iowrite16(1, card->bridge_io + 10);
146 return 0; 141 return 0;
147} 142}
148 143
149static int nortel_pci_init_one(struct pci_dev *pdev, 144static int orinoco_nortel_init_one(struct pci_dev *pdev,
150 const struct pci_device_id *ent) 145 const struct pci_device_id *ent)
151{ 146{
152 int err; 147 int err;
153 struct orinoco_private *priv; 148 struct orinoco_private *priv;
154 struct nortel_pci_card *card; 149 struct orinoco_pci_card *card;
155 struct net_device *dev; 150 struct net_device *dev;
156 void __iomem *iomem; 151 void __iomem *hermes_io, *bridge_io, *attr_io;
157 152
158 err = pci_enable_device(pdev); 153 err = pci_enable_device(pdev);
159 if (err) { 154 if (err) {
@@ -162,19 +157,34 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
162 } 157 }
163 158
164 err = pci_request_regions(pdev, DRIVER_NAME); 159 err = pci_request_regions(pdev, DRIVER_NAME);
165 if (err != 0) { 160 if (err) {
166 printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 161 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
167 goto fail_resources; 162 goto fail_resources;
168 } 163 }
169 164
170 iomem = pci_iomap(pdev, 2, 0); 165 bridge_io = pci_iomap(pdev, 0, 0);
171 if (!iomem) { 166 if (!bridge_io) {
172 err = -ENOMEM; 167 printk(KERN_ERR PFX "Cannot map bridge registers\n");
173 goto fail_map_io; 168 err = -EIO;
169 goto fail_map_bridge;
170 }
171
172 attr_io = pci_iomap(pdev, 1, 0);
173 if (!attr_io) {
174 printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
175 err = -EIO;
176 goto fail_map_attr;
177 }
178
179 hermes_io = pci_iomap(pdev, 2, 0);
180 if (!hermes_io) {
181 printk(KERN_ERR PFX "Cannot map chipset registers\n");
182 err = -EIO;
183 goto fail_map_hermes;
174 } 184 }
175 185
176 /* Allocate network device */ 186 /* Allocate network device */
177 dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset); 187 dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset);
178 if (!dev) { 188 if (!dev) {
179 printk(KERN_ERR PFX "Cannot allocate network device\n"); 189 printk(KERN_ERR PFX "Cannot allocate network device\n");
180 err = -ENOMEM; 190 err = -ENOMEM;
@@ -183,16 +193,12 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
183 193
184 priv = netdev_priv(dev); 194 priv = netdev_priv(dev);
185 card = priv->card; 195 card = priv->card;
186 card->iobase1 = pci_resource_start(pdev, 0); 196 card->bridge_io = bridge_io;
187 card->iobase2 = pci_resource_start(pdev, 1); 197 card->attr_io = attr_io;
188 dev->base_addr = pci_resource_start(pdev, 2);
189 SET_MODULE_OWNER(dev); 198 SET_MODULE_OWNER(dev);
190 SET_NETDEV_DEV(dev, &pdev->dev); 199 SET_NETDEV_DEV(dev, &pdev->dev);
191 200
192 hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING); 201 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
193
194 printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
195 "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
196 202
197 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, 203 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
198 dev->name, dev); 204 dev->name, dev);
@@ -201,21 +207,20 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
201 err = -EBUSY; 207 err = -EBUSY;
202 goto fail_irq; 208 goto fail_irq;
203 } 209 }
204 dev->irq = pdev->irq; 210 orinoco_pci_setup_netdev(dev, pdev, 2);
205 211
206 err = nortel_pci_hw_init(card); 212 err = orinoco_nortel_hw_init(card);
207 if (err) { 213 if (err) {
208 printk(KERN_ERR PFX "Hardware initialization failed\n"); 214 printk(KERN_ERR PFX "Hardware initialization failed\n");
209 goto fail; 215 goto fail;
210 } 216 }
211 217
212 err = nortel_pci_cor_reset(priv); 218 err = orinoco_nortel_cor_reset(priv);
213 if (err) { 219 if (err) {
214 printk(KERN_ERR PFX "Initial reset failed\n"); 220 printk(KERN_ERR PFX "Initial reset failed\n");
215 goto fail; 221 goto fail;
216 } 222 }
217 223
218
219 err = register_netdev(dev); 224 err = register_netdev(dev);
220 if (err) { 225 if (err) {
221 printk(KERN_ERR PFX "Cannot register network device\n"); 226 printk(KERN_ERR PFX "Cannot register network device\n");
@@ -234,9 +239,15 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
234 free_orinocodev(dev); 239 free_orinocodev(dev);
235 240
236 fail_alloc: 241 fail_alloc:
237 pci_iounmap(pdev, iomem); 242 pci_iounmap(pdev, hermes_io);
243
244 fail_map_hermes:
245 pci_iounmap(pdev, attr_io);
246
247 fail_map_attr:
248 pci_iounmap(pdev, bridge_io);
238 249
239 fail_map_io: 250 fail_map_bridge:
240 pci_release_regions(pdev); 251 pci_release_regions(pdev);
241 252
242 fail_resources: 253 fail_resources:
@@ -245,103 +256,27 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
245 return err; 256 return err;
246} 257}
247 258
248static void __devexit nortel_pci_remove_one(struct pci_dev *pdev) 259static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
249{ 260{
250 struct net_device *dev = pci_get_drvdata(pdev); 261 struct net_device *dev = pci_get_drvdata(pdev);
251 struct orinoco_private *priv = netdev_priv(dev); 262 struct orinoco_private *priv = netdev_priv(dev);
252 struct nortel_pci_card *card = priv->card; 263 struct orinoco_pci_card *card = priv->card;
253 264
254 /* clear leds */ 265 /* Clear LEDs */
255 outw_p(0, card->iobase1 + 10); 266 iowrite16(0, card->bridge_io + 10);
256 267
257 unregister_netdev(dev); 268 unregister_netdev(dev);
258 free_irq(dev->irq, dev); 269 free_irq(dev->irq, dev);
259 pci_set_drvdata(pdev, NULL); 270 pci_set_drvdata(pdev, NULL);
260 free_orinocodev(dev); 271 free_orinocodev(dev);
261 pci_iounmap(pdev, priv->hw.iobase); 272 pci_iounmap(pdev, priv->hw.iobase);
273 pci_iounmap(pdev, card->attr_io);
274 pci_iounmap(pdev, card->bridge_io);
262 pci_release_regions(pdev); 275 pci_release_regions(pdev);
263 pci_disable_device(pdev); 276 pci_disable_device(pdev);
264} 277}
265 278
266static int orinoco_nortel_suspend(struct pci_dev *pdev, pm_message_t state) 279static struct pci_device_id orinoco_nortel_id_table[] = {
267{
268 struct net_device *dev = pci_get_drvdata(pdev);
269 struct orinoco_private *priv = netdev_priv(dev);
270 unsigned long flags;
271 int err;
272
273 err = orinoco_lock(priv, &flags);
274 if (err) {
275 printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
276 dev->name);
277 return err;
278 }
279
280 err = __orinoco_down(dev);
281 if (err)
282 printk(KERN_WARNING "%s: error %d bringing interface down "
283 "for suspend\n", dev->name, err);
284
285 netif_device_detach(dev);
286
287 priv->hw_unavailable++;
288
289 orinoco_unlock(priv, &flags);
290
291 free_irq(pdev->irq, dev);
292 pci_save_state(pdev);
293 pci_disable_device(pdev);
294 pci_set_power_state(pdev, PCI_D3hot);
295
296 return 0;
297}
298
299static int orinoco_nortel_resume(struct pci_dev *pdev)
300{
301 struct net_device *dev = pci_get_drvdata(pdev);
302 struct orinoco_private *priv = netdev_priv(dev);
303 unsigned long flags;
304 int err;
305
306 pci_set_power_state(pdev, 0);
307 pci_enable_device(pdev);
308 pci_restore_state(pdev);
309
310 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
311 dev->name, dev);
312 if (err) {
313 printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
314 dev->name);
315 pci_disable_device(pdev);
316 return -EBUSY;
317 }
318
319 err = orinoco_reinit_firmware(dev);
320 if (err) {
321 printk(KERN_ERR "%s: error %d re-initializing firmware "
322 "on resume\n", dev->name, err);
323 return err;
324 }
325
326 spin_lock_irqsave(&priv->lock, flags);
327
328 netif_device_attach(dev);
329
330 priv->hw_unavailable--;
331
332 if (priv->open && (! priv->hw_unavailable)) {
333 err = __orinoco_up(dev);
334 if (err)
335 printk(KERN_ERR "%s: Error %d restarting card on resume\n",
336 dev->name, err);
337 }
338
339 spin_unlock_irqrestore(&priv->lock, flags);
340
341 return 0;
342}
343
344static struct pci_device_id nortel_pci_id_table[] = {
345 /* Nortel emobility PCI */ 280 /* Nortel emobility PCI */
346 {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, 281 {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
347 /* Symbol LA-4123 PCI */ 282 /* Symbol LA-4123 PCI */
@@ -349,15 +284,15 @@ static struct pci_device_id nortel_pci_id_table[] = {
349 {0,}, 284 {0,},
350}; 285};
351 286
352MODULE_DEVICE_TABLE(pci, nortel_pci_id_table); 287MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table);
353 288
354static struct pci_driver nortel_pci_driver = { 289static struct pci_driver orinoco_nortel_driver = {
355 .name = DRIVER_NAME, 290 .name = DRIVER_NAME,
356 .id_table = nortel_pci_id_table, 291 .id_table = orinoco_nortel_id_table,
357 .probe = nortel_pci_init_one, 292 .probe = orinoco_nortel_init_one,
358 .remove = __devexit_p(nortel_pci_remove_one), 293 .remove = __devexit_p(orinoco_nortel_remove_one),
359 .suspend = orinoco_nortel_suspend, 294 .suspend = orinoco_pci_suspend,
360 .resume = orinoco_nortel_resume, 295 .resume = orinoco_pci_resume,
361}; 296};
362 297
363static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 298static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -367,20 +302,19 @@ MODULE_DESCRIPTION
367 ("Driver for wireless LAN cards using the Nortel PCI bridge"); 302 ("Driver for wireless LAN cards using the Nortel PCI bridge");
368MODULE_LICENSE("Dual MPL/GPL"); 303MODULE_LICENSE("Dual MPL/GPL");
369 304
370static int __init nortel_pci_init(void) 305static int __init orinoco_nortel_init(void)
371{ 306{
372 printk(KERN_DEBUG "%s\n", version); 307 printk(KERN_DEBUG "%s\n", version);
373 return pci_module_init(&nortel_pci_driver); 308 return pci_module_init(&orinoco_nortel_driver);
374} 309}
375 310
376static void __exit nortel_pci_exit(void) 311static void __exit orinoco_nortel_exit(void)
377{ 312{
378 pci_unregister_driver(&nortel_pci_driver); 313 pci_unregister_driver(&orinoco_nortel_driver);
379 ssleep(1);
380} 314}
381 315
382module_init(nortel_pci_init); 316module_init(orinoco_nortel_init);
383module_exit(nortel_pci_exit); 317module_exit(orinoco_nortel_exit);
384 318
385/* 319/*
386 * Local variables: 320 * Local variables:
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 75df90ff1dc9..41efac22ba6a 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -100,6 +100,7 @@
100#include <linux/pci.h> 100#include <linux/pci.h>
101 101
102#include "orinoco.h" 102#include "orinoco.h"
103#include "orinoco_pci.h"
103 104
104/* All the magic there is from wlan-ng */ 105/* All the magic there is from wlan-ng */
105/* Magic offset of the reset register of the PCI card */ 106/* Magic offset of the reset register of the PCI card */
@@ -113,11 +114,6 @@
113#define HERMES_PCI_COR_OFFT (500) /* ms */ 114#define HERMES_PCI_COR_OFFT (500) /* ms */
114#define HERMES_PCI_COR_BUSYT (500) /* ms */ 115#define HERMES_PCI_COR_BUSYT (500) /* ms */
115 116
116/* Orinoco PCI specific data */
117struct orinoco_pci_card {
118 void __iomem *pci_ioaddr;
119};
120
121/* 117/*
122 * Do a soft reset of the PCI card using the Configuration Option Register 118 * Do a soft reset of the PCI card using the Configuration Option Register
123 * We need this to get going... 119 * We need this to get going...
@@ -131,12 +127,11 @@ struct orinoco_pci_card {
131 * Note bis : Don't try to access HERMES_CMD during the reset phase. 127 * Note bis : Don't try to access HERMES_CMD during the reset phase.
132 * It just won't work ! 128 * It just won't work !
133 */ 129 */
134static int 130static int orinoco_pci_cor_reset(struct orinoco_private *priv)
135orinoco_pci_cor_reset(struct orinoco_private *priv)
136{ 131{
137 hermes_t *hw = &priv->hw; 132 hermes_t *hw = &priv->hw;
138 unsigned long timeout; 133 unsigned long timeout;
139 u16 reg; 134 u16 reg;
140 135
141 /* Assert the reset until the card notice */ 136 /* Assert the reset until the card notice */
142 hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); 137 hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
@@ -163,17 +158,14 @@ orinoco_pci_cor_reset(struct orinoco_private *priv)
163 return 0; 158 return 0;
164} 159}
165 160
166/*
167 * Initialise a card. Mostly similar to PLX code.
168 */
169static int orinoco_pci_init_one(struct pci_dev *pdev, 161static int orinoco_pci_init_one(struct pci_dev *pdev,
170 const struct pci_device_id *ent) 162 const struct pci_device_id *ent)
171{ 163{
172 int err = 0; 164 int err;
173 void __iomem *pci_ioaddr = NULL; 165 struct orinoco_private *priv;
174 struct orinoco_private *priv = NULL;
175 struct orinoco_pci_card *card; 166 struct orinoco_pci_card *card;
176 struct net_device *dev = NULL; 167 struct net_device *dev;
168 void __iomem *hermes_io;
177 169
178 err = pci_enable_device(pdev); 170 err = pci_enable_device(pdev);
179 if (err) { 171 if (err) {
@@ -182,38 +174,32 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
182 } 174 }
183 175
184 err = pci_request_regions(pdev, DRIVER_NAME); 176 err = pci_request_regions(pdev, DRIVER_NAME);
185 if (err != 0) { 177 if (err) {
186 printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 178 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
187 goto fail_resources; 179 goto fail_resources;
188 } 180 }
189 181
190 /* Resource 0 is mapped to the hermes registers */ 182 hermes_io = pci_iomap(pdev, 0, 0);
191 pci_ioaddr = pci_iomap(pdev, 0, 0); 183 if (!hermes_io) {
192 if (!pci_ioaddr) { 184 printk(KERN_ERR PFX "Cannot remap chipset registers\n");
193 err = -EIO; 185 err = -EIO;
194 printk(KERN_ERR PFX "Cannot remap hardware registers\n"); 186 goto fail_map_hermes;
195 goto fail_map;
196 } 187 }
197 188
198 /* Allocate network device */ 189 /* Allocate network device */
199 dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); 190 dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
200 if (! dev) { 191 if (!dev) {
192 printk(KERN_ERR PFX "Cannot allocate network device\n");
201 err = -ENOMEM; 193 err = -ENOMEM;
202 goto fail_alloc; 194 goto fail_alloc;
203 } 195 }
204 196
205 priv = netdev_priv(dev); 197 priv = netdev_priv(dev);
206 card = priv->card; 198 card = priv->card;
207 card->pci_ioaddr = pci_ioaddr;
208 dev->mem_start = pci_resource_start(pdev, 0);
209 dev->mem_end = dev->mem_start + pci_resource_len(pdev, 0) - 1;
210 SET_MODULE_OWNER(dev); 199 SET_MODULE_OWNER(dev);
211 SET_NETDEV_DEV(dev, &pdev->dev); 200 SET_NETDEV_DEV(dev, &pdev->dev);
212 201
213 hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING); 202 hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
214
215 printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n",
216 pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq);
217 203
218 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, 204 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
219 dev->name, dev); 205 dev->name, dev);
@@ -222,9 +208,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
222 err = -EBUSY; 208 err = -EBUSY;
223 goto fail_irq; 209 goto fail_irq;
224 } 210 }
225 dev->irq = pdev->irq; 211 orinoco_pci_setup_netdev(dev, pdev, 0);
226 212
227 /* Perform a COR reset to start the card */
228 err = orinoco_pci_cor_reset(priv); 213 err = orinoco_pci_cor_reset(priv);
229 if (err) { 214 if (err) {
230 printk(KERN_ERR PFX "Initial reset failed\n"); 215 printk(KERN_ERR PFX "Initial reset failed\n");
@@ -233,7 +218,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
233 218
234 err = register_netdev(dev); 219 err = register_netdev(dev);
235 if (err) { 220 if (err) {
236 printk(KERN_ERR PFX "Failed to register net device\n"); 221 printk(KERN_ERR PFX "Cannot register network device\n");
237 goto fail; 222 goto fail;
238 } 223 }
239 224
@@ -249,9 +234,9 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
249 free_orinocodev(dev); 234 free_orinocodev(dev);
250 235
251 fail_alloc: 236 fail_alloc:
252 iounmap(pci_ioaddr); 237 pci_iounmap(pdev, hermes_io);
253 238
254 fail_map: 239 fail_map_hermes:
255 pci_release_regions(pdev); 240 pci_release_regions(pdev);
256 241
257 fail_resources: 242 fail_resources:
@@ -264,98 +249,17 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
264{ 249{
265 struct net_device *dev = pci_get_drvdata(pdev); 250 struct net_device *dev = pci_get_drvdata(pdev);
266 struct orinoco_private *priv = netdev_priv(dev); 251 struct orinoco_private *priv = netdev_priv(dev);
267 struct orinoco_pci_card *card = priv->card;
268 252
269 unregister_netdev(dev); 253 unregister_netdev(dev);
270 free_irq(dev->irq, dev); 254 free_irq(dev->irq, dev);
271 pci_set_drvdata(pdev, NULL); 255 pci_set_drvdata(pdev, NULL);
272 free_orinocodev(dev); 256 free_orinocodev(dev);
273 iounmap(card->pci_ioaddr); 257 pci_iounmap(pdev, priv->hw.iobase);
274 pci_release_regions(pdev); 258 pci_release_regions(pdev);
275 pci_disable_device(pdev); 259 pci_disable_device(pdev);
276} 260}
277 261
278static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) 262static struct pci_device_id orinoco_pci_id_table[] = {
279{
280 struct net_device *dev = pci_get_drvdata(pdev);
281 struct orinoco_private *priv = netdev_priv(dev);
282 unsigned long flags;
283 int err;
284
285
286 err = orinoco_lock(priv, &flags);
287 if (err) {
288 printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n",
289 dev->name);
290 return err;
291 }
292
293 err = __orinoco_down(dev);
294 if (err)
295 printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n",
296 dev->name, err);
297
298 netif_device_detach(dev);
299
300 priv->hw_unavailable++;
301
302 orinoco_unlock(priv, &flags);
303
304 free_irq(pdev->irq, dev);
305 pci_save_state(pdev);
306 pci_disable_device(pdev);
307 pci_set_power_state(pdev, PCI_D3hot);
308
309 return 0;
310}
311
312static int orinoco_pci_resume(struct pci_dev *pdev)
313{
314 struct net_device *dev = pci_get_drvdata(pdev);
315 struct orinoco_private *priv = netdev_priv(dev);
316 unsigned long flags;
317 int err;
318
319 printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);
320
321 pci_set_power_state(pdev, 0);
322 pci_enable_device(pdev);
323 pci_restore_state(pdev);
324
325 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
326 dev->name, dev);
327 if (err) {
328 printk(KERN_ERR "%s: Cannot re-allocate IRQ\n", dev->name);
329 pci_disable_device(pdev);
330 return -EBUSY;
331 }
332
333 err = orinoco_reinit_firmware(dev);
334 if (err) {
335 printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n",
336 dev->name, err);
337 return err;
338 }
339
340 spin_lock_irqsave(&priv->lock, flags);
341
342 netif_device_attach(dev);
343
344 priv->hw_unavailable--;
345
346 if (priv->open && (! priv->hw_unavailable)) {
347 err = __orinoco_up(dev);
348 if (err)
349 printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n",
350 dev->name, err);
351 }
352
353 spin_unlock_irqrestore(&priv->lock, flags);
354
355 return 0;
356}
357
358static struct pci_device_id orinoco_pci_pci_id_table[] = {
359 /* Intersil Prism 3 */ 263 /* Intersil Prism 3 */
360 {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, 264 {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
361 /* Intersil Prism 2.5 */ 265 /* Intersil Prism 2.5 */
@@ -365,11 +269,11 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = {
365 {0,}, 269 {0,},
366}; 270};
367 271
368MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table); 272MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);
369 273
370static struct pci_driver orinoco_pci_driver = { 274static struct pci_driver orinoco_pci_driver = {
371 .name = DRIVER_NAME, 275 .name = DRIVER_NAME,
372 .id_table = orinoco_pci_pci_id_table, 276 .id_table = orinoco_pci_id_table,
373 .probe = orinoco_pci_init_one, 277 .probe = orinoco_pci_init_one,
374 .remove = __devexit_p(orinoco_pci_remove_one), 278 .remove = __devexit_p(orinoco_pci_remove_one),
375 .suspend = orinoco_pci_suspend, 279 .suspend = orinoco_pci_suspend,
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h
new file mode 100644
index 000000000000..b05a9a5b1f5f
--- /dev/null
+++ b/drivers/net/wireless/orinoco_pci.h
@@ -0,0 +1,125 @@
1/* orinoco_pci.h
2 *
3 * Common code for all Orinoco drivers for PCI devices, including
4 * both native PCI and PCMCIA-to-PCI bridges.
5 *
6 * Copyright (C) 2005, Pavel Roskin.
7 * See orinoco.c for license.
8 */
9
10#ifndef _ORINOCO_PCI_H
11#define _ORINOCO_PCI_H
12
13#include <linux/netdevice.h>
14
15/* Driver specific data */
16struct orinoco_pci_card {
17 void __iomem *bridge_io;
18 void __iomem *attr_io;
19};
20
21/* Set base address or memory range of the network device based on
22 * the PCI device it's using. Specify BAR of the "main" resource.
23 * To be used after request_irq(). */
24static inline void orinoco_pci_setup_netdev(struct net_device *dev,
25 struct pci_dev *pdev, int bar)
26{
27 char *range_type;
28 unsigned long start = pci_resource_start(pdev, bar);
29 unsigned long len = pci_resource_len(pdev, bar);
30 unsigned long flags = pci_resource_flags(pdev, bar);
31 unsigned long end = start + len - 1;
32
33 dev->irq = pdev->irq;
34 if (flags & IORESOURCE_IO) {
35 dev->base_addr = start;
36 range_type = "ports";
37 } else {
38 dev->mem_start = start;
39 dev->mem_end = end;
40 range_type = "memory";
41 }
42
43 printk(KERN_DEBUG PFX "%s: irq %d, %s 0x%lx-0x%lx\n",
44 pci_name(pdev), pdev->irq, range_type, start, end);
45}
46
47static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
48{
49 struct net_device *dev = pci_get_drvdata(pdev);
50 struct orinoco_private *priv = netdev_priv(dev);
51 unsigned long flags;
52 int err;
53
54 err = orinoco_lock(priv, &flags);
55 if (err) {
56 printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
57 dev->name);
58 return err;
59 }
60
61 err = __orinoco_down(dev);
62 if (err)
63 printk(KERN_WARNING "%s: error %d bringing interface down "
64 "for suspend\n", dev->name, err);
65
66 netif_device_detach(dev);
67
68 priv->hw_unavailable++;
69
70 orinoco_unlock(priv, &flags);
71
72 free_irq(pdev->irq, dev);
73 pci_save_state(pdev);
74 pci_disable_device(pdev);
75 pci_set_power_state(pdev, PCI_D3hot);
76
77 return 0;
78}
79
80static int orinoco_pci_resume(struct pci_dev *pdev)
81{
82 struct net_device *dev = pci_get_drvdata(pdev);
83 struct orinoco_private *priv = netdev_priv(dev);
84 unsigned long flags;
85 int err;
86
87 pci_set_power_state(pdev, 0);
88 pci_enable_device(pdev);
89 pci_restore_state(pdev);
90
91 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
92 dev->name, dev);
93 if (err) {
94 printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
95 dev->name);
96 pci_disable_device(pdev);
97 return -EBUSY;
98 }
99
100 err = orinoco_reinit_firmware(dev);
101 if (err) {
102 printk(KERN_ERR "%s: error %d re-initializing firmware "
103 "on resume\n", dev->name, err);
104 return err;
105 }
106
107 spin_lock_irqsave(&priv->lock, flags);
108
109 netif_device_attach(dev);
110
111 priv->hw_unavailable--;
112
113 if (priv->open && (! priv->hw_unavailable)) {
114 err = __orinoco_up(dev);
115 if (err)
116 printk(KERN_ERR "%s: Error %d restarting card on resume\n",
117 dev->name, err);
118 }
119
120 spin_unlock_irqrestore(&priv->lock, flags);
121
122 return 0;
123}
124
125#endif /* _ORINOCO_PCI_H */
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 3fe7a2f37896..c00388ec9460 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -33,7 +33,7 @@
33 33
34 * Caution: this is experimental and probably buggy. For success and 34 * Caution: this is experimental and probably buggy. For success and
35 * failure reports for different cards and adaptors, see 35 * failure reports for different cards and adaptors, see
36 * orinoco_plx_pci_id_table near the end of the file. If you have a 36 * orinoco_plx_id_table near the end of the file. If you have a
37 * card we don't have the PCI id for, and looks like it should work, 37 * card we don't have the PCI id for, and looks like it should work,
38 * drop me mail with the id and "it works"/"it doesn't work". 38 * drop me mail with the id and "it works"/"it doesn't work".
39 * 39 *
@@ -125,6 +125,7 @@
125#include <pcmcia/cisreg.h> 125#include <pcmcia/cisreg.h>
126 126
127#include "orinoco.h" 127#include "orinoco.h"
128#include "orinoco_pci.h"
128 129
129#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */ 130#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */
130#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ 131#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
@@ -134,30 +135,20 @@
134#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ 135#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */
135#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ 136#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
136 137
137static const u8 cis_magic[] = {
138 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
139};
140
141/* Orinoco PLX specific data */
142struct orinoco_plx_card {
143 void __iomem *attr_mem;
144};
145
146/* 138/*
147 * Do a soft reset of the card using the Configuration Option Register 139 * Do a soft reset of the card using the Configuration Option Register
148 */ 140 */
149static int orinoco_plx_cor_reset(struct orinoco_private *priv) 141static int orinoco_plx_cor_reset(struct orinoco_private *priv)
150{ 142{
151 hermes_t *hw = &priv->hw; 143 hermes_t *hw = &priv->hw;
152 struct orinoco_plx_card *card = priv->card; 144 struct orinoco_pci_card *card = priv->card;
153 u8 __iomem *attr_mem = card->attr_mem;
154 unsigned long timeout; 145 unsigned long timeout;
155 u16 reg; 146 u16 reg;
156 147
157 writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET); 148 iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET);
158 mdelay(1); 149 mdelay(1);
159 150
160 writeb(COR_VALUE, attr_mem + COR_OFFSET); 151 iowrite8(COR_VALUE, card->attr_io + COR_OFFSET);
161 mdelay(1); 152 mdelay(1);
162 153
163 /* Just in case, wait more until the card is no longer busy */ 154 /* Just in case, wait more until the card is no longer busy */
@@ -168,7 +159,7 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv)
168 reg = hermes_read_regn(hw, CMD); 159 reg = hermes_read_regn(hw, CMD);
169 } 160 }
170 161
171 /* Did we timeout ? */ 162 /* Still busy? */
172 if (reg & HERMES_CMD_BUSY) { 163 if (reg & HERMES_CMD_BUSY) {
173 printk(KERN_ERR PFX "Busy timeout\n"); 164 printk(KERN_ERR PFX "Busy timeout\n");
174 return -ETIMEDOUT; 165 return -ETIMEDOUT;
@@ -177,20 +168,55 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv)
177 return 0; 168 return 0;
178} 169}
179 170
171static int orinoco_plx_hw_init(struct orinoco_pci_card *card)
172{
173 int i;
174 u32 csr_reg;
175 static const u8 cis_magic[] = {
176 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
177 };
178
179 printk(KERN_DEBUG PFX "CIS: ");
180 for (i = 0; i < 16; i++) {
181 printk("%02X:", ioread8(card->attr_io + (i << 1)));
182 }
183 printk("\n");
184
185 /* Verify whether a supported PC card is present */
186 /* FIXME: we probably need to be smarted about this */
187 for (i = 0; i < sizeof(cis_magic); i++) {
188 if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) {
189 printk(KERN_ERR PFX "The CIS value of Prism2 PC "
190 "card is unexpected\n");
191 return -ENODEV;
192 }
193 }
194
195 /* bjoern: We need to tell the card to enable interrupts, in
196 case the serial eprom didn't do this already. See the
197 PLX9052 data book, p8-1 and 8-24 for reference. */
198 csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
199 if (!(csr_reg & PLX_INTCSR_INTEN)) {
200 csr_reg |= PLX_INTCSR_INTEN;
201 iowrite32(csr_reg, card->bridge_io + PLX_INTCSR);
202 csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
203 if (!(csr_reg & PLX_INTCSR_INTEN)) {
204 printk(KERN_ERR PFX "Cannot enable interrupts\n");
205 return -EIO;
206 }
207 }
208
209 return 0;
210}
180 211
181static int orinoco_plx_init_one(struct pci_dev *pdev, 212static int orinoco_plx_init_one(struct pci_dev *pdev,
182 const struct pci_device_id *ent) 213 const struct pci_device_id *ent)
183{ 214{
184 int err = 0; 215 int err;
185 u8 __iomem *attr_mem = NULL; 216 struct orinoco_private *priv;
186 u32 csr_reg, plx_addr; 217 struct orinoco_pci_card *card;
187 struct orinoco_private *priv = NULL; 218 struct net_device *dev;
188 struct orinoco_plx_card *card; 219 void __iomem *hermes_io, *attr_io, *bridge_io;
189 unsigned long pccard_ioaddr = 0;
190 unsigned long pccard_iolen = 0;
191 struct net_device *dev = NULL;
192 void __iomem *mem;
193 int i;
194 220
195 err = pci_enable_device(pdev); 221 err = pci_enable_device(pdev);
196 if (err) { 222 if (err) {
@@ -199,30 +225,30 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
199 } 225 }
200 226
201 err = pci_request_regions(pdev, DRIVER_NAME); 227 err = pci_request_regions(pdev, DRIVER_NAME);
202 if (err != 0) { 228 if (err) {
203 printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 229 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
204 goto fail_resources; 230 goto fail_resources;
205 } 231 }
206 232
207 /* Resource 1 is mapped to PLX-specific registers */ 233 bridge_io = pci_iomap(pdev, 1, 0);
208 plx_addr = pci_resource_start(pdev, 1); 234 if (!bridge_io) {
235 printk(KERN_ERR PFX "Cannot map bridge registers\n");
236 err = -EIO;
237 goto fail_map_bridge;
238 }
209 239
210 /* Resource 2 is mapped to the PCMCIA attribute memory */ 240 attr_io = pci_iomap(pdev, 2, 0);
211 attr_mem = ioremap(pci_resource_start(pdev, 2), 241 if (!attr_io) {
212 pci_resource_len(pdev, 2)); 242 printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
213 if (!attr_mem) { 243 err = -EIO;
214 printk(KERN_ERR PFX "Cannot remap PCMCIA space\n");
215 goto fail_map_attr; 244 goto fail_map_attr;
216 } 245 }
217 246
218 /* Resource 3 is mapped to the PCMCIA I/O address space */ 247 hermes_io = pci_iomap(pdev, 3, 0);
219 pccard_ioaddr = pci_resource_start(pdev, 3); 248 if (!hermes_io) {
220 pccard_iolen = pci_resource_len(pdev, 3); 249 printk(KERN_ERR PFX "Cannot map chipset registers\n");
221 250 err = -EIO;
222 mem = pci_iomap(pdev, 3, 0); 251 goto fail_map_hermes;
223 if (!mem) {
224 err = -ENOMEM;
225 goto fail_map_io;
226 } 252 }
227 253
228 /* Allocate network device */ 254 /* Allocate network device */
@@ -235,16 +261,12 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
235 261
236 priv = netdev_priv(dev); 262 priv = netdev_priv(dev);
237 card = priv->card; 263 card = priv->card;
238 card->attr_mem = attr_mem; 264 card->bridge_io = bridge_io;
239 dev->base_addr = pccard_ioaddr; 265 card->attr_io = attr_io;
240 SET_MODULE_OWNER(dev); 266 SET_MODULE_OWNER(dev);
241 SET_NETDEV_DEV(dev, &pdev->dev); 267 SET_NETDEV_DEV(dev, &pdev->dev);
242 268
243 hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); 269 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
244
245 printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device "
246 "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
247 pccard_ioaddr);
248 270
249 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, 271 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
250 dev->name, dev); 272 dev->name, dev);
@@ -253,20 +275,12 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
253 err = -EBUSY; 275 err = -EBUSY;
254 goto fail_irq; 276 goto fail_irq;
255 } 277 }
256 dev->irq = pdev->irq; 278 orinoco_pci_setup_netdev(dev, pdev, 2);
257 279
258 /* bjoern: We need to tell the card to enable interrupts, in 280 err = orinoco_plx_hw_init(card);
259 case the serial eprom didn't do this already. See the 281 if (err) {
260 PLX9052 data book, p8-1 and 8-24 for reference. */ 282 printk(KERN_ERR PFX "Hardware initialization failed\n");
261 csr_reg = inl(plx_addr + PLX_INTCSR); 283 goto fail;
262 if (!(csr_reg & PLX_INTCSR_INTEN)) {
263 csr_reg |= PLX_INTCSR_INTEN;
264 outl(csr_reg, plx_addr + PLX_INTCSR);
265 csr_reg = inl(plx_addr + PLX_INTCSR);
266 if (!(csr_reg & PLX_INTCSR_INTEN)) {
267 printk(KERN_ERR PFX "Cannot enable interrupts\n");
268 goto fail;
269 }
270 } 284 }
271 285
272 err = orinoco_plx_cor_reset(priv); 286 err = orinoco_plx_cor_reset(priv);
@@ -275,23 +289,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
275 goto fail; 289 goto fail;
276 } 290 }
277 291
278 printk(KERN_DEBUG PFX "CIS: ");
279 for (i = 0; i < 16; i++) {
280 printk("%02X:", readb(attr_mem + 2*i));
281 }
282 printk("\n");
283
284 /* Verify whether a supported PC card is present */
285 /* FIXME: we probably need to be smarted about this */
286 for (i = 0; i < sizeof(cis_magic); i++) {
287 if (cis_magic[i] != readb(attr_mem +2*i)) {
288 printk(KERN_ERR PFX "The CIS value of Prism2 PC "
289 "card is unexpected\n");
290 err = -EIO;
291 goto fail;
292 }
293 }
294
295 err = register_netdev(dev); 292 err = register_netdev(dev);
296 if (err) { 293 if (err) {
297 printk(KERN_ERR PFX "Cannot register network device\n"); 294 printk(KERN_ERR PFX "Cannot register network device\n");
@@ -310,12 +307,15 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
310 free_orinocodev(dev); 307 free_orinocodev(dev);
311 308
312 fail_alloc: 309 fail_alloc:
313 pci_iounmap(pdev, mem); 310 pci_iounmap(pdev, hermes_io);
314 311
315 fail_map_io: 312 fail_map_hermes:
316 iounmap(attr_mem); 313 pci_iounmap(pdev, attr_io);
317 314
318 fail_map_attr: 315 fail_map_attr:
316 pci_iounmap(pdev, bridge_io);
317
318 fail_map_bridge:
319 pci_release_regions(pdev); 319 pci_release_regions(pdev);
320 320
321 fail_resources: 321 fail_resources:
@@ -328,100 +328,20 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
328{ 328{
329 struct net_device *dev = pci_get_drvdata(pdev); 329 struct net_device *dev = pci_get_drvdata(pdev);
330 struct orinoco_private *priv = netdev_priv(dev); 330 struct orinoco_private *priv = netdev_priv(dev);
331 struct orinoco_plx_card *card = priv->card; 331 struct orinoco_pci_card *card = priv->card;
332 u8 __iomem *attr_mem = card->attr_mem;
333
334 BUG_ON(! dev);
335 332
336 unregister_netdev(dev); 333 unregister_netdev(dev);
337 free_irq(dev->irq, dev); 334 free_irq(dev->irq, dev);
338 pci_set_drvdata(pdev, NULL); 335 pci_set_drvdata(pdev, NULL);
339 free_orinocodev(dev); 336 free_orinocodev(dev);
340 pci_iounmap(pdev, priv->hw.iobase); 337 pci_iounmap(pdev, priv->hw.iobase);
341 iounmap(attr_mem); 338 pci_iounmap(pdev, card->attr_io);
339 pci_iounmap(pdev, card->bridge_io);
342 pci_release_regions(pdev); 340 pci_release_regions(pdev);
343 pci_disable_device(pdev); 341 pci_disable_device(pdev);
344} 342}
345 343
346static int orinoco_plx_suspend(struct pci_dev *pdev, pm_message_t state) 344static struct pci_device_id orinoco_plx_id_table[] = {
347{
348 struct net_device *dev = pci_get_drvdata(pdev);
349 struct orinoco_private *priv = netdev_priv(dev);
350 unsigned long flags;
351 int err;
352
353 err = orinoco_lock(priv, &flags);
354 if (err) {
355 printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
356 dev->name);
357 return err;
358 }
359
360 err = __orinoco_down(dev);
361 if (err)
362 printk(KERN_WARNING "%s: error %d bringing interface down "
363 "for suspend\n", dev->name, err);
364
365 netif_device_detach(dev);
366
367 priv->hw_unavailable++;
368
369 orinoco_unlock(priv, &flags);
370
371 free_irq(pdev->irq, dev);
372 pci_save_state(pdev);
373 pci_disable_device(pdev);
374 pci_set_power_state(pdev, PCI_D3hot);
375
376 return 0;
377}
378
379static int orinoco_plx_resume(struct pci_dev *pdev)
380{
381 struct net_device *dev = pci_get_drvdata(pdev);
382 struct orinoco_private *priv = netdev_priv(dev);
383 unsigned long flags;
384 int err;
385
386 pci_set_power_state(pdev, 0);
387 pci_enable_device(pdev);
388 pci_restore_state(pdev);
389
390 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
391 dev->name, dev);
392 if (err) {
393 printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
394 dev->name);
395 pci_disable_device(pdev);
396 return -EBUSY;
397 }
398
399 err = orinoco_reinit_firmware(dev);
400 if (err) {
401 printk(KERN_ERR "%s: error %d re-initializing firmware "
402 "on resume\n", dev->name, err);
403 return err;
404 }
405
406 spin_lock_irqsave(&priv->lock, flags);
407
408 netif_device_attach(dev);
409
410 priv->hw_unavailable--;
411
412 if (priv->open && (! priv->hw_unavailable)) {
413 err = __orinoco_up(dev);
414 if (err)
415 printk(KERN_ERR "%s: Error %d restarting card on resume\n",
416 dev->name, err);
417 }
418
419 spin_unlock_irqrestore(&priv->lock, flags);
420
421 return 0;
422}
423
424static struct pci_device_id orinoco_plx_pci_id_table[] = {
425 {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ 345 {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */
426 {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ 346 {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */
427 {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ 347 {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */
@@ -439,15 +359,15 @@ static struct pci_device_id orinoco_plx_pci_id_table[] = {
439 {0,}, 359 {0,},
440}; 360};
441 361
442MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table); 362MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table);
443 363
444static struct pci_driver orinoco_plx_driver = { 364static struct pci_driver orinoco_plx_driver = {
445 .name = DRIVER_NAME, 365 .name = DRIVER_NAME,
446 .id_table = orinoco_plx_pci_id_table, 366 .id_table = orinoco_plx_id_table,
447 .probe = orinoco_plx_init_one, 367 .probe = orinoco_plx_init_one,
448 .remove = __devexit_p(orinoco_plx_remove_one), 368 .remove = __devexit_p(orinoco_plx_remove_one),
449 .suspend = orinoco_plx_suspend, 369 .suspend = orinoco_pci_suspend,
450 .resume = orinoco_plx_resume, 370 .resume = orinoco_pci_resume,
451}; 371};
452 372
453static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 373static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -467,7 +387,6 @@ static int __init orinoco_plx_init(void)
467static void __exit orinoco_plx_exit(void) 387static void __exit orinoco_plx_exit(void)
468{ 388{
469 pci_unregister_driver(&orinoco_plx_driver); 389 pci_unregister_driver(&orinoco_plx_driver);
470 ssleep(1);
471} 390}
472 391
473module_init(orinoco_plx_init); 392module_init(orinoco_plx_init);
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index b74807d4141f..438fe545b184 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -1,5 +1,5 @@
1/* orinoco_tmd.c 1/* orinoco_tmd.c
2 * 2 *
3 * Driver for Prism II devices which would usually be driven by orinoco_cs, 3 * Driver for Prism II devices which would usually be driven by orinoco_cs,
4 * but are connected to the PCI bus by a TMD7160. 4 * but are connected to the PCI bus by a TMD7160.
5 * 5 *
@@ -29,14 +29,14 @@
29 29
30 * Caution: this is experimental and probably buggy. For success and 30 * Caution: this is experimental and probably buggy. For success and
31 * failure reports for different cards and adaptors, see 31 * failure reports for different cards and adaptors, see
32 * orinoco_tmd_pci_id_table near the end of the file. If you have a 32 * orinoco_tmd_id_table near the end of the file. If you have a
33 * card we don't have the PCI id for, and looks like it should work, 33 * card we don't have the PCI id for, and looks like it should work,
34 * drop me mail with the id and "it works"/"it doesn't work". 34 * drop me mail with the id and "it works"/"it doesn't work".
35 * 35 *
36 * Note: if everything gets detected fine but it doesn't actually send 36 * Note: if everything gets detected fine but it doesn't actually send
37 * or receive packets, your first port of call should probably be to 37 * or receive packets, your first port of call should probably be to
38 * try newer firmware in the card. Especially if you're doing Ad-Hoc 38 * try newer firmware in the card. Especially if you're doing Ad-Hoc
39 * modes 39 * modes.
40 * 40 *
41 * The actual driving is done by orinoco.c, this is just resource 41 * The actual driving is done by orinoco.c, this is just resource
42 * allocation stuff. 42 * allocation stuff.
@@ -61,32 +61,26 @@
61#include <pcmcia/cisreg.h> 61#include <pcmcia/cisreg.h>
62 62
63#include "orinoco.h" 63#include "orinoco.h"
64#include "orinoco_pci.h"
64 65
65#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ 66#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
66#define COR_RESET (0x80) /* reset bit in the COR register */ 67#define COR_RESET (0x80) /* reset bit in the COR register */
67#define TMD_RESET_TIME (500) /* milliseconds */ 68#define TMD_RESET_TIME (500) /* milliseconds */
68 69
69/* Orinoco TMD specific data */
70struct orinoco_tmd_card {
71 u32 tmd_io;
72};
73
74
75/* 70/*
76 * Do a soft reset of the card using the Configuration Option Register 71 * Do a soft reset of the card using the Configuration Option Register
77 */ 72 */
78static int orinoco_tmd_cor_reset(struct orinoco_private *priv) 73static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
79{ 74{
80 hermes_t *hw = &priv->hw; 75 hermes_t *hw = &priv->hw;
81 struct orinoco_tmd_card *card = priv->card; 76 struct orinoco_pci_card *card = priv->card;
82 u32 addr = card->tmd_io;
83 unsigned long timeout; 77 unsigned long timeout;
84 u16 reg; 78 u16 reg;
85 79
86 outb(COR_VALUE | COR_RESET, addr); 80 iowrite8(COR_VALUE | COR_RESET, card->bridge_io);
87 mdelay(1); 81 mdelay(1);
88 82
89 outb(COR_VALUE, addr); 83 iowrite8(COR_VALUE, card->bridge_io);
90 mdelay(1); 84 mdelay(1);
91 85
92 /* Just in case, wait more until the card is no longer busy */ 86 /* Just in case, wait more until the card is no longer busy */
@@ -97,7 +91,7 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
97 reg = hermes_read_regn(hw, CMD); 91 reg = hermes_read_regn(hw, CMD);
98 } 92 }
99 93
100 /* Did we timeout ? */ 94 /* Still busy? */
101 if (reg & HERMES_CMD_BUSY) { 95 if (reg & HERMES_CMD_BUSY) {
102 printk(KERN_ERR PFX "Busy timeout\n"); 96 printk(KERN_ERR PFX "Busy timeout\n");
103 return -ETIMEDOUT; 97 return -ETIMEDOUT;
@@ -110,11 +104,11 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
110static int orinoco_tmd_init_one(struct pci_dev *pdev, 104static int orinoco_tmd_init_one(struct pci_dev *pdev,
111 const struct pci_device_id *ent) 105 const struct pci_device_id *ent)
112{ 106{
113 int err = 0; 107 int err;
114 struct orinoco_private *priv = NULL; 108 struct orinoco_private *priv;
115 struct orinoco_tmd_card *card; 109 struct orinoco_pci_card *card;
116 struct net_device *dev = NULL; 110 struct net_device *dev;
117 void __iomem *mem; 111 void __iomem *hermes_io, *bridge_io;
118 112
119 err = pci_enable_device(pdev); 113 err = pci_enable_device(pdev);
120 if (err) { 114 if (err) {
@@ -123,20 +117,28 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
123 } 117 }
124 118
125 err = pci_request_regions(pdev, DRIVER_NAME); 119 err = pci_request_regions(pdev, DRIVER_NAME);
126 if (err != 0) { 120 if (err) {
127 printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 121 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
128 goto fail_resources; 122 goto fail_resources;
129 } 123 }
130 124
131 mem = pci_iomap(pdev, 2, 0); 125 bridge_io = pci_iomap(pdev, 1, 0);
132 if (! mem) { 126 if (!bridge_io) {
133 err = -ENOMEM; 127 printk(KERN_ERR PFX "Cannot map bridge registers\n");
134 goto fail_iomap; 128 err = -EIO;
129 goto fail_map_bridge;
130 }
131
132 hermes_io = pci_iomap(pdev, 2, 0);
133 if (!hermes_io) {
134 printk(KERN_ERR PFX "Cannot map chipset registers\n");
135 err = -EIO;
136 goto fail_map_hermes;
135 } 137 }
136 138
137 /* Allocate network device */ 139 /* Allocate network device */
138 dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); 140 dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
139 if (! dev) { 141 if (!dev) {
140 printk(KERN_ERR PFX "Cannot allocate network device\n"); 142 printk(KERN_ERR PFX "Cannot allocate network device\n");
141 err = -ENOMEM; 143 err = -ENOMEM;
142 goto fail_alloc; 144 goto fail_alloc;
@@ -144,16 +146,11 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
144 146
145 priv = netdev_priv(dev); 147 priv = netdev_priv(dev);
146 card = priv->card; 148 card = priv->card;
147 card->tmd_io = pci_resource_start(pdev, 1); 149 card->bridge_io = bridge_io;
148 dev->base_addr = pci_resource_start(pdev, 2);
149 SET_MODULE_OWNER(dev); 150 SET_MODULE_OWNER(dev);
150 SET_NETDEV_DEV(dev, &pdev->dev); 151 SET_NETDEV_DEV(dev, &pdev->dev);
151 152
152 hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); 153 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
153
154 printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
155 "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
156 dev->base_addr);
157 154
158 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, 155 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
159 dev->name, dev); 156 dev->name, dev);
@@ -162,7 +159,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
162 err = -EBUSY; 159 err = -EBUSY;
163 goto fail_irq; 160 goto fail_irq;
164 } 161 }
165 dev->irq = pdev->irq; 162 orinoco_pci_setup_netdev(dev, pdev, 2);
166 163
167 err = orinoco_tmd_cor_reset(priv); 164 err = orinoco_tmd_cor_reset(priv);
168 if (err) { 165 if (err) {
@@ -188,9 +185,12 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
188 free_orinocodev(dev); 185 free_orinocodev(dev);
189 186
190 fail_alloc: 187 fail_alloc:
191 pci_iounmap(pdev, mem); 188 pci_iounmap(pdev, hermes_io);
192 189
193 fail_iomap: 190 fail_map_hermes:
191 pci_iounmap(pdev, bridge_io);
192
193 fail_map_bridge:
194 pci_release_regions(pdev); 194 pci_release_regions(pdev);
195 195
196 fail_resources: 196 fail_resources:
@@ -203,110 +203,32 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
203{ 203{
204 struct net_device *dev = pci_get_drvdata(pdev); 204 struct net_device *dev = pci_get_drvdata(pdev);
205 struct orinoco_private *priv = dev->priv; 205 struct orinoco_private *priv = dev->priv;
206 206 struct orinoco_pci_card *card = priv->card;
207 BUG_ON(! dev);
208 207
209 unregister_netdev(dev); 208 unregister_netdev(dev);
210 free_irq(dev->irq, dev); 209 free_irq(dev->irq, dev);
211 pci_set_drvdata(pdev, NULL); 210 pci_set_drvdata(pdev, NULL);
212 free_orinocodev(dev); 211 free_orinocodev(dev);
213 pci_iounmap(pdev, priv->hw.iobase); 212 pci_iounmap(pdev, priv->hw.iobase);
213 pci_iounmap(pdev, card->bridge_io);
214 pci_release_regions(pdev); 214 pci_release_regions(pdev);
215 pci_disable_device(pdev); 215 pci_disable_device(pdev);
216} 216}
217 217
218static int orinoco_tmd_suspend(struct pci_dev *pdev, pm_message_t state) 218static struct pci_device_id orinoco_tmd_id_table[] = {
219{
220 struct net_device *dev = pci_get_drvdata(pdev);
221 struct orinoco_private *priv = netdev_priv(dev);
222 unsigned long flags;
223 int err;
224
225 err = orinoco_lock(priv, &flags);
226 if (err) {
227 printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
228 dev->name);
229 return err;
230 }
231
232 err = __orinoco_down(dev);
233 if (err)
234 printk(KERN_WARNING "%s: error %d bringing interface down "
235 "for suspend\n", dev->name, err);
236
237 netif_device_detach(dev);
238
239 priv->hw_unavailable++;
240
241 orinoco_unlock(priv, &flags);
242
243 free_irq(pdev->irq, dev);
244 pci_save_state(pdev);
245 pci_disable_device(pdev);
246 pci_set_power_state(pdev, PCI_D3hot);
247
248 return 0;
249}
250
251static int orinoco_tmd_resume(struct pci_dev *pdev)
252{
253 struct net_device *dev = pci_get_drvdata(pdev);
254 struct orinoco_private *priv = netdev_priv(dev);
255 unsigned long flags;
256 int err;
257
258 pci_set_power_state(pdev, 0);
259 pci_enable_device(pdev);
260 pci_restore_state(pdev);
261
262 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
263 dev->name, dev);
264 if (err) {
265 printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
266 dev->name);
267 pci_disable_device(pdev);
268 return -EBUSY;
269 }
270
271 err = orinoco_reinit_firmware(dev);
272 if (err) {
273 printk(KERN_ERR "%s: error %d re-initializing firmware "
274 "on resume\n", dev->name, err);
275 return err;
276 }
277
278 spin_lock_irqsave(&priv->lock, flags);
279
280 netif_device_attach(dev);
281
282 priv->hw_unavailable--;
283
284 if (priv->open && (! priv->hw_unavailable)) {
285 err = __orinoco_up(dev);
286 if (err)
287 printk(KERN_ERR "%s: Error %d restarting card on resume\n",
288 dev->name, err);
289 }
290
291 spin_unlock_irqrestore(&priv->lock, flags);
292
293 return 0;
294}
295
296static struct pci_device_id orinoco_tmd_pci_id_table[] = {
297 {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ 219 {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */
298 {0,}, 220 {0,},
299}; 221};
300 222
301MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); 223MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table);
302 224
303static struct pci_driver orinoco_tmd_driver = { 225static struct pci_driver orinoco_tmd_driver = {
304 .name = DRIVER_NAME, 226 .name = DRIVER_NAME,
305 .id_table = orinoco_tmd_pci_id_table, 227 .id_table = orinoco_tmd_id_table,
306 .probe = orinoco_tmd_init_one, 228 .probe = orinoco_tmd_init_one,
307 .remove = __devexit_p(orinoco_tmd_remove_one), 229 .remove = __devexit_p(orinoco_tmd_remove_one),
308 .suspend = orinoco_tmd_suspend, 230 .suspend = orinoco_pci_suspend,
309 .resume = orinoco_tmd_resume, 231 .resume = orinoco_pci_resume,
310}; 232};
311 233
312static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 234static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -324,7 +246,6 @@ static int __init orinoco_tmd_init(void)
324static void __exit orinoco_tmd_exit(void) 246static void __exit orinoco_tmd_exit(void)
325{ 247{
326 pci_unregister_driver(&orinoco_tmd_driver); 248 pci_unregister_driver(&orinoco_tmd_driver);
327 ssleep(1);
328} 249}
329 250
330module_init(orinoco_tmd_init); 251module_init(orinoco_tmd_init);