summary refs log tree commit diff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 10:19:19 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 10:19:19 -0700
commita9a0aff5b56d4c40288c000ff09c3f238b6b6fec (patch)
tree496cce8240689a61b4c76a4318ac53487287c74b /drivers/scsi
parentade61088bc77dd209f8edadbe544f1e5dad6c287 (diff)
parent0779c862e43e052c58a350a8bd2bf97e6908de04 (diff)
downloadlinux-a9a0aff5b56d4c40288c000ff09c3f238b6b6fec.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k: (24 commits)
  m68k: amiga - RTC platform device conversion
  m68k: amiga - Parallel port platform device conversion
  m68k: amiga - Serial port platform device conversion
  m68k: amiga - Mouse platform device conversion
  m68k: amiga - Keyboard platform device conversion
  m68k: amiga - Amiga Gayle IDE platform device conversion
  m68k: amiga - A4000T SCSI platform device conversion
  m68k/scsi: a3000 - Do not use legacy Scsi_Host.base
  m68k: amiga - A3000 SCSI platform device conversion
  m68k/scsi: gvp11 - Do not use legacy Scsi_Host.base
  m68k: amiga - GVP Series II SCSI zorro_driver conversion
  m68k/scsi: a2091 - Do not use legacy Scsi_Host.base
  m68k: amiga - A2091/A590 SCSI zorro_driver conversion
  m68k/scsi: mvme147 - Kill obsolete HOSTS_C logic
  m68k/scsi: a3000 - Kill a3000_scsiregs typedef
  m68k/scsi: gvp11 - Kill gvp11_scsiregs typedef
  m68k/scsi: a2091 - Kill a2091_scsiregs typedef
  m68k/scsi: gvp11 - Extract check_wd33c93()
  m68k/scsi: a3000 - Kill static global a3000_host
  m68k/scsi: mvme147 - Kill static global mvme147_host
  ...
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/a2091.c245
-rw-r--r--drivers/scsi/a2091.h4
-rw-r--r--drivers/scsi/a3000.c256
-rw-r--r--drivers/scsi/a3000.h4
-rw-r--r--drivers/scsi/a4000t.c101
-rw-r--r--drivers/scsi/gvp11.c541
-rw-r--r--drivers/scsi/gvp11.h11
-rw-r--r--drivers/scsi/mvme147.c33
8 files changed, 641 insertions, 554 deletions
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 308541ff85cf..1bb5d3f0e260 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -1,34 +1,31 @@
 #include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/zorro.h>
 
-#include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <linux/spinlock.h>
 
 #include "scsi.h"
-#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "a2091.h"
 
-#include <linux/stat.h>
-
 
-static int a2091_release(struct Scsi_Host *instance);
+struct a2091_hostdata {
+	struct WD33C93_hostdata wh;
+	struct a2091_scsiregs *regs;
+};
 
 static irqreturn_t a2091_intr(int irq, void *data)
 {
 	struct Scsi_Host *instance = data;
-	a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
-	unsigned int status = regs->ISTR;
+	struct a2091_hostdata *hdata = shost_priv(instance);
+	unsigned int status = hdata->regs->ISTR;
 	unsigned long flags;
 
 	if (!(status & (ISTR_INT_F | ISTR_INT_P)) || !(status & ISTR_INTS))
@@ -43,38 +40,39 @@ static irqreturn_t a2091_intr(int irq, void *data)
 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 {
 	struct Scsi_Host *instance = cmd->device->host;
-	struct WD33C93_hostdata *hdata = shost_priv(instance);
-	a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
+	struct a2091_hostdata *hdata = shost_priv(instance);
+	struct WD33C93_hostdata *wh = &hdata->wh;
+	struct a2091_scsiregs *regs = hdata->regs;
 	unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
 	unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 
 	/* don't allow DMA if the physical address is bad */
 	if (addr & A2091_XFER_MASK) {
-		hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
-		hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len,
-						   GFP_KERNEL);
+		wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
+		wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len,
+						GFP_KERNEL);
 
 		/* can't allocate memory; use PIO */
-		if (!hdata->dma_bounce_buffer) {
-			hdata->dma_bounce_len = 0;
+		if (!wh->dma_bounce_buffer) {
+			wh->dma_bounce_len = 0;
 			return 1;
 		}
 
 		/* get the physical address of the bounce buffer */
-		addr = virt_to_bus(hdata->dma_bounce_buffer);
+		addr = virt_to_bus(wh->dma_bounce_buffer);
 
 		/* the bounce buffer may not be in the first 16M of physmem */
 		if (addr & A2091_XFER_MASK) {
 			/* we could use chipmem... maybe later */
-			kfree(hdata->dma_bounce_buffer);
-			hdata->dma_bounce_buffer = NULL;
-			hdata->dma_bounce_len = 0;
+			kfree(wh->dma_bounce_buffer);
+			wh->dma_bounce_buffer = NULL;
+			wh->dma_bounce_len = 0;
 			return 1;
 		}
 
 		if (!dir_in) {
 			/* copy to bounce buffer for a write */
-			memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr,
+			memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr,
 			       cmd->SCp.this_residual);
 		}
 	}
@@ -84,7 +82,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 		cntr |= CNTR_DDIR;
 
 	/* remember direction */
-	hdata->dma_dir = dir_in;
+	wh->dma_dir = dir_in;
 
 	regs->CNTR = cntr;
 
@@ -108,20 +106,21 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 		     int status)
 {
-	struct WD33C93_hostdata *hdata = shost_priv(instance);
-	a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
+	struct a2091_hostdata *hdata = shost_priv(instance);
+	struct WD33C93_hostdata *wh = &hdata->wh;
+	struct a2091_scsiregs *regs = hdata->regs;
 
 	/* disable SCSI interrupts */
 	unsigned short cntr = CNTR_PDMD;
 
-	if (!hdata->dma_dir)
+	if (!wh->dma_dir)
 		cntr |= CNTR_DDIR;
 
 	/* disable SCSI interrupts */
 	regs->CNTR = cntr;
 
 	/* flush if we were reading */
-	if (hdata->dma_dir) {
+	if (wh->dma_dir) {
 		regs->FLUSH = 1;
 		while (!(regs->ISTR & ISTR_FE_FLG))
 			;
@@ -137,95 +136,37 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 	regs->CNTR = CNTR_PDMD | CNTR_INTEN;
 
 	/* copy from a bounce buffer, if necessary */
-	if (status && hdata->dma_bounce_buffer) {
-		if (hdata->dma_dir)
-			memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer,
+	if (status && wh->dma_bounce_buffer) {
+		if (wh->dma_dir)
+			memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer,
 			       SCpnt->SCp.this_residual);
-		kfree(hdata->dma_bounce_buffer);
-		hdata->dma_bounce_buffer = NULL;
-		hdata->dma_bounce_len = 0;
-	}
-}
-
-static int __init a2091_detect(struct scsi_host_template *tpnt)
-{
-	static unsigned char called = 0;
-	struct Scsi_Host *instance;
-	unsigned long address;
-	struct zorro_dev *z = NULL;
-	wd33c93_regs wdregs;
-	a2091_scsiregs *regs;
-	struct WD33C93_hostdata *hdata;
-	int num_a2091 = 0;
-
-	if (!MACH_IS_AMIGA || called)
-		return 0;
-	called = 1;
-
-	tpnt->proc_name = "A2091";
-	tpnt->proc_info = &wd33c93_proc_info;
-
-	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-		if (z->id != ZORRO_PROD_CBM_A590_A2091_1 &&
-		    z->id != ZORRO_PROD_CBM_A590_A2091_2)
-			continue;
-		address = z->resource.start;
-		if (!request_mem_region(address, 256, "wd33c93"))
-			continue;
-
-		instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
-		if (instance == NULL)
-			goto release;
-		instance->base = ZTWO_VADDR(address);
-		instance->irq = IRQ_AMIGA_PORTS;
-		instance->unique_id = z->slotaddr;
-		regs = (a2091_scsiregs *)(instance->base);
-		regs->DAWR = DAWR_A2091;
-		wdregs.SASR = &regs->SASR;
-		wdregs.SCMD = &regs->SCMD;
-		hdata = shost_priv(instance);
-		hdata->no_sync = 0xff;
-		hdata->fast = 0;
-		hdata->dma_mode = CTRL_DMA;
-		wd33c93_init(instance, wdregs, dma_setup, dma_stop,
-			     WD33C93_FS_8_10);
-		if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED,
-				"A2091 SCSI", instance))
-			goto unregister;
-		regs->CNTR = CNTR_PDMD | CNTR_INTEN;
-		num_a2091++;
-		continue;
-
-unregister:
-		scsi_unregister(instance);
-release:
-		release_mem_region(address, 256);
+		kfree(wh->dma_bounce_buffer);
+		wh->dma_bounce_buffer = NULL;
+		wh->dma_bounce_len = 0;
 	}
