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 4a65fc2dd92..534c0f38483 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) ; |
