fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / scsi / esp.c
index 3bbfba0..2c2fe80 100644 (file)
@@ -1,7 +1,6 @@
-/* $Id: esp.c,v 1.101 2002/01/15 06:48:55 davem Exp $
- * esp.c:  EnhancedScsiProcessor Sun SCSI driver code.
+/* esp.c: ESP Sun SCSI driver.
  *
- * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 1998, 2006 David S. Miller (davem@davemloft.net)
  */
 
 /* TODO:
@@ -13,7 +12,6 @@
  * 3) Add tagged queueing.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -25,9 +23,8 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
-#include "scsi.h"
-#include "hosts.h"
 #include "esp.h"
 
 #include <asm/sbus.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-
 #ifndef __sparc_v9__
 #include <asm/machines.h>
 #include <asm/idprom.h>
 #endif
 
-#include <linux/module.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+#define DRV_VERSION "1.101"
 
 #define DEBUG_ESP
 /* #define DEBUG_ESP_HME */
@@ -180,13 +183,8 @@ enum {
 /*5*/  do_intr_end
 };
 
-/* The master ring of all esp hosts we are managing in this driver. */
-static struct esp *espchain;
-static spinlock_t espchain_lock = SPIN_LOCK_UNLOCKED;
-static int esps_running = 0;
-
 /* Forward declarations. */
-static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+static irqreturn_t esp_intr(int irq, void *dev_id);
 
 /* Debugging routines */
 struct esp_cmdstrings {
@@ -366,7 +364,7 @@ static char *phase_string(int phase)
 }
 
 #ifdef DEBUG_STATE_MACHINE
-static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
+static inline void esp_advance_phase(struct scsi_cmnd *s, int newphase)
 {
        ESPLOG(("<%s>", phase_string(newphase)));
        s->SCp.sent_command = s->SCp.phase;
@@ -419,48 +417,48 @@ static inline void esp_cmd(struct esp *esp, u8 cmd)
  * Note that these are per-ESP queues, not global queues like
  * the aha152x driver uses.
  */
-static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void append_SC(struct scsi_cmnd **SC, struct scsi_cmnd *new_SC)
 {
-       Scsi_Cmnd *end;
+       struct scsi_cmnd *end;
 
        new_SC->host_scribble = (unsigned char *) NULL;
        if (!*SC)
                *SC = new_SC;
        else {
-               for (end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble)
+               for (end=*SC;end->host_scribble;end=(struct scsi_cmnd *)end->host_scribble)
                        ;
                end->host_scribble = (unsigned char *) new_SC;
        }
 }
 
-static inline void prepend_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void prepend_SC(struct scsi_cmnd **SC, struct scsi_cmnd *new_SC)
 {
        new_SC->host_scribble = (unsigned char *) *SC;
        *SC = new_SC;
 }
 
-static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
+static inline struct scsi_cmnd *remove_first_SC(struct scsi_cmnd **SC)
 {
-       Scsi_Cmnd *ptr;
+       struct scsi_cmnd *ptr;
        ptr = *SC;
        if (ptr)
-               *SC = (Scsi_Cmnd *) (*SC)->host_scribble;
+               *SC = (struct scsi_cmnd *) (*SC)->host_scribble;
        return ptr;
 }
 
-static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
+static inline struct scsi_cmnd *remove_SC(struct scsi_cmnd **SC, int target, int lun)
 {
-       Scsi_Cmnd *ptr, *prev;
+       struct scsi_cmnd *ptr, *prev;
 
        for (ptr = *SC, prev = NULL;
             ptr && ((ptr->device->id != target) || (ptr->device->lun != lun));
-            prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
+            prev = ptr, ptr = (struct scsi_cmnd *) ptr->host_scribble)
                ;
        if (ptr) {
                if (prev)
                        prev->host_scribble=ptr->host_scribble;
                else
-                       *SC=(Scsi_Cmnd *)ptr->host_scribble;
+                       *SC=(struct scsi_cmnd *)ptr->host_scribble;
        }
        return ptr;
 }
@@ -689,36 +687,6 @@ static void __init esp_bootup_reset(struct esp *esp)
        sbus_readb(esp->eregs + ESP_INTRPT);
 }
 