-
-	return num_a2091;
 }
 
 static int a2091_bus_reset(struct scsi_cmnd *cmd)
 {
+	struct Scsi_Host *instance = cmd->device->host;
+
 	/* FIXME perform bus-specific reset */
 
 	/* FIXME 2: kill this function, and let midlayer fall back
 	   to the same action, calling wd33c93_host_reset() */
 
-	spin_lock_irq(cmd->device->host->host_lock);
+	spin_lock_irq(instance->host_lock);
 	wd33c93_host_reset(cmd);
-	spin_unlock_irq(cmd->device->host->host_lock);
+	spin_unlock_irq(instance->host_lock);
 
 	return SUCCESS;
 }
 
-#define HOSTS_C
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "A2901",
+static struct scsi_host_template a2091_scsi_template = {
+	.module			= THIS_MODULE,
 	.name			= "Commodore A2091/A590 SCSI",
-	.detect			= a2091_detect,
-	.release		= a2091_release,
+	.proc_info		= wd33c93_proc_info,
+	.proc_name		= "A2901",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
 	.eh_bus_reset_handler	= a2091_bus_reset,
@@ -237,19 +178,103 @@ static struct scsi_host_template driver_template = {
 	.use_clustering		= DISABLE_CLUSTERING
 };
 
+static int __devinit a2091_probe(struct zorro_dev *z,
+				 const struct zorro_device_id *ent)
+{
+	struct Scsi_Host *instance;
+	int error;
+	struct a2091_scsiregs *regs;
+	wd33c93_regs wdregs;
+	struct a2091_hostdata *hdata;
 
-#include "scsi_module.c"
+	if (!request_mem_region(z->resource.start, 256, "wd33c93"))
+		return -EBUSY;
 
-static int a2091_release(struct Scsi_Host *instance)
+	instance = scsi_host_alloc(&a2091_scsi_template,
+				   sizeof(struct a2091_hostdata));
+	if (!instance) {
+		error = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	instance->irq = IRQ_AMIGA_PORTS;
+	instance->unique_id = z->slotaddr;
+
+	regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start);
+	regs->DAWR = DAWR_A2091;
+
+	wdregs.SASR = &regs->SASR;
+	wdregs.SCMD = &regs->SCMD;
+
+	hdata = shost_priv(instance);
+	hdata->wh.no_sync = 0xff;
+	hdata->wh.fast = 0;
+	hdata->wh.dma_mode = CTRL_DMA;
+	hdata->regs = regs;
+
+	wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_8_10);
+	error = request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED,
+			    "A2091 SCSI", instance);
+	if (error)
+		goto fail_irq;
+
+	regs->CNTR = CNTR_PDMD | CNTR_INTEN;
+
+	error = scsi_add_host(instance, NULL);
+	if (error)
+		goto fail_host;
+
+	zorro_set_drvdata(z, instance);
+
+	scsi_scan_host(instance);
+	return 0;
+
+fail_host:
+	free_irq(IRQ_AMIGA_PORTS, instance);
+fail_irq:
+	scsi_host_put(instance);
+fail_alloc:
+	release_mem_region(z->resource.start, 256);
+	return error;
+}
+
+static void __devexit a2091_remove(struct zorro_dev *z)
 {
-#ifdef MODULE
-	a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
+	struct Scsi_Host *instance = zorro_get_drvdata(z);
+	struct a2091_hostdata *hdata = shost_priv(instance);
 
-	regs->CNTR = 0;
-	release_mem_region(ZTWO_PADDR(instance->base), 256);
+	hdata->regs->CNTR = 0;
+	scsi_remove_host(instance);
 	free_irq(IRQ_AMIGA_PORTS, instance);
-#endif
-	return 1;
+	scsi_host_put(instance);
+	release_mem_region(z->resource.start, 256);
+}
+
+static struct zorro_device_id a2091_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_CBM_A590_A2091_1 },
+	{ ZORRO_PROD_CBM_A590_A2091_2 },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, a2091_zorro_tbl);
+
+static struct zorro_driver a2091_driver = {
+	.name		= "a2091",
+	.id_table	= a2091_zorro_tbl,
+	.probe		= a2091_probe,
+	.remove		= __devexit_p(a2091_remove),
+};
+
+static int __init a2091_init(void)
+{
+	return zorro_register_driver(&a2091_driver);
+}
+module_init(a2091_init);
+
+static void __exit a2091_exit(void)
+{
+	zorro_unregister_driver(&a2091_driver);
 }
+module_exit(a2091_exit);
 
+MODULE_DESCRIPTION("Commodore A2091/A590 SCSI");
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h
index 1c3daa1fd754..794b8e65c711 100644
--- a/drivers/scsi/a2091.h
+++ b/drivers/scsi/a2091.h
@@ -25,7 +25,7 @@
  */
 #define A2091_XFER_MASK		(0xff000001)
 
