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