1
2#include <linux/types.h>
3#include <linux/init.h>
4#include <linux/interrupt.h>
5#include <linux/mm.h>
6#include <linux/slab.h>
7#include <linux/spinlock.h>
8#include <linux/zorro.h>
9#include <linux/module.h>
10
11#include <asm/page.h>
12#include <asm/amigaints.h>
13#include <asm/amigahw.h>
14
15#include <scsi/scsi.h>
16#include <scsi/scsi_cmnd.h>
17#include <scsi/scsi_device.h>
18#include <scsi/scsi_eh.h>
19#include <scsi/scsi_tcq.h>
20#include "wd33c93.h"
21#include "gvp11.h"
22
23
24#define CHECK_WD33C93
25
26struct gvp11_hostdata {
27 struct WD33C93_hostdata wh;
28 struct gvp11_scsiregs *regs;
29};
30
31static irqreturn_t gvp11_intr(int irq, void *data)
32{
33 struct Scsi_Host *instance = data;
34 struct gvp11_hostdata *hdata = shost_priv(instance);
35 unsigned int status = hdata->regs->CNTR;
36 unsigned long flags;
37
38 if (!(status & GVP11_DMAC_INT_PENDING))
39 return IRQ_NONE;
40
41 spin_lock_irqsave(instance->host_lock, flags);
42 wd33c93_intr(instance);
43 spin_unlock_irqrestore(instance->host_lock, flags);
44 return IRQ_HANDLED;
45}
46
47static int gvp11_xfer_mask = 0;
48
49void gvp11_setup(char *str, int *ints)
50{
51 gvp11_xfer_mask = ints[1];
52}
53
54static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
55{
56 struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
57 struct Scsi_Host *instance = cmd->device->host;
58 struct gvp11_hostdata *hdata = shost_priv(instance);
59 struct WD33C93_hostdata *wh = &hdata->wh;
60 struct gvp11_scsiregs *regs = hdata->regs;
61 unsigned short cntr = GVP11_DMAC_INT_ENABLE;
62 unsigned long addr = virt_to_bus(scsi_pointer->ptr);
63 int bank_mask;
64 static int scsi_alloc_out_of_range = 0;
65
66
67 if (addr & wh->dma_xfer_mask) {
68 wh->dma_bounce_len = (scsi_pointer->this_residual + 511) & ~0x1ff;
69
70 if (!scsi_alloc_out_of_range) {
71 wh->dma_bounce_buffer =
72 kmalloc(wh->dma_bounce_len, GFP_KERNEL);
73 wh->dma_buffer_pool = BUF_SCSI_ALLOCED;
74 }
75
76 if (scsi_alloc_out_of_range ||
77 !wh->dma_bounce_buffer) {
78 wh->dma_bounce_buffer =
79 amiga_chip_alloc(wh->dma_bounce_len,
80 "GVP II SCSI Bounce Buffer");
81
82 if (!wh->dma_bounce_buffer) {
83 wh->dma_bounce_len = 0;
84 return 1;
85 }
86
87 wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
88 }
89
90
91 addr = virt_to_bus(wh->dma_bounce_buffer);
92
93 if (addr & wh->dma_xfer_mask) {
94
95 if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
96 kfree(wh->dma_bounce_buffer);
97 scsi_alloc_out_of_range = 1;
98 } else {
99 amiga_chip_free(wh->dma_bounce_buffer);
100 }
101
102 wh->dma_bounce_buffer =
103 amiga_chip_alloc(wh->dma_bounce_len,
104 "GVP II SCSI Bounce Buffer");
105
106 if (!wh->dma_bounce_buffer) {
107 wh->dma_bounce_len = 0;
108 return 1;
109 }
110
111 addr = virt_to_bus(wh->dma_bounce_buffer);
112 wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
113 }
114
115 if (!dir_in) {
116
117 memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
118 scsi_pointer->this_residual);
119 }
120 }
121
122
123 if (!dir_in)
124 cntr |= GVP11_DMAC_DIR_WRITE;
125
126 wh->dma_dir = dir_in;
127 regs->CNTR = cntr;
128
129
130 regs->ACR = addr;
131
132 if (dir_in) {
133
134 cache_clear(addr, scsi_pointer->this_residual);
135 } else {
136
137 cache_push(addr, scsi_pointer->this_residual);
138 }
139
140 bank_mask = (~wh->dma_xfer_mask >> 18) & 0x01c0;
141 if (bank_mask)
142 regs->BANK = bank_mask & (addr >> 18);
143
144
145 regs->ST_DMA = 1;
146
147
148 return 0;
149}
150
151static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
152 int status)
153{
154 struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(SCpnt);
155 struct gvp11_hostdata *hdata = shost_priv(instance);
156 struct WD33C93_hostdata *wh = &hdata->wh;
157 struct gvp11_scsiregs *regs = hdata->regs;
158
159
160 regs->SP_DMA = 1;
161
162 regs->CNTR = GVP11_DMAC_INT_ENABLE;
163
164
165 if (status && wh->dma_bounce_buffer) {
166 if (wh->dma_dir && SCpnt)
167 memcpy(scsi_pointer->ptr, wh->dma_bounce_buffer,
168 scsi_pointer->this_residual);
169
170 if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
171 kfree(wh->dma_bounce_buffer);
172 else
173 amiga_chip_free(wh->dma_bounce_buffer);
174
175 wh->dma_bounce_buffer = NULL;
176 wh->dma_bounce_len = 0;
177 }
178}
179
180static struct scsi_host_template gvp11_scsi_template = {
181 .module = THIS_MODULE,
182 .name = "GVP Series II SCSI",
183 .show_info = wd33c93_show_info,
184 .write_info = wd33c93_write_info,
185 .proc_name = "GVP11",
186 .queuecommand = wd33c93_queuecommand,
187 .eh_abort_handler = wd33c93_abort,
188 .eh_host_reset_handler = wd33c93_host_reset,
189 .can_queue = CAN_QUEUE,
190 .this_id = 7,
191 .sg_tablesize = SG_ALL,
192 .cmd_per_lun = CMD_PER_LUN,
193 .dma_boundary = PAGE_SIZE - 1,
194 .cmd_size = sizeof(struct scsi_pointer),
195};
196
197static int check_wd33c93(struct gvp11_scsiregs *regs)
198{
199#ifdef CHECK_WD33C93
200 volatile unsigned char *sasr_3393, *scmd_3393;
201 unsigned char save_sasr;
202 unsigned char q, qq;
203
204
205
206
207
208
209
210
211
212
213
214
215 sasr_3393 = ®s->SASR;
216 scmd_3393 = ®s->SCMD;
217 save_sasr = *sasr_3393;
218
219
220
221 q = *sasr_3393;
222 if (q & 0x08)
223 return -ENODEV;
224 *sasr_3393 = WD_AUXILIARY_STATUS;
225 if (*sasr_3393 == WD_AUXILIARY_STATUS) {
226 *sasr_3393 = save_sasr;
227 return -ENODEV;
228 }
229 if (*sasr_3393 != q) {
230 *sasr_3393 = save_sasr;
231 return -ENODEV;
232 }
233 if (*scmd_3393 != q)
234 return -ENODEV;
235
236
237
238
239
240
241
242 *sasr_3393 = WD_SCSI_STATUS;
243 q = *scmd_3393;
244 *sasr_3393 = WD_SCSI_STATUS;
245 *scmd_3393 = ~q;
246 *sasr_3393 = WD_SCSI_STATUS;
247 qq = *scmd_3393;
248 *sasr_3393 = WD_SCSI_STATUS;
249 *scmd_3393 = q;
250 if (qq != q)
251 return -ENODEV;
252 *sasr_3393 = 0x1e;
253 q = *scmd_3393;
254 *sasr_3393 = 0x1e;
255 *scmd_3393 = ~q;
256 *sasr_3393 = 0x1e;
257 qq = *scmd_3393;
258 *sasr_3393 = 0x1e;
259 *scmd_3393 = q;
260 if (qq != q || qq != 0xff)
261 return -ENODEV;
262 *sasr_3393 = WD_TIMEOUT_PERIOD;
263 q = *scmd_3393;
264 *sasr_3393 = WD_TIMEOUT_PERIOD;
265 *scmd_3393 = ~q;
266 *sasr_3393 = WD_TIMEOUT_PERIOD;
267 qq = *scmd_3393;
268 *sasr_3393 = WD_TIMEOUT_PERIOD;
269 *scmd_3393 = q;
270 if (qq != (~q & 0xff))
271 return -ENODEV;
272#endif
273
274 return 0;
275}
276
277static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
278{
279 struct Scsi_Host *instance;
280 unsigned long address;
281 int error;
282 unsigned int epc;
283 unsigned int default_dma_xfer_mask;
284 struct gvp11_hostdata *hdata;
285 struct gvp11_scsiregs *regs;
286 wd33c93_regs wdregs;
287
288 default_dma_xfer_mask = ent->driver_data;
289
290
291
292
293
294
295 if (zorro_resource_len(z) != 0x10000)
296 return -ENODEV;
297
298 address = z->resource.start;
299 if (!request_mem_region(address, 256, "wd33c93"))
300 return -EBUSY;
301
302 regs = ZTWO_VADDR(address);
303
304 error = check_wd33c93(regs);
305 if (error)
306 goto fail_check_or_alloc;
307
308 instance = scsi_host_alloc(&gvp11_scsi_template,
309 sizeof(struct gvp11_hostdata));
310 if (!instance) {
311 error = -ENOMEM;
312 goto fail_check_or_alloc;
313 }
314
315 instance->irq = IRQ_AMIGA_PORTS;
316 instance->unique_id = z->slotaddr;
317
318 regs->secret2 = 1;
319 regs->secret1 = 0;
320 regs->secret3 = 15;
321 while (regs->CNTR & GVP11_DMAC_BUSY)
322 ;
323 regs->CNTR = 0;
324 regs->BANK = 0;
325
326 wdregs.SASR = ®s->SASR;
327 wdregs.SCMD = ®s->SCMD;
328
329 hdata = shost_priv(instance);
330 if (gvp11_xfer_mask)
331 hdata->wh.dma_xfer_mask = gvp11_xfer_mask;
332 else
333 hdata->wh.dma_xfer_mask = default_dma_xfer_mask;
334
335 hdata->wh.no_sync = 0xff;
336 hdata->wh.fast = 0;
337 hdata->wh.dma_mode = CTRL_DMA;
338 hdata->regs = regs;
339
340
341
342
343 epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
344 wd33c93_init(instance, wdregs, dma_setup, dma_stop,
345 (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
346 : WD33C93_FS_12_15);
347
348 error = request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED,
349 "GVP11 SCSI", instance);
350 if (error)
351 goto fail_irq;
352
353 regs->CNTR = GVP11_DMAC_INT_ENABLE;
354
355 error = scsi_add_host(instance, NULL);
356 if (error)
357 goto fail_host;
358
359 zorro_set_drvdata(z, instance);
360 scsi_scan_host(instance);
361 return 0;
362
363fail_host:
364 free_irq(IRQ_AMIGA_PORTS, instance);
365fail_irq:
366 scsi_host_put(instance);
367fail_check_or_alloc:
368 release_mem_region(address, 256);
369 return error;
370}
371
372static void gvp11_remove(struct zorro_dev *z)
373{
374 struct Scsi_Host *instance = zorro_get_drvdata(z);
375 struct gvp11_hostdata *hdata = shost_priv(instance);
376
377 hdata->regs->CNTR = 0;
378 scsi_remove_host(instance);
379 free_irq(IRQ_AMIGA_PORTS, instance);
380 scsi_host_put(instance);
381 release_mem_region(z->resource.start, 256);
382}
383
384
385
386
387
388
389
390static struct zorro_device_id gvp11_zorro_tbl[] = {
391 { ZORRO_PROD_GVP_COMBO_030_R3_SCSI, ~0x00ffffff },
392 { ZORRO_PROD_GVP_SERIES_II, ~0x00ffffff },
393 { ZORRO_PROD_GVP_GFORCE_030_SCSI, ~0x01ffffff },
394 { ZORRO_PROD_GVP_A530_SCSI, ~0x01ffffff },
395 { ZORRO_PROD_GVP_COMBO_030_R4_SCSI, ~0x01ffffff },
396 { ZORRO_PROD_GVP_A1291, ~0x07ffffff },
397 { ZORRO_PROD_GVP_GFORCE_040_SCSI_1, ~0x07ffffff },
398 { 0 }
399};
400MODULE_DEVICE_TABLE(zorro, gvp11_zorro_tbl);
401
402static struct zorro_driver gvp11_driver = {
403 .name = "gvp11",
404 .id_table = gvp11_zorro_tbl,
405 .probe = gvp11_probe,
406 .remove = gvp11_remove,
407};
408
409static int __init gvp11_init(void)
410{
411 return zorro_register_driver(&gvp11_driver);
412}
413module_init(gvp11_init);
414
415static void __exit gvp11_exit(void)
416{
417 zorro_unregister_driver(&gvp11_driver);
418}
419module_exit(gvp11_exit);
420
421MODULE_DESCRIPTION("GVP Series II SCSI");
422MODULE_LICENSE("GPL");
423