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); |