-typedef struct {
+struct a2091_scsiregs {
 		 unsigned char	pad1[64];
 	volatile unsigned short	ISTR;
 	volatile unsigned short	CNTR;
@@ -44,7 +44,7 @@ typedef struct {
 	volatile unsigned short	CINT;
 		 unsigned char	pad7[2];
 	volatile unsigned short	FLUSH;
-} a2091_scsiregs;
+};
 
 #define DAWR_A2091		(3)
 
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index bc6eb69f5fd0..d9468027fb61 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -1,53 +1,52 @@
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 
-#include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <asm/irq.h>
 
 #include "scsi.h"
-#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "a3000.h"
 
-#include <linux/stat.h>
-
 
-#define DMA(ptr)	((a3000_scsiregs *)((ptr)->base))
-
-static struct Scsi_Host *a3000_host = NULL;
-
-static int a3000_release(struct Scsi_Host *instance);
+struct a3000_hostdata {
+	struct WD33C93_hostdata wh;
+	struct a3000_scsiregs *regs;
+};
 
-static irqreturn_t a3000_intr(int irq, void *dummy)
+static irqreturn_t a3000_intr(int irq, void *data)
 {
+	struct Scsi_Host *instance = data;
+	struct a3000_hostdata *hdata = shost_priv(instance);
+	unsigned int status = hdata->regs->ISTR;
 	unsigned long flags;
-	unsigned int status = DMA(a3000_host)->ISTR;
 
 	if (!(status & ISTR_INT_P))
 		return IRQ_NONE;
 	if (status & ISTR_INTS) {
-		spin_lock_irqsave(a3000_host->host_lock, flags);
-		wd33c93_intr(a3000_host);
-		spin_unlock_irqrestore(a3000_host->host_lock, flags);
+		spin_lock_irqsave(instance->host_lock, flags);
+		wd33c93_intr(instance);
+		spin_unlock_irqrestore(instance->host_lock, flags);
 		return IRQ_HANDLED;
 	}
-	printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
+	pr_warning("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
 	return IRQ_NONE;
 }
 
 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 {
-	struct WD33C93_hostdata *hdata = shost_priv(a3000_host);
+	struct Scsi_Host *instance = cmd->device->host;
+	struct a3000_hostdata *hdata = shost_priv(instance);
+	struct WD33C93_hostdata *wh = &hdata->wh;
+	struct a3000_scsiregs *regs = hdata->regs;
 	unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
 	unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 
@@ -58,23 +57,23 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 	 * buffer
 	 */
 	if (addr & A3000_XFER_MASK) {
-		hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
-		hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len,
-						   GFP_KERNEL);
+		wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
+		wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len,
+						GFP_KERNEL);
 
 		/* can't allocate memory; use PIO */
-		if (!hdata->dma_bounce_buffer) {
-			hdata->dma_bounce_len = 0;
+		if (!wh->dma_bounce_buffer) {
+			wh->dma_bounce_len = 0;
 			return 1;
 		}
 
 		if (!dir_in) {
 			/* copy to bounce buffer for a write */
-			memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr,
+			memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr,
 			       cmd->SCp.this_residual);
 		}
 
-		addr = virt_to_bus(hdata->dma_bounce_buffer);
+		addr = virt_to_bus(wh->dma_bounce_buffer);
 	}
 
 	/* setup dma direction */
@@ -82,12 +81,12 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 		cntr |= CNTR_DDIR;
 
 	/* remember direction */
-	hdata->dma_dir = dir_in;
+	wh->dma_dir = dir_in;
 
-	DMA(a3000_host)->CNTR = cntr;
+	regs->CNTR = cntr;
 
 	/* setup DMA *physical* address */
-	DMA(a3000_host)->ACR = addr;
+	regs->ACR = addr;
 
 	if (dir_in) {
 		/* invalidate any cache */
@@ -99,7 +98,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 
 	/* start DMA */
 	mb();			/* make sure setup is completed */
-	DMA(a3000_host)->ST_DMA = 1;
+	regs->ST_DMA = 1;
 	mb();			/* make sure DMA has started before next IO */
 
 	/* return success */
@@ -109,22 +108,24 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 		     int status)
 {
-	struct WD33C93_hostdata *hdata = shost_priv(instance);
+	struct a3000_hostdata *hdata = shost_priv(instance);
+	struct WD33C93_hostdata *wh = &hdata->wh;
+	struct a3000_scsiregs *regs = hdata->regs;
 
 	/* disable SCSI interrupts */
 	unsigned short cntr = CNTR_PDMD;
 
-	if (!hdata->dma_dir)
+	if (!wh->dma_dir)
 		cntr |= CNTR_DDIR;
 
-	DMA(instance)->CNTR = cntr;
+	regs->CNTR = cntr;
 	mb();			/* make sure CNTR is updated before next IO */
 
 	/* flush if we were reading */
-	if (hdata->dma_dir) {
-		DMA(instance)->FLUSH = 1;
+	if (wh->dma_dir) {
+		regs->FLUSH = 1;
 		mb();		/* don't allow prefetch */
-		while (!(DMA(instance)->ISTR & ISTR_FE_FLG))
+		while (!(regs->ISTR & ISTR_FE_FLG))
 			barrier();
 		mb();		/* no IO until FLUSH is done */
 	}
@@ -133,96 +134,54 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 	/* I think that this CINT is only necessary if you are
 	 * using the terminal count features.   HM 7 Mar 1994
 	 */
-	DMA(instance)->CINT = 1;
+	regs->CINT = 1;
 
 	/* stop DMA */
-	DMA(instance)->SP_DMA = 1;
+	regs->SP_DMA = 1;
 	mb();			/* make sure DMA is stopped before next IO */
 
 	/* restore the CONTROL bits (minus the direction flag) */
-	DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
+	regs->CNTR = CNTR_PDMD | CNTR_INTEN;
 	mb();			/* make sure CNTR is updated before next IO */
 
 	/* copy from a bounce buffer, if necessary */
-	if (status && hdata->dma_bounce_buffer) {
+	if (status && wh->dma_bounce_buffer) {
 		if (SCpnt) {
-			if (hdata->dma_dir && SCpnt)
-				memcpy(SCpnt->SCp.ptr,
-				       hdata->dma_bounce_buffer,
+			if (wh->dma_dir && SCpnt)
+				memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer,
 				       SCpnt->SCp.this_residual);
-			kfree(hdata->dma_bounce_buffer);
-			hdata->dma_bounce_buffer = NULL;
-			hdata->dma_bounce_len = 0;
+			kfree(wh->dma_bounce_buffer);
+			wh->dma_bounce_buffer = NULL;
+			wh->dma_bounce_len = 0;
 		} else {
-			kfree(hdata->dma_bounce_buffer);
-			hdata->dma_bounce_buffer = NULL;
-			hdata->dma_bounce_len = 0;
+			kfree(wh->dma_bounce_buffer);
+			wh->dma_bounce_buffer = NULL;
+			wh->dma_bounce_len = 0;
 		}
 	}
 }
 
-static int __init a3000_detect(struct scsi_host_template *tpnt)
-{
-	wd33c93_regs regs;
-	struct WD33C93_hostdata *hdata;
-
-	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
-		return 0;
-	if (!request_mem_region(0xDD0000, 256, "wd33c93"))
-		return 0;
-
-	tpnt->proc_name = "A3000";
-	tpnt->proc_info = &wd33c93_proc_info;
-
-	a3000_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
-	if (a3000_host == NULL)
-		goto fail_register;
-
-	a3000_host->base = ZTWO_VADDR(0xDD0000);
-	a3000_host->irq = IRQ_AMIGA_PORTS;
-	DMA(a3000_host)->DAWR = DAWR_A3000;
-	regs.SASR = &(DMA(a3000_host)->SASR);
-	regs.SCMD = &(DMA(a3000_host)->SCMD);
-	hdata = shost_priv(a3000_host);
-	hdata->no_sync = 0xff;
-	hdata->fast = 0;
-	hdata->dma_mode = CTRL_DMA;
-	wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
-	if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
-			a3000_intr))
-		goto fail_irq;
-	DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN;
-
-	return 1;
-
-fail_irq:
-	scsi_unregister(a3000_host);
-fail_register:
-	release_mem_region(0xDD0000, 256);
-	return 0;
-}
-
 static int a3000_bus_reset(struct scsi_cmnd *cmd)
 {
+	struct Scsi_Host *instance = cmd->device->host;
+
 	/* FIXME perform bus-specific reset */
 
 	/* FIXME 2: kill this entire function, which should
 	   cause mid-layer to call wd33c93_host_reset anyway? */
 
-	spin_lock_irq(cmd->device->host->host_lock);
+	spin_lock_irq(instance->host_lock);
 	wd33c93_host_reset(cmd);
-	spin_unlock_irq(cmd->device->host->host_lock);
+	spin_unlock_irq(instance->host_lock);
 
 	return SUCCESS;
 }
 
-#define HOSTS_C
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "A3000",
+static struct scsi_host_template amiga_a3000_scsi_template = {
+	.module			= THIS_MODULE,
 	.name			= "Amiga 3000 built-in SCSI",
-	.detect			= a3000_detect,
-	.release		= a3000_release,
+	.proc_info		= wd33c93_proc_info,
+	.proc_name		= "A3000",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
 	.eh_bus_reset_handler	= a3000_bus_reset,
@@ -234,15 +193,104 @@ static struct scsi_host_template driver_template = {
 	.use_clustering		= ENABLE_CLUSTERING
 };
 
+static int __init amiga_a3000_scsi_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct Scsi_Host *instance;
+	int error;
+	struct a3000_scsiregs *regs;
+	wd33c93_regs wdregs;
+	struct a3000_hostdata *hdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	if (!request_mem_region(res->start, resource_size(res), "wd33c93"))
+		return -EBUSY;
+
+	instance = scsi_host_alloc(&amiga_a3000_scsi_template,
+				   sizeof(struct a3000_hostdata));
+	if (!instance) {
+		error = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	instance->irq = IRQ_AMIGA_PORTS;
 
-#include "scsi_module.c"
+	regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start);
+	regs->DAWR = DAWR_A3000;
+
+	wdregs.SASR = &regs->SASR;
+	wdregs.SCMD = &regs->SCMD;
+
+	hdata = shost_priv(instance);
+	hdata->wh.no_sync = 0xff;
+	hdata->wh.fast = 0;
+	hdata->wh.dma_mode = CTRL_DMA;
+	hdata->regs = regs;
+
+	wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15);
+	error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED,
+			    "A3000 SCSI", instance);
+	if (error)
+		goto fail_irq;
+
+	regs->CNTR = CNTR_PDMD | CNTR_INTEN;
+
+	error = scsi_add_host(instance, NULL);
+	if (error)
+		goto fail_host;
+
+	platform_set_drvdata(pdev, instance);
+
+	scsi_scan_host(instance);
+	return 0;
+
+fail_host:
+	free_irq(IRQ_AMIGA_PORTS, instance);
+fail_irq:
+	scsi_host_put(instance);
+fail_alloc:
+	release_mem_region(res->start, resource_size(res));
+	return error;
+}
+
+static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
+{
+	struct Scsi_Host *instance = platform_get_drvdata(pdev);
+	struct a3000_hostdata *hdata = shost_priv(instance);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	hdata->regs->CNTR = 0;
+	scsi_remove_host(instance);
+	free_irq(IRQ_AMIGA_PORTS, instance);
+	scsi_host_put(instance);
+	release_mem_region(res->start, resource_size(res));
+	return 0;
+}
+
+static struct platform_driver amiga_a3000_scsi_driver = {
+	.remove = __exit_p(amiga_a3000_scsi_remove),
+	.driver   = {
+		.name	= "amiga-a3000-scsi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init amiga_a3000_scsi_init(void)
+{
+	return platform_driver_probe(&amiga_a3000_scsi_driver,
+				     amiga_a3000_scsi_probe);
+}
+module_init(amiga_a3000_scsi_init);
 
-static int a3000_release(struct Scsi_Host *instance)
+static void __exit amiga_a3000_scsi_exit(void)
 {
-	DMA(instance)->CNTR = 0;
-	release_mem_region(0xDD0000, 256);
-	free_irq(IRQ_AMIGA_PORTS, a3000_intr);
-	return 1;
+	platform_driver_unregister(&amiga_a3000_scsi_driver);
 }
+module_exit(amiga_a3000_scsi_exit);
 
+MODULE_DESCRIPTION("Amiga 3000 built-in SCSI");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:amiga-a3000-scsi");
diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h
index 684813ee378c..49db4a335aab 100644
--- a/drivers/scsi/a3000.h
+++ b/drivers/scsi/a3000.h
@@ -25,7 +25,7 @@
  */
 #define A3000_XFER_MASK		(0x00000003)
 
-typedef struct {
+struct a3000_scsiregs {
 		 unsigned char	pad1[2];
 	volatile unsigned short	DAWR;
 	volatile unsigned int	WTC;
@@ -46,7 +46,7 @@ typedef struct {
 	volatile unsigned char	SASR;
 		 unsigned char	pad9;
 	volatile unsigned char	SCMD;
-} a3000_scsiregs;
+};
 
 #define DAWR_A3000		(3)
 
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
index 11ae6be8aeaf..23c76f41883c 100644
--- a/drivers/scsi/a4000t.c
+++ b/drivers/scsi/a4000t.c
@@ -20,10 +20,6 @@
 
 #include "53c700.h"
 
-MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
-MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
-MODULE_LICENSE("GPL");
-
 
 static struct scsi_host_template a4000t_scsi_driver_template = {
 	.name		= "A4000T builtin SCSI",
@@ -32,30 +28,35 @@ static struct scsi_host_template a4000t_scsi_driver_template = {
 	.module		= THIS_MODULE,
 };
 
-static struct platform_device *a4000t_scsi_device;
 
-#define A4000T_SCSI_ADDR 0xdd0040
+#define A4000T_SCSI_OFFSET	0x40
 
-static int __devinit a4000t_probe(struct platform_device *dev)
+static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev)
 {
-	struct Scsi_Host *host;
+	struct resource *res;
+	phys_addr_t scsi_addr;
 	struct NCR_700_Host_Parameters *hostdata;
+	struct Scsi_Host *host;
 
-	if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
-		goto out;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
 
-	if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000,
+	if (!request_mem_region(res->start, resource_size(res),
 				"A4000T builtin SCSI"))
-		goto out;
+		return -EBUSY;
 
-	hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
+	hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters),
+			   GFP_KERNEL);
 	if (!hostdata) {
-		printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
+		dev_err(&pdev->dev, "Failed to allocate host data\n");
 		goto out_release;
 	}
 
+	scsi_addr = res->start + A4000T_SCSI_OFFSET;
+
 	/* Fill in the required pieces of hostdata */
-	hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
+	hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr);
 	hostdata->clock = 50;
 	hostdata->chip710 = 1;
 	hostdata->dmode_extra = DMODE_FC2;
@@ -63,26 +64,25 @@ static int __devinit a4000t_probe(struct platform_device *dev)
 
 	/* and register the chip */
 	host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata,
-			      &dev->dev);
+			      &pdev->dev);
 	if (!host) {
-		printk(KERN_ERR "a4000t-scsi: No host detected; "
-				"board configuration problem?\n");
+		dev_err(&pdev->dev,
+			"No host detected; board configuration problem?\n");
 		goto out_free;
 	}
 
 	host->this_id = 7;