-static void esp_chain_add(struct esp *esp)
-{
-       spin_lock_irq(&espchain_lock);
-       if (espchain) {
-               struct esp *elink = espchain;
-               while (elink->next)
-                       elink = elink->next;
-               elink->next = esp;
-       } else {
-               espchain = esp;
-       }
-       esp->next = NULL;
-       spin_unlock_irq(&espchain_lock);
-}
-
-static void esp_chain_del(struct esp *esp)
-{
-       spin_lock_irq(&espchain_lock);
-       if (espchain == esp) {
-               espchain = esp->next;
-       } else {
-               struct esp *elink = espchain;
-               while (elink->next != esp)
-                       elink = elink->next;
-               elink->next = esp->next;
-       }
-       esp->next = NULL;
-       spin_unlock_irq(&espchain_lock);
-}
-
 static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev)
 {
        struct sbus_dev *sdev = esp->sdev;
@@ -810,14 +778,14 @@ static int __init esp_register_irq(struct esp *esp)
         * sanely maintain.
         */
        if (request_irq(esp->ehost->irq, esp_intr,
-                       SA_SHIRQ, "ESP SCSI", esp)) {
+                       IRQF_SHARED, "ESP SCSI", esp)) {
                printk("esp%d: Cannot acquire irq line\n",
                       esp->esp_id);
                return -1;
        }
 
-       printk("esp%d: IRQ %s ", esp->esp_id,
-              __irq_itoa(esp->ehost->irq));
+       printk("esp%d: IRQ %d ", esp->esp_id,
+              esp->ehost->irq);
 
        return 0;
 }
@@ -825,19 +793,20 @@ static int __init esp_register_irq(struct esp *esp)
 static void __init esp_get_scsi_id(struct esp *esp)
 {
        struct sbus_dev *sdev = esp->sdev;
+       struct device_node *dp = sdev->ofdev.node;
 
-       esp->scsi_id = prom_getintdefault(esp->prom_node,
-                                         "initiator-id",
-                                         -1);
+       esp->scsi_id = of_getintprop_default(dp,
+                                            "initiator-id",
+                                            -1);
        if (esp->scsi_id == -1)
-               esp->scsi_id = prom_getintdefault(esp->prom_node,
-                                                 "scsi-initiator-id",
-                                                 -1);
+               esp->scsi_id = of_getintprop_default(dp,
+                                                    "scsi-initiator-id",
+                                                    -1);
        if (esp->scsi_id == -1)
                esp->scsi_id = (sdev->bus == NULL) ? 7 :
-                       prom_getintdefault(sdev->bus->prom_node,
-                                          "scsi-initiator-id",
-                                          7);
+                       of_getintprop_default(sdev->bus->ofdev.node,
+                                             "scsi-initiator-id",
+                                             7);
        esp->ehost->this_id = esp->scsi_id;
        esp->scsi_id_mask = (1 << esp->scsi_id);
 
@@ -1062,28 +1031,30 @@ static void __init esp_init_swstate(struct esp *esp)
        esp->prev_hme_dmacsr = 0xffffffff;
 }
 
-static int __init detect_one_esp(Scsi_Host_Template *tpnt, struct sbus_dev *esp_dev,
-                                struct sbus_dev *espdma, struct sbus_bus *sbus,
-                                int id, int hme)
+static int __init detect_one_esp(struct scsi_host_template *tpnt,
+                                struct device *dev,
+                                struct sbus_dev *esp_dev,
+                                struct sbus_dev *espdma,
+                                struct sbus_bus *sbus,
+                                int hme)
 {
-       struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp));
+       static int instance;
+       struct Scsi_Host *esp_host = scsi_host_alloc(tpnt, sizeof(struct esp));
        struct esp *esp;
        
-       if (!esp_host) {
-               printk("ESP: Cannot register SCSI host\n");
-               return -1;
-       }
+       if (!esp_host)
+               return -ENOMEM;
+
        if (hme)
                esp_host->max_id = 16;
        esp = (struct esp *) esp_host->hostdata;
        esp->ehost = esp_host;
        esp->sdev = esp_dev;
-       esp->esp_id = id;
+       esp->esp_id = instance;
        esp->prom_node = esp_dev->prom_node;
        prom_getstring(esp->prom_node, "name", esp->prom_name,
                       sizeof(esp->prom_name));
 
