aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/sgi-ip22/Makefile2
-rw-r--r--arch/mips/sgi-ip22/ip22-platform.c177
-rw-r--r--drivers/net/sgiseeq.c83
-rw-r--r--drivers/scsi/sgiwd93.c264
-rw-r--r--include/asm-mips/sgi/seeq.h21
-rw-r--r--include/asm-mips/sgi/wd.h20
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
6obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ 6obj-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
9obj-$(CONFIG_EISA) += ip22-eisa.o 9obj-$(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
13static 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
22static struct sgiwd93_platform_data sgiwd93_0_pd = {
23 .unit = 0,
24 .irq = SGI_WD93_0_IRQ,
25};
26
27static 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
37static 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
46static struct sgiwd93_platform_data sgiwd93_1_pd = {
47 .unit = 1,
48 .irq = SGI_WD93_1_IRQ,
49};
50
51static 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 */
65static 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
85device_initcall(sgiwd93_devinit);
86
87static 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
96static struct sgiseeq_platform_data eth0_pd;
97
98static 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 = &eth0_pd,
105 },
106};
107
108static 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
117static struct sgiseeq_platform_data eth1_pd;
118
119static 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 = &eth1_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 */
133static 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(&eth0_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(&eth1_device);
175}
176
177device_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. */
100static struct net_device *root_sgiseeq_dev;
101
102static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs) 100static 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
627static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom) 625static 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
728err_out_free_page: 720err_out_free_page:
@@ -734,43 +726,42 @@ err_out:
734 return err; 726 return err;
735} 727}
736 728
737static int __init sgiseeq_probe(void) 729static 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
758static void __exit sgiseeq_exit(void) 740static 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) { 748static 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
758static void __exit sgiseeq_module_exit(void)
759{
760 platform_driver_unregister(&sgiseeq_driver);
770} 761}
771 762
772module_init(sgiseeq_probe); 763module_init(sgiseeq_module_init);
773module_exit(sgiseeq_exit); 764module_exit(sgiseeq_module_exit);
774 765
775MODULE_DESCRIPTION("SGI Seeq 8003 driver"); 766MODULE_DESCRIPTION("SGI Seeq 8003 driver");
776MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>"); 767MODULE_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
46struct ip22_hostdata { 34struct 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
54struct hpc_chunk { 44struct 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
59struct Scsi_Host *sgiwd93_host;
60struct Scsi_Host *sgiwd93_host1;
61
62/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
63static 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
74static 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
87static irqreturn_t sgiwd93_intr(int irq, void *dev_id) 49static 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
132static int dma_setup(struct scsi_cmnd *cmd, int datainp) 94static 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)
166static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, 128static 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
192void sgiwd93_reset(unsigned long base) 154void 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
219static struct Scsi_Host * __init sgiwd93_setup_scsi( 181static 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 */
200static 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
215static 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
259out_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
263out_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
269static 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
292static 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); 273out_irq:
274 free_irq(irq, host);
275out_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(); 277out_put:
278 scsi_host_put(host);
279out:
305 280
306 return 1; 281 return err;
307} 282}
308 283
309static int sgiwd93_bus_reset(struct scsi_cmnd *cmd) 284static 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 296static 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); 304static 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; 309static void __exit sgiwd93_module_exit(void)
310{
311 return platform_driver_unregister(&sgiwd93_driver);
321} 312}
322 313
323/* 314module_init(sgiwd93_module_init);
324 * Kludge alert - the SCSI code calls the abort and reset method with int 315module_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. 317MODULE_DESCRIPTION("SGI WD33C93 driver");
327 */ 318MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
328static struct scsi_host_template driver_template = { 319MODULE_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
15struct 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
13struct 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 */