diff options
Diffstat (limited to 'drivers/net/tokenring/3c359.c')
-rw-r--r-- | drivers/net/tokenring/3c359.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index 4a65fc2dd928..534c0f38483c 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/pci.h> | 62 | #include <linux/pci.h> |
63 | #include <linux/spinlock.h> | 63 | #include <linux/spinlock.h> |
64 | #include <linux/bitops.h> | 64 | #include <linux/bitops.h> |
65 | #include <linux/firmware.h> | ||
65 | 66 | ||
66 | #include <net/checksum.h> | 67 | #include <net/checksum.h> |
67 | 68 | ||
@@ -73,8 +74,10 @@ | |||
73 | static char version[] __devinitdata = | 74 | static char version[] __devinitdata = |
74 | "3c359.c v1.2.0 2/17/01 - Mike Phillips (mikep@linuxtr.net)" ; | 75 | "3c359.c v1.2.0 2/17/01 - Mike Phillips (mikep@linuxtr.net)" ; |
75 | 76 | ||
77 | #define FW_NAME "3com/3C359.bin" | ||
76 | MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ; | 78 | MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ; |
77 | MODULE_DESCRIPTION("3Com 3C359 Velocity XL Token Ring Adapter Driver \n") ; | 79 | MODULE_DESCRIPTION("3Com 3C359 Velocity XL Token Ring Adapter Driver \n") ; |
80 | MODULE_FIRMWARE(FW_NAME); | ||
78 | 81 | ||
79 | /* Module paramters */ | 82 | /* Module paramters */ |
80 | 83 | ||
@@ -114,8 +117,6 @@ MODULE_PARM_DESC(message_level, "3c359: Level of reported messages") ; | |||
114 | * will be stuck with 1555 lines of hex #'s in the code. | 117 | * will be stuck with 1555 lines of hex #'s in the code. |
115 | */ | 118 | */ |
116 | 119 | ||
117 | #include "3c359_microcode.h" | ||
118 | |||
119 | static struct pci_device_id xl_pci_tbl[] = | 120 | static struct pci_device_id xl_pci_tbl[] = |
120 | { | 121 | { |
121 | {PCI_VENDOR_ID_3COM,PCI_DEVICE_ID_3COM_3C359, PCI_ANY_ID, PCI_ANY_ID, }, | 122 | {PCI_VENDOR_ID_3COM,PCI_DEVICE_ID_3COM_3C359, PCI_ANY_ID, PCI_ANY_ID, }, |
@@ -364,10 +365,30 @@ static int __devinit xl_probe(struct pci_dev *pdev, | |||
364 | return 0; | 365 | return 0; |
365 | } | 366 | } |
366 | 367 | ||
368 | static int xl_init_firmware(struct xl_private *xl_priv) | ||
369 | { | ||
370 | int err; | ||
371 | |||
372 | err = request_firmware(&xl_priv->fw, FW_NAME, &xl_priv->pdev->dev); | ||
373 | if (err) { | ||
374 | printk(KERN_ERR "Failed to load firmware \"%s\"\n", FW_NAME); | ||
375 | return err; | ||
376 | } | ||
377 | |||
378 | if (xl_priv->fw->size < 16) { | ||
379 | printk(KERN_ERR "Bogus length %zu in \"%s\"\n", | ||
380 | xl_priv->fw->size, FW_NAME); | ||
381 | release_firmware(xl_priv->fw); | ||
382 | err = -EINVAL; | ||
383 | } | ||
384 | |||
385 | return err; | ||
386 | } | ||
367 | 387 | ||
368 | static int __devinit xl_init(struct net_device *dev) | 388 | static int __devinit xl_init(struct net_device *dev) |
369 | { | 389 | { |
370 | struct xl_private *xl_priv = netdev_priv(dev); | 390 | struct xl_private *xl_priv = netdev_priv(dev); |
391 | int err; | ||
371 | 392 | ||
372 | printk(KERN_INFO "%s \n", version); | 393 | printk(KERN_INFO "%s \n", version); |
373 | printk(KERN_INFO "%s: I/O at %hx, MMIO at %p, using irq %d\n", | 394 | printk(KERN_INFO "%s: I/O at %hx, MMIO at %p, using irq %d\n", |
@@ -375,8 +396,11 @@ static int __devinit xl_init(struct net_device *dev) | |||
375 | 396 | ||
376 | spin_lock_init(&xl_priv->xl_lock) ; | 397 | spin_lock_init(&xl_priv->xl_lock) ; |
377 | 398 | ||
378 | return xl_hw_reset(dev) ; | 399 | err = xl_init_firmware(xl_priv); |
400 | if (err == 0) | ||
401 | err = xl_hw_reset(dev); | ||
379 | 402 | ||
403 | return err; | ||
380 | } | 404 | } |
381 | 405 | ||
382 | 406 | ||
@@ -386,7 +410,7 @@ static int __devinit xl_init(struct net_device *dev) | |||
386 | */ | 410 | */ |
387 | 411 | ||
388 | static int xl_hw_reset(struct net_device *dev) | 412 | static int xl_hw_reset(struct net_device *dev) |
389 | { | 413 | { |
390 | struct xl_private *xl_priv = netdev_priv(dev); | 414 | struct xl_private *xl_priv = netdev_priv(dev); |
391 | u8 __iomem *xl_mmio = xl_priv->xl_mmio ; | 415 | u8 __iomem *xl_mmio = xl_priv->xl_mmio ; |
392 | unsigned long t ; | 416 | unsigned long t ; |
@@ -396,6 +420,9 @@ static int xl_hw_reset(struct net_device *dev) | |||
396 | u16 start ; | 420 | u16 start ; |
397 | int j ; | 421 | int j ; |
398 | 422 | ||
423 | if (xl_priv->fw == NULL) | ||
424 | return -EINVAL; | ||
425 | |||
399 | /* | 426 | /* |
400 | * Reset the card. If the card has got the microcode on board, we have | 427 | * Reset the card. If the card has got the microcode on board, we have |
401 | * missed the initialization interrupt, so we must always do this. | 428 | * missed the initialization interrupt, so we must always do this. |
@@ -458,25 +485,30 @@ static int xl_hw_reset(struct net_device *dev) | |||
458 | 485 | ||
459 | /* | 486 | /* |
460 | * Now to write the microcode into the shared ram | 487 | * Now to write the microcode into the shared ram |
461 | * The microcode must finish at position 0xFFFF, so we must subtract | 488 | * The microcode must finish at position 0xFFFF, |
462 | * to get the start position for the code | 489 | * so we must subtract to get the start position for the code |
490 | * | ||
491 | * Looks strange but ensures compiler only uses | ||
492 | * 16 bit unsigned int | ||
463 | */ | 493 | */ |
494 | start = (0xFFFF - (xl_priv->fw->size) + 1) ; | ||
464 | 495 | ||
465 | start = (0xFFFF - (mc_size) + 1 ) ; /* Looks strange but ensures compiler only uses 16 bit unsigned int for this */ | ||
466 | |||
467 | printk(KERN_INFO "3C359: Uploading Microcode: "); | 496 | printk(KERN_INFO "3C359: Uploading Microcode: "); |
468 | 497 | ||
469 | for (i = start, j = 0; j < mc_size; i++, j++) { | 498 | for (i = start, j = 0; j < xl_priv->fw->size; i++, j++) { |
470 | writel(MEM_BYTE_WRITE | 0XD0000 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; | 499 | writel(MEM_BYTE_WRITE | 0XD0000 | i, |
471 | writeb(microcode[j],xl_mmio + MMIO_MACDATA) ; | 500 | xl_mmio + MMIO_MAC_ACCESS_CMD); |
501 | writeb(xl_priv->fw->data[j], xl_mmio + MMIO_MACDATA); | ||
472 | if (j % 1024 == 0) | 502 | if (j % 1024 == 0) |
473 | printk("."); | 503 | printk("."); |
474 | } | 504 | } |
475 | printk("\n") ; | 505 | printk("\n") ; |
476 | 506 | ||
477 | for (i=0;i < 16; i++) { | 507 | for (i = 0; i < 16; i++) { |
478 | writel( (MEM_BYTE_WRITE | 0xDFFF0) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; | 508 | writel((MEM_BYTE_WRITE | 0xDFFF0) + i, |
479 | writeb(microcode[mc_size - 16 + i], xl_mmio + MMIO_MACDATA) ; | 509 | xl_mmio + MMIO_MAC_ACCESS_CMD); |
510 | writeb(xl_priv->fw->data[xl_priv->fw->size - 16 + i], | ||
511 | xl_mmio + MMIO_MACDATA); | ||
480 | } | 512 | } |
481 | 513 | ||
482 | /* | 514 | /* |
@@ -1782,6 +1814,7 @@ static void __devexit xl_remove_one (struct pci_dev *pdev) | |||
1782 | struct net_device *dev = pci_get_drvdata(pdev); | 1814 | struct net_device *dev = pci_get_drvdata(pdev); |
1783 | struct xl_private *xl_priv=netdev_priv(dev); | 1815 | struct xl_private *xl_priv=netdev_priv(dev); |
1784 | 1816 | ||
1817 | release_firmware(xl_priv->fw); | ||
1785 | unregister_netdev(dev); | 1818 | unregister_netdev(dev); |
1786 | iounmap(xl_priv->xl_mmio) ; | 1819 | iounmap(xl_priv->xl_mmio) ; |
1787 | pci_release_regions(pdev) ; | 1820 | pci_release_regions(pdev) ; |