-       esp_chain_add(esp);
        if (esp_find_dvma(esp, espdma) < 0)
                goto fail_unlink;
        if (esp_map_regs(esp, hme) < 0) {
@@ -1110,8 +1081,19 @@ static int __init detect_one_esp(Scsi_Host_Template *tpnt, struct sbus_dev *esp_
 
        esp_bootup_reset(esp);
 
+       if (scsi_add_host(esp_host, dev))
+               goto fail_free_irq;
+
+       dev_set_drvdata(&esp_dev->ofdev.dev, esp);
+
+       scsi_scan_host(esp_host);
+       instance++;
+
        return 0;
 
+fail_free_irq:
+       free_irq(esp->ehost->irq, esp);
+
 fail_unmap_cmdarea:
        sbus_free_consistent(esp->sdev, 16,
                             (void *) esp->esp_command,
@@ -1124,119 +1106,99 @@ fail_dvma_release:
        esp->dma->allocated = 0;
 
 fail_unlink:
-       esp_chain_del(esp);
-       scsi_unregister(esp_host);
+       scsi_host_put(esp_host);
        return -1;
 }
 
 /* Detecting ESP chips on the machine.  This is the simple and easy
  * version.
  */
+static int __devexit esp_remove_common(struct esp *esp)
+{
+       unsigned int irq = esp->ehost->irq;
+
+       scsi_remove_host(esp->ehost);
+
+       ESP_INTSOFF(esp->dregs);
+#if 0
+       esp_reset_dma(esp);
+       esp_reset_esp(esp);
+#endif
+
+       free_irq(irq, esp);
+       sbus_free_consistent(esp->sdev, 16,
+                            (void *) esp->esp_command, esp->esp_command_dvma);
+       sbus_iounmap(esp->eregs, ESP_REG_SIZE);
+       esp->dma->allocated = 0;
+
+       scsi_host_put(esp->ehost);
+
+       return 0;
+}
+
 
 #ifdef CONFIG_SUN4
 
 #include <asm/sun4paddr.h>
 
-static int __init esp_detect(Scsi_Host_Template *tpnt)
-{
-       static struct sbus_dev esp_dev;
-       int esps_in_use = 0;
-
-       espchain = 0;
+static struct sbus_dev sun4_esp_dev;
 
+static int __init esp_sun4_probe(struct scsi_host_template *tpnt)
+{
        if (sun4_esp_physaddr) {
-               memset (&esp_dev, 0, sizeof(esp_dev));
-               esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
-               esp_dev.irqs[0] = 4;
-               esp_dev.resource[0].start = sun4_esp_physaddr;
-               esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1;
-               esp_dev.resource[0].flags = IORESOURCE_IO;
-
-               if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0))
-                       esps_in_use++;
-               printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use);
-               esps_running =  esps_in_use;
+               memset(&sun4_esp_dev, 0, sizeof(sun4_esp_dev));
+               sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
+               sun4_esp_dev.irqs[0] = 4;
+               sun4_esp_dev.resource[0].start = sun4_esp_physaddr;
+               sun4_esp_dev.resource[0].end =
+                       sun4_esp_physaddr + ESP_REG_SIZE - 1;
+               sun4_esp_dev.resource[0].flags = IORESOURCE_IO;
+
+               return detect_one_esp(tpnt, NULL,
+                                     &sun4_esp_dev, NULL, NULL, 0);
        }
-       return esps_in_use;
+       return 0;
 }
 
-#else /* !CONFIG_SUN4 */
-
-static int __init esp_detect(Scsi_Host_Template *tpnt)
+static int __devexit esp_sun4_remove(void)
 {
-       struct sbus_bus *sbus;
-       struct sbus_dev *esp_dev, *sbdev_iter;
-       int nesps = 0, esps_in_use = 0;
+       struct of_device *dev = &sun4_esp_dev.ofdev;
+       struct esp *esp = dev_get_drvdata(&dev->dev);
 
-       espchain = 0;
-       if (!sbus_root) {
-#ifdef CONFIG_PCI
-               return 0;
-#else
-               panic("No SBUS in esp_detect()");
-#endif
-       }
-       for_each_sbus(sbus) {
-               for_each_sbusdev(sbdev_iter, sbus) {
-                       struct sbus_dev *espdma = NULL;
-                       int hme = 0;
-
-                       /* Is it an esp sbus device? */
-                       esp_dev = sbdev_iter;
-                       if (strcmp(esp_dev->prom_name, "esp") &&
-                           strcmp(esp_dev->prom_name, "SUNW,esp")) {
-                               if (!strcmp(esp_dev->prom_name, "SUNW,fas")) {
-                                       hme = 1;
-                                       espdma = esp_dev;
-                               } else {
-                                       if (!esp_dev->child ||
-                                           (strcmp(esp_dev->prom_name, "espdma") &&
-                                            strcmp(esp_dev->prom_name, "dma")))
-                                               continue; /* nope... */
-                                       espdma = esp_dev;
-                                       esp_dev = esp_dev->child;
-                                       if (strcmp(esp_dev->prom_name, "esp") &&
-                                           strcmp(esp_dev->prom_name, "SUNW,esp"))
-                                               continue; /* how can this happen? */
-                               }
-                       }
-                       
-                       if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0)
-                               continue;
-                               
-                       esps_in_use++;
-               } /* for each sbusdev */
-       } /* for each sbus */
-       printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
-              esps_in_use);
-       esps_running = esps_in_use;
-       return esps_in_use;
+       return esp_remove_common(esp);
 }
 
