109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds #include <linux/types.h>
31da177e4SLinus Torvalds #include <linux/init.h>
41da177e4SLinus Torvalds #include <linux/interrupt.h>
5c1d288a5SGeert Uytterhoeven #include <linux/mm.h>
6c1d288a5SGeert Uytterhoeven #include <linux/slab.h>
7c1d288a5SGeert Uytterhoeven #include <linux/spinlock.h>
8c1d288a5SGeert Uytterhoeven #include <linux/zorro.h>
9acf3368fSPaul Gortmaker #include <linux/module.h>
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds #include <asm/page.h>
121da177e4SLinus Torvalds #include <asm/amigaints.h>
131da177e4SLinus Torvalds #include <asm/amigahw.h>
141da177e4SLinus Torvalds
1553555fb7SBart Van Assche #include <scsi/scsi.h>
1653555fb7SBart Van Assche #include <scsi/scsi_cmnd.h>
1753555fb7SBart Van Assche #include <scsi/scsi_device.h>
1853555fb7SBart Van Assche #include <scsi/scsi_eh.h>
1953555fb7SBart Van Assche #include <scsi/scsi_tcq.h>
201da177e4SLinus Torvalds #include "wd33c93.h"
211da177e4SLinus Torvalds #include "gvp11.h"
221da177e4SLinus Torvalds
23bb17b787SGeert Uytterhoeven
2411ca46eaSGeert Uytterhoeven #define CHECK_WD33C93
2511ca46eaSGeert Uytterhoeven
26cf2ed279SGeert Uytterhoeven struct gvp11_hostdata {
27cf2ed279SGeert Uytterhoeven struct WD33C93_hostdata wh;
28cf2ed279SGeert Uytterhoeven struct gvp11_scsiregs *regs;
29158da6bcSMichael Schmitz struct device *dev;
30cf2ed279SGeert Uytterhoeven };
31cf2ed279SGeert Uytterhoeven
32158da6bcSMichael Schmitz #define DMA_DIR(d) ((d == DATA_OUT_DIR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)
33f712e24cSMichael Schmitz #define TO_DMA_MASK(m) (~((unsigned long long)m & 0xffffffff))
34158da6bcSMichael Schmitz
gvp11_intr(int irq,void * data)356869b15eSGeert Uytterhoeven static irqreturn_t gvp11_intr(int irq, void *data)
361da177e4SLinus Torvalds {
376869b15eSGeert Uytterhoeven struct Scsi_Host *instance = data;
38cf2ed279SGeert Uytterhoeven struct gvp11_hostdata *hdata = shost_priv(instance);
39cf2ed279SGeert Uytterhoeven unsigned int status = hdata->regs->CNTR;
401da177e4SLinus Torvalds unsigned long flags;
411da177e4SLinus Torvalds
421da177e4SLinus Torvalds if (!(status & GVP11_DMAC_INT_PENDING))
431da177e4SLinus Torvalds return IRQ_NONE;
441da177e4SLinus Torvalds
451da177e4SLinus Torvalds spin_lock_irqsave(instance->host_lock, flags);
461da177e4SLinus Torvalds wd33c93_intr(instance);
471da177e4SLinus Torvalds spin_unlock_irqrestore(instance->host_lock, flags);
481da177e4SLinus Torvalds return IRQ_HANDLED;
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds
511da177e4SLinus Torvalds static int gvp11_xfer_mask = 0;
521da177e4SLinus Torvalds
dma_setup(struct scsi_cmnd * cmd,int dir_in)5365396410SHenrik Kretzschmar static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
541da177e4SLinus Torvalds {
55dbb2da55SBart Van Assche struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
56158da6bcSMichael Schmitz unsigned long len = scsi_pointer->this_residual;
5752c3d8a6SGeert Uytterhoeven struct Scsi_Host *instance = cmd->device->host;
58cf2ed279SGeert Uytterhoeven struct gvp11_hostdata *hdata = shost_priv(instance);
59cf2ed279SGeert Uytterhoeven struct WD33C93_hostdata *wh = &hdata->wh;
60cf2ed279SGeert Uytterhoeven struct gvp11_scsiregs *regs = hdata->regs;
611da177e4SLinus Torvalds unsigned short cntr = GVP11_DMAC_INT_ENABLE;
62158da6bcSMichael Schmitz dma_addr_t addr;
631da177e4SLinus Torvalds int bank_mask;
641da177e4SLinus Torvalds static int scsi_alloc_out_of_range = 0;
651da177e4SLinus Torvalds
66158da6bcSMichael Schmitz addr = dma_map_single(hdata->dev, scsi_pointer->ptr,
67158da6bcSMichael Schmitz len, DMA_DIR(dir_in));
68158da6bcSMichael Schmitz if (dma_mapping_error(hdata->dev, addr)) {
69158da6bcSMichael Schmitz dev_warn(hdata->dev, "cannot map SCSI data block %p\n",
70158da6bcSMichael Schmitz scsi_pointer->ptr);
71158da6bcSMichael Schmitz return 1;
72158da6bcSMichael Schmitz }
73158da6bcSMichael Schmitz scsi_pointer->dma_handle = addr;
74158da6bcSMichael Schmitz
751da177e4SLinus Torvalds /* use bounce buffer if the physical address is bad */
76cf2ed279SGeert Uytterhoeven if (addr & wh->dma_xfer_mask) {
77158da6bcSMichael Schmitz /* drop useless mapping */
78158da6bcSMichael Schmitz dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
79158da6bcSMichael Schmitz scsi_pointer->this_residual,
80158da6bcSMichael Schmitz DMA_DIR(dir_in));
81158da6bcSMichael Schmitz scsi_pointer->dma_handle = (dma_addr_t) NULL;
82158da6bcSMichael Schmitz
83dbb2da55SBart Van Assche wh->dma_bounce_len = (scsi_pointer->this_residual + 511) & ~0x1ff;
841da177e4SLinus Torvalds
851da177e4SLinus Torvalds if (!scsi_alloc_out_of_range) {
86cf2ed279SGeert Uytterhoeven wh->dma_bounce_buffer =
87cf2ed279SGeert Uytterhoeven kmalloc(wh->dma_bounce_len, GFP_KERNEL);
88cf2ed279SGeert Uytterhoeven wh->dma_buffer_pool = BUF_SCSI_ALLOCED;
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds
911da177e4SLinus Torvalds if (scsi_alloc_out_of_range ||
92cf2ed279SGeert Uytterhoeven !wh->dma_bounce_buffer) {
93cf2ed279SGeert Uytterhoeven wh->dma_bounce_buffer =
94cf2ed279SGeert Uytterhoeven amiga_chip_alloc(wh->dma_bounce_len,
951da177e4SLinus Torvalds "GVP II SCSI Bounce Buffer");
961da177e4SLinus Torvalds
97cf2ed279SGeert Uytterhoeven if (!wh->dma_bounce_buffer) {
98cf2ed279SGeert Uytterhoeven wh->dma_bounce_len = 0;
991da177e4SLinus Torvalds return 1;
1001da177e4SLinus Torvalds }
1011da177e4SLinus Torvalds
102cf2ed279SGeert Uytterhoeven wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
1031da177e4SLinus Torvalds }
1041da177e4SLinus Torvalds
105158da6bcSMichael Schmitz if (!dir_in) {
106158da6bcSMichael Schmitz /* copy to bounce buffer for a write */
107158da6bcSMichael Schmitz memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
108158da6bcSMichael Schmitz scsi_pointer->this_residual);
109158da6bcSMichael Schmitz }
110158da6bcSMichael Schmitz
111158da6bcSMichael Schmitz if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
112158da6bcSMichael Schmitz /* will flush/invalidate cache for us */
113158da6bcSMichael Schmitz addr = dma_map_single(hdata->dev,
114158da6bcSMichael Schmitz wh->dma_bounce_buffer,
115158da6bcSMichael Schmitz wh->dma_bounce_len,
116158da6bcSMichael Schmitz DMA_DIR(dir_in));
117158da6bcSMichael Schmitz /* can't map buffer; use PIO */
118158da6bcSMichael Schmitz if (dma_mapping_error(hdata->dev, addr)) {
119158da6bcSMichael Schmitz dev_warn(hdata->dev,
120158da6bcSMichael Schmitz "cannot map bounce buffer %p\n",
121158da6bcSMichael Schmitz wh->dma_bounce_buffer);
122158da6bcSMichael Schmitz return 1;
123158da6bcSMichael Schmitz }
124158da6bcSMichael Schmitz }
1251da177e4SLinus Torvalds
126cf2ed279SGeert Uytterhoeven if (addr & wh->dma_xfer_mask) {
127158da6bcSMichael Schmitz /* drop useless mapping */
128158da6bcSMichael Schmitz dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
129158da6bcSMichael Schmitz scsi_pointer->this_residual,
130158da6bcSMichael Schmitz DMA_DIR(dir_in));
1311da177e4SLinus Torvalds /* fall back to Chip RAM if address out of range */
132cf2ed279SGeert Uytterhoeven if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
133cf2ed279SGeert Uytterhoeven kfree(wh->dma_bounce_buffer);
1341da177e4SLinus Torvalds scsi_alloc_out_of_range = 1;
1351da177e4SLinus Torvalds } else {
136cf2ed279SGeert Uytterhoeven amiga_chip_free(wh->dma_bounce_buffer);
1371da177e4SLinus Torvalds }
1381da177e4SLinus Torvalds
139cf2ed279SGeert Uytterhoeven wh->dma_bounce_buffer =
140cf2ed279SGeert Uytterhoeven amiga_chip_alloc(wh->dma_bounce_len,
1411da177e4SLinus Torvalds "GVP II SCSI Bounce Buffer");
1421da177e4SLinus Torvalds
143cf2ed279SGeert Uytterhoeven if (!wh->dma_bounce_buffer) {
144cf2ed279SGeert Uytterhoeven wh->dma_bounce_len = 0;
1451da177e4SLinus Torvalds return 1;
1461da177e4SLinus Torvalds }
1471da177e4SLinus Torvalds
1481da177e4SLinus Torvalds if (!dir_in) {
1491da177e4SLinus Torvalds /* copy to bounce buffer for a write */
150dbb2da55SBart Van Assche memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
151dbb2da55SBart Van Assche scsi_pointer->this_residual);
1521da177e4SLinus Torvalds }
153158da6bcSMichael Schmitz /* chip RAM can be mapped to phys. address directly */
154158da6bcSMichael Schmitz addr = virt_to_phys(wh->dma_bounce_buffer);
155158da6bcSMichael Schmitz /* no need to flush/invalidate cache */
156158da6bcSMichael Schmitz wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
157158da6bcSMichael Schmitz }
158158da6bcSMichael Schmitz /* finally, have OK mapping (punted for PIO else) */
159158da6bcSMichael Schmitz scsi_pointer->dma_handle = addr;
160158da6bcSMichael Schmitz
1611da177e4SLinus Torvalds }
1621da177e4SLinus Torvalds
1631da177e4SLinus Torvalds /* setup dma direction */
1641da177e4SLinus Torvalds if (!dir_in)
1651da177e4SLinus Torvalds cntr |= GVP11_DMAC_DIR_WRITE;
1661da177e4SLinus Torvalds
167cf2ed279SGeert Uytterhoeven wh->dma_dir = dir_in;
1686869b15eSGeert Uytterhoeven regs->CNTR = cntr;
1691da177e4SLinus Torvalds
1701da177e4SLinus Torvalds /* setup DMA *physical* address */
1716869b15eSGeert Uytterhoeven regs->ACR = addr;
1721da177e4SLinus Torvalds
173158da6bcSMichael Schmitz /* no more cache flush here - dma_map_single() takes care */
1741da177e4SLinus Torvalds
175cf2ed279SGeert Uytterhoeven bank_mask = (~wh->dma_xfer_mask >> 18) & 0x01c0;
17652c3d8a6SGeert Uytterhoeven if (bank_mask)
1776869b15eSGeert Uytterhoeven regs->BANK = bank_mask & (addr >> 18);
1781da177e4SLinus Torvalds
1791da177e4SLinus Torvalds /* start DMA */
1806869b15eSGeert Uytterhoeven regs->ST_DMA = 1;
1811da177e4SLinus Torvalds
1821da177e4SLinus Torvalds /* return success */
1831da177e4SLinus Torvalds return 0;
1841da177e4SLinus Torvalds }
1851da177e4SLinus Torvalds
dma_stop(struct Scsi_Host * instance,struct scsi_cmnd * SCpnt,int status)18665396410SHenrik Kretzschmar static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
1871da177e4SLinus Torvalds int status)
1881da177e4SLinus Torvalds {
189dbb2da55SBart Van Assche struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(SCpnt);
190cf2ed279SGeert Uytterhoeven struct gvp11_hostdata *hdata = shost_priv(instance);
191cf2ed279SGeert Uytterhoeven struct WD33C93_hostdata *wh = &hdata->wh;
192cf2ed279SGeert Uytterhoeven struct gvp11_scsiregs *regs = hdata->regs;
19352c3d8a6SGeert Uytterhoeven
1941da177e4SLinus Torvalds /* stop DMA */
1956869b15eSGeert Uytterhoeven regs->SP_DMA = 1;
1961da177e4SLinus Torvalds /* remove write bit from CONTROL bits */
1976869b15eSGeert Uytterhoeven regs->CNTR = GVP11_DMAC_INT_ENABLE;
1981da177e4SLinus Torvalds
199158da6bcSMichael Schmitz if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
200158da6bcSMichael Schmitz dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
201158da6bcSMichael Schmitz scsi_pointer->this_residual,
202158da6bcSMichael Schmitz DMA_DIR(wh->dma_dir));
203158da6bcSMichael Schmitz
2041da177e4SLinus Torvalds /* copy from a bounce buffer, if necessary */
205cf2ed279SGeert Uytterhoeven if (status && wh->dma_bounce_buffer) {
206cf2ed279SGeert Uytterhoeven if (wh->dma_dir && SCpnt)
207dbb2da55SBart Van Assche memcpy(scsi_pointer->ptr, wh->dma_bounce_buffer,
208dbb2da55SBart Van Assche scsi_pointer->this_residual);
2091da177e4SLinus Torvalds
210cf2ed279SGeert Uytterhoeven if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
211cf2ed279SGeert Uytterhoeven kfree(wh->dma_bounce_buffer);
2121da177e4SLinus Torvalds else
213cf2ed279SGeert Uytterhoeven amiga_chip_free(wh->dma_bounce_buffer);
2141da177e4SLinus Torvalds
215cf2ed279SGeert Uytterhoeven wh->dma_bounce_buffer = NULL;
216cf2ed279SGeert Uytterhoeven wh->dma_bounce_len = 0;
2171da177e4SLinus Torvalds }
2181da177e4SLinus Torvalds }
2191da177e4SLinus Torvalds
220*ccc54750SBart Van Assche static const struct scsi_host_template gvp11_scsi_template = {
221c1d288a5SGeert Uytterhoeven .module = THIS_MODULE,
222c1d288a5SGeert Uytterhoeven .name = "GVP Series II SCSI",
223408bb25bSAl Viro .show_info = wd33c93_show_info,
224408bb25bSAl Viro .write_info = wd33c93_write_info,
225c1d288a5SGeert Uytterhoeven .proc_name = "GVP11",
226c1d288a5SGeert Uytterhoeven .queuecommand = wd33c93_queuecommand,
227c1d288a5SGeert Uytterhoeven .eh_abort_handler = wd33c93_abort,
228c1d288a5SGeert Uytterhoeven .eh_host_reset_handler = wd33c93_host_reset,
229c1d288a5SGeert Uytterhoeven .can_queue = CAN_QUEUE,
230c1d288a5SGeert Uytterhoeven .this_id = 7,
231c1d288a5SGeert Uytterhoeven .sg_tablesize = SG_ALL,
232c1d288a5SGeert Uytterhoeven .cmd_per_lun = CMD_PER_LUN,
2334af14d11SChristoph Hellwig .dma_boundary = PAGE_SIZE - 1,
234dbb2da55SBart Van Assche .cmd_size = sizeof(struct scsi_pointer),
235c1d288a5SGeert Uytterhoeven };
236c1d288a5SGeert Uytterhoeven
check_wd33c93(struct gvp11_scsiregs * regs)2376f039790SGreg Kroah-Hartman static int check_wd33c93(struct gvp11_scsiregs *regs)
23811ca46eaSGeert Uytterhoeven {
23911ca46eaSGeert Uytterhoeven #ifdef CHECK_WD33C93
24011ca46eaSGeert Uytterhoeven volatile unsigned char *sasr_3393, *scmd_3393;
24111ca46eaSGeert Uytterhoeven unsigned char save_sasr;
24211ca46eaSGeert Uytterhoeven unsigned char q, qq;
24311ca46eaSGeert Uytterhoeven
24411ca46eaSGeert Uytterhoeven /*
24511ca46eaSGeert Uytterhoeven * These darn GVP boards are a problem - it can be tough to tell
24611ca46eaSGeert Uytterhoeven * whether or not they include a SCSI controller. This is the
24711ca46eaSGeert Uytterhoeven * ultimate Yet-Another-GVP-Detection-Hack in that it actually
24811ca46eaSGeert Uytterhoeven * probes for a WD33c93 chip: If we find one, it's extremely
24911ca46eaSGeert Uytterhoeven * likely that this card supports SCSI, regardless of Product_
25011ca46eaSGeert Uytterhoeven * Code, Board_Size, etc.
25111ca46eaSGeert Uytterhoeven */
25211ca46eaSGeert Uytterhoeven
25311ca46eaSGeert Uytterhoeven /* Get pointers to the presumed register locations and save contents */
25411ca46eaSGeert Uytterhoeven
25511ca46eaSGeert Uytterhoeven sasr_3393 = ®s->SASR;
25611ca46eaSGeert Uytterhoeven scmd_3393 = ®s->SCMD;
25711ca46eaSGeert Uytterhoeven save_sasr = *sasr_3393;
25811ca46eaSGeert Uytterhoeven
25911ca46eaSGeert Uytterhoeven /* First test the AuxStatus Reg */
26011ca46eaSGeert Uytterhoeven
26111ca46eaSGeert Uytterhoeven q = *sasr_3393; /* read it */
26211ca46eaSGeert Uytterhoeven if (q & 0x08) /* bit 3 should always be clear */
26311ca46eaSGeert Uytterhoeven return -ENODEV;
26411ca46eaSGeert Uytterhoeven *sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */
26511ca46eaSGeert Uytterhoeven if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */
26611ca46eaSGeert Uytterhoeven *sasr_3393 = save_sasr; /* Oops - restore this byte */
26711ca46eaSGeert Uytterhoeven return -ENODEV;
26811ca46eaSGeert Uytterhoeven }
26911ca46eaSGeert Uytterhoeven if (*sasr_3393 != q) { /* should still read the same */
27011ca46eaSGeert Uytterhoeven *sasr_3393 = save_sasr; /* Oops - restore this byte */
27111ca46eaSGeert Uytterhoeven return -ENODEV;
27211ca46eaSGeert Uytterhoeven }
27311ca46eaSGeert Uytterhoeven if (*scmd_3393 != q) /* and so should the image at 0x1f */
27411ca46eaSGeert Uytterhoeven return -ENODEV;
27511ca46eaSGeert Uytterhoeven
27611ca46eaSGeert Uytterhoeven /*
27711ca46eaSGeert Uytterhoeven * Ok, we probably have a wd33c93, but let's check a few other places
27811ca46eaSGeert Uytterhoeven * for good measure. Make sure that this works for both 'A and 'B
27911ca46eaSGeert Uytterhoeven * chip versions.
28011ca46eaSGeert Uytterhoeven */
28111ca46eaSGeert Uytterhoeven
28211ca46eaSGeert Uytterhoeven *sasr_3393 = WD_SCSI_STATUS;
28311ca46eaSGeert Uytterhoeven q = *scmd_3393;
28411ca46eaSGeert Uytterhoeven *sasr_3393 = WD_SCSI_STATUS;
28511ca46eaSGeert Uytterhoeven *scmd_3393 = ~q;
28611ca46eaSGeert Uytterhoeven *sasr_3393 = WD_SCSI_STATUS;
28711ca46eaSGeert Uytterhoeven qq = *scmd_3393;
28811ca46eaSGeert Uytterhoeven *sasr_3393 = WD_SCSI_STATUS;
28911ca46eaSGeert Uytterhoeven *scmd_3393 = q;
29011ca46eaSGeert Uytterhoeven if (qq != q) /* should be read only */
29111ca46eaSGeert Uytterhoeven return -ENODEV;
29211ca46eaSGeert Uytterhoeven *sasr_3393 = 0x1e; /* this register is unimplemented */
29311ca46eaSGeert Uytterhoeven q = *scmd_3393;
29411ca46eaSGeert Uytterhoeven *sasr_3393 = 0x1e;
29511ca46eaSGeert Uytterhoeven *scmd_3393 = ~q;
29611ca46eaSGeert Uytterhoeven *sasr_3393 = 0x1e;
29711ca46eaSGeert Uytterhoeven qq = *scmd_3393;
29811ca46eaSGeert Uytterhoeven *sasr_3393 = 0x1e;
29911ca46eaSGeert Uytterhoeven *scmd_3393 = q;
30011ca46eaSGeert Uytterhoeven if (qq != q || qq != 0xff) /* should be read only, all 1's */
30111ca46eaSGeert Uytterhoeven return -ENODEV;
30211ca46eaSGeert Uytterhoeven *sasr_3393 = WD_TIMEOUT_PERIOD;
30311ca46eaSGeert Uytterhoeven q = *scmd_3393;
30411ca46eaSGeert Uytterhoeven *sasr_3393 = WD_TIMEOUT_PERIOD;
30511ca46eaSGeert Uytterhoeven *scmd_3393 = ~q;
30611ca46eaSGeert Uytterhoeven *sasr_3393 = WD_TIMEOUT_PERIOD;
30711ca46eaSGeert Uytterhoeven qq = *scmd_3393;
30811ca46eaSGeert Uytterhoeven *sasr_3393 = WD_TIMEOUT_PERIOD;
30911ca46eaSGeert Uytterhoeven *scmd_3393 = q;
31011ca46eaSGeert Uytterhoeven if (qq != (~q & 0xff)) /* should be read/write */
31111ca46eaSGeert Uytterhoeven return -ENODEV;
31211ca46eaSGeert Uytterhoeven #endif /* CHECK_WD33C93 */
31311ca46eaSGeert Uytterhoeven
31411ca46eaSGeert Uytterhoeven return 0;
31511ca46eaSGeert Uytterhoeven }
3161da177e4SLinus Torvalds
gvp11_probe(struct zorro_dev * z,const struct zorro_device_id * ent)3176f039790SGreg Kroah-Hartman static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
3181da177e4SLinus Torvalds {
3191da177e4SLinus Torvalds struct Scsi_Host *instance;
3201da177e4SLinus Torvalds unsigned long address;
321c1d288a5SGeert Uytterhoeven int error;
3221da177e4SLinus Torvalds unsigned int epc;
3231da177e4SLinus Torvalds unsigned int default_dma_xfer_mask;
324cf2ed279SGeert Uytterhoeven struct gvp11_hostdata *hdata;
325349d65fdSGeert Uytterhoeven struct gvp11_scsiregs *regs;
3266869b15eSGeert Uytterhoeven wd33c93_regs wdregs;
3271da177e4SLinus Torvalds
328c1d288a5SGeert Uytterhoeven default_dma_xfer_mask = ent->driver_data;
3291da177e4SLinus Torvalds
330158da6bcSMichael Schmitz if (dma_set_mask_and_coherent(&z->dev,
331158da6bcSMichael Schmitz TO_DMA_MASK(default_dma_xfer_mask))) {
332f712e24cSMichael Schmitz dev_warn(&z->dev, "cannot use DMA mask %llx\n",
333158da6bcSMichael Schmitz TO_DMA_MASK(default_dma_xfer_mask));
334158da6bcSMichael Schmitz return -ENODEV;
335158da6bcSMichael Schmitz }
336158da6bcSMichael Schmitz
3371da177e4SLinus Torvalds /*
3381da177e4SLinus Torvalds * Rumors state that some GVP ram boards use the same product
3391da177e4SLinus Torvalds * code as the SCSI controllers. Therefore if the board-size
34025985edcSLucas De Marchi * is not 64KB we assume it is a ram board and bail out.
3411da177e4SLinus Torvalds */
342c1d288a5SGeert Uytterhoeven if (zorro_resource_len(z) != 0x10000)
343c1d288a5SGeert Uytterhoeven return -ENODEV;
3441da177e4SLinus Torvalds
3451da177e4SLinus Torvalds address = z->resource.start;
3461da177e4SLinus Torvalds if (!request_mem_region(address, 256, "wd33c93"))
347c1d288a5SGeert Uytterhoeven return -EBUSY;
3481da177e4SLinus Torvalds
3496112ea08SGeert Uytterhoeven regs = ZTWO_VADDR(address);
3501da177e4SLinus Torvalds
351c1d288a5SGeert Uytterhoeven error = check_wd33c93(regs);
352c1d288a5SGeert Uytterhoeven if (error)
353c1d288a5SGeert Uytterhoeven goto fail_check_or_alloc;
354c1d288a5SGeert Uytterhoeven
355c1d288a5SGeert Uytterhoeven instance = scsi_host_alloc(&gvp11_scsi_template,
356cf2ed279SGeert Uytterhoeven sizeof(struct gvp11_hostdata));
357c1d288a5SGeert Uytterhoeven if (!instance) {
358c1d288a5SGeert Uytterhoeven error = -ENOMEM;
359c1d288a5SGeert Uytterhoeven goto fail_check_or_alloc;
360c1d288a5SGeert Uytterhoeven }
361c1d288a5SGeert Uytterhoeven
3621da177e4SLinus Torvalds instance->irq = IRQ_AMIGA_PORTS;
3631da177e4SLinus Torvalds instance->unique_id = z->slotaddr;
3641da177e4SLinus Torvalds
3656869b15eSGeert Uytterhoeven regs->secret2 = 1;
3666869b15eSGeert Uytterhoeven regs->secret1 = 0;
3676869b15eSGeert Uytterhoeven regs->secret3 = 15;
3686869b15eSGeert Uytterhoeven while (regs->CNTR & GVP11_DMAC_BUSY)
369bb17b787SGeert Uytterhoeven ;
3706869b15eSGeert Uytterhoeven regs->CNTR = 0;
3716869b15eSGeert Uytterhoeven regs->BANK = 0;
3721da177e4SLinus Torvalds
373c1d288a5SGeert Uytterhoeven wdregs.SASR = ®s->SASR;
374c1d288a5SGeert Uytterhoeven wdregs.SCMD = ®s->SCMD;
375c1d288a5SGeert Uytterhoeven
376c1d288a5SGeert Uytterhoeven hdata = shost_priv(instance);
377158da6bcSMichael Schmitz if (gvp11_xfer_mask) {
378cf2ed279SGeert Uytterhoeven hdata->wh.dma_xfer_mask = gvp11_xfer_mask;
379158da6bcSMichael Schmitz if (dma_set_mask_and_coherent(&z->dev,
380158da6bcSMichael Schmitz TO_DMA_MASK(gvp11_xfer_mask))) {
381f712e24cSMichael Schmitz dev_warn(&z->dev, "cannot use DMA mask %llx\n",
382158da6bcSMichael Schmitz TO_DMA_MASK(gvp11_xfer_mask));
383158da6bcSMichael Schmitz error = -ENODEV;
384158da6bcSMichael Schmitz goto fail_check_or_alloc;
385158da6bcSMichael Schmitz }
386158da6bcSMichael Schmitz } else
387cf2ed279SGeert Uytterhoeven hdata->wh.dma_xfer_mask = default_dma_xfer_mask;
388c1d288a5SGeert Uytterhoeven
389cf2ed279SGeert Uytterhoeven hdata->wh.no_sync = 0xff;
390cf2ed279SGeert Uytterhoeven hdata->wh.fast = 0;
391cf2ed279SGeert Uytterhoeven hdata->wh.dma_mode = CTRL_DMA;
392cf2ed279SGeert Uytterhoeven hdata->regs = regs;
3931da177e4SLinus Torvalds
3941da177e4SLinus Torvalds /*
3951da177e4SLinus Torvalds * Check for 14MHz SCSI clock
3961da177e4SLinus Torvalds */
397c1d288a5SGeert Uytterhoeven epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
3986869b15eSGeert Uytterhoeven wd33c93_init(instance, wdregs, dma_setup, dma_stop,
3991da177e4SLinus Torvalds (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
4001da177e4SLinus Torvalds : WD33C93_FS_12_15);
4011da177e4SLinus Torvalds
402c1d288a5SGeert Uytterhoeven error = request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED,
403c1d288a5SGeert Uytterhoeven "GVP11 SCSI", instance);
404c1d288a5SGeert Uytterhoeven if (error)
405c1d288a5SGeert Uytterhoeven goto fail_irq;
406c1d288a5SGeert Uytterhoeven
4076869b15eSGeert Uytterhoeven regs->CNTR = GVP11_DMAC_INT_ENABLE;
4081da177e4SLinus Torvalds
409c1d288a5SGeert Uytterhoeven error = scsi_add_host(instance, NULL);
410c1d288a5SGeert Uytterhoeven if (error)
411c1d288a5SGeert Uytterhoeven goto fail_host;
412c1d288a5SGeert Uytterhoeven
413c1d288a5SGeert Uytterhoeven zorro_set_drvdata(z, instance);
414c1d288a5SGeert Uytterhoeven scsi_scan_host(instance);
415c1d288a5SGeert Uytterhoeven return 0;
416c1d288a5SGeert Uytterhoeven
417c1d288a5SGeert Uytterhoeven fail_host:
418c1d288a5SGeert Uytterhoeven free_irq(IRQ_AMIGA_PORTS, instance);
419c1d288a5SGeert Uytterhoeven fail_irq:
420c1d288a5SGeert Uytterhoeven scsi_host_put(instance);
421c1d288a5SGeert Uytterhoeven fail_check_or_alloc:
4221da177e4SLinus Torvalds release_mem_region(address, 256);
423c1d288a5SGeert Uytterhoeven return error;
4241da177e4SLinus Torvalds }
4251da177e4SLinus Torvalds
gvp11_remove(struct zorro_dev * z)4266f039790SGreg Kroah-Hartman static void gvp11_remove(struct zorro_dev *z)
4271da177e4SLinus Torvalds {
428c1d288a5SGeert Uytterhoeven struct Scsi_Host *instance = zorro_get_drvdata(z);
429cf2ed279SGeert Uytterhoeven struct gvp11_hostdata *hdata = shost_priv(instance);
4306869b15eSGeert Uytterhoeven
431cf2ed279SGeert Uytterhoeven hdata->regs->CNTR = 0;
432c1d288a5SGeert Uytterhoeven scsi_remove_host(instance);
4331da177e4SLinus Torvalds free_irq(IRQ_AMIGA_PORTS, instance);
434c1d288a5SGeert Uytterhoeven scsi_host_put(instance);
435c1d288a5SGeert Uytterhoeven release_mem_region(z->resource.start, 256);
4361da177e4SLinus Torvalds }
4371da177e4SLinus Torvalds
438c1d288a5SGeert Uytterhoeven /*
439c1d288a5SGeert Uytterhoeven * This should (hopefully) be the correct way to identify
440c1d288a5SGeert Uytterhoeven * all the different GVP SCSI controllers (except for the
441c1d288a5SGeert Uytterhoeven * SERIES I though).
442c1d288a5SGeert Uytterhoeven */
443c1d288a5SGeert Uytterhoeven
4446f039790SGreg Kroah-Hartman static struct zorro_device_id gvp11_zorro_tbl[] = {
445c1d288a5SGeert Uytterhoeven { ZORRO_PROD_GVP_COMBO_030_R3_SCSI, ~0x00ffffff },
446c1d288a5SGeert Uytterhoeven { ZORRO_PROD_GVP_SERIES_II, ~0x00ffffff },
447c1d288a5SGeert Uytterhoeven { ZORRO_PROD_GVP_GFORCE_030_SCSI, ~0x01ffffff },
448c1d288a5SGeert Uytterhoeven { ZORRO_PROD_GVP_A530_SCSI, ~0x01ffffff },
449c1d288a5SGeert Uytterhoeven { ZORRO_PROD_GVP_COMBO_030_R4_SCSI, ~0x01ffffff },
450c1d288a5SGeert Uytterhoeven { ZORRO_PROD_GVP_A1291, ~0x07ffffff },
451c1d288a5SGeert Uytterhoeven { ZORRO_PROD_GVP_GFORCE_040_SCSI_1, ~0x07ffffff },
452c1d288a5SGeert Uytterhoeven { 0 }
453c1d288a5SGeert Uytterhoeven };
454c1d288a5SGeert Uytterhoeven MODULE_DEVICE_TABLE(zorro, gvp11_zorro_tbl);
455c1d288a5SGeert Uytterhoeven
456c1d288a5SGeert Uytterhoeven static struct zorro_driver gvp11_driver = {
457c1d288a5SGeert Uytterhoeven .name = "gvp11",
458c1d288a5SGeert Uytterhoeven .id_table = gvp11_zorro_tbl,
459c1d288a5SGeert Uytterhoeven .probe = gvp11_probe,
4606f039790SGreg Kroah-Hartman .remove = gvp11_remove,
461c1d288a5SGeert Uytterhoeven };
462c1d288a5SGeert Uytterhoeven
gvp11_init(void)463c1d288a5SGeert Uytterhoeven static int __init gvp11_init(void)
464c1d288a5SGeert Uytterhoeven {
465c1d288a5SGeert Uytterhoeven return zorro_register_driver(&gvp11_driver);
466c1d288a5SGeert Uytterhoeven }
467c1d288a5SGeert Uytterhoeven module_init(gvp11_init);
468c1d288a5SGeert Uytterhoeven
gvp11_exit(void)469c1d288a5SGeert Uytterhoeven static void __exit gvp11_exit(void)
470c1d288a5SGeert Uytterhoeven {
471c1d288a5SGeert Uytterhoeven zorro_unregister_driver(&gvp11_driver);
472c1d288a5SGeert Uytterhoeven }
473c1d288a5SGeert Uytterhoeven module_exit(gvp11_exit);
474c1d288a5SGeert Uytterhoeven
475c1d288a5SGeert Uytterhoeven MODULE_DESCRIPTION("GVP Series II SCSI");
4761da177e4SLinus Torvalds MODULE_LICENSE("GPL");
477