1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/types.h>
4 #include <linux/ioport.h>
5 #include <linux/init.h>
6 #include <linux/slab.h>
7 #include <linux/spinlock.h>
8 #include <linux/interrupt.h>
9 #include <linux/platform_device.h>
10 #include <linux/dma-mapping.h>
11 #include <linux/module.h>
14 #include <asm/amigaints.h>
15 #include <asm/amigahw.h>
17 #include <scsi/scsi.h>
18 #include <scsi/scsi_cmnd.h>
19 #include <scsi/scsi_device.h>
20 #include <scsi/scsi_eh.h>
21 #include <scsi/scsi_tcq.h>
26 struct a3000_hostdata
{
27 struct WD33C93_hostdata wh
;
28 struct a3000_scsiregs
*regs
;
32 #define DMA_DIR(d) ((d == DATA_OUT_DIR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)
34 static irqreturn_t
a3000_intr(int irq
, void *data
)
36 struct Scsi_Host
*instance
= data
;
37 struct a3000_hostdata
*hdata
= shost_priv(instance
);
38 unsigned int status
= hdata
->regs
->ISTR
;
41 if (!(status
& ISTR_INT_P
))
43 if (status
& ISTR_INTS
) {
44 spin_lock_irqsave(instance
->host_lock
, flags
);
45 wd33c93_intr(instance
);
46 spin_unlock_irqrestore(instance
->host_lock
, flags
);
49 pr_warn("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status
);
53 static int dma_setup(struct scsi_cmnd
*cmd
, int dir_in
)
55 struct scsi_pointer
*scsi_pointer
= WD33C93_scsi_pointer(cmd
);
56 unsigned long len
= scsi_pointer
->this_residual
;
57 struct Scsi_Host
*instance
= cmd
->device
->host
;
58 struct a3000_hostdata
*hdata
= shost_priv(instance
);
59 struct WD33C93_hostdata
*wh
= &hdata
->wh
;
60 struct a3000_scsiregs
*regs
= hdata
->regs
;
61 unsigned short cntr
= CNTR_PDMD
| CNTR_INTEN
;
64 addr
= dma_map_single(hdata
->dev
, scsi_pointer
->ptr
,
65 len
, DMA_DIR(dir_in
));
66 if (dma_mapping_error(hdata
->dev
, addr
)) {
67 dev_warn(hdata
->dev
, "cannot map SCSI data block %p\n",
71 scsi_pointer
->dma_handle
= addr
;
74 * if the physical address has the wrong alignment, or if
75 * physical address is bad, or if it is a write and at the
76 * end of a physical memory chunk, then allocate a bounce
78 * MSch 20220629 - only wrong alignment tested - bounce
79 * buffer returned by kmalloc is guaranteed to be aligned
81 if (addr
& A3000_XFER_MASK
) {
82 WARN_ONCE(1, "Invalid alignment for DMA!");
83 /* drop useless mapping */
84 dma_unmap_single(hdata
->dev
, scsi_pointer
->dma_handle
,
85 scsi_pointer
->this_residual
,
88 wh
->dma_bounce_len
= (scsi_pointer
->this_residual
+ 511) & ~0x1ff;
89 wh
->dma_bounce_buffer
= kmalloc(wh
->dma_bounce_len
,
92 /* can't allocate memory; use PIO */
93 if (!wh
->dma_bounce_buffer
) {
94 wh
->dma_bounce_len
= 0;
95 scsi_pointer
->dma_handle
= (dma_addr_t
) NULL
;
100 /* copy to bounce buffer for a write */
101 memcpy(wh
->dma_bounce_buffer
, scsi_pointer
->ptr
,
102 scsi_pointer
->this_residual
);
105 addr
= dma_map_single(hdata
->dev
, scsi_pointer
->ptr
,
106 len
, DMA_DIR(dir_in
));
107 if (dma_mapping_error(hdata
->dev
, addr
)) {
109 "cannot map SCSI data block %p\n",
113 scsi_pointer
->dma_handle
= addr
;
116 /* setup dma direction */
120 /* remember direction */
121 wh
->dma_dir
= dir_in
;
125 /* setup DMA *physical* address */
128 /* no more cache flush here - dma_map_single() takes care */
131 mb(); /* make sure setup is completed */
133 mb(); /* make sure DMA has started before next IO */
139 static void dma_stop(struct Scsi_Host
*instance
, struct scsi_cmnd
*SCpnt
,
142 struct scsi_pointer
*scsi_pointer
= WD33C93_scsi_pointer(SCpnt
);
143 struct a3000_hostdata
*hdata
= shost_priv(instance
);
144 struct WD33C93_hostdata
*wh
= &hdata
->wh
;
145 struct a3000_scsiregs
*regs
= hdata
->regs
;
147 /* disable SCSI interrupts */
148 unsigned short cntr
= CNTR_PDMD
;
154 mb(); /* make sure CNTR is updated before next IO */
156 /* flush if we were reading */
159 mb(); /* don't allow prefetch */
160 while (!(regs
->ISTR
& ISTR_FE_FLG
))
162 mb(); /* no IO until FLUSH is done */
165 /* clear a possible interrupt */
166 /* I think that this CINT is only necessary if you are
167 * using the terminal count features. HM 7 Mar 1994
173 mb(); /* make sure DMA is stopped before next IO */
175 /* restore the CONTROL bits (minus the direction flag) */
176 regs
->CNTR
= CNTR_PDMD
| CNTR_INTEN
;
177 mb(); /* make sure CNTR is updated before next IO */
179 dma_unmap_single(hdata
->dev
, scsi_pointer
->dma_handle
,
180 scsi_pointer
->this_residual
,
181 DMA_DIR(wh
->dma_dir
));
183 /* copy from a bounce buffer, if necessary */
184 if (status
&& wh
->dma_bounce_buffer
) {
186 if (wh
->dma_dir
&& SCpnt
)
187 memcpy(scsi_pointer
->ptr
, wh
->dma_bounce_buffer
,
188 scsi_pointer
->this_residual
);
189 kfree(wh
->dma_bounce_buffer
);
190 wh
->dma_bounce_buffer
= NULL
;
191 wh
->dma_bounce_len
= 0;
193 kfree(wh
->dma_bounce_buffer
);
194 wh
->dma_bounce_buffer
= NULL
;
195 wh
->dma_bounce_len
= 0;
200 static const struct scsi_host_template amiga_a3000_scsi_template
= {
201 .module
= THIS_MODULE
,
202 .name
= "Amiga 3000 built-in SCSI",
203 .show_info
= wd33c93_show_info
,
204 .write_info
= wd33c93_write_info
,
205 .proc_name
= "A3000",
206 .queuecommand
= wd33c93_queuecommand
,
207 .eh_abort_handler
= wd33c93_abort
,
208 .eh_host_reset_handler
= wd33c93_host_reset
,
209 .can_queue
= CAN_QUEUE
,
211 .sg_tablesize
= SG_ALL
,
212 .cmd_per_lun
= CMD_PER_LUN
,
213 .cmd_size
= sizeof(struct scsi_pointer
),
216 static int __init
amiga_a3000_scsi_probe(struct platform_device
*pdev
)
218 struct resource
*res
;
219 struct Scsi_Host
*instance
;
221 struct a3000_scsiregs
*regs
;
223 struct a3000_hostdata
*hdata
;
225 if (dma_set_mask_and_coherent(&pdev
->dev
, DMA_BIT_MASK(32))) {
226 dev_warn(&pdev
->dev
, "cannot use 32 bit DMA\n");
230 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
234 if (!request_mem_region(res
->start
, resource_size(res
), "wd33c93"))
237 instance
= scsi_host_alloc(&amiga_a3000_scsi_template
,
238 sizeof(struct a3000_hostdata
));
244 instance
->irq
= IRQ_AMIGA_PORTS
;
246 regs
= ZTWO_VADDR(res
->start
);
247 regs
->DAWR
= DAWR_A3000
;
249 wdregs
.SASR
= ®s
->SASR
;
250 wdregs
.SCMD
= ®s
->SCMD
;
252 hdata
= shost_priv(instance
);
253 hdata
->dev
= &pdev
->dev
;
254 hdata
->wh
.no_sync
= 0xff;
256 hdata
->wh
.dma_mode
= CTRL_DMA
;
259 wd33c93_init(instance
, wdregs
, dma_setup
, dma_stop
, WD33C93_FS_12_15
);
260 error
= request_irq(IRQ_AMIGA_PORTS
, a3000_intr
, IRQF_SHARED
,
261 "A3000 SCSI", instance
);
265 regs
->CNTR
= CNTR_PDMD
| CNTR_INTEN
;
267 error
= scsi_add_host(instance
, NULL
);
271 platform_set_drvdata(pdev
, instance
);
273 scsi_scan_host(instance
);
277 free_irq(IRQ_AMIGA_PORTS
, instance
);
279 scsi_host_put(instance
);
281 release_mem_region(res
->start
, resource_size(res
));
285 static void __exit
amiga_a3000_scsi_remove(struct platform_device
*pdev
)
287 struct Scsi_Host
*instance
= platform_get_drvdata(pdev
);
288 struct a3000_hostdata
*hdata
= shost_priv(instance
);
289 struct resource
*res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
291 hdata
->regs
->CNTR
= 0;
292 scsi_remove_host(instance
);
293 free_irq(IRQ_AMIGA_PORTS
, instance
);
294 scsi_host_put(instance
);
295 release_mem_region(res
->start
, resource_size(res
));
299 * amiga_a3000_scsi_remove() lives in .exit.text. For drivers registered via
300 * module_platform_driver_probe() this is ok because they cannot get unbound at
301 * runtime. So mark the driver struct with __refdata to prevent modpost
302 * triggering a section mismatch warning.
304 static struct platform_driver amiga_a3000_scsi_driver __refdata
= {
305 .remove_new
= __exit_p(amiga_a3000_scsi_remove
),
307 .name
= "amiga-a3000-scsi",
311 module_platform_driver_probe(amiga_a3000_scsi_driver
, amiga_a3000_scsi_probe
);
313 MODULE_DESCRIPTION("Amiga 3000 built-in SCSI");
314 MODULE_LICENSE("GPL");
315 MODULE_ALIAS("platform:amiga-a3000-scsi");