Commit 4d4ffdcf authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley

[PATCH] update NCR_D700 for new-style probing

Pretty big patch and untested due to lack of hardware, so handle
it with care :)
parent 7cbecb83
...@@ -92,18 +92,12 @@ ...@@ -92,18 +92,12 @@
#define NCR_D700_VERSION "2.2" #define NCR_D700_VERSION "2.2"
#include <linux/config.h> #include <linux/blkdev.h>
#include <linux/blk.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mca.h> #include <linux/mca.h>
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/byteorder.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -111,16 +105,6 @@ ...@@ -111,16 +105,6 @@
#include "53c700.h" #include "53c700.h"
#include "NCR_D700.h" #include "NCR_D700.h"
#ifndef CONFIG_MCA
#error "NCR_D700 driver only compiles for MCA"
#endif
#ifdef NCR_D700_DEBUG
#define STATIC
#else
#define STATIC static
#endif
char *NCR_D700; /* command line from insmod */ char *NCR_D700; /* command line from insmod */
MODULE_AUTHOR("James Bottomley"); MODULE_AUTHOR("James Bottomley");
...@@ -170,34 +154,91 @@ param_setup(char *string) ...@@ -170,34 +154,91 @@ param_setup(char *string)
return 1; return 1;
} }
#ifndef MODULE /* Host template. The 53c700 routine NCR_700_detect will
__setup("NCR_D700=", param_setup); * fill in all of the missing routines */
#endif static Scsi_Host_Template NCR_D700_driver_template = {
.module = THIS_MODULE,
.name = "NCR Dual 700 MCA",
.proc_name = "NCR_D700",
.this_id = 7,
};
/* private stack allocated structure for passing device information from /* We needs this helper because we have two hosts per struct device */
* detect to probe */ struct NCR_D700_private {
struct NCR_700_info { struct device *dev;
Scsi_Host_Template *tpnt; struct Scsi_Host *hosts[2];
int found;
}; };
/* Detect a D700 card. Note, because of the set up---the chips are static int NCR_D700_probe_one(struct NCR_D700_private *p, int chan,
int irq, int slot, u32 region, int differential)
{
struct NCR_700_Host_Parameters *hostdata;
struct Scsi_Host *host;
hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL);
if (!hostdata) {
printk(KERN_ERR "NCR D700: Failed to allocate host data "
"for channel %d, detatching\n", chan);
return -ENOMEM;
}
memset(hostdata, 0, sizeof(*hostdata));
if (!request_region(region, 64, "NCR_D700")) {
printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n",
region);
kfree(hostdata);
return -ENODEV;
}
/* Fill in the three required pieces of hostdata */
hostdata->base = region;
hostdata->differential = (((1<<chan) & differential) != 0);
hostdata->clock = NCR_D700_CLOCK_MHZ;
/* and register the chip */
host = NCR_700_detect(&NCR_D700_driver_template, hostdata);
if (!host) {
kfree(hostdata);
release_region(host->base, 64);
return -ENOMEM;
}
host->irq = irq;
/* FIXME: Read this from SUS */
host->this_id = id_array[slot * 2 + chan];
printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n",
chan, host->this_id);
if (request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) {
printk(KERN_ERR "NCR D700, channel %d: irq problem, "
"detatching\n", chan);
scsi_unregister(host);
NCR_700_release(host);
return -ENODEV;
}
scsi_add_host(host, NULL);
p->hosts[chan] = host;
hostdata->dev = p->dev;
return 0;
}
/* Detect a D700 card. Note, because of the setup --- the chips are
* essentially connectecd to the MCA bus independently, it is easier * essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one * to set them up as two separate host adapters, rather than one
* adapter with two channels */ * adapter with two channels */
static int static int
NCR_D700_probe(struct device *dev) NCR_D700_probe(struct device *dev)
{ {
struct NCR_D700_private *p;
int differential; int differential;
static int banner = 1; static int banner = 1;
struct mca_device *mca_dev = to_mca_device(dev); struct mca_device *mca_dev = to_mca_device(dev);
int slot = mca_dev->slot; int slot = mca_dev->slot;
struct NCR_700_info *info = to_mca_driver(dev->driver)->driver_data;
int found = 0; int found = 0;
int irq, i; int irq, i;
int pos3j, pos3k, pos3a, pos3b, pos4; int pos3j, pos3k, pos3a, pos3b, pos4;
__u32 base_addr, offset_addr; __u32 base_addr, offset_addr;
struct Scsi_Host *host = NULL;
/* enable board interrupt */ /* enable board interrupt */
pos4 = mca_device_read_pos(mca_dev, 4); pos4 = mca_device_read_pos(mca_dev, 4);
...@@ -232,8 +273,6 @@ NCR_D700_probe(struct device *dev) ...@@ -232,8 +273,6 @@ NCR_D700_probe(struct device *dev)
printk(KERN_NOTICE "NCR D700: found in slot %d irq = %d I/O base = 0x%x\n", slot, irq, offset_addr); printk(KERN_NOTICE "NCR D700: found in slot %d irq = %d I/O base = 0x%x\n", slot, irq, offset_addr);
info->tpnt->proc_name = "NCR_D700";
/*outb(BOARD_RESET, base_addr);*/ /*outb(BOARD_RESET, base_addr);*/
/* clear any pending interrupts */ /* clear any pending interrupts */
...@@ -259,70 +298,49 @@ NCR_D700_probe(struct device *dev) ...@@ -259,70 +298,49 @@ NCR_D700_probe(struct device *dev)
break; break;
} }
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
p->dev = dev;
/* plumb in both 700 chips */ /* plumb in both 700 chips */
for(i=0; i<2; i++) { for (i = 0; i < 2; i++) {
__u32 region = offset_addr | (0x80 * i); found |= NCR_D700_probe_one(p, i, irq, slot,
struct NCR_700_Host_Parameters *hostdata = offset_addr | (0x80 * i), differential);
kmalloc(sizeof(struct NCR_700_Host_Parameters),
GFP_KERNEL);
if(hostdata == NULL) {
printk(KERN_ERR "NCR D700: Failed to allocate host data for channel %d, detatching\n", i);
continue;
}
memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
if(request_region(region, 64, "NCR_D700") == NULL) {
printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", region);
kfree(hostdata);
continue;
}
/* Fill in the three required pieces of hostdata */
hostdata->base = region;
hostdata->differential = (((1<<i) & differential) != 0);
hostdata->clock = NCR_D700_CLOCK_MHZ;
/* and register the chip */
if((host = NCR_700_detect(info->tpnt, hostdata)) == NULL) {
kfree(hostdata);
release_region(host->base, 64);
continue;
}
host->irq = irq;
/* FIXME: Read this from SUS */
host->this_id = id_array[slot * 2 + i];
printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n",
i, host->this_id);
if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) {
printk(KERN_ERR "NCR D700, channel %d: irq problem, detatching\n", i);
scsi_unregister(host);
NCR_700_release(host);
continue;
}
scsi_set_device(host, dev);
hostdata->dev = dev;
found++;
} }
info->found += found;
if(found) { if (!found) {
mca_device_set_claim(mca_dev, 1); kfree(p);
strncpy(dev->name, "NCR_D700", sizeof(dev->name)); return -ENODEV;
} }
return found? 0 : -ENODEV; mca_device_set_claim(mca_dev, 1);
strncpy(dev->name, "NCR_D700", sizeof(dev->name));
dev_set_drvdata(dev, p);
return 0;
} }
static void
STATIC int NCR_D700_remove_one(struct Scsi_Host *host)
D700_release(struct Scsi_Host *host)
{ {
struct D700_Host_Parameters *hostdata = scsi_remove_host(host);
(struct D700_Host_Parameters *)host->hostdata[0];
NCR_700_release(host); NCR_700_release(host);
kfree(hostdata); kfree((struct NCR_700_Host_Parameters *)host->hostdata[0]);
free_irq(host->irq, host); free_irq(host->irq, host);
release_region(host->base, 64); release_region(host->base, 64);
return 1; }
static int
NCR_D700_remove(struct device *dev)
{
struct NCR_D700_private *p = dev_get_drvdata(dev);
int i;
for (i = 0; i < 2; i++)
NCR_D700_remove_one(p->hosts[i]);
kfree(p);
return 0;
} }
static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 }; static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
...@@ -330,34 +348,29 @@ static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 }; ...@@ -330,34 +348,29 @@ static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
struct mca_driver NCR_D700_driver = { struct mca_driver NCR_D700_driver = {
.id_table = NCR_D700_id_table, .id_table = NCR_D700_id_table,
.driver = { .driver = {
.name = "NCR_D700", .name = "NCR_D700",
.bus = &mca_bus_type, .bus = &mca_bus_type,
.probe = NCR_D700_probe, .probe = NCR_D700_probe,
.remove = NCR_D700_remove,
}, },
}; };
STATIC int __init static int __init NCR_D700_init(void)
D700_detect(Scsi_Host_Template *tpnt)
{ {
struct NCR_700_info info;
if(!MCA_bus)
return 0;
#ifdef MODULE #ifdef MODULE
if(NCR_D700) if (NCR_D700)
param_setup(NCR_D700); param_setup(NCR_D700);
#endif #endif
info.tpnt = tpnt;
info.found = 0;
NCR_D700_driver.driver_data = &info;
mca_register_driver(&NCR_D700_driver);
return info.found; return mca_register_driver(&NCR_D700_driver);
} }
static Scsi_Host_Template driver_template = NCR_D700_SCSI;
#include "scsi_module.c" static void __exit NCR_D700_exit(void)
{
mca_unregister_driver(&NCR_D700_driver);
}
module_init(NCR_D700_init);
module_exit(NCR_D700_exit);
__setup("NCR_D700=", param_setup);
...@@ -14,22 +14,6 @@ ...@@ -14,22 +14,6 @@
/* The MCA identifier */ /* The MCA identifier */
#define NCR_D700_MCA_ID 0x0092 #define NCR_D700_MCA_ID 0x0092
static int D700_detect(Scsi_Host_Template *);
static int D700_release(struct Scsi_Host *host);
/* Host template. Note the name and proc_name are optional, all the
* remaining parameters shown below must be filled in. The 53c700
* routine NCR_700_detect will fill in all of the missing routines */
#define NCR_D700_SCSI { \
.name = "NCR Dual 700 MCA", \
.proc_name = "NCR_D700", \
.detect = D700_detect, \
.release = D700_release, \
.this_id = 7, \
}
/* Defines for the Board registers */ /* Defines for the Board registers */
#define BOARD_RESET 0x80 /* board level reset */ #define BOARD_RESET 0x80 /* board level reset */
#define ADD_PARENB 0x04 /* Address Parity Enabled */ #define ADD_PARENB 0x04 /* Address Parity Enabled */
......
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