-	host->base = A4000T_SCSI_ADDR;
+	host->base = scsi_addr;
 	host->irq = IRQ_AMIGA_PORTS;
 
 	if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi",
 			host)) {
-		printk(KERN_ERR "a4000t-scsi: request_irq failed\n");
+		dev_err(&pdev->dev, "request_irq failed\n");
 		goto out_put_host;
 	}
 
-	platform_set_drvdata(dev, host);
+	platform_set_drvdata(pdev, host);
 	scsi_scan_host(host);
-
 	return 0;
 
  out_put_host:
@@ -90,58 +90,49 @@ static int __devinit a4000t_probe(struct platform_device *dev)
  out_free:
 	kfree(hostdata);
  out_release:
-	release_mem_region(A4000T_SCSI_ADDR, 0x1000);
- out:
+	release_mem_region(res->start, resource_size(res));
 	return -ENODEV;
 }
 
-static __devexit int a4000t_device_remove(struct platform_device *dev)
+static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
 {
-	struct Scsi_Host *host = platform_get_drvdata(dev);
+	struct Scsi_Host *host = platform_get_drvdata(pdev);
 	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	scsi_remove_host(host);
-
 	NCR_700_release(host);
 	kfree(hostdata);
 	free_irq(host->irq, host);
-	release_mem_region(A4000T_SCSI_ADDR, 0x1000);
-
+	release_mem_region(res->start, resource_size(res));
 	return 0;
 }
 
