From: viro@parcelfarce.linux.theplanet.co.uk

* starting to kill ppa_detect - we move the "probe a single port" logics
  into a separate function and shift scanning into ppa_driver_init().  Later
  that will give us a parport_driver ->attach().



---

 25-akpm/drivers/scsi/ppa.c |  269 ++++++++++++++++++---------------------------
 1 files changed, 112 insertions(+), 157 deletions(-)

diff -puN drivers/scsi/ppa.c~PPA4-ppa_probe-RC1 drivers/scsi/ppa.c
--- 25/drivers/scsi/ppa.c~PPA4-ppa_probe-RC1	Wed Jan 14 13:35:48 2004
+++ 25-akpm/drivers/scsi/ppa.c	Wed Jan 14 13:35:48 2004
@@ -26,7 +26,6 @@ typedef struct {
 	struct pardevice *dev;	/* Parport device entry         */
 	int base;		/* Actual port address          */
 	int mode;		/* Transfer mode                */
-	int host;		/* Host number (for proc)       */
 	Scsi_Cmnd *cur_cmd;	/* Current queued command       */
 	struct work_struct ppa_tq;	/* Polling interrupt stuff       */
 	unsigned long jstart;	/* Jiffies at start             */
@@ -35,19 +34,10 @@ typedef struct {
 	unsigned int p_busy:1;	/* Parport sharing busy flag    */
 } ppa_struct;
 
-#define PPA_EMPTY	\
-{	.base		= -1,		\
-	.mode		= PPA_AUTODETECT,	\
-	.host		= -1,		\
-	.ppa_tq		= { .func = ppa_interrupt },	\
-	.recon_tmo      = PPA_RECON_TMO,	\
-}
-
 #include  "ppa.h"
 
 #define NO_HOSTS 4
-static ppa_struct ppa_hosts[NO_HOSTS] =
-    { PPA_EMPTY, PPA_EMPTY, PPA_EMPTY, PPA_EMPTY };
+static ppa_struct ppa_hosts[NO_HOSTS];
 
 static inline ppa_struct *ppa_dev(struct Scsi_Host *host)
 {
@@ -95,135 +85,108 @@ static inline void ppa_pb_release(ppa_st
 /*
  * Start of Chipset kludges
  */
+static Scsi_Host_Template ppa_template;
 
-static int ppa_detect(Scsi_Host_Template *host)
+static int ppa_probe(ppa_struct *dev, struct parport *pb)
 {
-	struct Scsi_Host *hreg = NULL;
+	struct Scsi_Host *host;
 	int ports;
-	int i, nhosts, try_again;
-	struct parport *pb;
-
-	/*
-	 * unlock to allow the lowlevel parport driver to probe
-	 * the irqs
-	 */
-	pb = parport_enumerate();
+	int err;
+	int modes, ppb, ppb_hi;
 
-	printk("ppa: Version %s\n", PPA_VERSION);
-	nhosts = 0;
-	try_again = 0;
-
-	if (!pb) {
-		printk("ppa: parport reports no devices.\n");
-		return 0;
-	}
-      retry_entry:
-	for (i = 0; pb; i++, pb = pb->next) {
-		int modes, ppb, ppb_hi;
-		ppa_struct *dev = &ppa_hosts[i];
-
-		dev->dev =
-		    parport_register_device(pb, "ppa", NULL, ppa_wakeup,
+	dev->base = -1;
+	dev->mode = PPA_AUTODETECT;
+	dev->recon_tmo = PPA_RECON_TMO;
+	dev->dev = parport_register_device(pb, "ppa", NULL, ppa_wakeup,
 					    NULL, 0, dev);
 
-		if (!dev->dev)
-			continue;
+	if (!dev->dev)
+		return -ENOMEM;
 
-		/* Claim the bus so it remembers what we do to the control
-		 * registers. [ CTR and ECP ]
-		 */
-		if (ppa_pb_claim(dev)) {
-			unsigned long now = jiffies;
-			while (dev->p_busy) {
-				schedule();	/* We are safe to schedule here */
-				if (time_after(jiffies, now + 3 * HZ)) {
-					printk(KERN_ERR
-					       "ppa%d: failed to claim parport because a "
-					       "pardevice is owning the port for too longtime!\n",
-					       i);
-					parport_unregister_device(dev->dev);
-					spin_lock_irq(dev->cur_cmd->
-						      device->host->host_lock);
-					return 0;
-				}
+	/* Claim the bus so it remembers what we do to the control
+	 * registers. [ CTR and ECP ]
+	 */
+	err = -EBUSY;
+	if (ppa_pb_claim(dev)) {
+		unsigned long now = jiffies;
+		while (dev->p_busy) {
+			schedule();	/* We are safe to schedule here */
+			if (time_after(jiffies, now + 3 * HZ)) {
+				printk(KERN_ERR
+				       "ppa%d: failed to claim parport because a "
+				       "pardevice is owning the port for too longtime!\n",
+				       dev - ppa_hosts);
+				goto out;
 			}
 		}
-		ppb = dev->base = dev->dev->port->base;
-		ppb_hi = dev->dev->port->base_hi;
-		w_ctr(ppb, 0x0c);
-		modes = dev->dev->port->modes;
+	}
+	ppb = dev->base = dev->dev->port->base;
+	ppb_hi = dev->dev->port->base_hi;
+	w_ctr(ppb, 0x0c);
+	modes = dev->dev->port->modes;
 
-		/* Mode detection works up the chain of speed
-		 * This avoids a nasty if-then-else-if-... tree
-		 */
-		dev->mode = PPA_NIBBLE;
+	/* Mode detection works up the chain of speed
+	 * This avoids a nasty if-then-else-if-... tree
+	 */
+	dev->mode = PPA_NIBBLE;
 
-		if (modes & PARPORT_MODE_TRISTATE)
-			dev->mode = PPA_PS2;
+	if (modes & PARPORT_MODE_TRISTATE)
+		dev->mode = PPA_PS2;
 
-		if (modes & PARPORT_MODE_ECP) {
-			w_ecr(ppb_hi, 0x20);
-			dev->mode = PPA_PS2;
-		}
-		if ((modes & PARPORT_MODE_EPP) && (modes & PARPORT_MODE_ECP))
-			w_ecr(ppb_hi, 0x80);
+	if (modes & PARPORT_MODE_ECP) {
+		w_ecr(ppb_hi, 0x20);
+		dev->mode = PPA_PS2;
+	}
+	if ((modes & PARPORT_MODE_EPP) && (modes & PARPORT_MODE_ECP))
+		w_ecr(ppb_hi, 0x80);
 
-		/* Done configuration */
+	/* Done configuration */
 
-		if (ppa_init(dev)) {
-			ppa_pb_release(dev);
-			parport_unregister_device(dev->dev);
-			continue;
-		}
-		ppa_pb_release(dev);
-		/* now the glue ... */
-		switch (dev->mode) {
-		case PPA_NIBBLE:
-			ports = 3;
-			break;
-		case PPA_PS2:
-			ports = 3;
-			break;
-		case PPA_EPP_8:
-		case PPA_EPP_16:
-		case PPA_EPP_32:
-			ports = 8;
-			break;
-		default:	/* Never gets here */
-			continue;
-		}
+	err = ppa_init(dev);
+	ppa_pb_release(dev);
 
-		INIT_WORK(&dev->ppa_tq, ppa_interrupt, dev);
+	if (err)
+		goto out;
 
-		hreg = scsi_host_alloc(host, 0);
-		if (hreg == NULL)
-			continue;
-		list_add_tail(&hreg->sht_legacy_list, &host->legacy_hosts);
-		hreg->io_port = pb->base;
-		hreg->n_io_port = ports;
-		hreg->dma_channel = -1;
-		hreg->unique_id = i;
-		dev->host = hreg->host_no;
-		nhosts++;
-	}
-	if (nhosts == 0) {
-		if (try_again == 1) {
-			printk("WARNING - no ppa compatible devices found.\n");
-			printk
-			    ("  As of 31/Aug/1998 Iomega started shipping parallel\n");
-			printk
-			    ("  port ZIP drives with a different interface which is\n");
-			printk
-			    ("  supported by the imm (ZIP Plus) driver. If the\n");
-			printk
-			    ("  cable is marked with \"AutoDetect\", this is what has\n");
-			printk("  happened.\n");
-			return 0;
-		}
-		try_again = 1;
-		goto retry_entry;
-	} else
-		return 1;	/* return number of hosts detected */
+	/* now the glue ... */
+	switch (dev->mode) {
+	case PPA_NIBBLE:
+		ports = 3;
+		break;
+	case PPA_PS2:
+		ports = 3;
+		break;
+	case PPA_EPP_8:
+	case PPA_EPP_16:
+	case PPA_EPP_32:
+		ports = 8;
+		break;
+	default:	/* Never gets here */
+		BUG();
+	}
+
+	INIT_WORK(&dev->ppa_tq, ppa_interrupt, dev);
+
+	err = -ENOMEM;
+	host = scsi_host_alloc(&ppa_template, 0);
+	if (!host)
+		goto out;
+	list_add_tail(&host->sht_legacy_list, &ppa_template.legacy_hosts);
+	host->io_port = pb->base;
+	host->n_io_port = ports;
+	host->dma_channel = -1;
+	host->unique_id = dev - ppa_hosts;
+	err = scsi_add_host(host, NULL);
+	if (err)
+		goto out1;
+	scsi_scan_host(host);
+	return 0;
+out1:
+	list_del(&host->sht_legacy_list);
+	scsi_host_put(host);
+out:
+	parport_unregister_device(dev->dev);
+	return err;
 }
 
 /* This is to give the ppa driver a way to modify the timings (and other
@@ -616,10 +579,10 @@ static int ppa_init(ppa_struct *dev)
 	ppa_disconnect(dev);
 	udelay(1000);		/* Another delay to allow devices to settle */
 
-	if (!retv)
-		retv = device_check(dev);
+	if (retv)
+		return -EIO;
 
-	return retv;
+	return device_check(dev);
 }
 
 static inline int ppa_send_command(Scsi_Cmnd *cmd)
@@ -1061,9 +1024,7 @@ static int device_check(ppa_struct *dev)
 				dev->mode = old_mode;
 				goto second_pass;
 			}
-			printk
-			    ("ppa: Unable to establish communication, aborting driver load.\n");
-			return 1;
+			return -EIO;
 		}
 		w_ctr(ppb, 0x0c);
 		k = 1000000;	/* 1 Second */
@@ -1086,9 +1047,7 @@ static int device_check(ppa_struct *dev)
 				dev->mode = old_mode;
 				goto second_pass;
 			}
-			printk
-			    ("ppa: Unable to establish communication, aborting driver load.\n");
-			return 1;
+			return -EIO;
 		}
 		ppa_disconnect(dev);
 		printk("ppa: Communication established with ID %i using %s\n",
@@ -1100,8 +1059,7 @@ static int device_check(ppa_struct *dev)
 		udelay(1000);
 		return 0;
 	}
-	printk("ppa: No devices found, aborting driver load.\n");
-	return 1;
+	return -ENODEV;
 }
 
 static Scsi_Host_Template ppa_template = {
@@ -1123,29 +1081,26 @@ static Scsi_Host_Template ppa_template =
 
 static int __init ppa_driver_init(void)
 {
-	struct scsi_host_template *sht = &ppa_template;
-	struct Scsi_Host *shost;
-	struct list_head *l;
-	int error;
-
-	INIT_LIST_HEAD(&sht->legacy_hosts);
-
-	ppa_detect(sht);
-	if (list_empty(&sht->legacy_hosts))
-		return -ENODEV;
-
-	list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) {
-		error = scsi_add_host(shost, NULL);
-		if (error)
-			goto fail;
-		scsi_scan_host(shost);
+	struct parport *pb = parport_enumerate();
+	int i, nhosts;
+
+	INIT_LIST_HEAD(&ppa_template.legacy_hosts);
+
+	printk("ppa: Version %s\n", PPA_VERSION);
+	nhosts = 0;
+
+	if (!pb) {
+		printk("ppa: parport reports no devices.\n");
+		return 0;
 	}
-	return 0;
- fail:
-	l = &shost->sht_legacy_list;
-	while ((l = l->prev) != &sht->legacy_hosts)
-		scsi_remove_host(list_entry(l, struct Scsi_Host, sht_legacy_list));
-	return error;
+
+	for (i = 0; pb; i++, pb = pb->next) {
+		ppa_struct *dev = &ppa_hosts[i];
+		if (ppa_probe(dev, pb))
+			nhosts++;
+	}
+
+	return nhosts ? 0 : -ENODEV;
 }
 
 static void __exit ppa_driver_exit(void)

_