-#endif /* !CONFIG_SUN4 */
+#else /* !CONFIG_SUN4 */
 
-/*
- */
-static int esp_release(struct Scsi_Host *host)
+static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match)
 {
-       struct esp *esp = (struct esp *) host->hostdata;
+       struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+       struct device_node *dp = dev->node;
+       struct sbus_dev *dma_sdev = NULL;
+       int hme = 0;
+
+       if (dp->parent &&
+           (!strcmp(dp->parent->name, "espdma") ||
+            !strcmp(dp->parent->name, "dma")))
+               dma_sdev = sdev->parent;
+       else if (!strcmp(dp->name, "SUNW,fas")) {
+               dma_sdev = sdev;
+               hme = 1;
+       }
 
-       ESP_INTSOFF(esp->dregs);
-#if 0
-       esp_reset_dma(esp);
-       esp_reset_esp(esp);
-#endif
+       return detect_one_esp(match->data, &dev->dev,
+                             sdev, dma_sdev, sdev->bus, hme);
+}
 
-       free_irq(esp->ehost->irq, esp);
-       sbus_free_consistent(esp->sdev, 16,
-                            (void *) esp->esp_command, esp->esp_command_dvma);
-       sbus_iounmap(esp->eregs, ESP_REG_SIZE);
-       esp->dma->allocated = 0;
-       esp_chain_del(esp);
+static int __devexit esp_sbus_remove(struct of_device *dev)
+{
+       struct esp *esp = dev_get_drvdata(&dev->dev);
 
-        return 0;
+       return esp_remove_common(esp);
 }
 
+#endif /* !CONFIG_SUN4 */
+
 /* The info function will return whatever useful
  * information the developer sees fit.  If not provided, then
  * the name field will be used instead.
@@ -1410,25 +1372,18 @@ static int esp_host_info(struct esp *esp, char *ptr, off_t offset, int len)
 static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
                         int length, int inout)
 {
-       struct esp *esp;
+       struct esp *esp = (struct esp *) host->hostdata;
 
        if (inout)
                return -EINVAL; /* not yet */
 
-       for_each_esp(esp) {
-               if (esp->ehost == host)
-                       break;
-       }
-       if (!esp)
-               return -EINVAL;
-
        if (start)
                *start = buffer;
 
        return esp_host_info(esp, buffer, offset, length);
 }
 
-static void esp_get_dmabufs(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
 {
        if (sp->use_sg == 0) {
                sp->SCp.this_residual = sp->request_bufflen;
@@ -1437,36 +1392,36 @@ static void esp_get_dmabufs(struct esp *esp, Scsi_Cmnd *sp)
                if (sp->request_bufflen) {
                        sp->SCp.have_data_in = sbus_map_single(esp->sdev, sp->SCp.buffer,
                                                               sp->SCp.this_residual,
-                                                              scsi_to_sbus_dma_dir(sp->sc_data_direction));
+                                                              sp->sc_data_direction);
                        sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.have_data_in);
                } else {
                        sp->SCp.ptr = NULL;
                }
        } else {
-               sp->SCp.buffer = (struct scatterlist *) sp->buffer;
+               sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
                sp->SCp.buffers_residual = sbus_map_sg(esp->sdev,
                                                       sp->SCp.buffer,
                                                       sp->use_sg,
-                                                      scsi_to_sbus_dma_dir(sp->sc_data_direction));
+                                                      sp->sc_data_direction);
                sp->SCp.this_residual = sg_dma_len(sp->SCp.buffer);
                sp->SCp.ptr = (char *) ((unsigned long)sg_dma_address(sp->SCp.buffer));
        }
 }
 
-static void esp_release_dmabufs(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_release_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
 {
        if (sp->use_sg) {
-               sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg,
-                             scsi_to_sbus_dma_dir(sp->sc_data_direction));
+               sbus_unmap_sg(esp->sdev, sp->request_buffer, sp->use_sg,
+                             sp->sc_data_direction);
        } else if (sp->request_bufflen) {
                sbus_unmap_single(esp->sdev,
                                  sp->SCp.have_data_in,
                                  sp->request_bufflen,
-                                 scsi_to_sbus_dma_dir(sp->sc_data_direction));
+                                 sp->sc_data_direction);
        }
 }
 
