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
6 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
7 * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu)
8 * Copyright (C) 2001 Florian Lohoff (flo@rfc822.org)
9 * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
11 * (In all truth, Jed Schimmel wrote all this code.)
16 #include <linux/delay.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>
25 #include <linux/spinlock.h>
27 #include <asm/sgi/hpc3.h>
28 #include <asm/sgi/ip22.h>
29 #include <asm/sgi/wd.h>
34 struct ip22_hostdata
{
35 struct WD33C93_hostdata wh
;
42 #define host_to_hostdata(host) ((struct ip22_hostdata *)((host)->hostdata))
45 struct hpc_dma_desc desc
;
46 u32 _padding
; /* align to quadword boundary */
49 static irqreturn_t
sgiwd93_intr(int irq
, void *dev_id
)
51 struct Scsi_Host
* host
= dev_id
;
54 spin_lock_irqsave(host
->host_lock
, flags
);
56 spin_unlock_irqrestore(host
->host_lock
, flags
);
62 void fill_hpc_entries(struct hpc_chunk
*hcp
, struct scsi_cmnd
*cmd
, int datainp
)
64 unsigned long len
= cmd
->SCp
.this_residual
;
65 void *addr
= cmd
->SCp
.ptr
;
69 physaddr
= dma_map_single(NULL
, addr
, len
, cmd
->sc_data_direction
);
70 cmd
->SCp
.dma_handle
= physaddr
;
74 * even cntinfo could be up to 16383, without
75 * magic only 8192 works correctly
77 count
= len
> 8192 ? 8192 : len
;
78 hcp
->desc
.pbuf
= physaddr
;
79 hcp
->desc
.cntinfo
= count
;
86 * To make sure, if we trip an HPC bug, that we transfer every single
87 * byte, we tag on an extra zero length dma descriptor at the end of
91 hcp
->desc
.cntinfo
= HPCDMA_EOX
;
94 static int dma_setup(struct scsi_cmnd
*cmd
, int datainp
)
96 struct ip22_hostdata
*hdata
= host_to_hostdata(cmd
->device
->host
);
97 struct hpc3_scsiregs
*hregs
=
98 (struct hpc3_scsiregs
*) cmd
->device
->host
->base
;
99 struct hpc_chunk
*hcp
= (struct hpc_chunk
*) hdata
->hd
.cpu
;
101 pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp
, hcp
);
103 hdata
->wh
.dma_dir
= datainp
;
106 * wd33c93 shouldn't pass us bogus dma_setups, but it does:-( The
107 * other wd33c93 drivers deal with it the same way (which isn't that
108 * obvious). IMHO a better fix would be, not to do these dma setups
109 * in the first place.
111 if (cmd
->SCp
.ptr
== NULL
|| cmd
->SCp
.this_residual
== 0)
114 fill_hpc_entries(hcp
, cmd
, datainp
);
116 pr_debug(" HPCGO\n");
118 /* Start up the HPC. */
119 hregs
->ndptr
= hdata
->hd
.dma
;
121 hregs
->ctrl
= HPC3_SCTRL_ACTIVE
;
123 hregs
->ctrl
= HPC3_SCTRL_ACTIVE
| HPC3_SCTRL_DIR
;
128 static void dma_stop(struct Scsi_Host
*instance
, struct scsi_cmnd
*SCpnt
,
131 struct ip22_hostdata
*hdata
= host_to_hostdata(instance
);
132 struct hpc3_scsiregs
*hregs
;
137 hregs
= (struct hpc3_scsiregs
*) SCpnt
->device
->host
->base
;
139 pr_debug("dma_stop: status<%d> ", status
);
141 /* First stop the HPC and flush it's FIFO. */
142 if (hdata
->wh
.dma_dir
) {
143 hregs
->ctrl
|= HPC3_SCTRL_FLUSH
;
144 while (hregs
->ctrl
& HPC3_SCTRL_ACTIVE
)
148 dma_unmap_single(NULL
, SCpnt
->SCp
.dma_handle
, SCpnt
->SCp
.this_residual
,
149 SCpnt
->sc_data_direction
);
154 void sgiwd93_reset(unsigned long base
)
156 struct hpc3_scsiregs
*hregs
= (struct hpc3_scsiregs
*) base
;
158 hregs
->ctrl
= HPC3_SCTRL_CRESET
;
163 static inline void init_hpc_chain(struct hpc_data
*hd
)
165 struct hpc_chunk
*hcp
= (struct hpc_chunk
*) hd
->cpu
;
166 struct hpc_chunk
*dma
= (struct hpc_chunk
*) hd
->dma
;
167 unsigned long start
, end
;
169 start
= (unsigned long) hcp
;
170 end
= start
+ PAGE_SIZE
;
171 while (start
< end
) {
172 hcp
->desc
.pnext
= (u32
) (dma
+ 1);
173 hcp
->desc
.cntinfo
= HPCDMA_EOX
;
175 start
+= sizeof(struct hpc_chunk
);
178 hcp
->desc
.pnext
= hd
->dma
;
181 static int sgiwd93_bus_reset(struct scsi_cmnd
*cmd
)
183 /* FIXME perform bus-specific reset */
185 /* FIXME 2: kill this function, and let midlayer fallback
186 to the same result, calling wd33c93_host_reset() */
188 spin_lock_irq(cmd
->device
->host
->host_lock
);
189 wd33c93_host_reset(cmd
);
190 spin_unlock_irq(cmd
->device
->host
->host_lock
);
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.
200 static struct scsi_host_template sgiwd93_template
= {
201 .module
= THIS_MODULE
,
202 .proc_name
= "SGIWD93",
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
,
210 .sg_tablesize
= SG_ALL
,
212 .use_clustering
= DISABLE_CLUSTERING
,
215 static int __init
sgiwd93_probe(struct platform_device
*pdev
)
217 struct sgiwd93_platform_data
*pd
= pdev
->dev
.platform_data
;
218 unsigned char *wdregs
= pd
->wdregs
;
219 struct hpc3_scsiregs
*hregs
= pd
->hregs
;
220 struct ip22_hostdata
*hdata
;
221 struct Scsi_Host
*host
;
223 unsigned int unit
= pd
->unit
;
224 unsigned int irq
= pd
->irq
;
227 host
= scsi_host_alloc(&sgiwd93_template
, sizeof(struct ip22_hostdata
));
233 host
->base
= (unsigned long) hregs
;
236 hdata
= host_to_hostdata(host
);
237 hdata
->hd
.cpu
= dma_alloc_coherent(&pdev
->dev
, PAGE_SIZE
,
238 &hdata
->hd
.dma
, GFP_KERNEL
);
239 if (!hdata
->hd
.cpu
) {
240 printk(KERN_WARNING
"sgiwd93: Could not allocate memory for "
241 "host %d buffer.\n", unit
);
246 init_hpc_chain(&hdata
->hd
);
248 regs
.SASR
= wdregs
+ 3;
249 regs
.SCMD
= wdregs
+ 7;
251 wd33c93_init(host
, regs
, dma_setup
, dma_stop
, WD33C93_FS_MHZ(20));
253 if (hdata
->wh
.no_sync
== 0xff)
254 hdata
->wh
.no_sync
= 0;
256 err
= request_irq(irq
, sgiwd93_intr
, 0, "SGI WD93", host
);
258 printk(KERN_WARNING
"sgiwd93: Could not register irq %d "
259 "for host %d.\n", irq
, unit
);
263 platform_set_drvdata(pdev
, host
);
265 err
= scsi_add_host(host
, NULL
);
269 scsi_scan_host(host
);
276 dma_free_coherent(NULL
, PAGE_SIZE
, hdata
->hd
.cpu
, hdata
->hd
.dma
);
284 static void __exit
sgiwd93_remove(struct platform_device
*pdev
)
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
;
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
);
296 static struct platform_driver sgiwd93_driver
= {
297 .probe
= sgiwd93_probe
,
298 .remove
= __devexit_p(sgiwd93_remove
),
304 static int __init
sgiwd93_module_init(void)
306 return platform_driver_register(&sgiwd93_driver
);
309 static void __exit
sgiwd93_module_exit(void)
311 return platform_driver_unregister(&sgiwd93_driver
);
314 module_init(sgiwd93_module_init
);
315 module_exit(sgiwd93_module_exit
);
317 MODULE_DESCRIPTION("SGI WD33C93 driver");
318 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
319 MODULE_LICENSE("GPL");