linux/drivers/scsi/dmx3191d.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3    dmx3191d.c - driver for the Domex DMX3191D SCSI card.
   4    Copyright (C) 2000 by Massimo Piccioni <dafastidio@libero.it>
   5    Portions Copyright (C) 2004 by Christoph Hellwig <hch@lst.de>
   6
   7    Based on the generic NCR5380 driver by Drew Eckhardt et al.
   8
   9*/
  10
  11#include <linux/init.h>
  12#include <linux/ioport.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/pci.h>
  16#include <linux/interrupt.h>
  17#include <asm/io.h>
  18
  19#include <scsi/scsi_host.h>
  20
  21/*
  22 * Definitions for the generic 5380 driver.
  23 */
  24
  25#define NCR5380_read(reg)               inb(hostdata->base + (reg))
  26#define NCR5380_write(reg, value)       outb(value, hostdata->base + (reg))
  27
  28#define NCR5380_dma_xfer_len            NCR5380_dma_xfer_none
  29#define NCR5380_dma_recv_setup          NCR5380_dma_setup_none
  30#define NCR5380_dma_send_setup          NCR5380_dma_setup_none
  31#define NCR5380_dma_residual            NCR5380_dma_residual_none
  32
  33#define NCR5380_implementation_fields   /* none */
  34
  35#include "NCR5380.h"
  36#include "NCR5380.c"
  37
  38#define DMX3191D_DRIVER_NAME    "dmx3191d"
  39#define DMX3191D_REGION_LEN     8
  40
  41
  42static struct scsi_host_template dmx3191d_driver_template = {
  43        .module                 = THIS_MODULE,
  44        .proc_name              = DMX3191D_DRIVER_NAME,
  45        .name                   = "Domex DMX3191D",
  46        .info                   = NCR5380_info,
  47        .queuecommand           = NCR5380_queue_command,
  48        .eh_abort_handler       = NCR5380_abort,
  49        .eh_host_reset_handler  = NCR5380_host_reset,
  50        .can_queue              = 32,
  51        .this_id                = 7,
  52        .sg_tablesize           = SG_ALL,
  53        .cmd_per_lun            = 2,
  54        .dma_boundary           = PAGE_SIZE - 1,
  55        .cmd_size               = NCR5380_CMD_SIZE,
  56};
  57
  58static int dmx3191d_probe_one(struct pci_dev *pdev,
  59                              const struct pci_device_id *id)
  60{
  61        struct Scsi_Host *shost;
  62        struct NCR5380_hostdata *hostdata;
  63        unsigned long io;
  64        int error = -ENODEV;
  65
  66        if (pci_enable_device(pdev))
  67                goto out;
  68
  69        io = pci_resource_start(pdev, 0);
  70        if (!request_region(io, DMX3191D_REGION_LEN, DMX3191D_DRIVER_NAME)) {
  71                printk(KERN_ERR "dmx3191: region 0x%lx-0x%lx already reserved\n",
  72                                io, io + DMX3191D_REGION_LEN);
  73                goto out_disable_device;
  74        }
  75
  76        shost = scsi_host_alloc(&dmx3191d_driver_template,
  77                        sizeof(struct NCR5380_hostdata));
  78        if (!shost)
  79                goto out_release_region;       
  80
  81        hostdata = shost_priv(shost);
  82        hostdata->base = io;
  83
  84        /* This card does not seem to raise an interrupt on pdev->irq.
  85         * Steam-powered SCSI controllers run without an IRQ anyway.
  86         */
  87        shost->irq = NO_IRQ;
  88
  89        error = NCR5380_init(shost, 0);
  90        if (error)
  91                goto out_host_put;
  92
  93        NCR5380_maybe_reset_bus(shost);
  94
  95        pci_set_drvdata(pdev, shost);
  96
  97        error = scsi_add_host(shost, &pdev->dev);
  98        if (error)
  99                goto out_exit;
 100
 101        scsi_scan_host(shost);
 102        return 0;
 103
 104out_exit:
 105        NCR5380_exit(shost);
 106out_host_put:
 107        scsi_host_put(shost);
 108 out_release_region:
 109        release_region(io, DMX3191D_REGION_LEN);
 110 out_disable_device:
 111        pci_disable_device(pdev);
 112 out:
 113        return error;
 114}
 115
 116static void dmx3191d_remove_one(struct pci_dev *pdev)
 117{
 118        struct Scsi_Host *shost = pci_get_drvdata(pdev);
 119        struct NCR5380_hostdata *hostdata = shost_priv(shost);
 120        unsigned long io = hostdata->base;
 121
 122        scsi_remove_host(shost);
 123
 124        NCR5380_exit(shost);
 125        scsi_host_put(shost);
 126        release_region(io, DMX3191D_REGION_LEN);
 127        pci_disable_device(pdev);
 128}
 129
 130static struct pci_device_id dmx3191d_pci_tbl[] = {
 131        {PCI_VENDOR_ID_DOMEX, PCI_DEVICE_ID_DOMEX_DMX3191D,
 132                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
 133        { }
 134};
 135MODULE_DEVICE_TABLE(pci, dmx3191d_pci_tbl);
 136
 137static struct pci_driver dmx3191d_pci_driver = {
 138        .name           = DMX3191D_DRIVER_NAME,
 139        .id_table       = dmx3191d_pci_tbl,
 140        .probe          = dmx3191d_probe_one,
 141        .remove         = dmx3191d_remove_one,
 142};
 143
 144module_pci_driver(dmx3191d_pci_driver);
 145
 146MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 147MODULE_DESCRIPTION("Domex DMX3191D SCSI driver");
 148MODULE_LICENSE("GPL");
 149