sun3_scsi: Convert to platform device

Convert sun3_scsi to platform device and eliminate scsi_register().

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index bb660fe..ba51699 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -23,22 +23,15 @@
  */
 
 #include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/ctype.h>
 #include <linux/delay.h>
-
 #include <linux/module.h>
-#include <linux/signal.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
-
-#include <asm/sun3ints.h>
 #include <asm/dvma.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
 
 /* dma on! */
 #define REAL_DMA
@@ -59,8 +52,6 @@
 #endif
 
 
-static irqreturn_t scsi_sun3_intr(int irq, void *dummy);
-
 static int setup_can_queue = -1;
 module_param(setup_can_queue, int, 0);
 static int setup_cmd_per_lun = -1;
@@ -89,15 +80,14 @@
 /* minimum number of bytes to do dma on */
 #define SUN3_DMA_MINSIZE 128
 
-static volatile unsigned char *sun3_scsi_regp;
+static unsigned char *sun3_scsi_regp;
 static volatile struct sun3_dma_regs *dregs;
-#ifndef SUN3_SCSI_VME
-static struct sun3_udc_regs *udc_regs = NULL;
-#endif
+static struct sun3_udc_regs *udc_regs;
 static unsigned char *sun3_dma_orig_addr = NULL;
 static unsigned long sun3_dma_orig_count = 0;
 static int sun3_dma_active = 0;
 static unsigned long last_residual = 0;
+static struct Scsi_Host *default_instance;
 
 /*
  * NCR 5380 register access functions
@@ -105,12 +95,12 @@
 
 static inline unsigned char sun3scsi_read(int reg)
 {
-	return( sun3_scsi_regp[reg] );
+	return in_8(sun3_scsi_regp + reg);
 }
 
 static inline void sun3scsi_write(int reg, int value)
 {
-	sun3_scsi_regp[reg] = value;
+	out_8(sun3_scsi_regp + reg, value);
 }
 
 #ifndef SUN3_SCSI_VME
@@ -137,192 +127,7 @@
 }
 #endif
 
-/*
- * XXX: status debug
- */
-static struct Scsi_Host *default_instance;
-
-/*
- * Function : int sun3scsi_detect(struct scsi_host_template * tpnt)
- *
- * Purpose : initializes mac NCR5380 driver based on the
- *	command line / compile time port and irq definitions.
- *
- * Inputs : tpnt - template for this SCSI adapter.
- *
- * Returns : 1 if a host adapter was found, 0 if not.
- *
- */
- 
-static int __init sun3scsi_detect(struct scsi_host_template *tpnt)
-{
-	unsigned long ioaddr, irq;
-	static int called = 0;
-	struct Scsi_Host *instance;
-#ifdef SUN3_SCSI_VME
-	int i;
-	unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI,
-				   IOBASE_SUN3_VMESCSI + 0x4000,
-				   0 };
-	unsigned long vecs[3] = { SUN3_VEC_VMESCSI0,
-				  SUN3_VEC_VMESCSI1,
-				  0 };
-#endif
-
-	/* check that this machine has an onboard 5380 */
-	switch(idprom->id_machtype) {
-#ifdef SUN3_SCSI_VME
-	case SM_SUN3|SM_3_160:
-	case SM_SUN3|SM_3_260:
-		break;
-#else
-	case SM_SUN3|SM_3_50:
-	case SM_SUN3|SM_3_60:
-		break;
-#endif
-
-	default:
-		return 0;
-	}
-
-	if(called)
-		return 0;
-
-#ifdef SUN3_SCSI_VME
-	tpnt->proc_name = "Sun3 5380 VME SCSI";
-#else
-	tpnt->proc_name = "Sun3 5380 SCSI";
-#endif
-
-	/* setup variables */
-	if (setup_can_queue > 0)
-		tpnt->can_queue = setup_can_queue;
-	if (setup_cmd_per_lun > 0)
-		tpnt->cmd_per_lun = setup_cmd_per_lun;
-	if (setup_sg_tablesize >= 0)
-		tpnt->sg_tablesize = setup_sg_tablesize;
-
-	if (setup_hostid >= 0)
-		tpnt->this_id = setup_hostid;
-	else {
-		/* use 7 as default */
-		tpnt->this_id = 7;
-	}
-
-#ifdef SUN3_SCSI_VME
-	ioaddr = 0;
-	for (i = 0; addrs[i] != 0; i++) {
-		unsigned char x;
-
-		ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE,
-						     SUN3_PAGE_TYPE_VME16);
-		irq = vecs[i];
-		sun3_scsi_regp = (unsigned char *)ioaddr;
-
-		dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
-
-		if (sun3_map_test((unsigned long)dregs, &x)) {
-			unsigned short oldcsr;
-
-			oldcsr = dregs->csr;
-			dregs->csr = 0;
-			udelay(SUN3_DMA_DELAY);
-			if (dregs->csr == 0x1400)
-				break;
-
-			dregs->csr = oldcsr;
-		}
-
-		iounmap((void *)ioaddr);
-		ioaddr = 0;
-	}
-
-	if (!ioaddr)
-		return 0;
-#else
-	irq = IRQ_SUN3_SCSI;
-	ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE);
-	sun3_scsi_regp = (unsigned char *)ioaddr;
-
-	dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
-
-	if((udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs)))
-	   == NULL) {
-	     printk("SUN3 Scsi couldn't allocate DVMA memory!\n");
-	     return 0;
-	}
-#endif
-#ifdef SUPPORT_TAGS
-	if (setup_use_tagged_queuing < 0)
-		setup_use_tagged_queuing = 1;
-#endif
-
-	instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-	if(instance == NULL)
-		return 0;
-		
-	default_instance = instance;
-
-        instance->io_port = (unsigned long) ioaddr;
-	instance->irq = irq;
-
-	NCR5380_init(instance, 0);
-
-	instance->n_io_port = 32;
-
-	if (request_irq(instance->irq, scsi_sun3_intr,
-			     0, "Sun3SCSI-5380", instance)) {
-#ifndef REAL_DMA
-		printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-		       instance->host_no, instance->irq);
-		instance->irq = NO_IRQ;
-#else
-		printk("scsi%d: IRQ%d not free, bailing out\n",
-		       instance->host_no, instance->irq);
-		return 0;
-#endif
-	}
-	
-	dregs->csr = 0;
-	udelay(SUN3_DMA_DELAY);
-	dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
-	udelay(SUN3_DMA_DELAY);
-	dregs->fifo_count = 0;
-#ifdef SUN3_SCSI_VME
-	dregs->fifo_count_hi = 0;
-	dregs->dma_addr_hi = 0;
-	dregs->dma_addr_lo = 0;
-	dregs->dma_count_hi = 0;
-	dregs->dma_count_lo = 0;
-
-	dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
-#endif
-
-	called = 1;
-
 #ifdef RESET_BOOT