-static struct platform_driver a4000t_scsi_driver = {
-	.driver = {
-		.name           = "a4000t-scsi",
-		.owner          = THIS_MODULE,
+static struct platform_driver amiga_a4000t_scsi_driver = {
+	.remove = __exit_p(amiga_a4000t_scsi_remove),
+	.driver   = {
+		.name	= "amiga-a4000t-scsi",
+		.owner	= THIS_MODULE,
 	},
-	.probe          = a4000t_probe,
-	.remove         = __devexit_p(a4000t_device_remove),
 };
 
-static int __init a4000t_scsi_init(void)
+static int __init amiga_a4000t_scsi_init(void)
 {
-	int err;
-
-	err = platform_driver_register(&a4000t_scsi_driver);
-	if (err)
-		return err;
-
-	a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
-			-1, NULL, 0);
-	if (IS_ERR(a4000t_scsi_device)) {
-		platform_driver_unregister(&a4000t_scsi_driver);
-		return PTR_ERR(a4000t_scsi_device);
-	}
-
-	return err;
+	return platform_driver_probe(&amiga_a4000t_scsi_driver,
+				     amiga_a4000t_scsi_probe);
 }
 
-static void __exit a4000t_scsi_exit(void)
+module_init(amiga_a4000t_scsi_init);
+
+static void __exit amiga_a4000t_scsi_exit(void)
 {
-	platform_device_unregister(a4000t_scsi_device);
-	platform_driver_unregister(&a4000t_scsi_driver);
+	platform_driver_unregister(&amiga_a4000t_scsi_driver);
 }
 
-module_init(a4000t_scsi_init);
-module_exit(a4000t_scsi_exit);
+module_exit(amiga_a4000t_scsi_exit);
+
+MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / "
+	      "Kars de Jong <jongk@linux-m68k.org>");
+MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:amiga-a4000t-scsi");
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 18b7102bb80e..2ce26eb7a1ec 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -1,36 +1,35 @@
 #include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/zorro.h>
 
-#include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <linux/spinlock.h>
 
 #include "scsi.h"
-#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 #include "gvp11.h"
 
-#include <linux/stat.h>
 
+#define CHECK_WD33C93
 
-#define DMA(ptr)	((gvp11_scsiregs *)((ptr)->base))
+struct gvp11_hostdata {
+	struct WD33C93_hostdata wh;
+	struct gvp11_scsiregs *regs;
+};
 
