]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] scsi/imm.c cleanup and fixes (8/8)
authorAlexander Viro <viro@www.linux.org.uk>
Thu, 5 Feb 2004 01:43:11 +0000 (17:43 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Thu, 5 Feb 2004 01:43:11 +0000 (17:43 -0800)
* switched to proper parport_driver.

drivers/scsi/imm.c
drivers/scsi/imm.h

index c5e83f978eccab7e0beff113622ae718b34293e9..8b290ea429cf57b4ec662b26eea7c1b835c7e514 100644 (file)
@@ -44,14 +44,13 @@ typedef struct {
        unsigned wanted:1;      /* Parport sharing busy flag    */
        wait_queue_head_t *waiting;
        struct Scsi_Host *host;
+       struct list_head list;
 } imm_struct;
 
 static void imm_reset_pulse(unsigned int base);
 static int device_check(imm_struct *dev);
 
 #include "imm.h"
-#define NO_HOSTS 4
-static imm_struct imm_hosts[NO_HOSTS];
 
 static inline imm_struct *imm_dev(struct Scsi_Host *host)
 {
@@ -114,117 +113,6 @@ static inline void imm_pb_release(imm_struct *dev)
        parport_release(dev->dev);
 }
 
-/***************************************************************************
- *                   Parallel port probing routines                        *
- ***************************************************************************/
-
-static Scsi_Host_Template imm_template;
-
-static int imm_probe(imm_struct *dev, struct parport *pb)
-{
-       struct Scsi_Host *host;
-       DECLARE_WAIT_QUEUE_HEAD(waiting);
-       DEFINE_WAIT(wait);
-       int ports;
-       int modes, ppb;
-       int err;
-
-       init_waitqueue_head(&waiting);
-
-       memset(dev, 0, sizeof(dev));
-
-       dev->base = -1;
-       dev->mode = IMM_AUTODETECT;
-
-       dev->dev = parport_register_device(pb, "imm", NULL, imm_wakeup,
-                                               NULL, 0, dev);
-
-       if (!dev->dev)
-               return -ENOMEM;
-
-       /* Claim the bus so it remembers what we do to the control
-        * registers. [ CTR and ECP ]
-        */
-       err = -EBUSY;
-       dev->waiting = &waiting;
-       prepare_to_wait(&waiting, &wait, TASK_UNINTERRUPTIBLE);
-       if (imm_pb_claim(dev))
-               schedule_timeout(3 * HZ);
-       if (dev->wanted) {
-               printk(KERN_ERR "imm%d: failed to claim parport because "
-                       "a pardevice is owning the port for too long "
-                       "time!\n", dev - imm_hosts);
-               imm_pb_dismiss(dev);
-               dev->waiting = NULL;
-               finish_wait(&waiting, &wait);
-               goto out;
-       }
-       dev->waiting = NULL;
-       finish_wait(&waiting, &wait);
-       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
-        * This avoids a nasty if-then-else-if-... tree
-        */
-       dev->mode = IMM_NIBBLE;
-
-       if (modes & PARPORT_MODE_TRISTATE)
-               dev->mode = IMM_PS2;
-
-       /* Done configuration */
-
-       err = imm_init(dev);
-
-       imm_pb_release(dev);
-
-       if (err)
-               goto out;
-
-       /* now the glue ... */
-       switch (dev->mode) {
-       case IMM_NIBBLE:
-       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 */
-               BUG();
-       }
-
-       INIT_WORK(&dev->imm_tq, imm_interrupt, dev);
-
-       err = -ENOMEM;
-       host = scsi_host_alloc(&imm_template, sizeof(imm_struct *));
-       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;
-       *(imm_struct **)&host->hostdata = dev;
-       dev->host = host;
-       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 imm driver a way to modify the timings (and other
  * parameters) by writing to the /proc/scsi/imm/0 file.
  * Very simple method really... (Too simple, no error checking :( )
@@ -1243,38 +1131,163 @@ static Scsi_Host_Template imm_template = {
        .can_queue              = 1,
 };
 
-static int __init imm_driver_init(void)
+/***************************************************************************
+ *                   Parallel port probing routines                        *
+ ***************************************************************************/
+
+static LIST_HEAD(imm_hosts);
+
+static int __imm_attach(struct parport *pb)
 {
-       struct parport *pb = parport_enumerate();
-       int i, nhosts;
+       struct Scsi_Host *host;
+       imm_struct *dev;
+       DECLARE_WAIT_QUEUE_HEAD(waiting);
+       DEFINE_WAIT(wait);
+       int ports;
+       int modes, ppb;
+       int err = -ENOMEM;
 
-       INIT_LIST_HEAD(&imm_template.legacy_hosts);
+       init_waitqueue_head(&waiting);
 
-       printk("imm: Version %s\n", IMM_VERSION);
+       dev = kmalloc(sizeof(imm_struct), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       memset(dev, 0, sizeof(dev));
+
+       dev->base = -1;
+       dev->mode = IMM_AUTODETECT;
+       INIT_LIST_HEAD(&dev->list);
+
+       dev->dev = parport_register_device(pb, "imm", NULL, imm_wakeup,
+                                               NULL, 0, dev);
+
+       if (!dev->dev)
+               goto out;
+
+
+       /* Claim the bus so it remembers what we do to the control
+        * registers. [ CTR and ECP ]
+        */
+       err = -EBUSY;
+       dev->waiting = &waiting;
+       prepare_to_wait(&waiting, &wait, TASK_UNINTERRUPTIBLE);
+       if (imm_pb_claim(dev))
+               schedule_timeout(3 * HZ);
+       if (dev->wanted) {
+               printk(KERN_ERR "imm%d: failed to claim parport because "
+                       "a pardevice is owning the port for too long "
+                       "time!\n", pb->number);
+               imm_pb_dismiss(dev);
+               dev->waiting = NULL;
+               finish_wait(&waiting, &wait);
+               goto out1;
+       }
+       dev->waiting = NULL;
+       finish_wait(&waiting, &wait);
+       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
+        * This avoids a nasty if-then-else-if-... tree
+        */
+       dev->mode = IMM_NIBBLE;
+
+       if (modes & PARPORT_MODE_TRISTATE)
+               dev->mode = IMM_PS2;
+
+       /* Done configuration */
+
+       err = imm_init(dev);
+
+       imm_pb_release(dev);
+
+       if (err)
+               goto out1;
 
-       for (i = 0, nhosts = 0; pb; i++, pb = pb->next) {
-               imm_struct *dev = &imm_hosts[i];
-               if (imm_probe(dev, pb) == 0)
-                       nhosts++;
+       /* now the glue ... */
+       switch (dev->mode) {
+       case IMM_NIBBLE:
+       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 */
+               BUG();
        }
-       return nhosts ? 0 : -ENODEV;
+
+       INIT_WORK(&dev->imm_tq, imm_interrupt, dev);
+
+       err = -ENOMEM;
+       host = scsi_host_alloc(&imm_template, sizeof(imm_struct *));
+       if (!host)
+               goto out1;
+       host->io_port = pb->base;
+       host->n_io_port = ports;
+       host->dma_channel = -1;
+       host->unique_id = pb->number;
+       *(imm_struct **)&host->hostdata = dev;
+       dev->host = host;
+       list_add_tail(&dev->list, &imm_hosts);
+       err = scsi_add_host(host, NULL);
+       if (err)
+               goto out2;
+       scsi_scan_host(host);
+       return 0;
+
+out2:
+       list_del_init(&dev->list);
+       scsi_host_put(host);
+out1:
+       parport_unregister_device(dev->dev);
+out:
+       kfree(dev);
+       return err;
 }
 
-static void __exit imm_driver_exit(void)
+static void imm_attach(struct parport *pb)
 {
-       struct scsi_host_template *sht = &imm_template;
-       struct Scsi_Host *host, *s;
-
-       list_for_each_entry(host, &sht->legacy_hosts, sht_legacy_list)
-               scsi_remove_host(host);
-       list_for_each_entry_safe(host, s, &sht->legacy_hosts, sht_legacy_list) {
-               imm_struct *dev = imm_dev(host);
-               list_del(&host->sht_legacy_list);
-               scsi_host_put(host);
-               parport_unregister_device(dev->dev);
+       __imm_attach(pb);
+}
+
+static void imm_detach(struct parport *pb)
+{
+       imm_struct *dev;
+       list_for_each_entry(dev, &imm_hosts, list) {
+               if (dev->dev->port == pb) {
+                       list_del_init(&dev->list);
+                       scsi_remove_host(dev->host);
+                       scsi_host_put(dev->host);
+                       parport_unregister_device(dev->dev);
+                       kfree(dev);
+                       break;
+               }
        }
 }
 
+static struct parport_driver imm_driver = {
+       .name   = "imm",
+       .attach = imm_attach,
+       .detach = imm_detach,
+};
+
+static int __init imm_driver_init(void)
+{
+       printk("imm: Version %s\n", IMM_VERSION);
+       return parport_register_driver(&imm_driver);
+}
+
+static void __exit imm_driver_exit(void)
+{
+       parport_unregister_driver(&imm_driver);
+}
+
 module_init(imm_driver_init);
 module_exit(imm_driver_exit);
 
index 3aa53ae27c07437f66279d6e1fd5ba6ef50ff2a4..434a57e5cb914f0dac6b2d5230952763fd00aee7 100644 (file)
@@ -140,7 +140,5 @@ static char *IMM_MODE_STRING[] =
 #endif
 
 static int imm_engine(imm_struct *, Scsi_Cmnd *);
-static int imm_init(imm_struct *);
-static void imm_interrupt(void *);
 
 #endif                         /* _IMM_H */