diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-05-11 10:48:58 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-05-11 12:00:29 -0400 |
commit | df9f54084f1faf611cedd846d38b0631f9d4e9a5 (patch) | |
tree | a4e5f46b26a761d62d79d5b367e885cc8a88b4b6 | |
parent | 129a84de2347002f09721cda3155ccfd19fade40 (diff) |
Convert SGI IP22 and specific drivers to platform_device.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/sgi-ip22/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/sgi-ip22/ip22-platform.c | 177 | ||||
-rw-r--r-- | drivers/net/sgiseeq.c | 83 | ||||
-rw-r--r-- | drivers/scsi/sgiwd93.c | 264 | ||||
-rw-r--r-- | include/asm-mips/sgi/seeq.h | 21 | ||||
-rw-r--r-- | include/asm-mips/sgi/wd.h | 20 |
6 files changed, 376 insertions, 191 deletions
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile index b6d649241dc1..1fb3e353e212 100644 --- a/arch/mips/sgi-ip22/Makefile +++ b/arch/mips/sgi-ip22/Makefile | |||
@@ -4,6 +4,6 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ | 6 | obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ |
7 | ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o | 7 | ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o |
8 | 8 | ||
9 | obj-$(CONFIG_EISA) += ip22-eisa.o | 9 | obj-$(CONFIG_EISA) += ip22-eisa.o |
diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c new file mode 100644 index 000000000000..78b608d2d4e1 --- /dev/null +++ b/arch/mips/sgi-ip22/ip22-platform.c | |||
@@ -0,0 +1,177 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/if_ether.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/platform_device.h> | ||
5 | |||
6 | #include <asm/paccess.h> | ||
7 | #include <asm/sgi/ip22.h> | ||
8 | #include <asm/sgi/hpc3.h> | ||
9 | #include <asm/sgi/mc.h> | ||
10 | #include <asm/sgi/seeq.h> | ||
11 | #include <asm/sgi/wd.h> | ||
12 | |||
13 | static struct resource sgiwd93_0_resources[] = { | ||
14 | { | ||
15 | .name = "eth0 irq", | ||
16 | .start = SGI_WD93_0_IRQ, | ||
17 | .end = SGI_WD93_0_IRQ, | ||
18 | .flags = IORESOURCE_IRQ | ||
19 | } | ||
20 | }; | ||
21 | |||
22 | static struct sgiwd93_platform_data sgiwd93_0_pd = { | ||
23 | .unit = 0, | ||
24 | .irq = SGI_WD93_0_IRQ, | ||
25 | }; | ||
26 | |||
27 | static struct platform_device sgiwd93_0_device = { | ||
28 | .name = "sgiwd93", | ||
29 | .id = 0, | ||
30 | .num_resources = ARRAY_SIZE(sgiwd93_0_resources), | ||
31 | .resource = sgiwd93_0_resources, | ||
32 | .dev = { | ||
33 | .platform_data = &sgiwd93_0_pd, | ||
34 | }, | ||
35 | }; | ||
36 | |||
37 | static struct resource sgiwd93_1_resources[] = { | ||
38 | { | ||
39 | .name = "eth0 irq", | ||
40 | .start = SGI_WD93_1_IRQ, | ||
41 | .end = SGI_WD93_1_IRQ, | ||
42 | .flags = IORESOURCE_IRQ | ||
43 | } | ||
44 | }; | ||
45 | |||
46 | static struct sgiwd93_platform_data sgiwd93_1_pd = { | ||
47 | .unit = 1, | ||
48 | .irq = SGI_WD93_1_IRQ, | ||
49 | }; | ||
50 | |||
51 | static struct platform_device sgiwd93_1_device = { | ||
52 | .name = "sgiwd93", | ||
53 | .id = 1, | ||
54 | .num_resources = ARRAY_SIZE(sgiwd93_1_resources), | ||
55 | .resource = sgiwd93_1_resources, | ||
56 | .dev = { | ||
57 | .platform_data = &sgiwd93_1_pd, | ||
58 | }, | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | * Create a platform device for the GPI port that receives the | ||
63 | * image data from the embedded camera. | ||
64 | */ | ||
65 | static int __init sgiwd93_devinit(void) | ||
66 | { | ||
67 | int res; | ||
68 | |||
69 | sgiwd93_0_pd.hregs = &hpc3c0->scsi_chan0; | ||
70 | sgiwd93_0_pd.wdregs = (unsigned char *) hpc3c0->scsi0_ext; | ||
71 | |||
72 | res = platform_device_register(&sgiwd93_0_device); | ||
73 | if (res) | ||
74 | return res; | ||
75 | |||
76 | if (!ip22_is_fullhouse()) | ||
77 | return 0; | ||
78 | |||
79 | sgiwd93_1_pd.hregs = &hpc3c0->scsi_chan1; | ||
80 | sgiwd93_1_pd.wdregs = (unsigned char *) hpc3c0->scsi1_ext; | ||
81 | |||
82 | return platform_device_register(&sgiwd93_1_device); | ||
83 | } | ||
84 | |||
85 | device_initcall(sgiwd93_devinit); | ||
86 | |||
87 | static struct resource sgiseeq_0_resources[] = { | ||
88 | { | ||
89 | .name = "eth0 irq", | ||
90 | .start = SGI_ENET_IRQ, | ||
91 | .end = SGI_ENET_IRQ, | ||
92 | .flags = IORESOURCE_IRQ | ||
93 | } | ||
94 | }; | ||
95 | |||
96 | static struct sgiseeq_platform_data eth0_pd; | ||
97 | |||
98 | static struct platform_device eth0_device = { | ||
99 | .name = "sgiseeq", | ||
100 | .id = 0, | ||
101 | .num_resources = ARRAY_SIZE(sgiseeq_0_resources), | ||
102 | .resource = sgiseeq_0_resources, | ||
103 | .dev = { | ||
104 | .platform_data = ð0_pd, | ||
105 | }, | ||
106 | }; | ||
107 | |||
108 | static struct resource sgiseeq_1_resources[] = { | ||
109 | { | ||
110 | .name = "eth1 irq", | ||
111 | .start = SGI_GIO_0_IRQ, | ||
112 | .end = SGI_GIO_0_IRQ, | ||
113 | .flags = IORESOURCE_IRQ | ||
114 | } | ||
115 | }; | ||
116 | |||
117 | static struct sgiseeq_platform_data eth1_pd; | ||
118 | |||
119 | static struct platform_device eth1_device = { | ||
120 | .name = "sgiseeq", | ||
121 | .id = 1, | ||
122 | .num_resources = ARRAY_SIZE(sgiseeq_1_resources), | ||
123 | .resource = sgiseeq_1_resources, | ||
124 | .dev = { | ||
125 | .platform_data = ð1_pd, | ||
126 | }, | ||
127 | }; | ||
128 | |||
129 | /* | ||
130 | * Create a platform device for the GPI port that receives the | ||
131 | * image data from the embedded camera. | ||
132 | */ | ||
133 | static int __init sgiseeq_devinit(void) | ||
134 | { | ||
135 | unsigned int tmp; | ||
136 | int res, i; | ||
137 | |||
138 | eth0_pd.hpc = hpc3c0; | ||
139 | eth0_pd.irq = SGI_ENET_IRQ; | ||
140 | #define EADDR_NVOFS 250 | ||
141 | for (i = 0; i < 3; i++) { | ||
142 | unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i); | ||
143 | |||
144 | eth0_pd.mac[2 * i] = tmp >> 8; | ||
145 | eth0_pd.mac[2 * i + 1] = tmp & 0xff; | ||
146 | } | ||
147 | |||
148 | res = platform_device_register(ð0_device); | ||
149 | if (res) | ||
150 | return res; | ||
151 | |||
152 | /* Second HPC is missing? */ | ||
153 | if (ip22_is_fullhouse() || | ||
154 | !get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1])) | ||
155 | return 0; | ||
156 | |||
157 | sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | SGIMC_GIOPAR_EXP164 | | ||
158 | SGIMC_GIOPAR_HPC264; | ||
159 | hpc3c1->pbus_piocfg[0][0] = 0x3ffff; | ||
160 | /* interrupt/config register on Challenge S Mezz board */ | ||
161 | hpc3c1->pbus_extregs[0][0] = 0x30; | ||
162 | |||
163 | eth1_pd.hpc = hpc3c1; | ||
164 | eth1_pd.irq = SGI_GIO_0_IRQ; | ||
165 | #define EADDR_NVOFS 250 | ||
166 | for (i = 0; i < 3; i++) { | ||
167 | unsigned short tmp = ip22_eeprom_read(&hpc3c1->eeprom, | ||
168 | EADDR_NVOFS / 2 + i); | ||
169 | |||
170 | eth1_pd.mac[2 * i] = tmp >> 8; | ||
171 | eth1_pd.mac[2 * i + 1] = tmp & 0xff; | ||
172 | } | ||
173 | |||
174 | return platform_device_register(ð1_device); | ||
175 | } | ||
176 | |||
177 | device_initcall(sgiseeq_devinit); | ||
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 1fc77300b055..2106becf6990 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c | |||
@@ -16,11 +16,13 @@ | |||
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/netdevice.h> | 18 | #include <linux/netdevice.h> |
19 | #include <linux/platform_device.h> | ||
19 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
20 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
21 | 22 | ||
22 | #include <asm/sgi/hpc3.h> | 23 | #include <asm/sgi/hpc3.h> |
23 | #include <asm/sgi/ip22.h> | 24 | #include <asm/sgi/ip22.h> |
25 | #include <asm/sgi/seeq.h> | ||
24 | 26 | ||
25 | #include "sgiseeq.h" | 27 | #include "sgiseeq.h" |
26 | 28 | ||
@@ -92,13 +94,9 @@ struct sgiseeq_private { | |||
92 | 94 | ||
93 | struct net_device_stats stats; | 95 | struct net_device_stats stats; |
94 | 96 | ||
95 | struct net_device *next_module; | ||
96 | spinlock_t tx_lock; | 97 | spinlock_t tx_lock; |
97 | }; | 98 | }; |
98 | 99 | ||
99 | /* A list of all installed seeq devices, for removing the driver module. */ | ||
100 | static struct net_device *root_sgiseeq_dev; | ||
101 | |||
102 | static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs) | 100 | static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs) |
103 | { | 101 | { |
104 | hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ; | 102 | hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ; |
@@ -624,9 +622,12 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs) | |||
624 | 622 | ||
625 | #define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf)) | 623 | #define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf)) |
626 | 624 | ||
627 | static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) | 625 | static int __init sgiseeq_probe(struct platform_device *pdev) |
628 | { | 626 | { |
627 | struct sgiseeq_platform_data *pd = pdev->dev.platform_data; | ||
628 | struct hpc3_regs *hpcregs = pd->hpc; | ||
629 | struct sgiseeq_init_block *sr; | 629 | struct sgiseeq_init_block *sr; |
630 | unsigned int irq = pd->irq; | ||
630 | struct sgiseeq_private *sp; | 631 | struct sgiseeq_private *sp; |
631 | struct net_device *dev; | 632 | struct net_device *dev; |
632 | int err, i; | 633 | int err, i; |
@@ -637,6 +638,8 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) | |||
637 | err = -ENOMEM; | 638 | err = -ENOMEM; |
638 | goto err_out; | 639 | goto err_out; |
639 | } | 640 | } |
641 | |||
642 | platform_set_drvdata(pdev, dev); | ||
640 | sp = netdev_priv(dev); | 643 | sp = netdev_priv(dev); |
641 | 644 | ||
642 | /* Make private data page aligned */ | 645 | /* Make private data page aligned */ |
@@ -648,15 +651,7 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) | |||
648 | } | 651 | } |
649 | sp->srings = sr; | 652 | sp->srings = sr; |
650 | 653 | ||
651 | #define EADDR_NVOFS 250 | 654 | memcpy(dev->dev_addr, pd->mac, ETH_ALEN); |
652 | for (i = 0; i < 3; i++) { | ||
653 | unsigned short tmp = has_eeprom ? | ||
654 | ip22_eeprom_read(&hpcregs->eeprom, EADDR_NVOFS / 2+i) : | ||
655 | ip22_nvram_read(EADDR_NVOFS / 2+i); | ||
656 | |||
657 | dev->dev_addr[2 * i] = tmp >> 8; | ||
658 | dev->dev_addr[2 * i + 1] = tmp & 0xff; | ||
659 | } | ||
660 | 655 | ||
661 | #ifdef DEBUG | 656 | #ifdef DEBUG |
662 | gpriv = sp; | 657 | gpriv = sp; |
@@ -720,9 +715,6 @@ static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) | |||
720 | for (i = 0; i < 6; i++) | 715 | for (i = 0; i < 6; i++) |
721 | printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); | 716 | printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); |
722 | 717 | ||
723 | sp->next_module = root_sgiseeq_dev; | ||
724 | root_sgiseeq_dev = dev; | ||
725 | |||
726 | return 0; | 718 | return 0; |
727 | 719 | ||
728 | err_out_free_page: | 720 | err_out_free_page: |
@@ -734,43 +726,42 @@ err_out: | |||
734 | return err; | 726 | return err; |
735 | } | 727 | } |
736 | 728 | ||
737 | static int __init sgiseeq_probe(void) | 729 | static void __exit sgiseeq_remove(struct platform_device *pdev) |
738 | { | 730 | { |
739 | unsigned int tmp, ret1, ret2 = 0; | 731 | struct net_device *dev = platform_get_drvdata(pdev); |
740 | 732 | struct sgiseeq_private *sp = netdev_priv(dev); | |
741 | /* On board adapter on 1st HPC is always present */ | ||
742 | ret1 = sgiseeq_init(hpc3c0, SGI_ENET_IRQ, 0); | ||
743 | /* Let's see if second HPC is there */ | ||
744 | if (!(ip22_is_fullhouse()) && | ||
745 | get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]) == 0) { | ||
746 | sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | | ||
747 | SGIMC_GIOPAR_EXP164 | | ||
748 | SGIMC_GIOPAR_HPC264; | ||
749 | hpc3c1->pbus_piocfg[0][0] = 0x3ffff; | ||
750 | /* interrupt/config register on Challenge S Mezz board */ | ||
751 | hpc3c1->pbus_extregs[0][0] = 0x30; | ||
752 | ret2 = sgiseeq_init(hpc3c1, SGI_GIO_0_IRQ, 1); | ||
753 | } | ||
754 | 733 | ||
755 | return (ret1 & ret2) ? ret1 : 0; | 734 | unregister_netdev(dev); |
735 | free_page((unsigned long) sp->srings); | ||
736 | free_netdev(dev); | ||
737 | platform_set_drvdata(pdev, NULL); | ||
756 | } | 738 | } |
757 | 739 | ||
758 | static void __exit sgiseeq_exit(void) | 740 | static struct platform_driver sgiseeq_driver = { |
759 | { | 741 | .probe = sgiseeq_probe, |
760 | struct net_device *next, *dev; | 742 | .remove = __devexit_p(sgiseeq_remove), |
761 | struct sgiseeq_private *sp; | 743 | .driver = { |
744 | .name = "sgiseeq" | ||
745 | } | ||
746 | }; | ||
762 | 747 | ||
763 | for (dev = root_sgiseeq_dev; dev; dev = next) { | 748 | static int __init sgiseeq_module_init(void) |
764 | sp = (struct sgiseeq_private *) netdev_priv(dev); | 749 | { |
765 | next = sp->next_module; | 750 | if (platform_driver_register(&sgiseeq_driver)) { |
766 | unregister_netdev(dev); | 751 | printk(KERN_ERR "Driver registration failed\n"); |
767 | free_page((unsigned long) sp->srings); | 752 | return -ENODEV; |
768 | free_netdev(dev); | ||
769 | } | 753 | } |
754 | |||
755 | return 0; | ||
756 | } | ||
757 | |||
758 | static void __exit sgiseeq_module_exit(void) | ||
759 | { | ||
760 | platform_driver_unregister(&sgiseeq_driver); | ||
770 | } | 761 | } |
771 | 762 | ||
772 | module_init(sgiseeq_probe); | 763 | module_init(sgiseeq_module_init); |
773 | module_exit(sgiseeq_exit); | 764 | module_exit(sgiseeq_module_exit); |
774 | 765 | ||
775 | MODULE_DESCRIPTION("SGI Seeq 8003 driver"); | 766 | MODULE_DESCRIPTION("SGI Seeq 8003 driver"); |
776 | MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>"); | 767 | MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>"); |
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index a15752b37990..eef82758d047 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c | |||
@@ -6,87 +6,49 @@ | |||
6 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) | 6 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) |
7 | * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) | 7 | * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) |
8 | * Copyright (C) 2001 Florian Lohoff (flo@rfc822.org) | 8 | * Copyright (C) 2001 Florian Lohoff (flo@rfc822.org) |
9 | * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) | 9 | * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org) |
10 | * | 10 | * |
11 | * (In all truth, Jed Schimmel wrote all this code.) | 11 | * (In all truth, Jed Schimmel wrote all this code.) |
12 | */ | 12 | */ |
13 | #include <linux/init.h> | 13 | |
14 | #include <linux/interrupt.h> | 14 | #undef DEBUG |
15 | #include <linux/types.h> | 15 | |
16 | #include <linux/mm.h> | ||
17 | #include <linux/blkdev.h> | ||
18 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
19 | #include <linux/dma-mapping.h> | 17 | #include <linux/dma-mapping.h> |
18 | #include <linux/gfp.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
20 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
21 | 26 | ||
22 | #include <asm/page.h> | ||
23 | #include <asm/pgtable.h> | ||
24 | #include <asm/sgialib.h> | ||
25 | #include <asm/sgi/sgi.h> | ||
26 | #include <asm/sgi/mc.h> | ||
27 | #include <asm/sgi/hpc3.h> | 27 | #include <asm/sgi/hpc3.h> |
28 | #include <asm/sgi/ip22.h> | 28 | #include <asm/sgi/ip22.h> |
29 | #include <asm/irq.h> | 29 | #include <asm/sgi/wd.h> |
30 | #include <asm/io.h> | ||
31 | 30 | ||
32 | #include "scsi.h" | 31 | #include "scsi.h" |
33 | #include <scsi/scsi_host.h> | ||
34 | #include "wd33c93.h" | 32 | #include "wd33c93.h" |
35 | 33 | ||
36 | #include <linux/stat.h> | ||
37 | |||
38 | #if 0 | ||
39 | #define DPRINTK(args...) printk(args) | ||
40 | #else | ||
41 | #define DPRINTK(args...) | ||
42 | #endif | ||
43 | |||
44 | #define HDATA(ptr) ((struct ip22_hostdata *)((ptr)->hostdata)) | ||
45 | |||
46 | struct ip22_hostdata { | 34 | struct ip22_hostdata { |
47 | struct WD33C93_hostdata wh; | 35 | struct WD33C93_hostdata wh; |
48 | struct hpc_data { | 36 | struct hpc_data { |
49 | dma_addr_t dma; | 37 | dma_addr_t dma; |
50 | void * cpu; | 38 | void *cpu; |
51 | } hd; | 39 | } hd; |
52 | }; | 40 | }; |
53 | 41 | ||
42 | #define host_to_hostdata(host) ((struct ip22_hostdata *)((host)->hostdata)) | ||
43 | |||
54 | struct hpc_chunk { | 44 | struct hpc_chunk { |
55 | struct hpc_dma_desc desc; | 45 | struct hpc_dma_desc desc; |
56 | u32 _padding; /* align to quadword boundary */ | 46 | u32 _padding; /* align to quadword boundary */ |
57 | }; | 47 | }; |
58 | 48 | ||
59 | struct Scsi_Host *sgiwd93_host; | ||
60 | struct Scsi_Host *sgiwd93_host1; | ||
61 | |||
62 | /* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */ | ||
63 | static inline void write_wd33c93_count(const wd33c93_regs regs, | ||
64 | unsigned long value) | ||
65 | { | ||
66 | *regs.SASR = WD_TRANSFER_COUNT_MSB; | ||
67 | mb(); | ||
68 | *regs.SCMD = ((value >> 16) & 0xff); | ||
69 | *regs.SCMD = ((value >> 8) & 0xff); | ||
70 | *regs.SCMD = ((value >> 0) & 0xff); | ||
71 | mb(); | ||
72 | } | ||
73 | |||
74 | static inline unsigned long read_wd33c93_count(const wd33c93_regs regs) | ||
75 | { | ||
76 | unsigned long value; | ||
77 | |||
78 | *regs.SASR = WD_TRANSFER_COUNT_MSB; | ||
79 | mb(); | ||
80 | value = ((*regs.SCMD & 0xff) << 16); | ||
81 | value |= ((*regs.SCMD & 0xff) << 8); | ||
82 | value |= ((*regs.SCMD & 0xff) << 0); | ||
83 | mb(); | ||
84 | return value; | ||
85 | } | ||
86 | |||
87 | static irqreturn_t sgiwd93_intr(int irq, void *dev_id) | 49 | static irqreturn_t sgiwd93_intr(int irq, void *dev_id) |
88 | { | 50 | { |
89 | struct Scsi_Host * host = (struct Scsi_Host *) dev_id; | 51 | struct Scsi_Host * host = dev_id; |
90 | unsigned long flags; | 52 | unsigned long flags; |
91 | 53 | ||
92 | spin_lock_irqsave(host->host_lock, flags); | 54 | spin_lock_irqsave(host->host_lock, flags); |
@@ -131,12 +93,12 @@ void fill_hpc_entries(struct hpc_chunk *hcp, struct scsi_cmnd *cmd, int datainp) | |||
131 | 93 | ||
132 | static int dma_setup(struct scsi_cmnd *cmd, int datainp) | 94 | static int dma_setup(struct scsi_cmnd *cmd, int datainp) |
133 | { | 95 | { |
134 | struct ip22_hostdata *hdata = HDATA(cmd->device->host); | 96 | struct ip22_hostdata *hdata = host_to_hostdata(cmd->device->host); |
135 | struct hpc3_scsiregs *hregs = | 97 | struct hpc3_scsiregs *hregs = |
136 | (struct hpc3_scsiregs *) cmd->device->host->base; | 98 | (struct hpc3_scsiregs *) cmd->device->host->base; |
137 | struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu; | 99 | struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu; |
138 | 100 | ||
139 | DPRINTK("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp); | 101 | pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp); |
140 | 102 | ||
141 | hdata->wh.dma_dir = datainp; | 103 | hdata->wh.dma_dir = datainp; |
142 | 104 | ||
@@ -151,7 +113,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int datainp) | |||
151 | 113 | ||
152 | fill_hpc_entries(hcp, cmd, datainp); | 114 | fill_hpc_entries(hcp, cmd, datainp); |
153 | 115 | ||
154 | DPRINTK(" HPCGO\n"); | 116 | pr_debug(" HPCGO\n"); |
155 | 117 | ||
156 | /* Start up the HPC. */ | 118 | /* Start up the HPC. */ |
157 | hregs->ndptr = hdata->hd.dma; | 119 | hregs->ndptr = hdata->hd.dma; |
@@ -166,7 +128,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int datainp) | |||
166 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | 128 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, |
167 | int status) | 129 | int status) |
168 | { | 130 | { |
169 | struct ip22_hostdata *hdata = HDATA(instance); | 131 | struct ip22_hostdata *hdata = host_to_hostdata(instance); |
170 | struct hpc3_scsiregs *hregs; | 132 | struct hpc3_scsiregs *hregs; |
171 | 133 | ||
172 | if (!SCpnt) | 134 | if (!SCpnt) |
@@ -174,7 +136,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | |||
174 | 136 | ||
175 | hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base; | 137 | hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base; |
176 | 138 | ||
177 | DPRINTK("dma_stop: status<%d> ", status); | 139 | pr_debug("dma_stop: status<%d> ", status); |
178 | 140 | ||
179 | /* First stop the HPC and flush it's FIFO. */ | 141 | /* First stop the HPC and flush it's FIFO. */ |
180 | if (hdata->wh.dma_dir) { | 142 | if (hdata->wh.dma_dir) { |
@@ -186,7 +148,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | |||
186 | dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual, | 148 | dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual, |
187 | SCpnt->sc_data_direction); | 149 | SCpnt->sc_data_direction); |
188 | 150 | ||
189 | DPRINTK("\n"); | 151 | pr_debug("\n"); |
190 | } | 152 | } |
191 | 153 | ||
192 | void sgiwd93_reset(unsigned long base) | 154 | void sgiwd93_reset(unsigned long base) |
@@ -216,29 +178,71 @@ static inline void init_hpc_chain(struct hpc_data *hd) | |||
216 | hcp->desc.pnext = hd->dma; | 178 | hcp->desc.pnext = hd->dma; |
217 | } | 179 | } |
218 | 180 | ||
219 | static struct Scsi_Host * __init sgiwd93_setup_scsi( | 181 | static int sgiwd93_bus_reset(struct scsi_cmnd *cmd) |
220 | struct scsi_host_template *SGIblows, int unit, int irq, | 182 | { |
221 | struct hpc3_scsiregs *hregs, unsigned char *wdregs) | 183 | /* FIXME perform bus-specific reset */ |
184 | |||
185 | /* FIXME 2: kill this function, and let midlayer fallback | ||
186 | to the same result, calling wd33c93_host_reset() */ | ||
187 | |||
188 | spin_lock_irq(cmd->device->host->host_lock); | ||
189 | wd33c93_host_reset(cmd); | ||
190 | spin_unlock_irq(cmd->device->host->host_lock); | ||
191 | |||
192 | return SUCCESS; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Kludge alert - the SCSI code calls the abort and reset method with int | ||
197 | * arguments not with pointers. So this is going to blow up beautyfully | ||
198 | * on 64-bit systems with memory outside the compat address spaces. | ||
199 | */ | ||
200 | static struct scsi_host_template sgiwd93_template = { | ||
201 | .module = THIS_MODULE, | ||
202 | .proc_name = "SGIWD93", | ||
203 | .name = "SGI WD93", | ||
204 | .queuecommand = wd33c93_queuecommand, | ||
205 | .eh_abort_handler = wd33c93_abort, | ||
206 | .eh_bus_reset_handler = sgiwd93_bus_reset, | ||
207 | .eh_host_reset_handler = wd33c93_host_reset, | ||
208 | .can_queue = 16, | ||
209 | .this_id = 7, | ||
210 | .sg_tablesize = SG_ALL, | ||
211 | .cmd_per_lun = 8, | ||
212 | .use_clustering = DISABLE_CLUSTERING, | ||
213 | }; | ||
214 | |||
215 | static int __init sgiwd93_probe(struct platform_device *pdev) | ||
222 | { | 216 | { |
217 | struct sgiwd93_platform_data *pd = pdev->dev.platform_data; | ||
218 | unsigned char *wdregs = pd->wdregs; | ||
219 | struct hpc3_scsiregs *hregs = pd->hregs; | ||
223 | struct ip22_hostdata *hdata; | 220 | struct ip22_hostdata *hdata; |
224 | struct Scsi_Host *host; | 221 | struct Scsi_Host *host; |
225 | wd33c93_regs regs; | 222 | wd33c93_regs regs; |
226 | 223 | unsigned int unit = pd->unit; | |
227 | host = scsi_register(SGIblows, sizeof(struct ip22_hostdata)); | 224 | unsigned int irq = pd->irq; |
228 | if (!host) | 225 | int err; |
229 | return NULL; | 226 | |
227 | host = scsi_host_alloc(&sgiwd93_template, sizeof(struct ip22_hostdata)); | ||
228 | if (!host) { | ||
229 | err = -ENOMEM; | ||
230 | goto out; | ||
231 | } | ||
230 | 232 | ||
231 | host->base = (unsigned long) hregs; | 233 | host->base = (unsigned long) hregs; |
232 | host->irq = irq; | 234 | host->irq = irq; |
233 | 235 | ||
234 | hdata = HDATA(host); | 236 | hdata = host_to_hostdata(host); |
235 | hdata->hd.cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &hdata->hd.dma, | 237 | hdata->hd.cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, |
236 | GFP_KERNEL); | 238 | &hdata->hd.dma, GFP_KERNEL); |
237 | if (!hdata->hd.cpu) { | 239 | if (!hdata->hd.cpu) { |
238 | printk(KERN_WARNING "sgiwd93: Could not allocate memory for " | 240 | printk(KERN_WARNING "sgiwd93: Could not allocate memory for " |
239 | "host %d buffer.\n", unit); | 241 | "host %d buffer.\n", unit); |
240 | goto out_unregister; | 242 | err = -ENOMEM; |
243 | goto out_put; | ||
241 | } | 244 | } |
245 | |||
242 | init_hpc_chain(&hdata->hd); | 246 | init_hpc_chain(&hdata->hd); |
243 | 247 | ||
244 | regs.SASR = wdregs + 3; | 248 | regs.SASR = wdregs + 3; |
@@ -249,95 +253,67 @@ static struct Scsi_Host * __init sgiwd93_setup_scsi( | |||
249 | if (hdata->wh.no_sync == 0xff) | 253 | if (hdata->wh.no_sync == 0xff) |
250 | hdata->wh.no_sync = 0; | 254 | hdata->wh.no_sync = 0; |
251 | 255 | ||
252 | if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) { | 256 | err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host); |
257 | if (err) { | ||
253 | printk(KERN_WARNING "sgiwd93: Could not register irq %d " | 258 | printk(KERN_WARNING "sgiwd93: Could not register irq %d " |
254 | "for host %d.\n", irq, unit); | 259 | "for host %d.\n", irq, unit); |
255 | goto out_free; | 260 | goto out_free; |
256 | } | 261 | } |
257 | return host; | ||
258 | 262 | ||
259 | out_free: | 263 | platform_set_drvdata(pdev, host); |
260 | dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); | ||
261 | wd33c93_release(); | ||
262 | 264 | ||
263 | out_unregister: | 265 | err = scsi_add_host(host, NULL); |
264 | scsi_unregister(host); | 266 | if (err) |
267 | goto out_irq; | ||
265 | 268 | ||
266 | return NULL; | 269 | scsi_scan_host(host); |
267 | } | ||
268 | |||
269 | static int __init sgiwd93_detect(struct scsi_host_template *SGIblows) | ||
270 | { | ||
271 | int found = 0; | ||
272 | |||
273 | SGIblows->proc_name = "SGIWD93"; | ||
274 | sgiwd93_host = sgiwd93_setup_scsi(SGIblows, 0, SGI_WD93_0_IRQ, | ||
275 | &hpc3c0->scsi_chan0, | ||
276 | (unsigned char *)hpc3c0->scsi0_ext); | ||
277 | if (sgiwd93_host) | ||
278 | found++; | ||
279 | |||
280 | /* Set up second controller on the Indigo2 */ | ||
281 | if (ip22_is_fullhouse()) { | ||
282 | sgiwd93_host1 = sgiwd93_setup_scsi(SGIblows, 1, SGI_WD93_1_IRQ, | ||
283 | &hpc3c0->scsi_chan1, | ||
284 | (unsigned char *)hpc3c0->scsi1_ext); | ||
285 | if (sgiwd93_host1) | ||
286 | found++; | ||
287 | } | ||
288 | |||
289 | return found; | ||
290 | } | ||
291 | 270 | ||
292 | static int sgiwd93_release(struct Scsi_Host *instance) | 271 | return 0; |
293 | { | ||
294 | struct ip22_hostdata *hdata = HDATA(instance); | ||
295 | int irq = 0; | ||
296 | |||
297 | if (sgiwd93_host && sgiwd93_host == instance) | ||
298 | irq = SGI_WD93_0_IRQ; | ||
299 | else if (sgiwd93_host1 && sgiwd93_host1 == instance) | ||
300 | irq = SGI_WD93_1_IRQ; | ||
301 | 272 | ||
302 | free_irq(irq, sgiwd93_intr); | 273 | out_irq: |
274 | free_irq(irq, host); | ||
275 | out_free: | ||
303 | dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); | 276 | dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); |
304 | wd33c93_release(); | 277 | out_put: |
278 | scsi_host_put(host); | ||
279 | out: | ||
305 | 280 | ||
306 | return 1; | 281 | return err; |
307 | } | 282 | } |
308 | 283 | ||
309 | static int sgiwd93_bus_reset(struct scsi_cmnd *cmd) | 284 | static void __exit sgiwd93_remove(struct platform_device *pdev) |
310 | { | 285 | { |
311 | /* FIXME perform bus-specific reset */ | 286 | struct Scsi_Host *host = platform_get_drvdata(pdev); |
287 | struct ip22_hostdata *hdata = (struct ip22_hostdata *) host->hostdata; | ||
288 | struct sgiwd93_platform_data *pd = pdev->dev.platform_data; | ||
289 | |||
290 | scsi_remove_host(host); | ||
291 | free_irq(pd->irq, host); | ||
292 | dma_free_coherent(&pdev->dev, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); | ||
293 | scsi_host_put(host); | ||
294 | } | ||
312 | 295 | ||
313 | /* FIXME 2: kill this function, and let midlayer fallback | 296 | static struct platform_driver sgiwd93_driver = { |
314 | to the same result, calling wd33c93_host_reset() */ | 297 | .probe = sgiwd93_probe, |
298 | .remove = __devexit_p(sgiwd93_remove), | ||
299 | .driver = { | ||
300 | .name = "sgiwd93" | ||
301 | } | ||
302 | }; | ||
315 | 303 | ||
316 | spin_lock_irq(cmd->device->host->host_lock); | 304 | static int __init sgiwd93_module_init(void) |
317 | wd33c93_host_reset(cmd); | 305 | { |
318 | spin_unlock_irq(cmd->device->host->host_lock); | 306 | return platform_driver_register(&sgiwd93_driver); |
307 | } | ||
319 | 308 | ||
320 | return SUCCESS; | 309 | static void __exit sgiwd93_module_exit(void) |
310 | { | ||
311 | return platform_driver_unregister(&sgiwd93_driver); | ||
321 | } | 312 | } |
322 | 313 | ||
323 | /* | 314 | module_init(sgiwd93_module_init); |
324 | * Kludge alert - the SCSI code calls the abort and reset method with int | 315 | module_exit(sgiwd93_module_exit); |
325 | * arguments not with pointers. So this is going to blow up beautyfully | 316 | |
326 | * on 64-bit systems with memory outside the compat address spaces. | 317 | MODULE_DESCRIPTION("SGI WD33C93 driver"); |
327 | */ | 318 | MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); |
328 | static struct scsi_host_template driver_template = { | 319 | MODULE_LICENSE("GPL"); |
329 | .proc_name = "SGIWD93", | ||
330 | .name = "SGI WD93", | ||
331 | .detect = sgiwd93_detect, | ||
332 | .release = sgiwd93_release, | ||
333 | .queuecommand = wd33c93_queuecommand, | ||
334 | .eh_abort_handler = wd33c93_abort, | ||
335 | .eh_bus_reset_handler = sgiwd93_bus_reset, | ||
336 | .eh_host_reset_handler = wd33c93_host_reset, | ||
337 | .can_queue = 16, | ||
338 | .this_id = 7, | ||
339 | .sg_tablesize = SG_ALL, | ||
340 | .cmd_per_lun = 8, | ||
341 | .use_clustering = DISABLE_CLUSTERING, | ||
342 | }; | ||
343 | #include "scsi_module.c" | ||
diff --git a/include/asm-mips/sgi/seeq.h b/include/asm-mips/sgi/seeq.h new file mode 100644 index 000000000000..af0ffd76899d --- /dev/null +++ b/include/asm-mips/sgi/seeq.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2007 by Ralf Baechle | ||
7 | */ | ||
8 | #ifndef __ASM_SGI_SEEQ_H | ||
9 | #define __ASM_SGI_SEEQ_H | ||
10 | |||
11 | #include <linux/if_ether.h> | ||
12 | |||
13 | #include <asm/sgi/hpc3.h> | ||
14 | |||
15 | struct sgiseeq_platform_data { | ||
16 | struct hpc3_regs *hpc; | ||
17 | unsigned int irq; | ||
18 | unsigned char mac[ETH_ALEN]; | ||
19 | }; | ||
20 | |||
21 | #endif /* __ASM_SGI_SEEQ_H */ | ||
diff --git a/include/asm-mips/sgi/wd.h b/include/asm-mips/sgi/wd.h new file mode 100644 index 000000000000..0d6c3a4da891 --- /dev/null +++ b/include/asm-mips/sgi/wd.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2007 by Ralf Baechle | ||
7 | */ | ||
8 | #ifndef __ASM_SGI_WD_H | ||
9 | #define __ASM_SGI_WD_H | ||
10 | |||
11 | #include <asm/sgi/hpc3.h> | ||
12 | |||
13 | struct sgiwd93_platform_data { | ||
14 | unsigned int unit; | ||
15 | unsigned int irq; | ||
16 | struct hpc3_scsiregs *hregs; | ||
17 | unsigned char *wdregs; | ||
18 | }; | ||
19 | |||
20 | #endif /* __ASM_SGI_WD_H */ | ||