-static void esp_restore_pointers(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_restore_pointers(struct esp *esp, struct scsi_cmnd *sp)
 {
        struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
 
@@ -1476,7 +1431,7 @@ static void esp_restore_pointers(struct esp *esp, Scsi_Cmnd *sp)
        sp->SCp.buffers_residual = ep->saved_buffers_residual;
 }
 
-static void esp_save_pointers(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_save_pointers(struct esp *esp, struct scsi_cmnd *sp)
 {
        struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
 
@@ -1506,7 +1461,7 @@ static void esp_save_pointers(struct esp *esp, Scsi_Cmnd *sp)
  * case where we could see an interrupt is where we have disconnected
  * commands active and they are trying to reselect us.
  */
-static inline void esp_check_cmd(struct esp *esp, Scsi_Cmnd *sp)
+static inline void esp_check_cmd(struct esp *esp, struct scsi_cmnd *sp)
 {
        switch (sp->cmd_len) {
        case 6:
@@ -1557,8 +1512,8 @@ static inline void build_wide_nego_msg(struct esp *esp, int size)
 
 static void esp_exec_cmd(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr;
-       Scsi_Device *SDptr;
+       struct scsi_cmnd *SCptr;
+       struct scsi_device *SDptr;
        struct esp_device *esp_dev;
        volatile u8 *cmdp = esp->esp_command;
        u8 the_esp_command;
@@ -1834,7 +1789,7 @@ after_nego_msg_built:
 }
 
 /* Queue a SCSI command delivered from the mid-level Linux SCSI code. */
-static int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+static int esp_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
        struct esp *esp;
 
@@ -1871,7 +1826,7 @@ static int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 }
 
 /* Dump driver state. */
-static void esp_dump_cmd(Scsi_Cmnd *SCptr)
+static void esp_dump_cmd(struct scsi_cmnd *SCptr)
 {
        ESPLOG(("[tgt<%02x> lun<%02x> "
                "pphase<%s> cphase<%s>]",
@@ -1882,7 +1837,7 @@ static void esp_dump_cmd(Scsi_Cmnd *SCptr)
 
 static void esp_dump_state(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
 #ifdef DEBUG_ESP_CMDS
        int i;
 #endif
@@ -1921,13 +1876,13 @@ static void esp_dump_state(struct esp *esp)
        ESPLOG(("esp%d: disconnected ", esp->esp_id));
        while (SCptr) {
                esp_dump_cmd(SCptr);
-               SCptr = (Scsi_Cmnd *) SCptr->host_scribble;
+               SCptr = (struct scsi_cmnd *) SCptr->host_scribble;
        }
        ESPLOG(("\n"));
 }
 
 /* Abort a command.  The host_lock is acquired by caller. */
-static int esp_abort(Scsi_Cmnd *SCptr)
+static int esp_abort(struct scsi_cmnd *SCptr)
 {
        struct esp *esp = (struct esp *) SCptr->device->host->hostdata;
        int don;
@@ -1957,14 +1912,14 @@ static int esp_abort(Scsi_Cmnd *SCptr)
                ESP_INTSOFF(esp->dregs);
        }
        if (esp->issue_SC) {
-               Scsi_Cmnd **prev, *this;
+               struct scsi_cmnd **prev, *this;
                for (prev = (&esp->issue_SC), this = esp->issue_SC;
                     this != NULL;
-                    prev = (Scsi_Cmnd **) &(this->host_scribble),
-                            this = (Scsi_Cmnd *) this->host_scribble) {
+                    prev = (struct scsi_cmnd **) &(this->host_scribble),
+                            this = (struct scsi_cmnd *) this->host_scribble) {
 
                        if (this == SCptr) {
-                               *prev = (Scsi_Cmnd *) this->host_scribble;
+                               *prev = (struct scsi_cmnd *) this->host_scribble;
                                this->host_scribble = NULL;
 
                                esp_release_dmabufs(esp, this);
@@ -2010,7 +1965,7 @@ static int esp_abort(Scsi_Cmnd *SCptr)
  */
 static int esp_finish_reset(struct esp *esp)
 {
-       Scsi_Cmnd *sp = esp->current_SC;
+       struct scsi_cmnd *sp = esp->current_SC;
 
        /* Clean up currently executing command, if any. */
        if (sp != NULL) {
@@ -2059,25 +2014,23 @@ static int esp_do_resetbus(struct esp *esp)
  *
  * The host_lock is acquired by caller.
  */
-static int esp_reset(Scsi_Cmnd *SCptr)
+static int esp_reset(struct scsi_cmnd *SCptr)
 {
        struct esp *esp = (struct esp *) SCptr->device->host->hostdata;
 
+       spin_lock_irq(esp->ehost->host_lock);
        (void) esp_do_resetbus(esp);
-
        spin_unlock_irq(esp->ehost->host_lock);
 
        wait_event(esp->reset_queue, (esp->resetting_bus == 0));
 
-       spin_lock_irq(esp->ehost->host_lock);
-
        return SUCCESS;
 }
 
 /* Internal ESP done function. */
 static void esp_done(struct esp *esp, int error)
 {
-       Scsi_Cmnd *done_SC = esp->current_SC;
+       struct scsi_cmnd *done_SC = esp->current_SC;
 
        esp->current_SC = NULL;
 
@@ -2168,7 +2121,7 @@ static inline void hme_fifo_push(struct esp *esp, u8 *bytes, u8 count)
 /* We try to avoid some interrupts by jumping ahead and see if the ESP
  * has gotten far enough yet.  Hence the following.
  */
-static inline int skipahead1(struct esp *esp, Scsi_Cmnd *scp,
+static inline int skipahead1(struct esp *esp, struct scsi_cmnd *scp,
                             int prev_phase, int new_phase)
 {
        if (scp->SCp.sent_command != prev_phase)
@@ -2202,7 +2155,7 @@ static inline int skipahead1(struct esp *esp, Scsi_Cmnd *scp,
        return do_intr_end;
 }
 
-static inline int skipahead2(struct esp *esp, Scsi_Cmnd *scp,
+static inline int skipahead2(struct esp *esp, struct scsi_cmnd *scp,
                             int prev_phase1, int prev_phase2, int new_phase)
 {
        if (scp->SCp.sent_command != prev_phase1 &&
@@ -2318,7 +2271,7 @@ static inline void dma_flashclear(struct esp *esp)
        dma_invalidate(esp);
 }
 
-static int dma_can_transfer(struct esp *esp, Scsi_Cmnd *sp)
+static int dma_can_transfer(struct esp *esp, struct scsi_cmnd *sp)
 {
        __u32 base, end, sz;
 
@@ -2379,7 +2332,7 @@ static int dma_can_transfer(struct esp *esp, Scsi_Cmnd *sp)
  * tell the ESP to eat the extraneous byte so that we can proceed
  * to the next phase.
  */
-static int esp100_sync_hwbug(struct esp *esp, Scsi_Cmnd *sp, int fifocnt)
+static int esp100_sync_hwbug(struct esp *esp, struct scsi_cmnd *sp, int fifocnt)
 {
        /* Do not touch this piece of code. */
        if ((!(esp->erev == esp100)) ||
@@ -2479,7 +2432,7 @@ static inline int reconnect_lun(struct esp *esp)
 /* This puts the driver in a state where it can revitalize a command that
  * is being continued due to reselection.
  */
-static inline void esp_connect(struct esp *esp, Scsi_Cmnd *sp)
+static inline void esp_connect(struct esp *esp, struct scsi_cmnd *sp)
 {
        struct esp_device *esp_dev = sp->device->hostdata;
 
@@ -2502,13 +2455,13 @@ static inline void esp_connect(struct esp *esp, Scsi_Cmnd *sp)
 /* This will place the current working command back into the issue queue
  * if we are to receive a reselection amidst a selection attempt.
  */
-static inline void esp_reconnect(struct esp *esp, Scsi_Cmnd *sp)
+static inline void esp_reconnect(struct esp *esp, struct scsi_cmnd *sp)
 {
        if (!esp->disconnected_SC)
                ESPLOG(("esp%d: Weird, being reselected but disconnected "
                        "command queue is empty.\n", esp->esp_id));
        esp->snip = 0;
-       esp->current_SC = 0;
+       esp->current_SC = NULL;
        sp->SCp.phase = not_issued;
        append_SC(&esp->issue_SC, sp);
 }
@@ -2540,7 +2493,7 @@ static inline int esp_bytes_sent(struct esp *esp, int fifo_count)
        return rval - fifo_count;
 }
 
-static inline void advance_sg(Scsi_Cmnd *sp)
+static inline void advance_sg(struct scsi_cmnd *sp)
 {
        ++sp->SCp.buffer;
        --sp->SCp.buffers_residual;
@@ -2568,7 +2521,7 @@ static inline void advance_sg(Scsi_Cmnd *sp)
  */
 static int esp_do_data(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        int thisphase, hmuch;
 
        ESPDATA(("esp_do_data: "));
@@ -2619,7 +2572,7 @@ static int esp_do_data(struct esp *esp)
 /* See how successful the data transfer was. */
 static int esp_do_data_finale(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        struct esp_device *esp_dev = SCptr->device->hostdata;
        int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0;
 
@@ -2800,20 +2753,17 @@ static int esp_do_data_finale(struct esp *esp)
  * a tape, we don't want to go into a loop re-negotiating
  * synchronous capabilities over and over.
  */
-static int esp_should_clear_sync(Scsi_Cmnd *sp)
+static int esp_should_clear_sync(struct scsi_cmnd *sp)
 {
-       u8 cmd1 = sp->cmnd[0];
-       u8 cmd2 = sp->data_cmnd[0];
+       u8 cmd = sp->cmnd[0];
 
        /* These cases are for spinning up a disk and
         * waiting for that spinup to complete.
         */
-       if (cmd1 == START_STOP ||
-           cmd2 == START_STOP)
+       if (cmd == START_STOP)
                return 0;
 
-       if (cmd1 == TEST_UNIT_READY ||
-           cmd2 == TEST_UNIT_READY)
+       if (cmd == TEST_UNIT_READY)
                return 0;
 
        /* One more special case for SCSI tape drives,
@@ -2821,8 +2771,7 @@ static int esp_should_clear_sync(Scsi_Cmnd *sp)
         * completion of a rewind or tape load operation.
         */
        if (sp->device->type == TYPE_TAPE) {
-               if (cmd1 == MODE_SENSE ||
-                   cmd2 == MODE_SENSE)
+               if (cmd == MODE_SENSE)
                        return 0;
        }
 
@@ -2834,7 +2783,7 @@ static int esp_should_clear_sync(Scsi_Cmnd *sp)
  */
 static int esp_do_freebus(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        struct esp_device *esp_dev = SCptr->device->hostdata;
        int rval;
 
@@ -2905,7 +2854,7 @@ static int esp_do_freebus(struct esp *esp)
  */
 static int esp_bad_reconnect(struct esp *esp)
 {
-       Scsi_Cmnd *sp;
+       struct scsi_cmnd *sp;
 
        ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n",
                esp->esp_id));
@@ -2914,7 +2863,7 @@ static int esp_bad_reconnect(struct esp *esp)
        ESPLOG(("esp%d: issue_SC[", esp->esp_id));
        while (sp) {
                ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
-               sp = (Scsi_Cmnd *) sp->host_scribble;
+               sp = (struct scsi_cmnd *) sp->host_scribble;
        }
        ESPLOG(("]\n"));
        sp = esp->current_SC;
@@ -2928,7 +2877,7 @@ static int esp_bad_reconnect(struct esp *esp)
        ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
        while (sp) {
                ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
-               sp = (Scsi_Cmnd *) sp->host_scribble;
+               sp = (struct scsi_cmnd *) sp->host_scribble;
        }
        ESPLOG(("]\n"));
        return do_reset_bus;
@@ -2938,7 +2887,7 @@ static int esp_bad_reconnect(struct esp *esp)
 static int esp_do_reconnect(struct esp *esp)
 {
        int lun, target;
-       Scsi_Cmnd *SCptr;
+       struct scsi_cmnd *SCptr;
 
        /* Check for all bogus conditions first. */
        target = reconnect_target(esp);
@@ -2988,7 +2937,7 @@ static int esp_do_reconnect(struct esp *esp)
  */
 static int esp_do_status(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        int intr, rval;
 
        rval = skipahead1(esp, SCptr, in_the_dark, in_status);
@@ -3133,7 +3082,7 @@ static int esp_enter_status(struct esp *esp)
 
 static int esp_disconnect_amidst_phases(struct esp *esp)
 {
-       Scsi_Cmnd *sp = esp->current_SC;
+       struct scsi_cmnd *sp = esp->current_SC;
        struct esp_device *esp_dev = sp->device->hostdata;
 
        /* This means real problems if we see this
@@ -3226,7 +3175,7 @@ static int esp_do_phase_determine(struct esp *esp)
 /* First interrupt after exec'ing a cmd comes here. */
 static int esp_select_complete(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        struct esp_device *esp_dev = SCptr->device->hostdata;
        int cmd_bytes_sent, fcnt;
 
@@ -3582,7 +3531,7 @@ static int check_singlebyte_msg(struct esp *esp)
  * this because so many initiators cannot cope with this occurring.
  */
 static int target_with_ants_in_pants(struct esp *esp,
-                                    Scsi_Cmnd *SCptr,
+                                    struct scsi_cmnd *SCptr,
                                     struct esp_device *esp_dev)
 {
        if (esp_dev->sync || SCptr->device->borken) {
@@ -3641,7 +3590,7 @@ static void sync_report(struct esp *esp)
 
 static int check_multibyte_msg(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        struct esp_device *esp_dev = SCptr->device->hostdata;
        u8 regval = 0;
        int message_out = 0;
@@ -3822,7 +3771,7 @@ finish:
 
 static int esp_do_msgindone(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        int message_out = 0, it = 0, rval;
 
        rval = skipahead1(esp, SCptr, in_msgin, in_msgindone);
@@ -3904,7 +3853,7 @@ static int esp_do_msgindone(struct esp *esp)
 
 static int esp_do_cmdbegin(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
 
        esp_advance_phase(SCptr, in_cmdend);
        if (esp->erev == fashme) {
@@ -4125,7 +4074,7 @@ static espfunc_t bus_vector[] = {
 /* This is the second tier in our dual-level SCSI state machine. */
 static int esp_work_bus(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr = esp->current_SC;
+       struct scsi_cmnd *SCptr = esp->current_SC;
        unsigned int phase;
 
        ESPBUS(("esp_work_bus: "));
@@ -4143,7 +4092,7 @@ static int esp_work_bus(struct esp *esp)
 }
 
 static espfunc_t isvc_vector[] = {
-       0,
+       NULL,
        esp_do_phase_determine,
        esp_do_resetbus,
        esp_finish_reset,
@@ -4153,7 +4102,7 @@ static espfunc_t isvc_vector[] = {
 /* Main interrupt handler for an esp adapter. */
 static void esp_handle(struct esp *esp)
 {
-       Scsi_Cmnd *SCptr;
+       struct scsi_cmnd *SCptr;
        int what_next = do_intr_end;
 
        SCptr = esp->current_SC;
@@ -4333,7 +4282,7 @@ state_machine:
 }
 
 /* Service only the ESP described by dev_id. */
-static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+static irqreturn_t esp_intr(int irq, void *dev_id)
 {
        struct esp *esp = dev_id;
        unsigned long flags;
@@ -4353,7 +4302,7 @@ static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
        return IRQ_HANDLED;
 }
 
-static int esp_slave_alloc(Scsi_Device *SDptr)
+static int esp_slave_alloc(struct scsi_device *SDptr)
 {
        struct esp_device *esp_dev =
                kmalloc(sizeof(struct esp_device), GFP_ATOMIC);
@@ -4365,7 +4314,7 @@ static int esp_slave_alloc(Scsi_Device *SDptr)
        return 0;
 }
 
-static void esp_slave_destroy(Scsi_Device *SDptr)
+static void esp_slave_destroy(struct scsi_device *SDptr)
 {
        struct esp *esp = (struct esp *) SDptr->host->hostdata;
 
@@ -4374,15 +4323,12 @@ static void esp_slave_destroy(Scsi_Device *SDptr)
        SDptr->hostdata = NULL;
 }
 
-static Scsi_Host_Template driver_template = {
-       .proc_name              = "esp",
-       .proc_info              = esp_proc_info,
-       .name                   = "Sun ESP 100/100a/200",
-       .detect                 = esp_detect,
+static struct scsi_host_template esp_template = {
+       .module                 = THIS_MODULE,
+       .name                   = "esp",
+       .info                   = esp_info,
        .slave_alloc            = esp_slave_alloc,
        .slave_destroy          = esp_slave_destroy,
-       .release                = esp_release,
-       .info                   = esp_info,
        .queuecommand           = esp_queue,
        .eh_abort_handler       = esp_abort,
        .eh_bus_reset_handler   = esp_reset,
@@ -4391,9 +4337,58 @@ static Scsi_Host_Template driver_template = {
        .sg_tablesize           = SG_ALL,
        .cmd_per_lun            = 1,
        .use_clustering         = ENABLE_CLUSTERING,
+       .proc_name              = "esp",
+       .proc_info              = esp_proc_info,
 };
 
-#include "scsi_module.c"
+#ifndef CONFIG_SUN4
+static struct of_device_id esp_match[] = {
+       {
+               .name = "SUNW,esp",
+               .data = &esp_template,
+       },
+       {
+               .name = "SUNW,fas",
+               .data = &esp_template,
+       },
+       {
+               .name = "esp",
+               .data = &esp_template,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, esp_match);
+
+static struct of_platform_driver esp_sbus_driver = {
+       .name           = "esp",
+       .match_table    = esp_match,
+       .probe          = esp_sbus_probe,
+       .remove         = __devexit_p(esp_sbus_remove),
+};
+#endif
+
+static int __init esp_init(void)
+{
+#ifdef CONFIG_SUN4
+       return esp_sun4_probe(&esp_template);
+#else
+       return of_register_driver(&esp_sbus_driver, &sbus_bus_type);
+#endif
+}
+
+static void __exit esp_exit(void)
+{
+#ifdef CONFIG_SUN4
+       esp_sun4_remove();
+#else
+       of_unregister_driver(&esp_sbus_driver);
+#endif
+}
 
+MODULE_DESCRIPTION("ESP Sun SCSI driver");
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 
+module_init(esp_init);
+module_exit(esp_exit);