-	sun3_scsi_reset_boot(instance);
-#endif
-
-	return 1;
-}
-
-static int sun3scsi_release(struct Scsi_Host *shpnt)
-{
-	if (shpnt->irq != NO_IRQ)
-		free_irq(shpnt->irq, shpnt);
-
-	iounmap((void *)sun3_scsi_regp);
-
-	NCR5380_exit(shpnt);
-	return 0;
-}
-
-#ifdef RESET_BOOT
-/*
- * Our 'bus reset on boot' function
- */
-
 static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
 {
 	unsigned long end;
@@ -671,11 +476,21 @@
 	
 #include "sun3_NCR5380.c"
 
-static struct scsi_host_template driver_template = {
+#ifdef SUN3_SCSI_VME
+#define SUN3_SCSI_NAME          "Sun3 NCR5380 VME SCSI"
+#define DRV_MODULE_NAME         "sun3_scsi_vme"
+#else
+#define SUN3_SCSI_NAME          "Sun3 NCR5380 SCSI"
+#define DRV_MODULE_NAME         "sun3_scsi"
+#endif
+
+#define PFX                     DRV_MODULE_NAME ": "
+
+static struct scsi_host_template sun3_scsi_template = {
+	.module			= THIS_MODULE,
+	.proc_name		= DRV_MODULE_NAME,
 	.show_info		= sun3scsi_show_info,
 	.name			= SUN3_SCSI_NAME,
-	.detect			= sun3scsi_detect,
-	.release		= sun3scsi_release,
 	.info			= sun3scsi_info,
 	.queuecommand		= sun3scsi_queue_command,
 	.eh_abort_handler      	= sun3scsi_abort,
@@ -687,7 +502,172 @@
 	.use_clustering		= DISABLE_CLUSTERING
 };
 
+static int __init sun3_scsi_probe(struct platform_device *pdev)
+{
+	struct Scsi_Host *instance;
+	int error;
+	struct resource *irq, *mem;
+	unsigned char *ioaddr;
+#ifdef SUN3_SCSI_VME
+	int i;
+#endif
 
-#include "scsi_module.c"
+	if (setup_can_queue > 0)
+		sun3_scsi_template.can_queue = setup_can_queue;
+	if (setup_cmd_per_lun > 0)
+		sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun;
+	if (setup_sg_tablesize >= 0)
+		sun3_scsi_template.sg_tablesize = setup_sg_tablesize;
+	if (setup_hostid >= 0)
+		sun3_scsi_template.this_id = setup_hostid & 7;
 
+#ifdef SUPPORT_TAGS
+	if (setup_use_tagged_queuing < 0)
+		setup_use_tagged_queuing = 1;
+#endif
+
+#ifdef SUN3_SCSI_VME
+	ioaddr = NULL;
+	for (i = 0; i < 2; i++) {
+		unsigned char x;
+
+		irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!irq || !mem)
+			break;
+
+		ioaddr = sun3_ioremap(mem->start, resource_size(mem),
+		                      SUN3_PAGE_TYPE_VME16);
+		dregs = (struct sun3_dma_regs *)(ioaddr + 8);
+
+		if (sun3_map_test((unsigned long)dregs, &x)) {
+			unsigned short oldcsr;
+
+			oldcsr = dregs->csr;
+			dregs->csr = 0;
+			udelay(SUN3_DMA_DELAY);
+			if (dregs->csr == 0x1400)
+				break;
+
+			dregs->csr = oldcsr;
+		}
+
+		iounmap(ioaddr);
+		ioaddr = NULL;
+	}
+	if (!ioaddr)
+		return -ENODEV;
+#else
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!irq || !mem)
+		return -ENODEV;
+
+	ioaddr = ioremap(mem->start, resource_size(mem));
+	dregs = (struct sun3_dma_regs *)(ioaddr + 8);
+
+	udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs));
+	if (!udc_regs) {
+		pr_err(PFX "couldn't allocate DVMA memory!\n");
+		iounmap(ioaddr);
+		return -ENOMEM;
+	}
+#endif
+
+	sun3_scsi_regp = ioaddr;
+
+	instance = scsi_host_alloc(&sun3_scsi_template,
+	                           sizeof(struct NCR5380_hostdata));
+	if (!instance) {
+		error = -ENOMEM;
+		goto fail_alloc;
+	}
+	default_instance = instance;
+
+	instance->io_port = (unsigned long)ioaddr;
+	instance->irq = irq->start;
+
+	NCR5380_init(instance, 0);
+
+	error = request_irq(instance->irq, scsi_sun3_intr, 0,
+	                    "NCR5380", instance);
+	if (error) {
+#ifdef REAL_DMA
+		pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n",
+		       instance->host_no, instance->irq);
+		goto fail_irq;
+#else
+		pr_warn(PFX "scsi%d: IRQ %d not free, interrupts disabled\n",
+		        instance->host_no, instance->irq);
+		instance->irq = NO_IRQ;
+#endif
+	}
+
+	dregs->csr = 0;
+	udelay(SUN3_DMA_DELAY);
+	dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
+	udelay(SUN3_DMA_DELAY);
+	dregs->fifo_count = 0;
+#ifdef SUN3_SCSI_VME
+	dregs->fifo_count_hi = 0;
+	dregs->dma_addr_hi = 0;
+	dregs->dma_addr_lo = 0;
+	dregs->dma_count_hi = 0;
+	dregs->dma_count_lo = 0;
+
+	dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
+#endif
+
+#ifdef RESET_BOOT
+	sun3_scsi_reset_boot(instance);
+#endif
+
+	error = scsi_add_host(instance, NULL);
+	if (error)
+		goto fail_host;
+
+	platform_set_drvdata(pdev, instance);
+
+	scsi_scan_host(instance);
+	return 0;
+
+fail_host:
+	if (instance->irq != NO_IRQ)
+		free_irq(instance->irq, instance);
+fail_irq:
+	NCR5380_exit(instance);
+	scsi_host_put(instance);
+fail_alloc:
+	if (udc_regs)
+		dvma_free(udc_regs);
+	iounmap(sun3_scsi_regp);
+	return error;
+}
+
+static int __exit sun3_scsi_remove(struct platform_device *pdev)
+{
+	struct Scsi_Host *instance = platform_get_drvdata(pdev);
+
+	scsi_remove_host(instance);
+	if (instance->irq != NO_IRQ)
+		free_irq(instance->irq, instance);
+	NCR5380_exit(instance);
+	scsi_host_put(instance);
+	if (udc_regs)
+		dvma_free(udc_regs);
+	iounmap(sun3_scsi_regp);
+	return 0;
+}
+
+static struct platform_driver sun3_scsi_driver = {
+	.remove = __exit_p(sun3_scsi_remove),
+	.driver = {
+		.name	= DRV_MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver_probe(sun3_scsi_driver, sun3_scsi_probe);
+
+MODULE_ALIAS("platform:" DRV_MODULE_NAME);
 MODULE_LICENSE("GPL");