Commit 9234c5a2 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] scsi/imm.c cleanup and fixes (5/8)

	* starting to kill imm_detect - we move the "probe a single port"
logics into a separate function and shift scanning into imm_driver_init().
Later that will give us a parport_driver ->attach().
parent f7d83e8b
...@@ -100,112 +100,98 @@ static inline void imm_pb_release(imm_struct *dev) ...@@ -100,112 +100,98 @@ static inline void imm_pb_release(imm_struct *dev)
* Parallel port probing routines * * Parallel port probing routines *
***************************************************************************/ ***************************************************************************/
static int imm_detect(Scsi_Host_Template * host) static Scsi_Host_Template imm_template;
static int imm_probe(imm_struct *dev, struct parport *pb)
{ {
struct Scsi_Host *hreg; struct Scsi_Host *host;
int ports; int ports;
int i, nhosts, try_again; int modes, ppb;
struct parport *pb; int err;
pb = parport_enumerate(); dev->dev = parport_register_device(pb, "imm", NULL, imm_wakeup,
NULL, 0, dev);
printk("imm: Version %s\n", IMM_VERSION); if (!dev->dev)
nhosts = 0; return -ENOMEM;
try_again = 0;
if (!pb) { /* Claim the bus so it remembers what we do to the control
printk("imm: parport reports no devices.\n"); * registers. [ CTR and ECP ]
return 0; */
err = -EBUSY;
if (imm_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
"imm%d: failed to claim parport because a "
"pardevice is owning the port for too longtime!\n",
dev - imm_hosts);
goto out;
}
}
} }
retry_entry: ppb = dev->base = dev->dev->port->base;
for (i = 0; pb; i++, pb = pb->next) { dev->base_hi = dev->dev->port->base_hi;
imm_struct *dev = &imm_hosts[i]; w_ctr(ppb, 0x0c);
int modes, ppb; modes = dev->dev->port->modes;
dev->dev = /* Mode detection works up the chain of speed
parport_register_device(pb, "imm", NULL, imm_wakeup, * This avoids a nasty if-then-else-if-... tree
NULL, 0, dev); */
dev->mode = IMM_NIBBLE;
if (!dev->dev) if (modes & PARPORT_MODE_TRISTATE)
continue; dev->mode = IMM_PS2;
/* Claim the bus so it remembers what we do to the control /* Done configuration */
* registers. [ CTR and ECP ]
*/
if (imm_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
"imm%d: failed to claim parport because a "
"pardevice is owning the port for too longtime!\n",
i);
parport_unregister_device(dev->dev);
return 0;
}
}
}
ppb = dev->base = dev->dev->port->base;
dev->base_hi = dev->dev->port->base_hi;
w_ctr(ppb, 0x0c);
modes = dev->dev->port->modes;
/* Mode detection works up the chain of speed err = imm_init(dev);
* This avoids a nasty if-then-else-if-... tree
*/
dev->mode = IMM_NIBBLE;
if (modes & PARPORT_MODE_TRISTATE) imm_pb_release(dev);
dev->mode = IMM_PS2;
/* Done configuration */ if (err)
goto out;
if (imm_init(dev)) { /* now the glue ... */
imm_pb_release(dev); switch (dev->mode) {
parport_unregister_device(dev->dev); case IMM_NIBBLE:
continue; case IMM_PS2:
} ports = 3;
imm_pb_release(dev); break;
case IMM_EPP_8:
case IMM_EPP_16:
case IMM_EPP_32:
ports = 8;
break;
default: /* Never gets here */
BUG();
}
/* now the glue ... */ INIT_WORK(&dev->imm_tq, imm_interrupt, dev);
switch (dev->mode) {
case IMM_NIBBLE:
ports = 3;
break;
case IMM_PS2:
ports = 3;
break;
case IMM_EPP_8:
case IMM_EPP_16:
case IMM_EPP_32:
ports = 8;
break;
default: /* Never gets here */
continue;
}
INIT_WORK(&dev->imm_tq, imm_interrupt, dev); err = -ENOMEM;
host = scsi_host_alloc(&imm_template, 0);
if (!host)
goto out;
list_add_tail(&host->sht_legacy_list, &imm_template.legacy_hosts);
host->io_port = pb->base;
host->n_io_port = ports;
host->dma_channel = -1;
host->unique_id = dev - imm_hosts;
err = scsi_add_host(host, NULL);
if (err)
goto out1;
scsi_scan_host(host);
return 0;
hreg = scsi_host_alloc(host, 0); out1:
if (hreg == NULL) list_del(&host->sht_legacy_list);
continue; scsi_host_put(host);
list_add_tail(&hreg->sht_legacy_list, &host->legacy_hosts); out:
hreg->io_port = pb->base; parport_unregister_device(dev->dev);
hreg->n_io_port = ports; return err;
hreg->dma_channel = -1;
hreg->unique_id = i;
nhosts++;
}
if (nhosts == 0) {
if (try_again == 1) {
return 0;
}
try_again = 1;
goto retry_entry;
} else {
return 1; /* return number of hosts detected */
}
} }
/* This is to give the imm driver a way to modify the timings (and other /* This is to give the imm driver a way to modify the timings (and other
...@@ -700,7 +686,7 @@ static int imm_select(imm_struct *dev, int target) ...@@ -700,7 +686,7 @@ static int imm_select(imm_struct *dev, int target)
static int imm_init(imm_struct *dev) static int imm_init(imm_struct *dev)
{ {
if (imm_connect(dev, 0) != 1) if (imm_connect(dev, 0) != 1)
return 1; return -EIO;
imm_reset_pulse(dev->base); imm_reset_pulse(dev->base);
udelay(1000); /* Delay to allow devices to settle */ udelay(1000); /* Delay to allow devices to settle */
imm_disconnect(dev); imm_disconnect(dev);
...@@ -1165,9 +1151,8 @@ static int device_check(imm_struct *dev) ...@@ -1165,9 +1151,8 @@ static int device_check(imm_struct *dev)
dev->mode = old_mode; dev->mode = old_mode;
goto second_pass; goto second_pass;
} }
printk printk("imm: Unable to establish communication\n");
("imm: Unable to establish communication, aborting driver load.\n"); return -EIO;
return 1;
} }
w_ctr(ppb, 0x0c); w_ctr(ppb, 0x0c);
...@@ -1192,8 +1177,8 @@ static int device_check(imm_struct *dev) ...@@ -1192,8 +1177,8 @@ static int device_check(imm_struct *dev)
goto second_pass; goto second_pass;
} }
printk printk
("imm: Unable to establish communication, aborting driver load.\n"); ("imm: Unable to establish communication\n");
return 1; return -EIO;
} }
imm_disconnect(dev); imm_disconnect(dev);
printk printk
...@@ -1206,11 +1191,11 @@ static int device_check(imm_struct *dev) ...@@ -1206,11 +1191,11 @@ static int device_check(imm_struct *dev)
udelay(1000); udelay(1000);
return 0; return 0;
} }
printk("imm: No devices found, aborting driver load.\n"); printk("imm: No devices found\n");
return 1; return -ENODEV;
} }
static Scsi_Host_Template driver_template = { static Scsi_Host_Template imm_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.proc_name = "imm", .proc_name = "imm",
.proc_info = imm_proc_info, .proc_info = imm_proc_info,
...@@ -1229,34 +1214,24 @@ static Scsi_Host_Template driver_template = { ...@@ -1229,34 +1214,24 @@ static Scsi_Host_Template driver_template = {
static int __init imm_driver_init(void) static int __init imm_driver_init(void)
{ {
struct scsi_host_template *sht = &driver_template; struct parport *pb = parport_enumerate();
struct Scsi_Host *shost; int i, nhosts;
struct list_head *l;
int error; INIT_LIST_HEAD(&imm_template.legacy_hosts);
INIT_LIST_HEAD(&sht->legacy_hosts); printk("imm: Version %s\n", IMM_VERSION);
imm_detect(sht); for (i = 0, nhosts = 0; pb; i++, pb = pb->next) {
if (list_empty(&sht->legacy_hosts)) imm_struct *dev = &imm_hosts[i];
return -ENODEV; if (imm_probe(dev, pb) == 0)
nhosts++;
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);
} }
return 0; return nhosts ? 0 : -ENODEV;
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;
} }
static void __exit imm_driver_exit(void) static void __exit imm_driver_exit(void)
{ {
struct scsi_host_template *sht = &driver_template; struct scsi_host_template *sht = &imm_template;
struct Scsi_Host *host, *s; struct Scsi_Host *host, *s;
list_for_each_entry(host, &sht->legacy_hosts, sht_legacy_list) list_for_each_entry(host, &sht->legacy_hosts, sht_legacy_list)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment