fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / scsi / NCR_D700.c
index 329f0ee..9859cd1 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mca.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
-
-#include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 #include "53c700.h"
 #include "NCR_D700.h"
 
-char *NCR_D700;                        /* command line from insmod */
+static char *NCR_D700;         /* command line from insmod */
 
 MODULE_AUTHOR("James Bottomley");
 MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM(NCR_D700, "s");
+module_param(NCR_D700, charp, 0);
 
-static __u8 __initdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
+static __u8 __devinitdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
        { [0 ... 2*(MCA_MAX_SLOT_NR + 1)-1] = 7 };
 
 #ifdef MODULE
@@ -156,7 +158,7 @@ param_setup(char *string)
 
 /* Host template.  The 53c700 routine NCR_700_detect will
  * fill in all of the missing routines */
-static Scsi_Host_Template NCR_D700_driver_template = {
+static struct scsi_host_template NCR_D700_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = "NCR Dual 700 MCA",
        .proc_name              = "NCR_D700",
@@ -167,11 +169,13 @@ static Scsi_Host_Template NCR_D700_driver_template = {
 struct NCR_D700_private {
        struct device           *dev;
        struct Scsi_Host        *hosts[2];
+       char                    name[30];
+       char                    pad;
 };
 
-static int 
-NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
-               int irq, int slot, u32 region, int differential)
+static int __devinit
+NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
+                  int slot, u32 region, int differential)
 {
        struct NCR_700_Host_Parameters *hostdata;
        struct Scsi_Host *host;
@@ -193,54 +197,53 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
        }
                
        /* Fill in the three required pieces of hostdata */
-       hostdata->base = region;
+       hostdata->base = ioport_map(region, 64);
        hostdata->differential = (((1<<siop) & differential) != 0);
        hostdata->clock = NCR_D700_CLOCK_MHZ;
 
-       NCR_700_set_io_mapped(hostdata);
-
        /* and register the siop */
-       host = NCR_700_detect(&NCR_D700_driver_template, hostdata);
+       host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev);
        if (!host) {
                ret = -ENOMEM;
                goto detect_failed;
        }
 
-       host->irq = irq;
-       /* FIXME: Read this from SUS */
+       p->hosts[siop] = host;
+       /* FIXME: read this from SUS */
        host->this_id = id_array[slot * 2 + siop];
-       printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n",
-                       siop, host->this_id);
-       if (request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) {
-               printk(KERN_ERR "NCR D700: SIOP%d: irq problem, "
-                               "detatching\n", siop);
-               ret = -ENODEV;
-               goto irq_failed;
-       }
-
-       scsi_add_host(host, p->dev); /* XXX handle failure */
+       host->irq = irq;
+       host->base = region;
        scsi_scan_host(host);
 
-       p->hosts[siop] = host;
-       hostdata->dev = p->dev;
        return 0;
 
- irq_failed:
-       scsi_host_put(host);
-       NCR_700_release(host);
  detect_failed:
-       release_region(host->base, 64);
+       release_region(region, 64);
  region_failed:
        kfree(hostdata);
 
        return ret;
 }
 
+static int
+NCR_D700_intr(int irq, void *data)
+{
+       struct NCR_D700_private *p = (struct NCR_D700_private *)data;
+       int i, found = 0;
+
+       for (i = 0; i < 2; i++)
+               if (p->hosts[i] &&
+                   NCR_700_intr(irq, p->hosts[i]) == IRQ_HANDLED)
+                       found++;
+
+       return found ? IRQ_HANDLED : IRQ_NONE;
+}
+
 /* Detect a D700 card.  Note, because of the setup --- the chips are
  * essentially connectecd to the MCA bus independently, it is easier
  * to set them up as two separate host adapters, rather than one
  * adapter with two channels */
-static int
+static int __devinit
 NCR_D700_probe(struct device *dev)
 {
        struct NCR_D700_private *p;
@@ -314,8 +317,14 @@ NCR_D700_probe(struct device *dev)
        p = kmalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
                return -ENOMEM;
+       memset(p, '\0', sizeof(*p));
        p->dev = dev;
-
+       snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id);
+       if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) {
+               printk(KERN_ERR "D700: request_irq failed\n");
+               kfree(p);
+               return -EBUSY;
+       }
        /* plumb in both 700 chips */
        for (i = 0; i < 2; i++) {
                int err;
@@ -340,7 +349,7 @@ NCR_D700_probe(struct device *dev)
        return 0;
 }
 
-static void
+static void __devexit
 NCR_D700_remove_one(struct Scsi_Host *host)
 {
        scsi_remove_host(host);
@@ -350,7 +359,7 @@ NCR_D700_remove_one(struct Scsi_Host *host)
        release_region(host->base, 64);
 }
 
-static int
+static int __devexit
 NCR_D700_remove(struct device *dev)
 {
        struct NCR_D700_private *p = dev_get_drvdata(dev);
@@ -365,13 +374,13 @@ NCR_D700_remove(struct device *dev)
 
 static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
 
-struct mca_driver NCR_D700_driver = {
+static struct mca_driver NCR_D700_driver = {
        .id_table = NCR_D700_id_table,
        .driver = {
                .name           = "NCR_D700",
                .bus            = &mca_bus_type,
                .probe          = NCR_D700_probe,
-               .remove         = NCR_D700_remove,
+               .remove         = __devexit_p(NCR_D700_remove),
        },
 };