diff options
author | Geert Uytterhoeven <geert@linux-m68k.org> | 2009-08-16 05:17:35 -0400 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2010-05-26 13:51:08 -0400 |
commit | c1d288a58936cd0654844d807e53a203f4838fb4 (patch) | |
tree | e7ce5af31547f2d2e0e2d60a9377fc4710ef5aa1 /drivers/scsi/gvp11.c | |
parent | 65c2784a24d8d0a67ba3a50029846e0b82bdc223 (diff) |
m68k: amiga - GVP Series II SCSI zorro_driver conversion
Acked-by: James Bottomley <James.Bottomley@suse.de>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'drivers/scsi/gvp11.c')
-rw-r--r-- | drivers/scsi/gvp11.c | 298 |
1 files changed, 156 insertions, 142 deletions
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 874cbee1be23..4507a16ee1c6 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c | |||
@@ -1,26 +1,20 @@ | |||
1 | #include <linux/types.h> | 1 | #include <linux/types.h> |
2 | #include <linux/mm.h> | ||
3 | #include <linux/slab.h> | ||
4 | #include <linux/blkdev.h> | ||
5 | #include <linux/init.h> | 2 | #include <linux/init.h> |
6 | #include <linux/interrupt.h> | 3 | #include <linux/interrupt.h> |
4 | #include <linux/mm.h> | ||
5 | #include <linux/slab.h> | ||
6 | #include <linux/spinlock.h> | ||
7 | #include <linux/zorro.h> | ||
7 | 8 | ||
8 | #include <asm/setup.h> | ||
9 | #include <asm/page.h> | 9 | #include <asm/page.h> |
10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
11 | #include <asm/amigaints.h> | 11 | #include <asm/amigaints.h> |
12 | #include <asm/amigahw.h> | 12 | #include <asm/amigahw.h> |
13 | #include <linux/zorro.h> | ||
14 | #include <asm/irq.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | 13 | ||
17 | #include "scsi.h" | 14 | #include "scsi.h" |
18 | #include <scsi/scsi_host.h> | ||
19 | #include "wd33c93.h" | 15 | #include "wd33c93.h" |
20 | #include "gvp11.h" | 16 | #include "gvp11.h" |
21 | 17 | ||
22 | #include <linux/stat.h> | ||
23 | |||
24 | 18 | ||
25 | #define CHECK_WD33C93 | 19 | #define CHECK_WD33C93 |
26 | 20 | ||
@@ -169,7 +163,40 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | |||
169 | } | 163 | } |
170 | } | 164 | } |
171 | 165 | ||
172 | static int __init check_wd33c93(struct gvp11_scsiregs *regs) | 166 | static int gvp11_bus_reset(struct scsi_cmnd *cmd) |
167 | { | ||
168 | struct Scsi_Host *instance = cmd->device->host; | ||
169 | |||
170 | /* FIXME perform bus-specific reset */ | ||
171 | |||
172 | /* FIXME 2: shouldn't we no-op this function (return | ||
173 | FAILED), and fall back to host reset function, | ||
174 | wd33c93_host_reset ? */ | ||
175 | |||
176 | spin_lock_irq(instance->host_lock); | ||
177 | wd33c93_host_reset(cmd); | ||
178 | spin_unlock_irq(instance->host_lock); | ||
179 | |||
180 | return SUCCESS; | ||
181 | } | ||
182 | |||
183 | static struct scsi_host_template gvp11_scsi_template = { | ||
184 | .module = THIS_MODULE, | ||
185 | .name = "GVP Series II SCSI", | ||
186 | .proc_info = wd33c93_proc_info, | ||
187 | .proc_name = "GVP11", | ||
188 | .queuecommand = wd33c93_queuecommand, | ||
189 | .eh_abort_handler = wd33c93_abort, | ||
190 | .eh_bus_reset_handler = gvp11_bus_reset, | ||
191 | .eh_host_reset_handler = wd33c93_host_reset, | ||
192 | .can_queue = CAN_QUEUE, | ||
193 | .this_id = 7, | ||
194 | .sg_tablesize = SG_ALL, | ||
195 | .cmd_per_lun = CMD_PER_LUN, | ||
196 | .use_clustering = DISABLE_CLUSTERING | ||
197 | }; | ||
198 | |||
199 | static int __devinit check_wd33c93(struct gvp11_scsiregs *regs) | ||
173 | { | 200 | { |
174 | #ifdef CHECK_WD33C93 | 201 | #ifdef CHECK_WD33C93 |
175 | volatile unsigned char *sasr_3393, *scmd_3393; | 202 | volatile unsigned char *sasr_3393, *scmd_3393; |
@@ -249,163 +276,150 @@ static int __init check_wd33c93(struct gvp11_scsiregs *regs) | |||
249 | return 0; | 276 | return 0; |
250 | } | 277 | } |
251 | 278 | ||
252 | int __init gvp11_detect(struct scsi_host_template *tpnt) | 279 | static int __devinit gvp11_probe(struct zorro_dev *z, |
280 | const struct zorro_device_id *ent) | ||
253 | { | 281 | { |
254 | static unsigned char called = 0; | ||
255 | struct Scsi_Host *instance; | 282 | struct Scsi_Host *instance; |
256 | unsigned long address; | 283 | unsigned long address; |
284 | int error; | ||
257 | unsigned int epc; | 285 | unsigned int epc; |
258 | struct zorro_dev *z = NULL; | ||
259 | unsigned int default_dma_xfer_mask; | 286 | unsigned int default_dma_xfer_mask; |
260 | struct WD33C93_hostdata *hdata; | 287 | struct WD33C93_hostdata *hdata; |
261 | struct gvp11_scsiregs *regs; | 288 | struct gvp11_scsiregs *regs; |
262 | wd33c93_regs wdregs; | 289 | wd33c93_regs wdregs; |
263 | int num_gvp11 = 0; | 290 | |
264 | 291 | default_dma_xfer_mask = ent->driver_data; | |
265 | if (!MACH_IS_AMIGA || called) | 292 | |
266 | return 0; | 293 | /* |
267 | called = 1; | 294 | * Rumors state that some GVP ram boards use the same product |
268 | 295 | * code as the SCSI controllers. Therefore if the board-size | |
269 | tpnt->proc_name = "GVP11"; | 296 | * is not 64KB we asume it is a ram board and bail out. |
270 | tpnt->proc_info = &wd33c93_proc_info; | 297 | */ |
271 | 298 | if (zorro_resource_len(z) != 0x10000) | |
272 | while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { | 299 | return -ENODEV; |
273 | /* | 300 | |
274 | * This should (hopefully) be the correct way to identify | 301 | address = z->resource.start; |
275 | * all the different GVP SCSI controllers (except for the | 302 | if (!request_mem_region(address, 256, "wd33c93")) |
276 | * SERIES I though). | 303 | return -EBUSY; |
277 | */ | 304 | |
278 | 305 | regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); | |
279 | if (z->id == ZORRO_PROD_GVP_COMBO_030_R3_SCSI || | 306 | |
280 | z->id == ZORRO_PROD_GVP_SERIES_II) | 307 | error = check_wd33c93(regs); |
281 | default_dma_xfer_mask = ~0x00ffffff; | 308 | if (error) |
282 | else if (z->id == ZORRO_PROD_GVP_GFORCE_030_SCSI || | 309 | goto fail_check_or_alloc; |
283 | z->id == ZORRO_PROD_GVP_A530_SCSI || | 310 | |
284 | z->id == ZORRO_PROD_GVP_COMBO_030_R4_SCSI) | 311 | instance = scsi_host_alloc(&gvp11_scsi_template, |
285 | default_dma_xfer_mask = ~0x01ffffff; | 312 | sizeof(struct WD33C93_hostdata)); |
286 | else if (z->id == ZORRO_PROD_GVP_A1291 || | 313 | if (!instance) { |
287 | z->id == ZORRO_PROD_GVP_GFORCE_040_SCSI_1) | 314 | error = -ENOMEM; |
288 | default_dma_xfer_mask = ~0x07ffffff; | 315 | goto fail_check_or_alloc; |
289 | else | ||
290 | continue; | ||
291 | |||
292 | /* | ||
293 | * Rumors state that some GVP ram boards use the same product | ||
294 | * code as the SCSI controllers. Therefore if the board-size | ||
295 | * is not 64KB we asume it is a ram board and bail out. | ||
296 | */ | ||
297 | if (z->resource.end - z->resource.start != 0xffff) | ||
298 | continue; | ||
299 | |||
300 | address = z->resource.start; | ||
301 | if (!request_mem_region(address, 256, "wd33c93")) | ||
302 | continue; | ||
303 | |||
304 | regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); | ||
305 | if (check_wd33c93(regs)) | ||
306 | goto release; | ||
307 | |||
308 | instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); | ||
309 | if (instance == NULL) | ||
310 | goto release; | ||
311 | instance->base = ZTWO_VADDR(address); | ||
312 | instance->irq = IRQ_AMIGA_PORTS; | ||
313 | instance->unique_id = z->slotaddr; | ||
314 | |||
315 | hdata = shost_priv(instance); | ||
316 | if (gvp11_xfer_mask) | ||
317 | hdata->dma_xfer_mask = gvp11_xfer_mask; | ||
318 | else | ||
319 | hdata->dma_xfer_mask = default_dma_xfer_mask; | ||
320 | |||
321 | regs->secret2 = 1; | ||
322 | regs->secret1 = 0; | ||
323 | regs->secret3 = 15; | ||
324 | while (regs->CNTR & GVP11_DMAC_BUSY) | ||
325 | ; | ||
326 | regs->CNTR = 0; | ||
327 | |||
328 | regs->BANK = 0; | ||
329 | |||
330 | epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000); | ||
331 | |||
332 | /* | ||
333 | * Check for 14MHz SCSI clock | ||
334 | */ | ||
335 | wdregs.SASR = ®s->SASR; | ||
336 | wdregs.SCMD = ®s->SCMD; | ||
337 | hdata->no_sync = 0xff; | ||
338 | hdata->fast = 0; | ||
339 | hdata->dma_mode = CTRL_DMA; | ||
340 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, | ||
341 | (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10 | ||
342 | : WD33C93_FS_12_15); | ||
343 | |||
344 | if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, | ||
345 | "GVP11 SCSI", instance)) | ||
346 | goto unregister; | ||
347 | regs->CNTR = GVP11_DMAC_INT_ENABLE; | ||
348 | num_gvp11++; | ||
349 | continue; | ||
350 | |||
351 | unregister: | ||
352 | scsi_unregister(instance); | ||
353 | release: | ||
354 | release_mem_region(address, 256); | ||
355 | } | 316 | } |
356 | 317 | ||
357 | return num_gvp11; | 318 | instance->base = (unsigned long)regs; |
358 | } | 319 | instance->irq = IRQ_AMIGA_PORTS; |
320 | instance->unique_id = z->slotaddr; | ||
359 | 321 | ||
360 | static int gvp11_bus_reset(struct scsi_cmnd *cmd) | 322 | regs->secret2 = 1; |
361 | { | 323 | regs->secret1 = 0; |
362 | /* FIXME perform bus-specific reset */ | 324 | regs->secret3 = 15; |
325 | while (regs->CNTR & GVP11_DMAC_BUSY) | ||
326 | ; | ||
327 | regs->CNTR = 0; | ||
328 | regs->BANK = 0; | ||
363 | 329 | ||
364 | /* FIXME 2: shouldn't we no-op this function (return | 330 | wdregs.SASR = ®s->SASR; |
365 | FAILED), and fall back to host reset function, | 331 | wdregs.SCMD = ®s->SCMD; |
366 | wd33c93_host_reset ? */ | ||
367 | 332 | ||
368 | spin_lock_irq(cmd->device->host->host_lock); | 333 | hdata = shost_priv(instance); |
369 | wd33c93_host_reset(cmd); | 334 | if (gvp11_xfer_mask) |
370 | spin_unlock_irq(cmd->device->host->host_lock); | 335 | hdata->dma_xfer_mask = gvp11_xfer_mask; |
336 | else | ||
337 | hdata->dma_xfer_mask = default_dma_xfer_mask; | ||
371 | 338 | ||
372 | return SUCCESS; | 339 | hdata->no_sync = 0xff; |
373 | } | 340 | hdata->fast = 0; |
341 | hdata->dma_mode = CTRL_DMA; | ||
374 | 342 | ||
343 | /* | ||
344 | * Check for 14MHz SCSI clock | ||
345 | */ | ||
346 | epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000); | ||
347 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, | ||
348 | (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10 | ||
349 | : WD33C93_FS_12_15); | ||
375 | 350 | ||
376 | #define HOSTS_C | 351 | error = request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, |
352 | "GVP11 SCSI", instance); | ||
353 | if (error) | ||
354 | goto fail_irq; | ||
377 | 355 | ||
378 | #include "gvp11.h" | 356 | regs->CNTR = GVP11_DMAC_INT_ENABLE; |
379 | 357 | ||
380 | static struct scsi_host_template driver_template = { | 358 | error = scsi_add_host(instance, NULL); |
381 | .proc_name = "GVP11", | 359 | if (error) |
382 | .name = "GVP Series II SCSI", | 360 | goto fail_host; |
383 | .detect = gvp11_detect, | ||
384 | .release = gvp11_release, | ||
385 | .queuecommand = wd33c93_queuecommand, | ||
386 | .eh_abort_handler = wd33c93_abort, | ||
387 | .eh_bus_reset_handler = gvp11_bus_reset, | ||
388 | .eh_host_reset_handler = wd33c93_host_reset, | ||
389 | .can_queue = CAN_QUEUE, | ||
390 | .this_id = 7, | ||
391 | .sg_tablesize = SG_ALL, | ||
392 | .cmd_per_lun = CMD_PER_LUN, | ||
393 | .use_clustering = DISABLE_CLUSTERING | ||
394 | }; | ||
395 | 361 | ||
362 | zorro_set_drvdata(z, instance); | ||
363 | scsi_scan_host(instance); | ||
364 | return 0; | ||
396 | 365 | ||
397 | #include "scsi_module.c" | 366 | fail_host: |
367 | free_irq(IRQ_AMIGA_PORTS, instance); | ||
368 | fail_irq: | ||
369 | scsi_host_put(instance); | ||
370 | fail_check_or_alloc: | ||
371 | release_mem_region(address, 256); | ||
372 | return error; | ||
373 | } | ||
398 | 374 | ||
399 | int gvp11_release(struct Scsi_Host *instance) | 375 | static void __devexit gvp11_remove(struct zorro_dev *z) |
400 | { | 376 | { |
401 | #ifdef MODULE | 377 | struct Scsi_Host *instance = zorro_get_drvdata(z); |
402 | struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); | 378 | struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); |
403 | 379 | ||
404 | regs->CNTR = 0; | 380 | regs->CNTR = 0; |
405 | release_mem_region(ZTWO_PADDR(instance->base), 256); | 381 | scsi_remove_host(instance); |
406 | free_irq(IRQ_AMIGA_PORTS, instance); | 382 | free_irq(IRQ_AMIGA_PORTS, instance); |
407 | #endif | 383 | scsi_host_put(instance); |
408 | return 1; | 384 | release_mem_region(z->resource.start, 256); |
385 | } | ||
386 | |||
387 | /* | ||
388 | * This should (hopefully) be the correct way to identify | ||
389 | * all the different GVP SCSI controllers (except for the | ||
390 | * SERIES I though). | ||
391 | */ | ||
392 | |||
393 | static struct zorro_device_id gvp11_zorro_tbl[] __devinitdata = { | ||
394 | { ZORRO_PROD_GVP_COMBO_030_R3_SCSI, ~0x00ffffff }, | ||
395 | { ZORRO_PROD_GVP_SERIES_II, ~0x00ffffff }, | ||
396 | { ZORRO_PROD_GVP_GFORCE_030_SCSI, ~0x01ffffff }, | ||
397 | { ZORRO_PROD_GVP_A530_SCSI, ~0x01ffffff }, | ||
398 | { ZORRO_PROD_GVP_COMBO_030_R4_SCSI, ~0x01ffffff }, | ||
399 | { ZORRO_PROD_GVP_A1291, ~0x07ffffff }, | ||
400 | { ZORRO_PROD_GVP_GFORCE_040_SCSI_1, ~0x07ffffff }, | ||
401 | { 0 } | ||
402 | }; | ||
403 | MODULE_DEVICE_TABLE(zorro, gvp11_zorro_tbl); | ||
404 | |||
405 | static struct zorro_driver gvp11_driver = { | ||
406 | .name = "gvp11", | ||
407 | .id_table = gvp11_zorro_tbl, | ||
408 | .probe = gvp11_probe, | ||
409 | .remove = __devexit_p(gvp11_remove), | ||
410 | }; | ||
411 | |||
412 | static int __init gvp11_init(void) | ||
413 | { | ||
414 | return zorro_register_driver(&gvp11_driver); | ||
415 | } | ||
416 | module_init(gvp11_init); | ||
417 | |||
418 | static void __exit gvp11_exit(void) | ||
419 | { | ||
420 | zorro_unregister_driver(&gvp11_driver); | ||
409 | } | 421 | } |
422 | module_exit(gvp11_exit); | ||
410 | 423 | ||
424 | MODULE_DESCRIPTION("GVP Series II SCSI"); | ||
411 | MODULE_LICENSE("GPL"); | 425 | MODULE_LICENSE("GPL"); |