diff options
Diffstat (limited to 'drivers/net/sunhme.c')
| -rw-r--r-- | drivers/net/sunhme.c | 417 |
1 files changed, 210 insertions, 207 deletions
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index bd5d2668a362..c33ead3470db 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | /* $Id: sunhme.c,v 1.124 2002/01/15 06:25:51 davem Exp $ | 1 | /* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, |
| 2 | * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, | ||
| 3 | * auto carrier detecting ethernet driver. Also known as the | 2 | * auto carrier detecting ethernet driver. Also known as the |
| 4 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. | 3 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. |
| 5 | * | 4 | * |
| 6 | * Copyright (C) 1996, 1998, 1999, 2002, 2003 David S. Miller (davem@redhat.com) | 5 | * Copyright (C) 1996, 1998, 1999, 2002, 2003, |
| 6 | 2006 David S. Miller (davem@davemloft.net) | ||
| 7 | * | 7 | * |
| 8 | * Changes : | 8 | * Changes : |
| 9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> | 9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> |
| @@ -40,15 +40,13 @@ | |||
| 40 | #include <asm/dma.h> | 40 | #include <asm/dma.h> |
| 41 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
| 42 | 42 | ||
| 43 | #ifdef __sparc__ | 43 | #ifdef CONFIG_SPARC |
| 44 | #include <asm/idprom.h> | 44 | #include <asm/idprom.h> |
| 45 | #include <asm/sbus.h> | 45 | #include <asm/sbus.h> |
| 46 | #include <asm/openprom.h> | 46 | #include <asm/openprom.h> |
| 47 | #include <asm/oplib.h> | 47 | #include <asm/oplib.h> |
| 48 | #include <asm/prom.h> | ||
| 48 | #include <asm/auxio.h> | 49 | #include <asm/auxio.h> |
| 49 | #ifndef __sparc_v9__ | ||
| 50 | #include <asm/io-unit.h> | ||
| 51 | #endif | ||
| 52 | #endif | 50 | #endif |
| 53 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
| 54 | 52 | ||
| @@ -57,7 +55,7 @@ | |||
| 57 | 55 | ||
| 58 | #ifdef CONFIG_PCI | 56 | #ifdef CONFIG_PCI |
| 59 | #include <linux/pci.h> | 57 | #include <linux/pci.h> |
| 60 | #ifdef __sparc__ | 58 | #ifdef CONFIG_SPARC |
| 61 | #include <asm/pbm.h> | 59 | #include <asm/pbm.h> |
| 62 | #endif | 60 | #endif |
| 63 | #endif | 61 | #endif |
| @@ -65,9 +63,9 @@ | |||
| 65 | #include "sunhme.h" | 63 | #include "sunhme.h" |
| 66 | 64 | ||
| 67 | #define DRV_NAME "sunhme" | 65 | #define DRV_NAME "sunhme" |
| 68 | #define DRV_VERSION "2.02" | 66 | #define DRV_VERSION "3.00" |
| 69 | #define DRV_RELDATE "8/24/03" | 67 | #define DRV_RELDATE "June 23, 2006" |
| 70 | #define DRV_AUTHOR "David S. Miller (davem@redhat.com)" | 68 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
| 71 | 69 | ||
| 72 | static char version[] = | 70 | static char version[] = |
| 73 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; | 71 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; |
| @@ -83,8 +81,6 @@ static int macaddr[6]; | |||
| 83 | module_param_array(macaddr, int, NULL, 0); | 81 | module_param_array(macaddr, int, NULL, 0); |
| 84 | MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); | 82 | MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); |
| 85 | 83 | ||
| 86 | static struct happy_meal *root_happy_dev; | ||
| 87 | |||
| 88 | #ifdef CONFIG_SBUS | 84 | #ifdef CONFIG_SBUS |
| 89 | static struct quattro *qfe_sbus_list; | 85 | static struct quattro *qfe_sbus_list; |
| 90 | #endif | 86 | #endif |
| @@ -181,26 +177,6 @@ static __inline__ void tx_dump_ring(struct happy_meal *hp) | |||
| 181 | #define DEFAULT_IPG2 4 /* For all modes */ | 177 | #define DEFAULT_IPG2 4 /* For all modes */ |
| 182 | #define DEFAULT_JAMSIZE 4 /* Toe jam */ | 178 | #define DEFAULT_JAMSIZE 4 /* Toe jam */ |
| 183 | 179 | ||
| 184 | #if defined(CONFIG_PCI) && defined(MODULE) | ||
| 185 | /* This happy_pci_ids is declared __initdata because it is only used | ||
| 186 | as an advisory to depmod. If this is ported to the new PCI interface | ||
| 187 | where it could be referenced at any time due to hot plugging, | ||
| 188 | the __initdata reference should be removed. */ | ||
| 189 | |||
| 190 | static struct pci_device_id happymeal_pci_ids[] = { | ||
| 191 | { | ||
| 192 | .vendor = PCI_VENDOR_ID_SUN, | ||
| 193 | .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, | ||
| 194 | .subvendor = PCI_ANY_ID, | ||
| 195 | .subdevice = PCI_ANY_ID, | ||
| 196 | }, | ||
| 197 | { } /* Terminating entry */ | ||
| 198 | }; | ||
| 199 | |||
| 200 | MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); | ||
| 201 | |||
| 202 | #endif | ||
| 203 | |||
| 204 | /* NOTE: In the descriptor writes one _must_ write the address | 180 | /* NOTE: In the descriptor writes one _must_ write the address |
| 205 | * member _first_. The card must not be allowed to see | 181 | * member _first_. The card must not be allowed to see |
| 206 | * the updated descriptor flags until the address is | 182 | * the updated descriptor flags until the address is |
| @@ -1610,7 +1586,7 @@ static int happy_meal_init(struct happy_meal *hp) | |||
| 1610 | HMD(("happy_meal_init: old[%08x] bursts<", | 1586 | HMD(("happy_meal_init: old[%08x] bursts<", |
| 1611 | hme_read32(hp, gregs + GREG_CFG))); | 1587 | hme_read32(hp, gregs + GREG_CFG))); |
| 1612 | 1588 | ||
| 1613 | #ifndef __sparc__ | 1589 | #ifndef CONFIG_SPARC |
| 1614 | /* It is always PCI and can handle 64byte bursts. */ | 1590 | /* It is always PCI and can handle 64byte bursts. */ |
| 1615 | hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST64); | 1591 | hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST64); |
| 1616 | #else | 1592 | #else |
| @@ -1647,7 +1623,7 @@ static int happy_meal_init(struct happy_meal *hp) | |||
| 1647 | HMD(("XXX>")); | 1623 | HMD(("XXX>")); |
| 1648 | hme_write32(hp, gregs + GREG_CFG, 0); | 1624 | hme_write32(hp, gregs + GREG_CFG, 0); |
| 1649 | } | 1625 | } |
| 1650 | #endif /* __sparc__ */ | 1626 | #endif /* CONFIG_SPARC */ |
| 1651 | 1627 | ||
| 1652 | /* Turn off interrupts we do not want to hear. */ | 1628 | /* Turn off interrupts we do not want to hear. */ |
| 1653 | HMD((", enable global interrupts, ")); | 1629 | HMD((", enable global interrupts, ")); |
| @@ -2592,14 +2568,10 @@ static void __init quattro_apply_ranges(struct quattro *qp, struct happy_meal *h | |||
| 2592 | */ | 2568 | */ |
| 2593 | static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) | 2569 | static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) |
| 2594 | { | 2570 | { |
| 2595 | struct sbus_bus *sbus; | ||
| 2596 | struct sbus_dev *sdev; | 2571 | struct sbus_dev *sdev; |
| 2597 | struct quattro *qp; | 2572 | struct quattro *qp; |
| 2598 | int i; | 2573 | int i; |
| 2599 | 2574 | ||
| 2600 | if (qfe_sbus_list == NULL) | ||
| 2601 | goto found; | ||
| 2602 | |||
| 2603 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2575 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
| 2604 | for (i = 0, sdev = qp->quattro_dev; | 2576 | for (i = 0, sdev = qp->quattro_dev; |
| 2605 | (sdev != NULL) && (i < 4); | 2577 | (sdev != NULL) && (i < 4); |
| @@ -2608,17 +2580,7 @@ static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) | |||
| 2608 | return qp; | 2580 | return qp; |
| 2609 | } | 2581 | } |
| 2610 | } | 2582 | } |
| 2611 | for_each_sbus(sbus) { | ||
| 2612 | for_each_sbusdev(sdev, sbus) { | ||
| 2613 | if (sdev == goal_sdev) | ||
| 2614 | goto found; | ||
| 2615 | } | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | /* Cannot find quattro parent, fail. */ | ||
| 2619 | return NULL; | ||
| 2620 | 2583 | ||
| 2621 | found: | ||
| 2622 | qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); | 2584 | qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); |
| 2623 | if (qp != NULL) { | 2585 | if (qp != NULL) { |
| 2624 | int i; | 2586 | int i; |
| @@ -2655,6 +2617,17 @@ static void __init quattro_sbus_register_irqs(void) | |||
| 2655 | } | 2617 | } |
| 2656 | } | 2618 | } |
| 2657 | } | 2619 | } |
| 2620 | |||
| 2621 | static void __devexit quattro_sbus_free_irqs(void) | ||
| 2622 | { | ||
| 2623 | struct quattro *qp; | ||
| 2624 | |||
| 2625 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | ||
| 2626 | struct sbus_dev *sdev = qp->quattro_dev; | ||
| 2627 | |||
| 2628 | free_irq(sdev->irqs[0], qp); | ||
| 2629 | } | ||
| 2630 | } | ||
| 2658 | #endif /* CONFIG_SBUS */ | 2631 | #endif /* CONFIG_SBUS */ |
| 2659 | 2632 | ||
| 2660 | #ifdef CONFIG_PCI | 2633 | #ifdef CONFIG_PCI |
| @@ -2689,8 +2662,9 @@ static struct quattro * __init quattro_pci_find(struct pci_dev *pdev) | |||
| 2689 | #endif /* CONFIG_PCI */ | 2662 | #endif /* CONFIG_PCI */ |
| 2690 | 2663 | ||
| 2691 | #ifdef CONFIG_SBUS | 2664 | #ifdef CONFIG_SBUS |
| 2692 | static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | 2665 | static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) |
| 2693 | { | 2666 | { |
| 2667 | struct device_node *dp = sdev->ofdev.node; | ||
| 2694 | struct quattro *qp = NULL; | 2668 | struct quattro *qp = NULL; |
| 2695 | struct happy_meal *hp; | 2669 | struct happy_meal *hp; |
| 2696 | struct net_device *dev; | 2670 | struct net_device *dev; |
| @@ -2713,6 +2687,7 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2713 | if (!dev) | 2687 | if (!dev) |
| 2714 | goto err_out; | 2688 | goto err_out; |
| 2715 | SET_MODULE_OWNER(dev); | 2689 | SET_MODULE_OWNER(dev); |
| 2690 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | ||
| 2716 | 2691 | ||
| 2717 | if (hme_version_printed++ == 0) | 2692 | if (hme_version_printed++ == 0) |
| 2718 | printk(KERN_INFO "%s", version); | 2693 | printk(KERN_INFO "%s", version); |
| @@ -2728,13 +2703,16 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2728 | for (i = 0; i < 6; i++) | 2703 | for (i = 0; i < 6; i++) |
| 2729 | dev->dev_addr[i] = macaddr[i]; | 2704 | dev->dev_addr[i] = macaddr[i]; |
| 2730 | macaddr[5]++; | 2705 | macaddr[5]++; |
| 2731 | } else if (qfe_slot != -1 && | ||
| 2732 | prom_getproplen(sdev->prom_node, | ||
| 2733 | "local-mac-address") == 6) { | ||
| 2734 | prom_getproperty(sdev->prom_node, "local-mac-address", | ||
| 2735 | dev->dev_addr, 6); | ||
| 2736 | } else { | 2706 | } else { |
| 2737 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); | 2707 | unsigned char *addr; |
| 2708 | int len; | ||
| 2709 | |||
| 2710 | addr = of_get_property(dp, "local-mac-address", &len); | ||
| 2711 | |||
| 2712 | if (qfe_slot != -1 && addr && len == 6) | ||
| 2713 | memcpy(dev->dev_addr, addr, 6); | ||
| 2714 | else | ||
| 2715 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); | ||
| 2738 | } | 2716 | } |
| 2739 | 2717 | ||
| 2740 | hp = dev->priv; | 2718 | hp = dev->priv; |
| @@ -2745,9 +2723,8 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2745 | 2723 | ||
| 2746 | err = -ENODEV; | 2724 | err = -ENODEV; |
| 2747 | if (sdev->num_registers != 5) { | 2725 | if (sdev->num_registers != 5) { |
| 2748 | printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n", | 2726 | printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n", |
| 2749 | sdev->num_registers); | 2727 | sdev->num_registers); |
| 2750 | printk(KERN_ERR "happymeal: Would you like that for here or to go?\n"); | ||
| 2751 | goto err_out_free_netdev; | 2728 | goto err_out_free_netdev; |
| 2752 | } | 2729 | } |
| 2753 | 2730 | ||
| @@ -2761,39 +2738,39 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2761 | hp->gregs = sbus_ioremap(&sdev->resource[0], 0, | 2738 | hp->gregs = sbus_ioremap(&sdev->resource[0], 0, |
| 2762 | GREG_REG_SIZE, "HME Global Regs"); | 2739 | GREG_REG_SIZE, "HME Global Regs"); |
| 2763 | if (!hp->gregs) { | 2740 | if (!hp->gregs) { |
| 2764 | printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n"); | 2741 | printk(KERN_ERR "happymeal: Cannot map global registers.\n"); |
| 2765 | goto err_out_free_netdev; | 2742 | goto err_out_free_netdev; |
| 2766 | } | 2743 | } |
| 2767 | 2744 | ||
| 2768 | hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, | 2745 | hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, |
| 2769 | ETX_REG_SIZE, "HME TX Regs"); | 2746 | ETX_REG_SIZE, "HME TX Regs"); |
| 2770 | if (!hp->etxregs) { | 2747 | if (!hp->etxregs) { |
| 2771 | printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n"); | 2748 | printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); |
| 2772 | goto err_out_iounmap; | 2749 | goto err_out_iounmap; |
| 2773 | } | 2750 | } |
| 2774 | 2751 | ||
| 2775 | hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, | 2752 | hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, |
| 2776 | ERX_REG_SIZE, "HME RX Regs"); | 2753 | ERX_REG_SIZE, "HME RX Regs"); |
| 2777 | if (!hp->erxregs) { | 2754 | if (!hp->erxregs) { |
| 2778 | printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n"); | 2755 | printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); |
| 2779 | goto err_out_iounmap; | 2756 | goto err_out_iounmap; |
| 2780 | } | 2757 | } |
| 2781 | 2758 | ||
| 2782 | hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, | 2759 | hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, |
| 2783 | BMAC_REG_SIZE, "HME BIGMAC Regs"); | 2760 | BMAC_REG_SIZE, "HME BIGMAC Regs"); |
| 2784 | if (!hp->bigmacregs) { | 2761 | if (!hp->bigmacregs) { |
| 2785 | printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n"); | 2762 | printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); |
| 2786 | goto err_out_iounmap; | 2763 | goto err_out_iounmap; |
| 2787 | } | 2764 | } |
| 2788 | 2765 | ||
| 2789 | hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, | 2766 | hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, |
| 2790 | TCVR_REG_SIZE, "HME Tranceiver Regs"); | 2767 | TCVR_REG_SIZE, "HME Tranceiver Regs"); |
| 2791 | if (!hp->tcvregs) { | 2768 | if (!hp->tcvregs) { |
| 2792 | printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n"); | 2769 | printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); |
| 2793 | goto err_out_iounmap; | 2770 | goto err_out_iounmap; |
| 2794 | } | 2771 | } |
| 2795 | 2772 | ||
| 2796 | hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff); | 2773 | hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff); |
| 2797 | if (hp->hm_revision == 0xff) | 2774 | if (hp->hm_revision == 0xff) |
| 2798 | hp->hm_revision = 0xa0; | 2775 | hp->hm_revision = 0xa0; |
| 2799 | 2776 | ||
| @@ -2807,8 +2784,8 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2807 | hp->happy_flags |= HFLAG_QUATTRO; | 2784 | hp->happy_flags |= HFLAG_QUATTRO; |
| 2808 | 2785 | ||
| 2809 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ | 2786 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ |
| 2810 | hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node, | 2787 | hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node, |
| 2811 | "burst-sizes", 0x00); | 2788 | "burst-sizes", 0x00); |
| 2812 | 2789 | ||
| 2813 | hp->happy_block = sbus_alloc_consistent(hp->happy_dev, | 2790 | hp->happy_block = sbus_alloc_consistent(hp->happy_dev, |
| 2814 | PAGE_SIZE, | 2791 | PAGE_SIZE, |
| @@ -2871,6 +2848,8 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2871 | goto err_out_free_consistent; | 2848 | goto err_out_free_consistent; |
| 2872 | } | 2849 | } |
| 2873 | 2850 | ||
| 2851 | dev_set_drvdata(&sdev->ofdev.dev, hp); | ||
| 2852 | |||
| 2874 | if (qfe_slot != -1) | 2853 | if (qfe_slot != -1) |
| 2875 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", | 2854 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", |
| 2876 | dev->name, qfe_slot); | 2855 | dev->name, qfe_slot); |
| @@ -2883,12 +2862,6 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2883 | dev->dev_addr[i], i == 5 ? ' ' : ':'); | 2862 | dev->dev_addr[i], i == 5 ? ' ' : ':'); |
| 2884 | printk("\n"); | 2863 | printk("\n"); |
| 2885 | 2864 | ||
| 2886 | /* We are home free at this point, link us in to the happy | ||
| 2887 | * device list. | ||
| 2888 | */ | ||
| 2889 | hp->next_module = root_happy_dev; | ||
| 2890 | root_happy_dev = hp; | ||
| 2891 | |||
| 2892 | return 0; | 2865 | return 0; |
| 2893 | 2866 | ||
| 2894 | err_out_free_consistent: | 2867 | err_out_free_consistent: |
| @@ -2918,7 +2891,7 @@ err_out: | |||
| 2918 | #endif | 2891 | #endif |
| 2919 | 2892 | ||
| 2920 | #ifdef CONFIG_PCI | 2893 | #ifdef CONFIG_PCI |
| 2921 | #ifndef __sparc__ | 2894 | #ifndef CONFIG_SPARC |
| 2922 | static int is_quattro_p(struct pci_dev *pdev) | 2895 | static int is_quattro_p(struct pci_dev *pdev) |
| 2923 | { | 2896 | { |
| 2924 | struct pci_dev *busdev = pdev->bus->self; | 2897 | struct pci_dev *busdev = pdev->bus->self; |
| @@ -3006,14 +2979,14 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr) | |||
| 3006 | get_random_bytes(&dev_addr[3], 3); | 2979 | get_random_bytes(&dev_addr[3], 3); |
| 3007 | return; | 2980 | return; |
| 3008 | } | 2981 | } |
| 3009 | #endif /* !(__sparc__) */ | 2982 | #endif /* !(CONFIG_SPARC) */ |
| 3010 | 2983 | ||
| 3011 | static int __init happy_meal_pci_init(struct pci_dev *pdev) | 2984 | static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, |
| 2985 | const struct pci_device_id *ent) | ||
| 3012 | { | 2986 | { |
| 3013 | struct quattro *qp = NULL; | 2987 | struct quattro *qp = NULL; |
| 3014 | #ifdef __sparc__ | 2988 | #ifdef CONFIG_SPARC |
| 3015 | struct pcidev_cookie *pcp; | 2989 | struct pcidev_cookie *pcp; |
| 3016 | int node; | ||
| 3017 | #endif | 2990 | #endif |
| 3018 | struct happy_meal *hp; | 2991 | struct happy_meal *hp; |
| 3019 | struct net_device *dev; | 2992 | struct net_device *dev; |
| @@ -3024,15 +2997,14 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3024 | int err; | 2997 | int err; |
| 3025 | 2998 | ||
| 3026 | /* Now make sure pci_dev cookie is there. */ | 2999 | /* Now make sure pci_dev cookie is there. */ |
| 3027 | #ifdef __sparc__ | 3000 | #ifdef CONFIG_SPARC |
| 3028 | pcp = pdev->sysdata; | 3001 | pcp = pdev->sysdata; |
| 3029 | if (pcp == NULL || pcp->prom_node == -1) { | 3002 | if (pcp == NULL) { |
| 3030 | printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); | 3003 | printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); |
| 3031 | return -ENODEV; | 3004 | return -ENODEV; |
| 3032 | } | 3005 | } |
| 3033 | node = pcp->prom_node; | ||
| 3034 | 3006 | ||
| 3035 | prom_getstring(node, "name", prom_name, sizeof(prom_name)); | 3007 | strcpy(prom_name, pcp->prom_node->name); |
| 3036 | #else | 3008 | #else |
| 3037 | if (is_quattro_p(pdev)) | 3009 | if (is_quattro_p(pdev)) |
| 3038 | strcpy(prom_name, "SUNW,qfe"); | 3010 | strcpy(prom_name, "SUNW,qfe"); |
| @@ -3103,11 +3075,15 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3103 | dev->dev_addr[i] = macaddr[i]; | 3075 | dev->dev_addr[i] = macaddr[i]; |
| 3104 | macaddr[5]++; | 3076 | macaddr[5]++; |
| 3105 | } else { | 3077 | } else { |
| 3106 | #ifdef __sparc__ | 3078 | #ifdef CONFIG_SPARC |
| 3079 | unsigned char *addr; | ||
| 3080 | int len; | ||
| 3081 | |||
| 3107 | if (qfe_slot != -1 && | 3082 | if (qfe_slot != -1 && |
| 3108 | prom_getproplen(node, "local-mac-address") == 6) { | 3083 | (addr = of_get_property(pcp->prom_node, |
| 3109 | prom_getproperty(node, "local-mac-address", | 3084 | "local-mac-address", &len)) != NULL |
| 3110 | dev->dev_addr, 6); | 3085 | && len == 6) { |
| 3086 | memcpy(dev->dev_addr, addr, 6); | ||
| 3111 | } else { | 3087 | } else { |
| 3112 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); | 3088 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); |
| 3113 | } | 3089 | } |
| @@ -3123,8 +3099,8 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3123 | hp->bigmacregs = (hpreg_base + 0x6000UL); | 3099 | hp->bigmacregs = (hpreg_base + 0x6000UL); |
| 3124 | hp->tcvregs = (hpreg_base + 0x7000UL); | 3100 | hp->tcvregs = (hpreg_base + 0x7000UL); |
| 3125 | 3101 | ||
| 3126 | #ifdef __sparc__ | 3102 | #ifdef CONFIG_SPARC |
| 3127 | hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff); | 3103 | hp->hm_revision = of_getintprop_default(pcp->prom_node, "hm-rev", 0xff); |
| 3128 | if (hp->hm_revision == 0xff) { | 3104 | if (hp->hm_revision == 0xff) { |
| 3129 | unsigned char prev; | 3105 | unsigned char prev; |
| 3130 | 3106 | ||
| @@ -3148,7 +3124,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3148 | /* And of course, indicate this is PCI. */ | 3124 | /* And of course, indicate this is PCI. */ |
| 3149 | hp->happy_flags |= HFLAG_PCI; | 3125 | hp->happy_flags |= HFLAG_PCI; |
| 3150 | 3126 | ||
| 3151 | #ifdef __sparc__ | 3127 | #ifdef CONFIG_SPARC |
| 3152 | /* Assume PCI happy meals can handle all burst sizes. */ | 3128 | /* Assume PCI happy meals can handle all burst sizes. */ |
| 3153 | hp->happy_bursts = DMA_BURSTBITS; | 3129 | hp->happy_bursts = DMA_BURSTBITS; |
| 3154 | #endif | 3130 | #endif |
| @@ -3211,6 +3187,8 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3211 | goto err_out_iounmap; | 3187 | goto err_out_iounmap; |
| 3212 | } | 3188 | } |
| 3213 | 3189 | ||
| 3190 | dev_set_drvdata(&pdev->dev, hp); | ||
| 3191 | |||
| 3214 | if (!qfe_slot) { | 3192 | if (!qfe_slot) { |
| 3215 | struct pci_dev *qpdev = qp->quattro_dev; | 3193 | struct pci_dev *qpdev = qp->quattro_dev; |
| 3216 | 3194 | ||
| @@ -3240,12 +3218,6 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3240 | 3218 | ||
| 3241 | printk("\n"); | 3219 | printk("\n"); |
| 3242 | 3220 | ||
| 3243 | /* We are home free at this point, link us in to the happy | ||
| 3244 | * device list. | ||
| 3245 | */ | ||
| 3246 | hp->next_module = root_happy_dev; | ||
| 3247 | root_happy_dev = hp; | ||
| 3248 | |||
| 3249 | return 0; | 3221 | return 0; |
| 3250 | 3222 | ||
| 3251 | err_out_iounmap: | 3223 | err_out_iounmap: |
| @@ -3263,136 +3235,146 @@ err_out_clear_quattro: | |||
| 3263 | err_out: | 3235 | err_out: |
| 3264 | return err; | 3236 | return err; |
| 3265 | } | 3237 | } |
| 3266 | #endif | ||
| 3267 | 3238 | ||
| 3268 | #ifdef CONFIG_SBUS | 3239 | static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) |
| 3269 | static int __init happy_meal_sbus_probe(void) | ||
| 3270 | { | 3240 | { |
| 3271 | struct sbus_bus *sbus; | 3241 | struct happy_meal *hp = dev_get_drvdata(&pdev->dev); |
| 3272 | struct sbus_dev *sdev; | 3242 | struct net_device *net_dev = hp->dev; |
| 3273 | int cards = 0; | 3243 | |
| 3274 | char model[128]; | 3244 | unregister_netdev(net_dev); |
| 3275 | 3245 | ||
| 3276 | for_each_sbus(sbus) { | 3246 | pci_free_consistent(hp->happy_dev, |
| 3277 | for_each_sbusdev(sdev, sbus) { | 3247 | PAGE_SIZE, |
| 3278 | char *name = sdev->prom_name; | 3248 | hp->happy_block, |
| 3279 | 3249 | hp->hblock_dvma); | |
| 3280 | if (!strcmp(name, "SUNW,hme")) { | 3250 | iounmap(hp->gregs); |
| 3281 | cards++; | 3251 | pci_release_regions(hp->happy_dev); |
| 3282 | prom_getstring(sdev->prom_node, "model", | 3252 | |
| 3283 | model, sizeof(model)); | 3253 | free_netdev(net_dev); |
| 3284 | if (!strcmp(model, "SUNW,sbus-qfe")) | 3254 | |
| 3285 | happy_meal_sbus_init(sdev, 1); | 3255 | dev_set_drvdata(&pdev->dev, NULL); |
| 3286 | else | ||
| 3287 | happy_meal_sbus_init(sdev, 0); | ||
| 3288 | } else if (!strcmp(name, "qfe") || | ||
| 3289 | !strcmp(name, "SUNW,qfe")) { | ||
| 3290 | cards++; | ||
| 3291 | happy_meal_sbus_init(sdev, 1); | ||
| 3292 | } | ||
| 3293 | } | ||
| 3294 | } | ||
| 3295 | if (cards != 0) | ||
| 3296 | quattro_sbus_register_irqs(); | ||
| 3297 | return cards; | ||
| 3298 | } | 3256 | } |
| 3299 | #endif | ||
| 3300 | 3257 | ||
| 3301 | #ifdef CONFIG_PCI | 3258 | static struct pci_device_id happymeal_pci_ids[] = { |
| 3302 | static int __init happy_meal_pci_probe(void) | 3259 | { |
| 3260 | .vendor = PCI_VENDOR_ID_SUN, | ||
| 3261 | .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, | ||
| 3262 | .subvendor = PCI_ANY_ID, | ||
| 3263 | .subdevice = PCI_ANY_ID, | ||
| 3264 | }, | ||
| 3265 | { } /* Terminating entry */ | ||
| 3266 | }; | ||
| 3267 | |||
| 3268 | MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); | ||
| 3269 | |||
| 3270 | static struct pci_driver hme_pci_driver = { | ||
| 3271 | .name = "hme", | ||
| 3272 | .id_table = happymeal_pci_ids, | ||
| 3273 | .probe = happy_meal_pci_probe, | ||
| 3274 | .remove = __devexit_p(happy_meal_pci_remove), | ||
| 3275 | }; | ||
| 3276 | |||
| 3277 | static int __init happy_meal_pci_init(void) | ||
| 3303 | { | 3278 | { |
| 3304 | struct pci_dev *pdev = NULL; | 3279 | return pci_module_init(&hme_pci_driver); |
| 3305 | int cards = 0; | 3280 | } |
| 3306 | 3281 | ||
| 3307 | while ((pdev = pci_find_device(PCI_VENDOR_ID_SUN, | 3282 | static void happy_meal_pci_exit(void) |
| 3308 | PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) { | 3283 | { |
| 3309 | if (pci_enable_device(pdev)) | 3284 | pci_unregister_driver(&hme_pci_driver); |
| 3310 | continue; | 3285 | |
| 3311 | pci_set_master(pdev); | 3286 | while (qfe_pci_list) { |
| 3312 | cards++; | 3287 | struct quattro *qfe = qfe_pci_list; |
| 3313 | happy_meal_pci_init(pdev); | 3288 | struct quattro *next = qfe->next; |
| 3289 | |||
| 3290 | kfree(qfe); | ||
| 3291 | |||
| 3292 | qfe_pci_list = next; | ||
| 3314 | } | 3293 | } |
| 3315 | return cards; | ||
| 3316 | } | 3294 | } |
| 3295 | |||
| 3317 | #endif | 3296 | #endif |
| 3318 | 3297 | ||
| 3319 | static int __init happy_meal_probe(void) | 3298 | #ifdef CONFIG_SBUS |
| 3299 | static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
| 3320 | { | 3300 | { |
| 3321 | static int called = 0; | 3301 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
| 3322 | int cards; | 3302 | struct device_node *dp = dev->node; |
| 3303 | char *model = of_get_property(dp, "model", NULL); | ||
| 3304 | int is_qfe = (match->data != NULL); | ||
| 3323 | 3305 | ||
| 3324 | root_happy_dev = NULL; | 3306 | if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) |
| 3307 | is_qfe = 1; | ||
| 3325 | 3308 | ||
| 3326 | if (called) | 3309 | return happy_meal_sbus_probe_one(sdev, is_qfe); |
| 3327 | return -ENODEV; | 3310 | } |
| 3328 | called++; | 3311 | |
| 3312 | static int __devexit hme_sbus_remove(struct of_device *dev) | ||
| 3313 | { | ||
| 3314 | struct happy_meal *hp = dev_get_drvdata(&dev->dev); | ||
| 3315 | struct net_device *net_dev = hp->dev; | ||
| 3316 | |||
| 3317 | unregister_netdevice(net_dev); | ||
| 3318 | |||
| 3319 | /* XXX qfe parent interrupt... */ | ||
| 3320 | |||
| 3321 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | ||
| 3322 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | ||
| 3323 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | ||
| 3324 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | ||
| 3325 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | ||
| 3326 | sbus_free_consistent(hp->happy_dev, | ||
| 3327 | PAGE_SIZE, | ||
| 3328 | hp->happy_block, | ||
| 3329 | hp->hblock_dvma); | ||
| 3330 | |||
| 3331 | free_netdev(net_dev); | ||
| 3332 | |||
| 3333 | dev_set_drvdata(&dev->dev, NULL); | ||
| 3329 | 3334 | ||
| 3330 | cards = 0; | ||
| 3331 | #ifdef CONFIG_SBUS | ||
| 3332 | cards += happy_meal_sbus_probe(); | ||
| 3333 | #endif | ||
| 3334 | #ifdef CONFIG_PCI | ||
| 3335 | cards += happy_meal_pci_probe(); | ||
| 3336 | #endif | ||
| 3337 | if (!cards) | ||
| 3338 | return -ENODEV; | ||
| 3339 | return 0; | 3335 | return 0; |
| 3340 | } | 3336 | } |
| 3341 | 3337 | ||
| 3338 | static struct of_device_id hme_sbus_match[] = { | ||
| 3339 | { | ||
| 3340 | .name = "SUNW,hme", | ||
| 3341 | }, | ||
| 3342 | { | ||
| 3343 | .name = "SUNW,qfe", | ||
| 3344 | .data = (void *) 1, | ||
| 3345 | }, | ||
| 3346 | { | ||
| 3347 | .name = "qfe", | ||
| 3348 | .data = (void *) 1, | ||
| 3349 | }, | ||
| 3350 | {}, | ||
| 3351 | }; | ||
| 3342 | 3352 | ||
| 3343 | static void __exit happy_meal_cleanup_module(void) | 3353 | MODULE_DEVICE_TABLE(of, hme_sbus_match); |
| 3344 | { | ||
| 3345 | #ifdef CONFIG_SBUS | ||
| 3346 | struct quattro *last_seen_qfe = NULL; | ||
| 3347 | #endif | ||
| 3348 | 3354 | ||
| 3349 | while (root_happy_dev) { | 3355 | static struct of_platform_driver hme_sbus_driver = { |
| 3350 | struct happy_meal *hp = root_happy_dev; | 3356 | .name = "hme", |
| 3351 | struct happy_meal *next = root_happy_dev->next_module; | 3357 | .match_table = hme_sbus_match, |
| 3352 | struct net_device *dev = hp->dev; | 3358 | .probe = hme_sbus_probe, |
| 3359 | .remove = __devexit_p(hme_sbus_remove), | ||
| 3360 | }; | ||
| 3353 | 3361 | ||
| 3354 | /* Unregister netdev before unmapping registers as this | 3362 | static int __init happy_meal_sbus_init(void) |
| 3355 | * call can end up trying to access those registers. | 3363 | { |
| 3356 | */ | 3364 | int err; |
| 3357 | unregister_netdev(dev); | ||
| 3358 | 3365 | ||
| 3359 | #ifdef CONFIG_SBUS | 3366 | err = of_register_driver(&hme_sbus_driver, &sbus_bus_type); |
| 3360 | if (!(hp->happy_flags & HFLAG_PCI)) { | 3367 | if (!err) |
| 3361 | if (hp->happy_flags & HFLAG_QUATTRO) { | 3368 | quattro_sbus_register_irqs(); |
| 3362 | if (hp->qfe_parent != last_seen_qfe) { | ||
| 3363 | free_irq(dev->irq, hp->qfe_parent); | ||
| 3364 | last_seen_qfe = hp->qfe_parent; | ||
| 3365 | } | ||
| 3366 | } | ||
| 3367 | 3369 | ||
| 3368 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | 3370 | return err; |
| 3369 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | 3371 | } |
| 3370 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | ||
| 3371 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | ||
| 3372 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | ||
| 3373 | sbus_free_consistent(hp->happy_dev, | ||
| 3374 | PAGE_SIZE, | ||
| 3375 | hp->happy_block, | ||
| 3376 | hp->hblock_dvma); | ||
| 3377 | } | ||
| 3378 | #endif | ||
| 3379 | #ifdef CONFIG_PCI | ||
| 3380 | if ((hp->happy_flags & HFLAG_PCI)) { | ||
| 3381 | pci_free_consistent(hp->happy_dev, | ||
| 3382 | PAGE_SIZE, | ||
| 3383 | hp->happy_block, | ||
| 3384 | hp->hblock_dvma); | ||
| 3385 | iounmap(hp->gregs); | ||
| 3386 | pci_release_regions(hp->happy_dev); | ||
| 3387 | } | ||
| 3388 | #endif | ||
| 3389 | free_netdev(dev); | ||
| 3390 | 3372 | ||
| 3391 | root_happy_dev = next; | 3373 | static void happy_meal_sbus_exit(void) |
| 3392 | } | 3374 | { |
| 3375 | of_unregister_driver(&hme_sbus_driver); | ||
| 3376 | quattro_sbus_free_irqs(); | ||
| 3393 | 3377 | ||
| 3394 | /* Now cleanup the quattro lists. */ | ||
| 3395 | #ifdef CONFIG_SBUS | ||
| 3396 | while (qfe_sbus_list) { | 3378 | while (qfe_sbus_list) { |
| 3397 | struct quattro *qfe = qfe_sbus_list; | 3379 | struct quattro *qfe = qfe_sbus_list; |
| 3398 | struct quattro *next = qfe->next; | 3380 | struct quattro *next = qfe->next; |
| @@ -3401,18 +3383,39 @@ static void __exit happy_meal_cleanup_module(void) | |||
| 3401 | 3383 | ||
| 3402 | qfe_sbus_list = next; | 3384 | qfe_sbus_list = next; |
| 3403 | } | 3385 | } |
| 3386 | } | ||
| 3404 | #endif | 3387 | #endif |
| 3405 | #ifdef CONFIG_PCI | ||
| 3406 | while (qfe_pci_list) { | ||
| 3407 | struct quattro *qfe = qfe_pci_list; | ||
| 3408 | struct quattro *next = qfe->next; | ||
| 3409 | 3388 | ||
| 3410 | kfree(qfe); | 3389 | static int __init happy_meal_probe(void) |
| 3390 | { | ||
| 3391 | int err = 0; | ||
| 3411 | 3392 | ||
| 3412 | qfe_pci_list = next; | 3393 | #ifdef CONFIG_SBUS |
| 3394 | err = happy_meal_sbus_init(); | ||
| 3395 | #endif | ||
| 3396 | #ifdef CONFIG_PCI | ||
| 3397 | if (!err) { | ||
| 3398 | err = happy_meal_pci_init(); | ||
| 3399 | #ifdef CONFIG_SBUS | ||
| 3400 | if (err) | ||
| 3401 | happy_meal_sbus_exit(); | ||
| 3402 | #endif | ||
| 3413 | } | 3403 | } |
| 3414 | #endif | 3404 | #endif |
| 3405 | |||
| 3406 | return err; | ||
| 3407 | } | ||
| 3408 | |||
| 3409 | |||
| 3410 | static void __exit happy_meal_exit(void) | ||
| 3411 | { | ||
| 3412 | #ifdef CONFIG_SBUS | ||
| 3413 | happy_meal_sbus_exit(); | ||
| 3414 | #endif | ||
| 3415 | #ifdef CONFIG_PCI | ||
| 3416 | happy_meal_pci_exit(); | ||
| 3417 | #endif | ||
| 3415 | } | 3418 | } |
| 3416 | 3419 | ||
| 3417 | module_init(happy_meal_probe); | 3420 | module_init(happy_meal_probe); |
| 3418 | module_exit(happy_meal_cleanup_module); | 3421 | module_exit(happy_meal_exit); |