-static irqreturn_t gvp11_intr(int irq, void *_instance)
+static irqreturn_t gvp11_intr(int irq, void *data)
 {
+	struct Scsi_Host *instance = data;
+	struct gvp11_hostdata *hdata = shost_priv(instance);
+	unsigned int status = hdata->regs->CNTR;
 	unsigned long flags;
-	unsigned int status;
-	struct Scsi_Host *instance = (struct Scsi_Host *)_instance;
 
-	status = DMA(instance)->CNTR;
 	if (!(status & GVP11_DMAC_INT_PENDING))
 		return IRQ_NONE;
 
@@ -50,64 +49,66 @@ void gvp11_setup(char *str, int *ints)
 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 {
 	struct Scsi_Host *instance = cmd->device->host;
-	struct WD33C93_hostdata *hdata = shost_priv(instance);
+	struct gvp11_hostdata *hdata = shost_priv(instance);
+	struct WD33C93_hostdata *wh = &hdata->wh;
+	struct gvp11_scsiregs *regs = hdata->regs;
 	unsigned short cntr = GVP11_DMAC_INT_ENABLE;
 	unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 	int bank_mask;
 	static int scsi_alloc_out_of_range = 0;
 
 	/* use bounce buffer if the physical address is bad */
-	if (addr & hdata->dma_xfer_mask) {
-		hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
+	if (addr & wh->dma_xfer_mask) {
+		wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
 
 		if (!scsi_alloc_out_of_range) {
-			hdata->dma_bounce_buffer =
-				kmalloc(hdata->dma_bounce_len, GFP_KERNEL);
-			hdata->dma_buffer_pool = BUF_SCSI_ALLOCED;
+			wh->dma_bounce_buffer =
+				kmalloc(wh->dma_bounce_len, GFP_KERNEL);
+			wh->dma_buffer_pool = BUF_SCSI_ALLOCED;
 		}
 
 		if (scsi_alloc_out_of_range ||
-		    !hdata->dma_bounce_buffer) {
-			hdata->dma_bounce_buffer =
-				amiga_chip_alloc(hdata->dma_bounce_len,
+		    !wh->dma_bounce_buffer) {
+			wh->dma_bounce_buffer =
+				amiga_chip_alloc(wh->dma_bounce_len,
 						 "GVP II SCSI Bounce Buffer");
 
-			if (!hdata->dma_bounce_buffer) {
-				hdata->dma_bounce_len = 0;
+			if (!wh->dma_bounce_buffer) {
+				wh->dma_bounce_len = 0;
 				return 1;
 			}
 
-			hdata->dma_buffer_pool = BUF_CHIP_ALLOCED;
+			wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
 		}
 
 		/* check if the address of the bounce buffer is OK */
-		addr = virt_to_bus(hdata->dma_bounce_buffer);
+		addr = virt_to_bus(wh->dma_bounce_buffer);
 
-		if (addr & hdata->dma_xfer_mask) {
+		if (addr & wh->dma_xfer_mask) {
 			/* fall back to Chip RAM if address out of range */
-			if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) {
-				kfree(hdata->dma_bounce_buffer);
+			if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
+				kfree(wh->dma_bounce_buffer);
 				scsi_alloc_out_of_range = 1;
 			} else {
-				amiga_chip_free(hdata->dma_bounce_buffer);
+				amiga_chip_free(wh->dma_bounce_buffer);
 			}
 
-			hdata->dma_bounce_buffer =
-				amiga_chip_alloc(hdata->dma_bounce_len,
+			wh->dma_bounce_buffer =
+				amiga_chip_alloc(wh->dma_bounce_len,
 						 "GVP II SCSI Bounce Buffer");
 
-			if (!hdata->dma_bounce_buffer) {
-				hdata->dma_bounce_len = 0;
+			if (!wh->dma_bounce_buffer) {
+				wh->dma_bounce_len = 0;
 				return 1;
 			}
 
-			addr = virt_to_bus(hdata->dma_bounce_buffer);
-			hdata->dma_buffer_pool = BUF_CHIP_ALLOCED;
+			addr = virt_to_bus(wh->dma_bounce_buffer);
+			wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
 		}
 
 		if (!dir_in) {
 			/* copy to bounce buffer for a write */
-			memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr,
+			memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr,
 			       cmd->SCp.this_residual);
 		}
 	}
@@ -116,11 +117,11 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 	if (!dir_in)
 		cntr |= GVP11_DMAC_DIR_WRITE;
 
-	hdata->dma_dir = dir_in;
-	DMA(cmd->device->host)->CNTR = cntr;
+	wh->dma_dir = dir_in;
+	regs->CNTR = cntr;
 
 	/* setup DMA *physical* address */
-	DMA(cmd->device->host)->ACR = addr;
+	regs->ACR = addr;
 
 	if (dir_in) {
 		/* invalidate any cache */
@@ -130,12 +131,12 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 		cache_push(addr, cmd->SCp.this_residual);
 	}
 
-	bank_mask = (~hdata->dma_xfer_mask >> 18) & 0x01c0;
+	bank_mask = (~wh->dma_xfer_mask >> 18) & 0x01c0;
 	if (bank_mask)
-		DMA(cmd->device->host)->BANK = bank_mask & (addr >> 18);
+		regs->BANK = bank_mask & (addr >> 18);
 
 	/* start DMA */
-	DMA(cmd->device->host)->ST_DMA = 1;
+	regs->ST_DMA = 1;
 
 	/* return success */
 	return 0;
@@ -144,236 +145,53 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 		     int status)
 {
-	struct WD33C93_hostdata *hdata = shost_priv(instance);
+	struct gvp11_hostdata *hdata = shost_priv(instance);
+	struct WD33C93_hostdata *wh = &hdata->wh;
+	struct gvp11_scsiregs *regs = hdata->regs;
 
 	/* stop DMA */
-	DMA(instance)->SP_DMA = 1;
+	regs->SP_DMA = 1;
 	/* remove write bit from CONTROL bits */
-	DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
+	regs->CNTR = GVP11_DMAC_INT_ENABLE;
 
 	/* copy from a bounce buffer, if necessary */
-	if (status && hdata->dma_bounce_buffer) {
-		if (hdata->dma_dir && SCpnt)
-			memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer,
+	if (status && wh->dma_bounce_buffer) {
+		if (wh->dma_dir && SCpnt)
+			memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer,
 			       SCpnt->SCp.this_residual);
 
-		if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED)
-			kfree(hdata->dma_bounce_buffer);
-		else
-			amiga_chip_free(hdata->dma_bounce_buffer);
-
-		hdata->dma_bounce_buffer = NULL;
-		hdata->dma_bounce_len = 0;
-	}
-}
-
-#define CHECK_WD33C93
-
-int __init gvp11_detect(struct scsi_host_template *tpnt)
-{
-	static unsigned char called = 0;
-	struct Scsi_Host *instance;
-	unsigned long address;
-	unsigned int epc;
-	struct zorro_dev *z = NULL;
-	unsigned int default_dma_xfer_mask;
-	struct WD33C93_hostdata *hdata;
-	wd33c93_regs regs;
-	int num_gvp11 = 0;
-#ifdef CHECK_WD33C93
-	volatile unsigned char *sasr_3393, *scmd_3393;
-	unsigned char save_sasr;
-	unsigned char q, qq;
-#endif
-
-	if (!MACH_IS_AMIGA || called)
-		return 0;
-	called = 1;
-
-	tpnt->proc_name = "GVP11";
-	tpnt->proc_info = &wd33c93_proc_info;
-
-	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-		/*
-		 * This should (hopefully) be the correct way to identify
-		 * all the different GVP SCSI controllers (except for the
-		 * SERIES I though).
-		 */
-
-		if (z->id == ZORRO_PROD_GVP_COMBO_030_R3_SCSI ||
-		    z->id == ZORRO_PROD_GVP_SERIES_II)
-			default_dma_xfer_mask = ~0x00ffffff;
-		else if (z->id == ZORRO_PROD_GVP_GFORCE_030_SCSI ||
-			 z->id == ZORRO_PROD_GVP_A530_SCSI ||
-			 z->id == ZORRO_PROD_GVP_COMBO_030_R4_SCSI)
-			default_dma_xfer_mask = ~0x01ffffff;
-		else if (z->id == ZORRO_PROD_GVP_A1291 ||
-			 z->id == ZORRO_PROD_GVP_GFORCE_040_SCSI_1)
-			default_dma_xfer_mask = ~0x07ffffff;
+		if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
+			kfree(wh->dma_bounce_buffer);
 		else
-			continue;
-
-		/*
-		 * Rumors state that some GVP ram boards use the same product
-		 * code as the SCSI controllers. Therefore if the board-size
-		 * is not 64KB we asume it is a ram board and bail out.
-		 */
-		if (z->resource.end - z->resource.start != 0xffff)
-			continue;
+			amiga_chip_free(wh->dma_bounce_buffer);
 
-		address = z->resource.start;
-		if (!request_mem_region(address, 256, "wd33c93"))
-			continue;
-
-#ifdef CHECK_WD33C93
-
-		/*
-		 * These darn GVP boards are a problem - it can be tough to tell
-		 * whether or not they include a SCSI controller. This is the
-		 * ultimate Yet-Another-GVP-Detection-Hack in that it actually
-		 * probes for a WD33c93 chip: If we find one, it's extremely
-		 * likely that this card supports SCSI, regardless of Product_
-		 * Code, Board_Size, etc.
-		 */
-
-		/* Get pointers to the presumed register locations and save contents */
-
-		sasr_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SASR);
-		scmd_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SCMD);
-		save_sasr = *sasr_3393;
-
-		/* First test the AuxStatus Reg */
-
-		q = *sasr_3393;	/* read it */
-		if (q & 0x08)	/* bit 3 should always be clear */
-			goto release;
-		*sasr_3393 = WD_AUXILIARY_STATUS;	/* setup indirect address */
-		if (*sasr_3393 == WD_AUXILIARY_STATUS) {	/* shouldn't retain the write */
-			*sasr_3393 = save_sasr;	/* Oops - restore this byte */
-			goto release;
-		}
-		if (*sasr_3393 != q) {	/* should still read the same */
-			*sasr_3393 = save_sasr;	/* Oops - restore this byte */
-			goto release;
-		}
-		if (*scmd_3393 != q)	/* and so should the image at 0x1f */
-			goto release;
-
-		/*
-		 * Ok, we probably have a wd33c93, but let's check a few other places
-		 * for good measure. Make sure that this works for both 'A and 'B
-		 * chip versions.
-		 */
-
-		*sasr_3393 = WD_SCSI_STATUS;
-		q = *scmd_3393;
-		*sasr_3393 = WD_SCSI_STATUS;
-		*scmd_3393 = ~q;
-		*sasr_3393 = WD_SCSI_STATUS;
-		qq = *scmd_3393;
-		*sasr_3393 = WD_SCSI_STATUS;
-		*scmd_3393 = q;
-		if (qq != q)	/* should be read only */
-			goto release;
-		*sasr_3393 = 0x1e;	/* this register is unimplemented */
-		q = *scmd_3393;
-		*sasr_3393 = 0x1e;
-		*scmd_3393 = ~q;
-		*sasr_3393 = 0x1e;
-		qq = *scmd_3393;
-		*sasr_3393 = 0x1e;
-		*scmd_3393 = q;
-		if (qq != q || qq != 0xff)	/* should be read only, all 1's */
-			goto release;
-		*sasr_3393 = WD_TIMEOUT_PERIOD;
-		q = *scmd_3393;
-		*sasr_3393 = WD_TIMEOUT_PERIOD;
-		*scmd_3393 = ~q;
-		*sasr_3393 = WD_TIMEOUT_PERIOD;
-		qq = *scmd_3393;
-		*sasr_3393 = WD_TIMEOUT_PERIOD;
-		*scmd_3393 = q;
-		if (qq != (~q & 0xff))	/* should be read/write */
-			goto release;
-#endif
-
-		instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
-		if (instance == NULL)
-			goto release;
-		instance->base = ZTWO_VADDR(address);
-		instance->irq = IRQ_AMIGA_PORTS;
-		instance->unique_id = z->slotaddr;
-
-		hdata = shost_priv(instance);
-		if (gvp11_xfer_mask)
-			hdata->dma_xfer_mask = gvp11_xfer_mask;
-		else
-			hdata->dma_xfer_mask = default_dma_xfer_mask;
-
-		DMA(instance)->secret2 = 1;
-		DMA(instance)->secret1 = 0;
-		DMA(instance)->secret3 = 15;
-		while (DMA(instance)->CNTR & GVP11_DMAC_BUSY)
-			;
-		DMA(instance)->CNTR = 0;
-
-		DMA(instance)->BANK = 0;
-
-		epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
-
-		/*
-		 * Check for 14MHz SCSI clock
-		 */
-		regs.SASR = &(DMA(instance)->SASR);
-		regs.SCMD = &(DMA(instance)->SCMD);
-		hdata->no_sync = 0xff;
-		hdata->fast = 0;
-		hdata->dma_mode = CTRL_DMA;
-		wd33c93_init(instance, regs, dma_setup, dma_stop,
-			     (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
-						     : WD33C93_FS_12_15);
-
-		if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED,
-				"GVP11 SCSI", instance))
-			goto unregister;
-		DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
-		num_gvp11++;
-		continue;
-
-unregister:
-		scsi_unregister(instance);
-release:
-		release_mem_region(address, 256);
+		wh->dma_bounce_buffer = NULL;
+		wh->dma_bounce_len = 0;
 	}
-
-	return num_gvp11;
 }
 
 static int gvp11_bus_reset(struct scsi_cmnd *cmd)
 {
+	struct Scsi_Host *instance = cmd->device->host;
+
 	/* FIXME perform bus-specific reset */
 
 	/* FIXME 2: shouldn't we no-op this function (return
 	   FAILED), and fall back to host reset function,
 	   wd33c93_host_reset ? */
 
-	spin_lock_irq(cmd->device->host->host_lock);
+	spin_lock_irq(instance->host_lock);
 	wd33c93_host_reset(cmd);
-	spin_unlock_irq(cmd->device->host->host_lock);
+	spin_unlock_irq(instance->host_lock);
 
 	return SUCCESS;
 }
 
