xref: /linux/drivers/scsi/dmx3191d.c (revision 61e1ce588b101f13a4c6f713b95d65551c8572e3)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds     dmx3191d.c - driver for the Domex DMX3191D SCSI card.
31da177e4SLinus Torvalds     Copyright (C) 2000 by Massimo Piccioni <dafastidio@libero.it>
41da177e4SLinus Torvalds     Portions Copyright (C) 2004 by Christoph Hellwig <hch@lst.de>
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds     Based on the generic NCR5380 driver by Drew Eckhardt et al.
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds     This program is free software; you can redistribute it and/or modify
91da177e4SLinus Torvalds     it under the terms of the GNU General Public License as published by
101da177e4SLinus Torvalds     the Free Software Foundation; either version 2 of the License, or
111da177e4SLinus Torvalds     (at your option) any later version.
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds     This program is distributed in the hope that it will be useful,
141da177e4SLinus Torvalds     but WITHOUT ANY WARRANTY; without even the implied warranty of
151da177e4SLinus Torvalds     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161da177e4SLinus Torvalds     GNU General Public License for more details.
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds     You should have received a copy of the GNU General Public License
191da177e4SLinus Torvalds     along with this program; if not, write to the Free Software
201da177e4SLinus Torvalds     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
211da177e4SLinus Torvalds */
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/ioport.h>
251da177e4SLinus Torvalds #include <linux/kernel.h>
261da177e4SLinus Torvalds #include <linux/module.h>
271da177e4SLinus Torvalds #include <linux/pci.h>
281da177e4SLinus Torvalds #include <linux/interrupt.h>
291da177e4SLinus Torvalds #include <asm/io.h>
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #include <scsi/scsi_host.h>
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds /*
346070d81eSAdam Buchbinder  * Definitions for the generic 5380 driver.
351da177e4SLinus Torvalds  */
361da177e4SLinus Torvalds 
37*61e1ce58SFinn Thain #define NCR5380_read(reg)		inb(hostdata->base + (reg))
38*61e1ce58SFinn Thain #define NCR5380_write(reg, value)	outb(value, hostdata->base + (reg))
391da177e4SLinus Torvalds 
40f825e40bSFinn Thain #define NCR5380_dma_xfer_len(instance, cmd, phase)	(0)
416c4b88caSFinn Thain #define NCR5380_dma_recv_setup(instance, dst, len)	(0)
426c4b88caSFinn Thain #define NCR5380_dma_send_setup(instance, src, len)	(0)
438053b0eeSFinn Thain #define NCR5380_dma_residual(instance)			(0)
44f825e40bSFinn Thain 
45acfc8cadSFinn Thain #define NCR5380_implementation_fields	/* none */
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds #include "NCR5380.h"
481da177e4SLinus Torvalds #include "NCR5380.c"
491da177e4SLinus Torvalds 
501da177e4SLinus Torvalds #define DMX3191D_DRIVER_NAME	"dmx3191d"
511da177e4SLinus Torvalds #define DMX3191D_REGION_LEN	8
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds static struct scsi_host_template dmx3191d_driver_template = {
55aa2e2cb1SFinn Thain 	.module			= THIS_MODULE,
561da177e4SLinus Torvalds 	.proc_name		= DMX3191D_DRIVER_NAME,
571da177e4SLinus Torvalds 	.name			= "Domex DMX3191D",
588c32513bSFinn Thain 	.info			= NCR5380_info,
591da177e4SLinus Torvalds 	.queuecommand		= NCR5380_queue_command,
601da177e4SLinus Torvalds 	.eh_abort_handler	= NCR5380_abort,
611da177e4SLinus Torvalds 	.eh_bus_reset_handler	= NCR5380_bus_reset,
621da177e4SLinus Torvalds 	.can_queue		= 32,
631da177e4SLinus Torvalds 	.this_id		= 7,
641da177e4SLinus Torvalds 	.sg_tablesize		= SG_ALL,
651da177e4SLinus Torvalds 	.cmd_per_lun		= 2,
661da177e4SLinus Torvalds 	.use_clustering		= DISABLE_CLUSTERING,
6732b26a10SFinn Thain 	.cmd_size		= NCR5380_CMD_SIZE,
681da177e4SLinus Torvalds };
691da177e4SLinus Torvalds 
706f039790SGreg Kroah-Hartman static int dmx3191d_probe_one(struct pci_dev *pdev,
711da177e4SLinus Torvalds 			      const struct pci_device_id *id)
721da177e4SLinus Torvalds {
731da177e4SLinus Torvalds 	struct Scsi_Host *shost;
74820682b1SFinn Thain 	struct NCR5380_hostdata *hostdata;
751da177e4SLinus Torvalds 	unsigned long io;
761da177e4SLinus Torvalds 	int error = -ENODEV;
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds 	if (pci_enable_device(pdev))
791da177e4SLinus Torvalds 		goto out;
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds 	io = pci_resource_start(pdev, 0);
821da177e4SLinus Torvalds 	if (!request_region(io, DMX3191D_REGION_LEN, DMX3191D_DRIVER_NAME)) {
831da177e4SLinus Torvalds 		printk(KERN_ERR "dmx3191: region 0x%lx-0x%lx already reserved\n",
841da177e4SLinus Torvalds 				io, io + DMX3191D_REGION_LEN);
851da177e4SLinus Torvalds 		goto out_disable_device;
861da177e4SLinus Torvalds 	}
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	shost = scsi_host_alloc(&dmx3191d_driver_template,
891da177e4SLinus Torvalds 			sizeof(struct NCR5380_hostdata));
901da177e4SLinus Torvalds 	if (!shost)
911da177e4SLinus Torvalds 		goto out_release_region;
92820682b1SFinn Thain 
93820682b1SFinn Thain 	hostdata = shost_priv(shost);
94820682b1SFinn Thain 	hostdata->base = io;
95fd9cd67cSFinn Thain 
96fd9cd67cSFinn Thain 	/* This card does not seem to raise an interrupt on pdev->irq.
97fd9cd67cSFinn Thain 	 * Steam-powered SCSI controllers run without an IRQ anyway.
98fd9cd67cSFinn Thain 	 */
99fd9cd67cSFinn Thain 	shost->irq = NO_IRQ;
1001da177e4SLinus Torvalds 
1017e9ec8d9SFinn Thain 	error = NCR5380_init(shost, 0);
1020ad0eff9SFinn Thain 	if (error)
1030ad0eff9SFinn Thain 		goto out_host_put;
1041da177e4SLinus Torvalds 
105b6488f97SFinn Thain 	NCR5380_maybe_reset_bus(shost);
106b6488f97SFinn Thain 
1071da177e4SLinus Torvalds 	pci_set_drvdata(pdev, shost);
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	error = scsi_add_host(shost, &pdev->dev);
1101da177e4SLinus Torvalds 	if (error)
1110ad0eff9SFinn Thain 		goto out_exit;
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	scsi_scan_host(shost);
1141da177e4SLinus Torvalds 	return 0;
1151da177e4SLinus Torvalds 
1160ad0eff9SFinn Thain out_exit:
1170ad0eff9SFinn Thain 	NCR5380_exit(shost);
1180ad0eff9SFinn Thain out_host_put:
1190ad0eff9SFinn Thain 	scsi_host_put(shost);
1201da177e4SLinus Torvalds  out_release_region:
121c3c026baSAdrian Bunk 	release_region(io, DMX3191D_REGION_LEN);
1221da177e4SLinus Torvalds  out_disable_device:
1231da177e4SLinus Torvalds 	pci_disable_device(pdev);
1241da177e4SLinus Torvalds  out:
1251da177e4SLinus Torvalds 	return error;
1261da177e4SLinus Torvalds }
1271da177e4SLinus Torvalds 
1286f039790SGreg Kroah-Hartman static void dmx3191d_remove_one(struct pci_dev *pdev)
1291da177e4SLinus Torvalds {
1301da177e4SLinus Torvalds 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
131820682b1SFinn Thain 	struct NCR5380_hostdata *hostdata = shost_priv(shost);
132820682b1SFinn Thain 	unsigned long io = hostdata->base;
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	scsi_remove_host(shost);
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds 	NCR5380_exit(shost);
1371da177e4SLinus Torvalds 	scsi_host_put(shost);
1380ad0eff9SFinn Thain 	release_region(io, DMX3191D_REGION_LEN);
1390ad0eff9SFinn Thain 	pci_disable_device(pdev);
1401da177e4SLinus Torvalds }
1411da177e4SLinus Torvalds 
1421da177e4SLinus Torvalds static struct pci_device_id dmx3191d_pci_tbl[] = {
1431da177e4SLinus Torvalds 	{PCI_VENDOR_ID_DOMEX, PCI_DEVICE_ID_DOMEX_DMX3191D,
1441da177e4SLinus Torvalds 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
1451da177e4SLinus Torvalds 	{ }
1461da177e4SLinus Torvalds };
1471da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, dmx3191d_pci_tbl);
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds static struct pci_driver dmx3191d_pci_driver = {
1501da177e4SLinus Torvalds 	.name		= DMX3191D_DRIVER_NAME,
1511da177e4SLinus Torvalds 	.id_table	= dmx3191d_pci_tbl,
1521da177e4SLinus Torvalds 	.probe		= dmx3191d_probe_one,
1536f039790SGreg Kroah-Hartman 	.remove		= dmx3191d_remove_one,
1541da177e4SLinus Torvalds };
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds static int __init dmx3191d_init(void)
1571da177e4SLinus Torvalds {
158dcbccbdeSHenrik Kretzschmar 	return pci_register_driver(&dmx3191d_pci_driver);
1591da177e4SLinus Torvalds }
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds static void __exit dmx3191d_exit(void)
1621da177e4SLinus Torvalds {
1631da177e4SLinus Torvalds 	pci_unregister_driver(&dmx3191d_pci_driver);
1641da177e4SLinus Torvalds }
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds module_init(dmx3191d_init);
1671da177e4SLinus Torvalds module_exit(dmx3191d_exit);
1681da177e4SLinus Torvalds 
1691da177e4SLinus Torvalds MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
1701da177e4SLinus Torvalds MODULE_DESCRIPTION("Domex DMX3191D SCSI driver");
1711da177e4SLinus Torvalds MODULE_LICENSE("GPL");
172