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 (davem@davemloft.net)
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>
31 #include <scsi/scsi.h>
32 #include <scsi/scsi_cmnd.h>
33 #include <scsi/scsi_device.h>
34 #include <scsi/scsi_eh.h>
35 #include <scsi/scsi_tcq.h>
38 struct ip22_hostdata
{
39 struct WD33C93_hostdata wh
;
45 #define host_to_hostdata(host) ((struct ip22_hostdata *)((host)->hostdata))
48 struct hpc_dma_desc desc
;
49 u32 _padding
; /* align to quadword boundary */
52 /* space for hpc dma descriptors */
53 #define HPC_DMA_SIZE PAGE_SIZE
55 #define DMA_DIR(d) ((d == DATA_OUT_DIR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)
57 static irqreturn_t
sgiwd93_intr(int irq
, void *dev_id
)
59 struct Scsi_Host
* host
= dev_id
;
62 spin_lock_irqsave(host
->host_lock
, flags
);
64 spin_unlock_irqrestore(host
->host_lock
, flags
);
70 void fill_hpc_entries(struct ip22_hostdata
*hd
, struct scsi_cmnd
*cmd
, int din
)
72 struct scsi_pointer
*scsi_pointer
= WD33C93_scsi_pointer(cmd
);
73 unsigned long len
= scsi_pointer
->this_residual
;
74 void *addr
= scsi_pointer
->ptr
;
77 struct hpc_chunk
*hcp
;
79 physaddr
= dma_map_single(hd
->dev
, addr
, len
, DMA_DIR(din
));
80 scsi_pointer
->dma_handle
= physaddr
;
85 * even cntinfo could be up to 16383, without
86 * magic only 8192 works correctly
88 count
= len
> 8192 ? 8192 : len
;
89 hcp
->desc
.pbuf
= physaddr
;
90 hcp
->desc
.cntinfo
= count
;
97 * To make sure, if we trip an HPC bug, that we transfer every single
98 * byte, we tag on an extra zero length dma descriptor at the end of
102 hcp
->desc
.cntinfo
= HPCDMA_EOX
;
103 dma_sync_single_for_device(hd
->dev
, hd
->dma
,
104 (unsigned long)(hcp
+ 1) - (unsigned long)hd
->cpu
,
108 static int dma_setup(struct scsi_cmnd
*cmd
, int datainp
)
110 struct scsi_pointer
*scsi_pointer
= WD33C93_scsi_pointer(cmd
);
111 struct ip22_hostdata
*hdata
= host_to_hostdata(cmd
->device
->host
);
112 struct hpc3_scsiregs
*hregs
=
113 (struct hpc3_scsiregs
*) cmd
->device
->host
->base
;
115 pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp
, hdata
->cpu
);
117 hdata
->wh
.dma_dir
= datainp
;
120 * wd33c93 shouldn't pass us bogus dma_setups, but it does:-( The
121 * other wd33c93 drivers deal with it the same way (which isn't that
122 * obvious). IMHO a better fix would be, not to do these dma setups
123 * in the first place.
125 if (scsi_pointer
->ptr
== NULL
|| scsi_pointer
->this_residual
== 0)
128 fill_hpc_entries(hdata
, cmd
, datainp
);
130 pr_debug(" HPCGO\n");
132 /* Start up the HPC. */
133 hregs
->ndptr
= hdata
->dma
;
135 hregs
->ctrl
= HPC3_SCTRL_ACTIVE
;
137 hregs
->ctrl
= HPC3_SCTRL_ACTIVE
| HPC3_SCTRL_DIR
;
142 static void dma_stop(struct Scsi_Host
*instance
, struct scsi_cmnd
*SCpnt
,
145 struct scsi_pointer
*scsi_pointer
= WD33C93_scsi_pointer(SCpnt
);
146 struct ip22_hostdata
*hdata
= host_to_hostdata(instance
);
147 struct hpc3_scsiregs
*hregs
;
152 if (scsi_pointer
->ptr
== NULL
|| scsi_pointer
->this_residual
== 0)
155 hregs
= (struct hpc3_scsiregs
*) SCpnt
->device
->host
->base
;
157 pr_debug("dma_stop: status<%d> ", status
);
159 /* First stop the HPC and flush it's FIFO. */
160 if (hdata
->wh
.dma_dir
) {
161 hregs
->ctrl
|= HPC3_SCTRL_FLUSH
;
162 while (hregs
->ctrl
& HPC3_SCTRL_ACTIVE
)
166 dma_unmap_single(hdata
->dev
, scsi_pointer
->dma_handle
,
167 scsi_pointer
->this_residual
,
168 DMA_DIR(hdata
->wh
.dma_dir
));
173 void sgiwd93_reset(unsigned long base
)
175 struct hpc3_scsiregs
*hregs
= (struct hpc3_scsiregs
*) base
;
177 hregs
->ctrl
= HPC3_SCTRL_CRESET
;
181 EXPORT_SYMBOL_GPL(sgiwd93_reset
);
183 static inline void init_hpc_chain(struct ip22_hostdata
*hdata
)
185 struct hpc_chunk
*hcp
= (struct hpc_chunk
*)hdata
->cpu
;
186 dma_addr_t dma
= hdata
->dma
;
187 unsigned long start
, end
;
189 start
= (unsigned long) hcp
;
190 end
= start
+ HPC_DMA_SIZE
;
191 while (start
< end
) {
192 hcp
->desc
.pnext
= (u32
) (dma
+ sizeof(struct hpc_chunk
));
193 hcp
->desc
.cntinfo
= HPCDMA_EOX
;
195 dma
+= sizeof(struct hpc_chunk
);
196 start
+= sizeof(struct hpc_chunk
);
199 hcp
->desc
.pnext
= hdata
->dma
;
203 * Kludge alert - the SCSI code calls the abort and reset method with int
204 * arguments not with pointers. So this is going to blow up beautyfully
205 * on 64-bit systems with memory outside the compat address spaces.
207 static const struct scsi_host_template sgiwd93_template
= {
208 .module
= THIS_MODULE
,
209 .proc_name
= "SGIWD93",
211 .queuecommand
= wd33c93_queuecommand
,
212 .eh_abort_handler
= wd33c93_abort
,
213 .eh_host_reset_handler
= wd33c93_host_reset
,
216 .sg_tablesize
= SG_ALL
,
218 .dma_boundary
= PAGE_SIZE
- 1,
219 .cmd_size
= sizeof(struct scsi_pointer
),
222 static int sgiwd93_probe(struct platform_device
*pdev
)
224 struct sgiwd93_platform_data
*pd
= pdev
->dev
.platform_data
;
225 unsigned char *wdregs
= pd
->wdregs
;
226 struct hpc3_scsiregs
*hregs
= pd
->hregs
;
227 struct ip22_hostdata
*hdata
;
228 struct Scsi_Host
*host
;
230 unsigned int unit
= pd
->unit
;
231 unsigned int irq
= pd
->irq
;
234 host
= scsi_host_alloc(&sgiwd93_template
, sizeof(struct ip22_hostdata
));
240 host
->base
= (unsigned long) hregs
;
243 hdata
= host_to_hostdata(host
);
244 hdata
->dev
= &pdev
->dev
;
245 hdata
->cpu
= dma_alloc_noncoherent(&pdev
->dev
, HPC_DMA_SIZE
,
246 &hdata
->dma
, DMA_TO_DEVICE
, GFP_KERNEL
);
248 printk(KERN_WARNING
"sgiwd93: Could not allocate memory for "
249 "host %d buffer.\n", unit
);
254 init_hpc_chain(hdata
);
256 regs
.SASR
= wdregs
+ 3;
257 regs
.SCMD
= wdregs
+ 7;
259 hdata
->wh
.no_sync
= 0;
261 hdata
->wh
.dma_mode
= CTRL_BURST
;
263 wd33c93_init(host
, regs
, dma_setup
, dma_stop
, WD33C93_FS_MHZ(20));
265 err
= request_irq(irq
, sgiwd93_intr
, 0, "SGI WD93", host
);
267 printk(KERN_WARNING
"sgiwd93: Could not register irq %d "
268 "for host %d.\n", irq
, unit
);
272 platform_set_drvdata(pdev
, host
);
274 err
= scsi_add_host(host
, NULL
);
278 scsi_scan_host(host
);
285 dma_free_noncoherent(&pdev
->dev
, HPC_DMA_SIZE
, hdata
->cpu
, hdata
->dma
,
294 static void sgiwd93_remove(struct platform_device
*pdev
)
296 struct Scsi_Host
*host
= platform_get_drvdata(pdev
);
297 struct ip22_hostdata
*hdata
= (struct ip22_hostdata
*) host
->hostdata
;
298 struct sgiwd93_platform_data
*pd
= pdev
->dev
.platform_data
;
300 scsi_remove_host(host
);
301 free_irq(pd
->irq
, host
);
302 dma_free_noncoherent(&pdev
->dev
, HPC_DMA_SIZE
, hdata
->cpu
, hdata
->dma
,
307 static struct platform_driver sgiwd93_driver
= {
308 .probe
= sgiwd93_probe
,
309 .remove_new
= sgiwd93_remove
,
315 static int __init
sgiwd93_module_init(void)
317 return platform_driver_register(&sgiwd93_driver
);
320 static void __exit
sgiwd93_module_exit(void)
322 return platform_driver_unregister(&sgiwd93_driver
);
325 module_init(sgiwd93_module_init
);
326 module_exit(sgiwd93_module_exit
);
328 MODULE_DESCRIPTION("SGI WD33C93 driver");
329 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
330 MODULE_LICENSE("GPL");
331 MODULE_ALIAS("platform:sgiwd93");