-
-#define HOSTS_C
-
-#include "gvp11.h"
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "GVP11",
+static struct scsi_host_template gvp11_scsi_template = {
+	.module			= THIS_MODULE,
 	.name			= "GVP Series II SCSI",
-	.detect			= gvp11_detect,
-	.release		= gvp11_release,
+	.proc_info		= wd33c93_proc_info,
+	.proc_name		= "GVP11",
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
 	.eh_bus_reset_handler	= gvp11_bus_reset,
@@ -385,17 +203,230 @@ static struct scsi_host_template driver_template = {
 	.use_clustering		= DISABLE_CLUSTERING
 };
 
+static int __devinit check_wd33c93(struct gvp11_scsiregs *regs)
+{
+#ifdef CHECK_WD33C93
+	volatile unsigned char *sasr_3393, *scmd_3393;
+	unsigned char save_sasr;
+	unsigned char q, qq;
 
-#include "scsi_module.c"
+	/*
+	 * These darn GVP boards are a problem - it can be tough to tell
+	 * whether or not they include a SCSI controller. This is the
+	 * ultimate Yet-Another-GVP-Detection-Hack in that it actually
+	 * probes for a WD33c93 chip: If we find one, it's extremely
+	 * likely that this card supports SCSI, regardless of Product_
+	 * Code, Board_Size, etc.
+	 */
+
+	/* Get pointers to the presumed register locations and save contents */
+
+	sasr_3393 = &regs->SASR;
+	scmd_3393 = &regs->SCMD;
+	save_sasr = *sasr_3393;
+
+	/* First test the AuxStatus Reg */
+
+	q = *sasr_3393;	/* read it */
+	if (q & 0x08)	/* bit 3 should always be clear */
+		return -ENODEV;
+	*sasr_3393 = WD_AUXILIARY_STATUS;	/* setup indirect address */
+	if (*sasr_3393 == WD_AUXILIARY_STATUS) {	/* shouldn't retain the write */
+		*sasr_3393 = save_sasr;	/* Oops - restore this byte */
+		return -ENODEV;
+	}
+	if (*sasr_3393 != q) {	/* should still read the same */
+		*sasr_3393 = save_sasr;	/* Oops - restore this byte */
+		return -ENODEV;
+	}
+	if (*scmd_3393 != q)	/* and so should the image at 0x1f */
+		return -ENODEV;
+
+	/*
+	 * Ok, we probably have a wd33c93, but let's check a few other places
+	 * for good measure. Make sure that this works for both 'A and 'B
+	 * chip versions.
+	 */
+
+	*sasr_3393 = WD_SCSI_STATUS;
+	q = *scmd_3393;
+	*sasr_3393 = WD_SCSI_STATUS;
+	*scmd_3393 = ~q;
+	*sasr_3393 = WD_SCSI_STATUS;
+	qq = *scmd_3393;
+	*sasr_3393 = WD_SCSI_STATUS;
+	*scmd_3393 = q;
+	if (qq != q)	/* should be read only */
+		return -ENODEV;
+	*sasr_3393 = 0x1e;	/* this register is unimplemented */
+	q = *scmd_3393;
+	*sasr_3393 = 0x1e;
+	*scmd_3393 = ~q;
+	*sasr_3393 = 0x1e;
+	qq = *scmd_3393;
+	*sasr_3393 = 0x1e;
+	*scmd_3393 = q;
+	if (qq != q || qq != 0xff)	/* should be read only, all 1's */
+		return -ENODEV;
+	*sasr_3393 = WD_TIMEOUT_PERIOD;
+	q = *scmd_3393;
+	*sasr_3393 = WD_TIMEOUT_PERIOD;
+	*scmd_3393 = ~q;
+	*sasr_3393 = WD_TIMEOUT_PERIOD;
+	qq = *scmd_3393;
+	*sasr_3393 = WD_TIMEOUT_PERIOD;
+	*scmd_3393 = q;
+	if (qq != (~q & 0xff))	/* should be read/write */
+		return -ENODEV;
+#endif /* CHECK_WD33C93 */
 
-int gvp11_release(struct Scsi_Host *instance)
+	return 0;
+}
+
+static int __devinit gvp11_probe(struct zorro_dev *z,
+				 const struct zorro_device_id *ent)
 {
-#ifdef MODULE
-	DMA(instance)->CNTR = 0;
-	release_mem_region(ZTWO_PADDR(instance->base), 256);
+	struct Scsi_Host *instance;
+	unsigned long address;
+	int error;
+	unsigned int epc;
+	unsigned int default_dma_xfer_mask;
+	struct gvp11_hostdata *hdata;
+	struct gvp11_scsiregs *regs;
+	wd33c93_regs wdregs;
+
+	default_dma_xfer_mask = ent->driver_data;
+
+	/*
+	 * Rumors state that some GVP ram boards use the same product
+	 * code as the SCSI controllers. Therefore if the board-size
+	 * is not 64KB we asume it is a ram board and bail out.
+	 */
+	if (zorro_resource_len(z) != 0x10000)
+		return -ENODEV;
+
+	address = z->resource.start;
+	if (!request_mem_region(address, 256, "wd33c93"))
+		return -EBUSY;
+
+	regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address));
+
+	error = check_wd33c93(regs);
+	if (error)
+		goto fail_check_or_alloc;
+
+	instance = scsi_host_alloc(&gvp11_scsi_template,
+				   sizeof(struct gvp11_hostdata));
+	if (!instance) {
+		error = -ENOMEM;
+		goto fail_check_or_alloc;
+	}
+
+	instance->irq = IRQ_AMIGA_PORTS;
+	instance->unique_id = z->slotaddr;
+
+	regs->secret2 = 1;
+	regs->secret1 = 0;
+	regs->secret3 = 15;
+	while (regs->CNTR & GVP11_DMAC_BUSY)
+		;
+	regs->CNTR = 0;
+	regs->BANK = 0;
+
+	wdregs.SASR = &regs->SASR;
+	wdregs.SCMD = &regs->SCMD;
+
+	hdata = shost_priv(instance);
+	if (gvp11_xfer_mask)
+		hdata->wh.dma_xfer_mask = gvp11_xfer_mask;
+	else
+		hdata->wh.dma_xfer_mask = default_dma_xfer_mask;
+
+	hdata->wh.no_sync = 0xff;
+	hdata->wh.fast = 0;
+	hdata->wh.dma_mode = CTRL_DMA;
+	hdata->regs = regs;
+
+	/*
+	 * Check for 14MHz SCSI clock
+	 */
+	epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
+	wd33c93_init(instance, wdregs, dma_setup, dma_stop,
+		     (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
+					     : WD33C93_FS_12_15);
+
+	error = request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED,
+			    "GVP11 SCSI", instance);
+	if (error)
+		goto fail_irq;
+
+	regs->CNTR = GVP11_DMAC_INT_ENABLE;
+
+	error = scsi_add_host(instance, NULL);
+	if (error)
+		goto fail_host;
+
+	zorro_set_drvdata(z, instance);
+	scsi_scan_host(instance);
+	return 0;
+
+fail_host:
 	free_irq(IRQ_AMIGA_PORTS, instance);
