linux/drivers/scsi/lasi700.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2
   3/* PARISC LASI driver for the 53c700 chip
   4 *
   5 * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com
   6**-----------------------------------------------------------------------------
   7**  
   8**
   9**-----------------------------------------------------------------------------
  10 */
  11
  12/*
  13 * Many thanks to Richard Hirst <rhirst@linuxcare.com> for patiently
  14 * debugging this driver on the parisc architecture and suggesting
  15 * many improvements and bug fixes.
  16 *
  17 * Thanks also go to Linuxcare Inc. for providing several PARISC
  18 * machines for me to debug the driver on.
  19 */
  20
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/init.h>
  24#include <linux/types.h>
  25#include <linux/stat.h>
  26#include <linux/mm.h>
  27#include <linux/blkdev.h>
  28#include <linux/ioport.h>
  29#include <linux/dma-mapping.h>
  30#include <linux/slab.h>
  31
  32#include <asm/page.h>
  33#include <asm/irq.h>
  34#include <asm/hardware.h>
  35#include <asm/parisc-device.h>
  36#include <asm/delay.h>
  37
  38#include <scsi/scsi_host.h>
  39#include <scsi/scsi_device.h>
  40#include <scsi/scsi_transport.h>
  41#include <scsi/scsi_transport_spi.h>
  42
  43#include "53c700.h"
  44
  45MODULE_AUTHOR("James Bottomley");
  46MODULE_DESCRIPTION("lasi700 SCSI Driver");
  47MODULE_LICENSE("GPL");
  48
  49#define LASI_700_SVERSION 0x00071
  50#define LASI_710_SVERSION 0x00082
  51
  52#define LASI700_ID_TABLE {                      \
  53        .hw_type        = HPHW_FIO,             \
  54        .sversion       = LASI_700_SVERSION,    \
  55        .hversion       = HVERSION_ANY_ID,      \
  56        .hversion_rev   = HVERSION_REV_ANY_ID,  \
  57}
  58
  59#define LASI710_ID_TABLE {                      \
  60        .hw_type        = HPHW_FIO,             \
  61        .sversion       = LASI_710_SVERSION,    \
  62        .hversion       = HVERSION_ANY_ID,      \
  63        .hversion_rev   = HVERSION_REV_ANY_ID,  \
  64}
  65
  66#define LASI700_CLOCK   25
  67#define LASI710_CLOCK   40
  68#define LASI_SCSI_CORE_OFFSET 0x100
  69
  70static const struct parisc_device_id lasi700_ids[] __initconst = {
  71        LASI700_ID_TABLE,
  72        LASI710_ID_TABLE,
  73        { 0 }
  74};
  75
  76static struct scsi_host_template lasi700_template = {
  77        .name           = "LASI SCSI 53c700",
  78        .proc_name      = "lasi700",
  79        .this_id        = 7,
  80        .module         = THIS_MODULE,
  81};
  82MODULE_DEVICE_TABLE(parisc, lasi700_ids);
  83
  84static int __init
  85lasi700_probe(struct parisc_device *dev)
  86{
  87        unsigned long base = dev->hpa.start + LASI_SCSI_CORE_OFFSET;
  88        struct NCR_700_Host_Parameters *hostdata;
  89        struct Scsi_Host *host;
  90
  91        hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
  92        if (!hostdata) {
  93                dev_printk(KERN_ERR, &dev->dev, "Failed to allocate host data\n");
  94                return -ENOMEM;
  95        }
  96
  97        hostdata->dev = &dev->dev;
  98        dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
  99        hostdata->base = ioremap(base, 0x100);
 100        hostdata->differential = 0;
 101
 102        if (dev->id.sversion == LASI_700_SVERSION) {
 103                hostdata->clock = LASI700_CLOCK;
 104                hostdata->force_le_on_be = 1;
 105        } else {
 106                hostdata->clock = LASI710_CLOCK;
 107                hostdata->force_le_on_be = 0;
 108                hostdata->chip710 = 1;
 109                hostdata->dmode_extra = DMODE_FC2;
 110                hostdata->burst_length = 8;
 111        }
 112
 113        host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
 114        if (!host)
 115                goto out_kfree;
 116        host->this_id = 7;
 117        host->base = base;
 118        host->irq = dev->irq;
 119        if(request_irq(dev->irq, NCR_700_intr, IRQF_SHARED, "lasi700", host)) {
 120                printk(KERN_ERR "lasi700: request_irq failed!\n");
 121                goto out_put_host;
 122        }
 123
 124        dev_set_drvdata(&dev->dev, host);
 125        scsi_scan_host(host);
 126
 127        return 0;
 128
 129 out_put_host:
 130        scsi_host_put(host);
 131 out_kfree:
 132        iounmap(hostdata->base);
 133        kfree(hostdata);
 134        return -ENODEV;
 135}
 136
 137static void __exit
 138lasi700_driver_remove(struct parisc_device *dev)
 139{
 140        struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
 141        struct NCR_700_Host_Parameters *hostdata = 
 142                (struct NCR_700_Host_Parameters *)host->hostdata[0];
 143
 144        scsi_remove_host(host);
 145        NCR_700_release(host);
 146        free_irq(host->irq, host);
 147        iounmap(hostdata->base);
 148        kfree(hostdata);
 149}
 150
 151static struct parisc_driver lasi700_driver __refdata = {
 152        .name =         "lasi_scsi",
 153        .id_table =     lasi700_ids,
 154        .probe =        lasi700_probe,
 155        .remove =       __exit_p(lasi700_driver_remove),
 156};
 157
 158static int __init
 159lasi700_init(void)
 160{
 161        return register_parisc_driver(&lasi700_driver);
 162}
 163
 164static void __exit
 165lasi700_exit(void)
 166{
 167        unregister_parisc_driver(&lasi700_driver);
 168}
 169
 170module_init(lasi700_init);
 171module_exit(lasi700_exit);
 172