0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/blkdev.h>
0012 #include <linux/device.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/init.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/slab.h>
0017 #include <asm/bvme6000hw.h>
0018 #include <scsi/scsi_host.h>
0019 #include <scsi/scsi_device.h>
0020 #include <scsi/scsi_transport.h>
0021 #include <scsi/scsi_transport_spi.h>
0022
0023 #include "53c700.h"
0024
0025 MODULE_AUTHOR("Richard Hirst <richard@sleepie.demon.co.uk>");
0026 MODULE_DESCRIPTION("BVME6000 NCR53C710 driver");
0027 MODULE_LICENSE("GPL");
0028
0029 static struct scsi_host_template bvme6000_scsi_driver_template = {
0030 .name = "BVME6000 NCR53c710 SCSI",
0031 .proc_name = "BVME6000",
0032 .this_id = 7,
0033 .module = THIS_MODULE,
0034 };
0035
0036 static struct platform_device *bvme6000_scsi_device;
0037
0038 static int
0039 bvme6000_probe(struct platform_device *dev)
0040 {
0041 struct Scsi_Host *host;
0042 struct NCR_700_Host_Parameters *hostdata;
0043
0044 if (!MACH_IS_BVME6000)
0045 goto out;
0046
0047 hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
0048 if (!hostdata) {
0049 printk(KERN_ERR "bvme6000-scsi: "
0050 "Failed to allocate host data\n");
0051 goto out;
0052 }
0053
0054
0055 hostdata->base = (void __iomem *)BVME_NCR53C710_BASE;
0056 hostdata->clock = 40;
0057 hostdata->chip710 = 1;
0058 hostdata->dmode_extra = DMODE_FC2;
0059 hostdata->dcntl_extra = EA_710;
0060 hostdata->ctest7_extra = CTEST7_TT1;
0061
0062
0063 host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata,
0064 &dev->dev);
0065 if (!host) {
0066 printk(KERN_ERR "bvme6000-scsi: No host detected; "
0067 "board configuration problem?\n");
0068 goto out_free;
0069 }
0070 host->base = BVME_NCR53C710_BASE;
0071 host->this_id = 7;
0072 host->irq = BVME_IRQ_SCSI;
0073 if (request_irq(BVME_IRQ_SCSI, NCR_700_intr, 0, "bvme6000-scsi",
0074 host)) {
0075 printk(KERN_ERR "bvme6000-scsi: request_irq failed\n");
0076 goto out_put_host;
0077 }
0078
0079 platform_set_drvdata(dev, host);
0080 scsi_scan_host(host);
0081
0082 return 0;
0083
0084 out_put_host:
0085 scsi_host_put(host);
0086 out_free:
0087 kfree(hostdata);
0088 out:
0089 return -ENODEV;
0090 }
0091
0092 static int
0093 bvme6000_device_remove(struct platform_device *dev)
0094 {
0095 struct Scsi_Host *host = platform_get_drvdata(dev);
0096 struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
0097
0098 scsi_remove_host(host);
0099 NCR_700_release(host);
0100 kfree(hostdata);
0101 free_irq(host->irq, host);
0102
0103 return 0;
0104 }
0105
0106 static struct platform_driver bvme6000_scsi_driver = {
0107 .driver = {
0108 .name = "bvme6000-scsi",
0109 },
0110 .probe = bvme6000_probe,
0111 .remove = bvme6000_device_remove,
0112 };
0113
0114 static int __init bvme6000_scsi_init(void)
0115 {
0116 int err;
0117
0118 err = platform_driver_register(&bvme6000_scsi_driver);
0119 if (err)
0120 return err;
0121
0122 bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi",
0123 -1, NULL, 0);
0124 if (IS_ERR(bvme6000_scsi_device)) {
0125 platform_driver_unregister(&bvme6000_scsi_driver);
0126 return PTR_ERR(bvme6000_scsi_device);
0127 }
0128
0129 return 0;
0130 }
0131
0132 static void __exit bvme6000_scsi_exit(void)
0133 {
0134 platform_device_unregister(bvme6000_scsi_device);
0135 platform_driver_unregister(&bvme6000_scsi_driver);
0136 }
0137
0138 module_init(bvme6000_scsi_init);
0139 module_exit(bvme6000_scsi_exit);