-#endif
-	return 1;
+fail_irq:
+	scsi_host_put(instance);
+fail_check_or_alloc:
+	release_mem_region(address, 256);
+	return error;
+}
+
+static void __devexit gvp11_remove(struct zorro_dev *z)
+{
+	struct Scsi_Host *instance = zorro_get_drvdata(z);
+	struct gvp11_hostdata *hdata = shost_priv(instance);
+
+	hdata->regs->CNTR = 0;
+	scsi_remove_host(instance);
+	free_irq(IRQ_AMIGA_PORTS, instance);
+	scsi_host_put(instance);
+	release_mem_region(z->resource.start, 256);
+}
+
+	/*
+	 * This should (hopefully) be the correct way to identify
+	 * all the different GVP SCSI controllers (except for the
+	 * SERIES I though).
+	 */
+
+static struct zorro_device_id gvp11_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_GVP_COMBO_030_R3_SCSI,	~0x00ffffff },
+	{ ZORRO_PROD_GVP_SERIES_II,		~0x00ffffff },
+	{ ZORRO_PROD_GVP_GFORCE_030_SCSI,	~0x01ffffff },
+	{ ZORRO_PROD_GVP_A530_SCSI,		~0x01ffffff },
+	{ ZORRO_PROD_GVP_COMBO_030_R4_SCSI,	~0x01ffffff },
+	{ ZORRO_PROD_GVP_A1291,			~0x07ffffff },
+	{ ZORRO_PROD_GVP_GFORCE_040_SCSI_1,	~0x07ffffff },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, gvp11_zorro_tbl);
+
+static struct zorro_driver gvp11_driver = {
+	.name		= "gvp11",
+	.id_table	= gvp11_zorro_tbl,
+	.probe		= gvp11_probe,
+	.remove		= __devexit_p(gvp11_remove),
+};
+
+static int __init gvp11_init(void)
+{
+	return zorro_register_driver(&gvp11_driver);
+}
+module_init(gvp11_init);
+
+static void __exit gvp11_exit(void)
+{
+	zorro_unregister_driver(&gvp11_driver);
 }
+module_exit(gvp11_exit);
 
+MODULE_DESCRIPTION("GVP Series II SCSI");
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/gvp11.h b/drivers/scsi/gvp11.h
index e2efdf9601ef..852913cde5dd 100644
--- a/drivers/scsi/gvp11.h
+++ b/drivers/scsi/gvp11.h
@@ -11,9 +11,6 @@
 
 #include <linux/types.h>
 
-int gvp11_detect(struct scsi_host_template *);
-int gvp11_release(struct Scsi_Host *);
-
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN		2
 #endif
@@ -22,15 +19,13 @@ int gvp11_release(struct Scsi_Host *);
 #define CAN_QUEUE		16
 #endif
 
-#ifndef HOSTS_C
-
 /*
  * if the transfer address ANDed with this results in a non-zero
  * result, then we can't use DMA.
  */
 #define GVP11_XFER_MASK		(0xff000001)
 
-typedef struct {
+struct gvp11_scsiregs {
 		 unsigned char	pad1[64];
 	volatile unsigned short	CNTR;
 		 unsigned char	pad2[31];
@@ -46,7 +41,7 @@ typedef struct {
 	volatile unsigned short	SP_DMA;
 	volatile unsigned short	secret2; /* store 1 here */
 	volatile unsigned short	secret3; /* store 15 here */
-} gvp11_scsiregs;
+};
 
 /* bits in CNTR */
 #define GVP11_DMAC_BUSY		(1<<0)
@@ -54,6 +49,4 @@ typedef struct {
 #define GVP11_DMAC_INT_ENABLE	(1<<3)
 #define GVP11_DMAC_DIR_WRITE	(1<<4)
 
-#endif /* else def HOSTS_C */
-
 #endif /* GVP11_H */
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index 716d1785cda7..c29d0dbb9660 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -16,12 +16,12 @@
 #include <linux/stat.h>
 
 
-static struct Scsi_Host *mvme147_host = NULL;
-
-static irqreturn_t mvme147_intr(int irq, void *dummy)
+static irqreturn_t mvme147_intr(int irq, void *data)
 {
+	struct Scsi_Host *instance = data;
+
 	if (irq == MVME147_IRQ_SCSI_PORT)
-		wd33c93_intr(mvme147_host);
+		wd33c93_intr(instance);
 	else
 		m147_pcc->dma_intr = 0x89;	/* Ack and enable ints */
 	return IRQ_HANDLED;
@@ -29,7 +29,8 @@ static irqreturn_t mvme147_intr(int irq, void *dummy)
 
 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 {
-	struct WD33C93_hostdata *hdata = shost_priv(mvme147_host);
+	struct Scsi_Host *instance = cmd->device->host;
+	struct WD33C93_hostdata *hdata = shost_priv(instance);
 	unsigned char flags = 0x01;
 	unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 
@@ -66,6 +67,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 int mvme147_detect(struct scsi_host_template *tpnt)
 {
 	static unsigned char called = 0;
+	struct Scsi_Host *instance;
 	wd33c93_regs regs;
 	struct WD33C93_hostdata *hdata;
 
@@ -76,25 +78,25 @@ int mvme147_detect(struct scsi_host_template *tpnt)
 	tpnt->proc_name = "MVME147";
 	tpnt->proc_info = &wd33c93_proc_info;
 
-	mvme147_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
-	if (!mvme147_host)
+	instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
+	if (!instance)
 		goto err_out;
 
-	mvme147_host->base = 0xfffe4000;
-	mvme147_host->irq = MVME147_IRQ_SCSI_PORT;
+	instance->base = 0xfffe4000;
+	instance->irq = MVME147_IRQ_SCSI_PORT;
 	regs.SASR = (volatile unsigned char *)0xfffe4000;
 	regs.SCMD = (volatile unsigned char *)0xfffe4001;
-	hdata = shost_priv(mvme147_host);
+	hdata = shost_priv(instance);
 	hdata->no_sync = 0xff;
 	hdata->fast = 0;
 	hdata->dma_mode = CTRL_DMA;
-	wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
+	wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
 
 	if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
-			"MVME147 SCSI PORT", mvme147_intr))
+			"MVME147 SCSI PORT", instance))
 		goto err_unregister;
 	if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
-			"MVME147 SCSI DMA", mvme147_intr))
+			"MVME147 SCSI DMA", instance))
 		goto err_free_irq;
 #if 0	/* Disabled; causes problems booting */
 	m147_pcc->scsi_interrupt = 0x10;	/* Assert SCSI bus reset */
@@ -113,7 +115,7 @@ int mvme147_detect(struct scsi_host_template *tpnt)
 err_free_irq:
 	free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr);
 err_unregister:
-	scsi_unregister(mvme147_host);
+	scsi_unregister(instance);
 err_out:
 	return 0;
 }
@@ -132,9 +134,6 @@ static int mvme147_bus_reset(struct scsi_cmnd *cmd)
 	return SUCCESS;
 }
 
-#define HOSTS_C
-
-#include "mvme147.h"
 
 static struct scsi_host_template driver_template = {
 	.proc_name		= "MVME147",