linux/drivers/scsi/a4000t.c
<<
>>
Prefs
   1/*
   2 * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
   3 *              Amiga Technologies A4000T SCSI controller.
   4 *
   5 * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
   6 * plus modifications of the 53c7xx.c driver to support the Amiga.
   7 *
   8 * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13#include <linux/init.h>
  14#include <linux/interrupt.h>
  15#include <asm/amigahw.h>
  16#include <asm/amigaints.h>
  17#include <scsi/scsi_host.h>
  18#include <scsi/scsi_transport_spi.h>
  19
  20#include "53c700.h"
  21
  22MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
  23MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
  24MODULE_LICENSE("GPL");
  25
  26
  27static struct scsi_host_template a4000t_scsi_driver_template = {
  28        .name           = "A4000T builtin SCSI",
  29        .proc_name      = "A4000t",
  30        .this_id        = 7,
  31        .module         = THIS_MODULE,
  32};
  33
  34static struct platform_device *a4000t_scsi_device;
  35
  36#define A4000T_SCSI_ADDR 0xdd0040
  37
  38static int __devinit a4000t_probe(struct platform_device *dev)
  39{
  40        struct Scsi_Host *host;
  41        struct NCR_700_Host_Parameters *hostdata;
  42
  43        if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI)))
  44                goto out;
  45
  46        if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000,
  47                                "A4000T builtin SCSI"))
  48                goto out;
  49
  50        hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
  51        if (!hostdata) {
  52                printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n");
  53                goto out_release;
  54        }
  55
  56        /* Fill in the required pieces of hostdata */
  57        hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR);
  58        hostdata->clock = 50;
  59        hostdata->chip710 = 1;
  60        hostdata->dmode_extra = DMODE_FC2;
  61        hostdata->dcntl_extra = EA_710;
  62
  63        /* and register the chip */
  64        host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata,
  65                              &dev->dev);
  66        if (!host) {
  67                printk(KERN_ERR "a4000t-scsi: No host detected; "
  68                                "board configuration problem?\n");
  69                goto out_free;
  70        }
  71
  72        host->this_id = 7;
  73        host->base = A4000T_SCSI_ADDR;
  74        host->irq = IRQ_AMIGA_PORTS;
  75
  76        if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi",
  77                        host)) {
  78                printk(KERN_ERR "a4000t-scsi: request_irq failed\n");
  79                goto out_put_host;
  80        }
  81
  82        platform_set_drvdata(dev, host);
  83        scsi_scan_host(host);
  84
  85        return 0;
  86
  87 out_put_host:
  88        scsi_host_put(host);
  89 out_free:
  90        kfree(hostdata);
  91 out_release:
  92        release_mem_region(A4000T_SCSI_ADDR, 0x1000);
  93 out:
  94        return -ENODEV;
  95}
  96
  97static __devexit int a4000t_device_remove(struct platform_device *dev)
  98{
  99        struct Scsi_Host *host = platform_get_drvdata(dev);
 100        struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
 101
 102        scsi_remove_host(host);
 103
 104        NCR_700_release(host);
 105        kfree(hostdata);
 106        free_irq(host->irq, host);
 107        release_mem_region(A4000T_SCSI_ADDR, 0x1000);
 108
 109        return 0;
 110}
 111
 112static struct platform_driver a4000t_scsi_driver = {
 113        .driver = {
 114                .name           = "a4000t-scsi",
 115                .owner          = THIS_MODULE,
 116        },
 117        .probe          = a4000t_probe,
 118        .remove         = __devexit_p(a4000t_device_remove),
 119};
 120
 121static int __init a4000t_scsi_init(void)
 122{
 123        int err;
 124
 125        err = platform_driver_register(&a4000t_scsi_driver);
 126        if (err)
 127                return err;
 128
 129        a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
 130                        -1, NULL, 0);
 131        if (IS_ERR(a4000t_scsi_device)) {
 132                platform_driver_unregister(&a4000t_scsi_driver);
 133                return PTR_ERR(a4000t_scsi_device);
 134        }
 135
 136        return err;
 137}
 138
 139static void __exit a4000t_scsi_exit(void)
 140{
 141        platform_device_unregister(a4000t_scsi_device);
 142        platform_driver_unregister(&a4000t_scsi_driver);
 143}
 144
 145module_init(a4000t_scsi_init);
 146module_exit(a4000t_scsi_exit);
 147