aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco_nortel.c
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/orinoco_nortel.c
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/orinoco_nortel.c')
-rw-r--r--drivers/net/wireless/orinoco_nortel.c240
1 files changed, 87 insertions, 153 deletions
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index 3fff013f678..deb22fb3551 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: