aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco_plx.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_plx.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_plx.c')
-rw-r--r--drivers/net/wireless/orinoco_plx.c259
1 files changed, 89 insertions, 170 deletions
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);