From 6c223761eb5482dca2bd981d0a800c4aba3c9009 Mon Sep 17 00:00:00 2001 From: Kevin Barnett Date: Mon, 27 Jun 2016 16:41:00 -0500 Subject: smartpqi: initial commit of Microsemi smartpqi driver This initial commit contains Microsemi's smartpqi module. [mkp: Minor tweaks to apply to 4.9/scsi-queue] Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Kevin Barnett Signed-off-by: Don Brace Reviewed-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- MAINTAINERS | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 20bb1d00098c..5f502248ba7b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7819,6 +7819,17 @@ W: http://www.melexis.com S: Supported F: drivers/iio/temperature/mlx90614.c +MICROSEMI SMART ARRAY SMARTPQI DRIVER (smartpqi) +M: Don Brace +L: esc.storagedev@microsemi.com +L: linux-scsi@vger.kernel.org +S: Supported +F: drivers/scsi/smartpqi/smartpqi*.[ch] +F: drivers/scsi/smartpqi/Kconfig +F: drivers/scsi/smartpqi/Makefile +F: include/linux/cciss*.h +F: include/uapi/linux/cciss*.h + MN88472 MEDIA DRIVER M: Antti Palosaari L: linux-media@vger.kernel.org -- cgit v1.2.3 From 2a1e8447153259922c0d97eb5d35f76c9b41fbb0 Mon Sep 17 00:00:00 2001 From: Jitendra Bhivare Date: Fri, 19 Aug 2016 15:20:26 +0530 Subject: MAINTAINERS: Update be2iscsi contact info Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- MAINTAINERS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 5f502248ba7b..fec431c94002 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10562,12 +10562,12 @@ S: Maintained F: drivers/misc/phantom.c F: include/uapi/linux/phantom.h -SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER -M: Jayamohan Kallickal -M: Ketan Mukadam -M: John Soni Jose +Emulex 10Gbps iSCSI - OneConnect DRIVER +M: Subbu Seetharaman +M: Ketan Mukadam +M: Jitendra Bhivare L: linux-scsi@vger.kernel.org -W: http://www.avagotech.com +W: http://www.broadcom.com S: Supported F: drivers/scsi/be2iscsi/ -- cgit v1.2.3 From 425b490b2aa745740ea3618e1cdcc2bc37c0d996 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 31 Aug 2016 14:55:30 -0500 Subject: scsi: smartpqi: add smartpqi.txt added Documentation/scsi/smartpqi.txt [mkp: applied by hand] Reviewed-by: Kevin Barnett Reviewed-by: Scott Benesh Reviewed-by: Johannes Thumshirn Signed-off-by: Don Brace Reviewed-by: Tomas Henzl Signed-off-by: Martin K. Petersen --- Documentation/scsi/smartpqi.txt | 80 +++++++++++++++++++++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 81 insertions(+) create mode 100644 Documentation/scsi/smartpqi.txt (limited to 'MAINTAINERS') diff --git a/Documentation/scsi/smartpqi.txt b/Documentation/scsi/smartpqi.txt new file mode 100644 index 000000000000..ab377d9e5d1b --- /dev/null +++ b/Documentation/scsi/smartpqi.txt @@ -0,0 +1,80 @@ + +SMARTPQI - Microsemi Smart PQI Driver +----------------------------------------- + +This file describes the smartpqi SCSI driver for Microsemi +(http://www.microsemi.com) PQI controllers. The smartpqi driver +is the next generation SCSI driver for Microsemi Corp. The smartpqi +driver is the first SCSI driver to implement the PQI queuing model. + +The smartpqi driver will replace the aacraid driver for Adaptec Series 9 +controllers. Customers running an older kernel (Pre-4.9) using an Adaptec +Series 9 controller will have to configure the smartpqi driver or their +volumes will not be added to the OS. + +For Microsemi smartpqi controller support, enable the smartpqi driver +when configuring the kernel. + +For more information on the PQI Queuing Interface, please see: +http://www.t10.org/drafts.htm +http://www.t10.org/members/w_pqi2.htm + +Supported devices: +------------------ + + +smartpqi specific entries in /sys +----------------------------- + + smartpqi host attributes: + ------------------------- + /sys/class/scsi_host/host*/rescan + /sys/class/scsi_host/host*/version + + The host rescan attribute is a write only attribute. Writing to this + attribute will trigger the driver to scan for new, changed, or removed + devices and notify the SCSI mid-layer of any changes detected. + + The version attribute is read-only and will return the driver version + and the controller firmware version. + For example: + driver: 0.9.13-370 + firmware: 0.01-522 + + smartpqi sas device attributes + ------------------------------ + HBA devices are added to the SAS transport layer. These attributes are + automatically added by the SAS transport layer. + + /sys/class/sas_device/end_device-X:X/sas_address + /sys/class/sas_device/end_device-X:X/enclosure_identifier + /sys/class/sas_device/end_device-X:X/scsi_target_id + +smartpqi specific ioctls: +------------------------- + + For compatibility with applications written for the cciss protocol. + + CCISS_DEREGDISK + CCISS_REGNEWDISK + CCISS_REGNEWD + + The above three ioctls all do exactly the same thing, which is to cause the driver + to rescan for new devices. This does exactly the same thing as writing to the + smartpqi specific host "rescan" attribute. + + CCISS_GETPCIINFO + + Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID). + + CCISS_GETDRIVVER + + Returns driver version in three bytes encoded as: + (DRIVER_MAJOR << 28) | (DRIVER_MINOR << 24) | (DRIVER_RELEASE << 16) | DRIVER_REVISION; + + CCISS_PASSTHRU + + Allows "BMIC" and "CISS" commands to be passed through to the Smart Storage Array. + These are used extensively by the SSA Array Configuration Utility, SNMP storage + agents, etc. + diff --git a/MAINTAINERS b/MAINTAINERS index fec431c94002..dd4966d30a27 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7829,6 +7829,7 @@ F: drivers/scsi/smartpqi/Kconfig F: drivers/scsi/smartpqi/Makefile F: include/linux/cciss*.h F: include/uapi/linux/cciss*.h +F: Documentation/scsi/smartpqi.txt MN88472 MEDIA DRIVER M: Antti Palosaari -- cgit v1.2.3 From 9b3a34fb2125141720515b79ed2228545645a7bc Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Sep 2016 08:50:47 -0700 Subject: scsi: wd7000: remove from tree The driver has not seen any maintainer activity or other work that wasn't tree wide conversion or clenaups in the entire history of the git tree. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi-parameters.txt | 3 - MAINTAINERS | 6 - drivers/scsi/Kconfig | 12 - drivers/scsi/Makefile | 1 - drivers/scsi/wd7000.c | 1657 -------------------------------- 5 files changed, 1679 deletions(-) delete mode 100644 drivers/scsi/wd7000.c (limited to 'MAINTAINERS') diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index d5ae6ced6be3..5a5c6088a6ec 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -131,6 +131,3 @@ parameters may be changed at runtime by the command wd33c93= [HW,SCSI] See header of drivers/scsi/wd33c93.c. - - wd7000= [HW,SCSI] - See header of drivers/scsi/wd7000.c. diff --git a/MAINTAINERS b/MAINTAINERS index dd4966d30a27..fdcce6b52cba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12699,12 +12699,6 @@ F: drivers/watchdog/ F: include/linux/watchdog.h F: include/uapi/linux/watchdog.h -WD7000 SCSI DRIVER -M: Miroslav Zagorac -L: linux-scsi@vger.kernel.org -S: Maintained -F: drivers/scsi/wd7000.c - WIIMOTE HID DRIVER M: David Herrmann L: linux-input@vger.kernel.org diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 75de1dc725a1..15c6e9f2162d 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -396,18 +396,6 @@ config SCSI_3W_SAS Please read the comments at the top of . -config SCSI_7000FASST - tristate "7000FASST SCSI support" - depends on ISA && SCSI && ISA_DMA_API - select CHECK_SIGNATURE - help - This driver supports the Western Digital 7000 SCSI host adapter - family. Some information is in the source: - . - - To compile this driver as a module, choose M here: the - module will be called wd7000. - config SCSI_ACARD tristate "ACARD SCSI support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index fc0d9b8f2bdf..d870cc51d0bb 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -99,7 +99,6 @@ obj-$(CONFIG_SCSI_DTC3280) += dtc.o obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o -obj-$(CONFIG_SCSI_7000FASST) += wd7000.o obj-$(CONFIG_SCSI_EATA) += eata.o obj-$(CONFIG_SCSI_DC395x) += dc395x.o obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c deleted file mode 100644 index 409f959845c4..000000000000 --- a/drivers/scsi/wd7000.c +++ /dev/null @@ -1,1657 +0,0 @@ -/* $Id: $ - * linux/drivers/scsi/wd7000.c - * - * Copyright (C) 1992 Thomas Wuensche - * closely related to the aha1542 driver from Tommy Thorn - * ( as close as different hardware allows on a lowlevel-driver :-) ) - * - * Revised (and renamed) by John Boyd to - * accommodate Eric Youngdale's modifications to scsi.c. Nov 1992. - * - * Additional changes to support scatter/gather. Dec. 1992. tw/jb - * - * No longer tries to reset SCSI bus at boot (it wasn't working anyway). - * Rewritten to support multiple host adapters. - * Miscellaneous cleanup. - * So far, still doesn't do reset or abort correctly, since I have no idea - * how to do them with this board (8^(. Jan 1994 jb - * - * This driver now supports both of the two standard configurations (per - * the 3.36 Owner's Manual, my latest reference) by the same method as - * before; namely, by looking for a BIOS signature. Thus, the location of - * the BIOS signature determines the board configuration. Until I have - * time to do something more flexible, users should stick to one of the - * following: - * - * Standard configuration for single-adapter systems: - * - BIOS at CE00h - * - I/O base address 350h - * - IRQ level 15 - * - DMA channel 6 - * Standard configuration for a second adapter in a system: - * - BIOS at C800h - * - I/O base address 330h - * - IRQ level 11 - * - DMA channel 5 - * - * Anyone who can recompile the kernel is welcome to add others as need - * arises, but unpredictable results may occur if there are conflicts. - * In any event, if there are multiple adapters in a system, they MUST - * use different I/O bases, IRQ levels, and DMA channels, since they will be - * indistinguishable (and in direct conflict) otherwise. - * - * As a point of information, the NO_OP command toggles the CMD_RDY bit - * of the status port, and this fact could be used as a test for the I/O - * base address (or more generally, board detection). There is an interrupt - * status port, so IRQ probing could also be done. I suppose the full - * DMA diagnostic could be used to detect the DMA channel being used. I - * haven't done any of this, though, because I think there's too much of - * a chance that such explorations could be destructive, if some other - * board's resources are used inadvertently. So, call me a wimp, but I - * don't want to try it. The only kind of exploration I trust is memory - * exploration, since it's more certain that reading memory won't be - * destructive. - * - * More to my liking would be a LILO boot command line specification, such - * as is used by the aha152x driver (and possibly others). I'll look into - * it, as I have time... - * - * I get mail occasionally from people who either are using or are - * considering using a WD7000 with Linux. There is a variety of - * nomenclature describing WD7000's. To the best of my knowledge, the - * following is a brief summary (from an old WD doc - I don't work for - * them or anything like that): - * - * WD7000-FASST2: This is a WD7000 board with the real-mode SST ROM BIOS - * installed. Last I heard, the BIOS was actually done by Columbia - * Data Products. The BIOS is only used by this driver (and thus - * by Linux) to identify the board; none of it can be executed under - * Linux. - * - * WD7000-ASC: This is the original adapter board, with or without BIOS. - * The board uses a WD33C93 or WD33C93A SBIC, which in turn is - * controlled by an onboard Z80 processor. The board interface - * visible to the host CPU is defined effectively by the Z80's - * firmware, and it is this firmware's revision level that is - * determined and reported by this driver. (The version of the - * on-board BIOS is of no interest whatsoever.) The host CPU has - * no access to the SBIC; hence the fact that it is a WD33C93 is - * also of no interest to this driver. - * - * WD7000-AX: - * WD7000-MX: - * WD7000-EX: These are newer versions of the WD7000-ASC. The -ASC is - * largely built from discrete components; these boards use more - * integration. The -AX is an ISA bus board (like the -ASC), - * the -MX is an MCA (i.e., PS/2) bus board), and the -EX is an - * EISA bus board. - * - * At the time of my documentation, the -?X boards were "future" products, - * and were not yet available. However, I vaguely recall that Thomas - * Wuensche had an -AX, so I believe at least it is supported by this - * driver. I have no personal knowledge of either -MX or -EX boards. - * - * P.S. Just recently, I've discovered (directly from WD and Future - * Domain) that all but the WD7000-EX have been out of production for - * two years now. FD has production rights to the 7000-EX, and are - * producing it under a new name, and with a new BIOS. If anyone has - * one of the FD boards, it would be nice to come up with a signature - * for it. - * J.B. Jan 1994. - * - * - * Revisions by Miroslav Zagorac - * - * 08/24/1996. - * - * Enhancement for wd7000_detect function has been made, so you don't have - * to enter BIOS ROM address in initialisation data (see struct Config). - * We cannot detect IRQ, DMA and I/O base address for now, so we have to - * enter them as arguments while wd_7000 is detected. If someone has IRQ, - * DMA or I/O base address set to some other value, he can enter them in - * configuration without any problem. Also I wrote a function wd7000_setup, - * so now you can enter WD-7000 definition as kernel arguments, - * as in lilo.conf: - * - * append="wd7000=IRQ,DMA,IO" - * - * PS: If card BIOS ROM is disabled, function wd7000_detect now will recognize - * adapter, unlike the old one. Anyway, BIOS ROM from WD7000 adapter is - * useless for Linux. B^) - * - * - * 09/06/1996. - * - * Autodetecting of I/O base address from wd7000_detect function is removed, - * some little bugs removed, etc... - * - * Thanks to Roger Scott for driver debugging. - * - * 06/07/1997 - * - * Added support for /proc file system (/proc/scsi/wd7000/[0...] files). - * Now, driver can handle hard disks with capacity >1GB. - * - * 01/15/1998 - * - * Added support for BUS_ON and BUS_OFF parameters in config line. - * Miscellaneous cleanup. - * - * 03/01/1998 - * - * WD7000 driver now work on kernels >= 2.1.x - * - * - * 12/31/2001 - Arnaldo Carvalho de Melo - * - * use host->host_lock, not io_request_lock, cleanups - * - * 2002/10/04 - Alan Cox - * - * Use dev_id for interrupts, kill __func__ pasting - * Add a lock for the scb pool, clean up all other cli/sti usage stuff - * Use the adapter lock for the other places we had the cli's - * - * 2002/10/06 - Alan Cox - * - * Switch to new style error handling - * Clean up delay to udelay, and yielding sleeps - * Make host reset actually reset the card - * Make everything static - * - * 2003/02/12 - Christoph Hellwig - * - * Cleaned up host template definition - * Removed now obsolete wd7000.h - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - - -#undef WD7000_DEBUG /* general debug */ -#ifdef WD7000_DEBUG -#define dprintk printk -#else -#define dprintk no_printk -#endif - -/* - * Mailbox structure sizes. - * I prefer to keep the number of ICMBs much larger than the number of - * OGMBs. OGMBs are used very quickly by the driver to start one or - * more commands, while ICMBs are used by the host adapter per command. - */ -#define OGMB_CNT 16 -#define ICMB_CNT 32 - -/* - * Scb's are shared by all active adapters. So, if they all become busy, - * callers may be made to wait in alloc_scbs for them to free. That can - * be avoided by setting MAX_SCBS to NUM_CONFIG * WD7000_Q. If you'd - * rather conserve memory, use a smaller number (> 0, of course) - things - * will should still work OK. - */ -#define MAX_SCBS 32 - -/* - * In this version, sg_tablesize now defaults to WD7000_SG, and will - * be set to SG_NONE for older boards. This is the reverse of the - * previous default, and was changed so that the driver-level - * scsi_host_template would reflect the driver's support for scatter/ - * gather. - * - * Also, it has been reported that boards at Revision 6 support scatter/ - * gather, so the new definition of an "older" board has been changed - * accordingly. - */ -#define WD7000_Q 16 -#define WD7000_SG 16 - - -/* - * WD7000-specific mailbox structure - * - */ -typedef volatile struct mailbox { - unchar status; - unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */ -} Mailbox; - -/* - * This structure should contain all per-adapter global data. I.e., any - * new global per-adapter data should put in here. - */ -typedef struct adapter { - struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */ - int iobase; /* This adapter's I/O base address */ - int irq; /* This adapter's IRQ level */ - int dma; /* This adapter's DMA channel */ - int int_counter; /* This adapter's interrupt counter */ - int bus_on; /* This adapter's BUS_ON time */ - int bus_off; /* This adapter's BUS_OFF time */ - struct { /* This adapter's mailboxes */ - Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */ - Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */ - } mb; - int next_ogmb; /* to reduce contention at mailboxes */ - unchar control; /* shadows CONTROL port value */ - unchar rev1, rev2; /* filled in by wd7000_revision */ -} Adapter; - -/* - * (linear) base address for ROM BIOS - */ -static const long wd7000_biosaddr[] = { - 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000, - 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000 -}; -#define NUM_ADDRS ARRAY_SIZE(wd7000_biosaddr) - -static const unsigned short wd7000_iobase[] = { - 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, - 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378, - 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, - 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8 -}; -#define NUM_IOPORTS ARRAY_SIZE(wd7000_iobase) - -static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 }; -#define NUM_IRQS ARRAY_SIZE(wd7000_irq) - -static const short wd7000_dma[] = { 5, 6, 7 }; -#define NUM_DMAS ARRAY_SIZE(wd7000_dma) - -/* - * The following is set up by wd7000_detect, and used thereafter for - * proc and other global ookups - */ - -#define UNITS 8 -static struct Scsi_Host *wd7000_host[UNITS]; - -#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */ -#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */ - -/* - * Standard Adapter Configurations - used by wd7000_detect - */ -typedef struct { - short irq; /* IRQ level */ - short dma; /* DMA channel */ - unsigned iobase; /* I/O base address */ - short bus_on; /* Time that WD7000 spends on the AT-bus when */ - /* transferring data. BIOS default is 8000ns. */ - short bus_off; /* Time that WD7000 spends OFF THE BUS after */ - /* while it is transferring data. */ - /* BIOS default is 1875ns */ -} Config; - -/* - * Add here your configuration... - */ -static Config configs[] = { - {15, 6, 0x350, BUS_ON, BUS_OFF}, /* defaults for single adapter */ - {11, 5, 0x320, BUS_ON, BUS_OFF}, /* defaults for second adapter */ - {7, 6, 0x350, BUS_ON, BUS_OFF}, /* My configuration (Zaga) */ - {-1, -1, 0x0, BUS_ON, BUS_OFF} /* Empty slot */ -}; -#define NUM_CONFIGS ARRAY_SIZE(configs) - -/* - * The following list defines strings to look for in the BIOS that identify - * it as the WD7000-FASST2 SST BIOS. I suspect that something should be - * added for the Future Domain version. - */ -typedef struct signature { - const char *sig; /* String to look for */ - unsigned long ofs; /* offset from BIOS base address */ - unsigned len; /* length of string */ -} Signature; - -static const Signature signatures[] = { - {"SSTBIOS", 0x0000d, 7} /* "SSTBIOS" @ offset 0x0000d */ -}; -#define NUM_SIGNATURES ARRAY_SIZE(signatures) - - -/* - * I/O Port Offsets and Bit Definitions - * 4 addresses are used. Those not defined here are reserved. - */ -#define ASC_STAT 0 /* Status, Read */ -#define ASC_COMMAND 0 /* Command, Write */ -#define ASC_INTR_STAT 1 /* Interrupt Status, Read */ -#define ASC_INTR_ACK 1 /* Acknowledge, Write */ -#define ASC_CONTROL 2 /* Control, Write */ - -/* - * ASC Status Port - */ -#define INT_IM 0x80 /* Interrupt Image Flag */ -#define CMD_RDY 0x40 /* Command Port Ready */ -#define CMD_REJ 0x20 /* Command Port Byte Rejected */ -#define ASC_INIT 0x10 /* ASC Initialized Flag */ -#define ASC_STATMASK 0xf0 /* The lower 4 Bytes are reserved */ - -/* - * COMMAND opcodes - * - * Unfortunately, I have no idea how to properly use some of these commands, - * as the OEM manual does not make it clear. I have not been able to use - * enable/disable unsolicited interrupts or the reset commands with any - * discernible effect whatsoever. I think they may be related to certain - * ICB commands, but again, the OEM manual doesn't make that clear. - */ -#define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */ -#define INITIALIZATION 1 /* initialization (10 bytes) */ -#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */ -#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */ -#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */ -#define SOFT_RESET 5 /* SCSI bus soft reset */ -#define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */ -#define START_OGMB 0x80 /* start command in OGMB (n) */ -#define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */ - /* where (n) = lower 6 bits */ -/* - * For INITIALIZATION: - */ -typedef struct initCmd { - unchar op; /* command opcode (= 1) */ - unchar ID; /* Adapter's SCSI ID */ - unchar bus_on; /* Bus on time, x 125ns (see below) */ - unchar bus_off; /* Bus off time, "" "" */ - unchar rsvd; /* Reserved */ - unchar mailboxes[3]; /* Address of Mailboxes, MSB first */ - unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */ - unchar icmbs; /* Number of incoming MBs, "" "" */ -} InitCmd; - -/* - * Interrupt Status Port - also returns diagnostic codes at ASC reset - * - * if msb is zero, the lower bits are diagnostic status - * Diagnostics: - * 01 No diagnostic error occurred - * 02 RAM failure - * 03 FIFO R/W failed - * 04 SBIC register read/write failed - * 05 Initialization D-FF failed - * 06 Host IRQ D-FF failed - * 07 ROM checksum error - * Interrupt status (bitwise): - * 10NNNNNN outgoing mailbox NNNNNN is free - * 11NNNNNN incoming mailbox NNNNNN needs service - */ -#define MB_INTR 0xC0 /* Mailbox Service possible/required */ -#define IMB_INTR 0x40 /* 1 Incoming / 0 Outgoing */ -#define MB_MASK 0x3f /* mask for mailbox number */ - -/* - * CONTROL port bits - */ -#define INT_EN 0x08 /* Interrupt Enable */ -#define DMA_EN 0x04 /* DMA Enable */ -#define SCSI_RES 0x02 /* SCSI Reset */ -#define ASC_RES 0x01 /* ASC Reset */ - -/* - * Driver data structures: - * - mb and scbs are required for interfacing with the host adapter. - * An SCB has extra fields not visible to the adapter; mb's - * _cannot_ do this, since the adapter assumes they are contiguous in - * memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact - * to access them. - * - An icb is for host-only (non-SCSI) commands. ICBs are 16 bytes each; - * the additional bytes are used only by the driver. - * - For now, a pool of SCBs are kept in global storage by this driver, - * and are allocated and freed as needed. - * - * The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command, - * not when it has finished. Since the SCB must be around for completion, - * problems arise when SCBs correspond to OGMBs, which may be reallocated - * earlier (or delayed unnecessarily until a command completes). - * Mailboxes are used as transient data structures, simply for - * carrying SCB addresses to/from the 7000-FASST2. - * - * Note also since SCBs are not "permanently" associated with mailboxes, - * there is no need to keep a global list of scsi_cmnd pointers indexed - * by OGMB. Again, SCBs reference their scsi_cmnds directly, so mailbox - * indices need not be involved. - */ - -/* - * WD7000-specific scatter/gather element structure - */ -typedef struct sgb { - unchar len[3]; - unchar ptr[3]; /* Also SCSI-style - MSB first */ -} Sgb; - -typedef struct scb { /* Command Control Block 5.4.1 */ - unchar op; /* Command Control Block Operation Code */ - unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ - /* Outbound data transfer, length is checked */ - /* Inbound data transfer, length is checked */ - /* Logical Unit Number */ - unchar cdb[12]; /* SCSI Command Block */ - volatile unchar status; /* SCSI Return Status */ - volatile unchar vue; /* Vendor Unique Error Code */ - unchar maxlen[3]; /* Maximum Data Transfer Length */ - unchar dataptr[3]; /* SCSI Data Block Pointer */ - unchar linkptr[3]; /* Next Command Link Pointer */ - unchar direc; /* Transfer Direction */ - unchar reserved2[6]; /* SCSI Command Descriptor Block */ - /* end of hardware SCB */ - struct scsi_cmnd *SCpnt;/* scsi_cmnd using this SCB */ - Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */ - Adapter *host; /* host adapter */ - struct scb *next; /* for lists of scbs */ -} Scb; - -/* - * This driver is written to allow host-only commands to be executed. - * These use a 16-byte block called an ICB. The format is extended by the - * driver to 18 bytes, to support the status returned in the ICMB and - * an execution phase code. - * - * There are other formats besides these; these are the ones I've tried - * to use. Formats for some of the defined ICB opcodes are not defined - * (notably, get/set unsolicited interrupt status) in my copy of the OEM - * manual, and others are ambiguous/hard to follow. - */ -#define ICB_OP_MASK 0x80 /* distinguishes scbs from icbs */ -#define ICB_OP_OPEN_RBUF 0x80 /* open receive buffer */ -#define ICB_OP_RECV_CMD 0x81 /* receive command from initiator */ -#define ICB_OP_RECV_DATA 0x82 /* receive data from initiator */ -#define ICB_OP_RECV_SDATA 0x83 /* receive data with status from init. */ -#define ICB_OP_SEND_DATA 0x84 /* send data with status to initiator */ -#define ICB_OP_SEND_STAT 0x86 /* send command status to initiator */ - /* 0x87 is reserved */ -#define ICB_OP_READ_INIT 0x88 /* read initialization bytes */ -#define ICB_OP_READ_ID 0x89 /* read adapter's SCSI ID */ -#define ICB_OP_SET_UMASK 0x8A /* set unsolicited interrupt mask */ -#define ICB_OP_GET_UMASK 0x8B /* read unsolicited interrupt mask */ -#define ICB_OP_GET_REVISION 0x8C /* read firmware revision level */ -#define ICB_OP_DIAGNOSTICS 0x8D /* execute diagnostics */ -#define ICB_OP_SET_EPARMS 0x8E /* set execution parameters */ -#define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */ - -typedef struct icbRecvCmd { - unchar op; - unchar IDlun; /* Initiator SCSI ID/lun */ - unchar len[3]; /* command buffer length */ - unchar ptr[3]; /* command buffer address */ - unchar rsvd[7]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbRecvCmd; - -typedef struct icbSendStat { - unchar op; - unchar IDlun; /* Target SCSI ID/lun */ - unchar stat; /* (outgoing) completion status byte 1 */ - unchar rsvd[12]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbSendStat; - -typedef struct icbRevLvl { - unchar op; - volatile unchar primary; /* primary revision level (returned) */ - volatile unchar secondary; /* secondary revision level (returned) */ - unchar rsvd[12]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbRevLvl; - -typedef struct icbUnsMask { /* I'm totally guessing here */ - unchar op; - volatile unchar mask[14]; /* mask bits */ -#if 0 - unchar rsvd[12]; /* reserved */ -#endif - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbUnsMask; - -typedef struct icbDiag { - unchar op; - unchar type; /* diagnostics type code (0-3) */ - unchar len[3]; /* buffer length */ - unchar ptr[3]; /* buffer address */ - unchar rsvd[7]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbDiag; - -#define ICB_DIAG_POWERUP 0 /* Power-up diags only */ -#define ICB_DIAG_WALKING 1 /* walking 1's pattern */ -#define ICB_DIAG_DMA 2 /* DMA - system memory diags */ -#define ICB_DIAG_FULL 3 /* do both 1 & 2 */ - -typedef struct icbParms { - unchar op; - unchar rsvd1; /* reserved */ - unchar len[3]; /* parms buffer length */ - unchar ptr[3]; /* parms buffer address */ - unchar idx[2]; /* index (MSB-LSB) */ - unchar rsvd2[5]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbParms; - -typedef struct icbAny { - unchar op; - unchar data[14]; /* format-specific data */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbAny; - -typedef union icb { - unchar op; /* ICB opcode */ - IcbRecvCmd recv_cmd; /* format for receive command */ - IcbSendStat send_stat; /* format for send status */ - IcbRevLvl rev_lvl; /* format for get revision level */ - IcbDiag diag; /* format for execute diagnostics */ - IcbParms eparms; /* format for get/set exec parms */ - IcbAny icb; /* generic format */ - unchar data[18]; -} Icb; - -#ifdef MODULE -static char *wd7000; -module_param(wd7000, charp, 0); -#endif - -/* - * Driver SCB structure pool. - * - * The SCBs declared here are shared by all host adapters; hence, this - * structure is not part of the Adapter structure. - */ -static Scb scbs[MAX_SCBS]; -static Scb *scbfree; /* free list */ -static int freescbs = MAX_SCBS; /* free list counter */ -static spinlock_t scbpool_lock; /* guards the scb free list and count */ - -/* - * END of data/declarations - code follows. - */ -static void __init setup_error(char *mesg, int *ints) -{ - if (ints[0] == 3) - printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n", ints[1], ints[2], ints[3], mesg); - else if (ints[0] == 4) - printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n", ints[1], ints[2], ints[3], ints[4], mesg); - else - printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n", ints[1], ints[2], ints[3], ints[4], ints[5], mesg); -} - - -/* - * Note: You can now set these options from the kernel's "command line". - * The syntax is: - * - * wd7000=,,[,[,]] - * - * , where BUS_ON and BUS_OFF are in nanoseconds. BIOS default values - * are 8000ns for BUS_ON and 1875ns for BUS_OFF. - * eg: - * wd7000=7,6,0x350 - * - * will configure the driver for a WD-7000 controller - * using IRQ 15 with a DMA channel 6, at IO base address 0x350. - */ -static int __init wd7000_setup(char *str) -{ - static short wd7000_card_num; /* .bss will zero this */ - short i; - int ints[6]; - - (void) get_options(str, ARRAY_SIZE(ints), ints); - - if (wd7000_card_num >= NUM_CONFIGS) { - printk(KERN_ERR "%s: Too many \"wd7000=\" configurations in " "command line!\n", __func__); - return 0; - } - - if ((ints[0] < 3) || (ints[0] > 5)) { - printk(KERN_ERR "%s: Error in command line! " "Usage: wd7000=,,IO>[," "[,]]\n", __func__); - } else { - for (i = 0; i < NUM_IRQS; i++) - if (ints[1] == wd7000_irq[i]) - break; - - if (i == NUM_IRQS) { - setup_error("invalid IRQ.", ints); - return 0; - } else - configs[wd7000_card_num].irq = ints[1]; - - for (i = 0; i < NUM_DMAS; i++) - if (ints[2] == wd7000_dma[i]) - break; - - if (i == NUM_DMAS) { - setup_error("invalid DMA channel.", ints); - return 0; - } else - configs[wd7000_card_num].dma = ints[2]; - - for (i = 0; i < NUM_IOPORTS; i++) - if (ints[3] == wd7000_iobase[i]) - break; - - if (i == NUM_IOPORTS) { - setup_error("invalid I/O base address.", ints); - return 0; - } else - configs[wd7000_card_num].iobase = ints[3]; - - if (ints[0] > 3) { - if ((ints[4] < 500) || (ints[4] > 31875)) { - setup_error("BUS_ON value is out of range (500" " to 31875 nanoseconds)!", ints); - configs[wd7000_card_num].bus_on = BUS_ON; - } else - configs[wd7000_card_num].bus_on = ints[4] / 125; - } else - configs[wd7000_card_num].bus_on = BUS_ON; - - if (ints[0] > 4) { - if ((ints[5] < 500) || (ints[5] > 31875)) { - setup_error("BUS_OFF value is out of range (500" " to 31875 nanoseconds)!", ints); - configs[wd7000_card_num].bus_off = BUS_OFF; - } else - configs[wd7000_card_num].bus_off = ints[5] / 125; - } else - configs[wd7000_card_num].bus_off = BUS_OFF; - - if (wd7000_card_num) { - for (i = 0; i < (wd7000_card_num - 1); i++) { - int j = i + 1; - - for (; j < wd7000_card_num; j++) - if (configs[i].irq == configs[j].irq) { - setup_error("duplicated IRQ!", ints); - return 0; - } - if (configs[i].dma == configs[j].dma) { - setup_error("duplicated DMA " "channel!", ints); - return 0; - } - if (configs[i].iobase == configs[j].iobase) { - setup_error("duplicated I/O " "base address!", ints); - return 0; - } - } - } - - dprintk(KERN_DEBUG "wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, " - "BUS_ON=%dns, BUS_OFF=%dns\n", configs[wd7000_card_num].irq, configs[wd7000_card_num].dma, configs[wd7000_card_num].iobase, configs[wd7000_card_num].bus_on * 125, configs[wd7000_card_num].bus_off * 125); - - wd7000_card_num++; - } - return 1; -} - -__setup("wd7000=", wd7000_setup); - -static inline void any2scsi(unchar * scsi, int any) -{ - *scsi++ = (unsigned)any >> 16; - *scsi++ = (unsigned)any >> 8; - *scsi++ = any; -} - -static inline int scsi2int(unchar * scsi) -{ - return (scsi[0] << 16) | (scsi[1] << 8) | scsi[2]; -} - -static inline void wd7000_enable_intr(Adapter * host) -{ - host->control |= INT_EN; - outb(host->control, host->iobase + ASC_CONTROL); -} - - -static inline void wd7000_enable_dma(Adapter * host) -{ - unsigned long flags; - host->control |= DMA_EN; - outb(host->control, host->iobase + ASC_CONTROL); - - flags = claim_dma_lock(); - set_dma_mode(host->dma, DMA_MODE_CASCADE); - enable_dma(host->dma); - release_dma_lock(flags); - -} - - -#define WAITnexttimeout 200 /* 2 seconds */ - -static inline short WAIT(unsigned port, unsigned mask, unsigned allof, unsigned noneof) -{ - unsigned WAITbits; - unsigned long WAITtimeout = jiffies + WAITnexttimeout; - - while (time_before_eq(jiffies, WAITtimeout)) { - WAITbits = inb(port) & mask; - - if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0)) - return (0); - } - - return (1); -} - - -static inline int command_out(Adapter * host, unchar * cmd, int len) -{ - if (!WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { - while (len--) { - do { - outb(*cmd, host->iobase + ASC_COMMAND); - WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0); - } while (inb(host->iobase + ASC_STAT) & CMD_REJ); - - cmd++; - } - - return (1); - } - - printk(KERN_WARNING "wd7000 command_out: WAIT failed(%d)\n", len + 1); - - return (0); -} - - -/* - * This version of alloc_scbs is in preparation for supporting multiple - * commands per lun and command chaining, by queueing pending commands. - * We will need to allocate Scbs in blocks since they will wait to be - * executed so there is the possibility of deadlock otherwise. - * Also, to keep larger requests from being starved by smaller requests, - * we limit access to this routine with an internal busy flag, so that - * the satisfiability of a request is not dependent on the size of the - * request. - */ -static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed) -{ - Scb *scb, *p = NULL; - unsigned long flags; - unsigned long timeout = jiffies + WAITnexttimeout; - unsigned long now; - int i; - - if (needed <= 0) - return (NULL); /* sanity check */ - - spin_unlock_irq(host->host_lock); - - retry: - while (freescbs < needed) { - timeout = jiffies + WAITnexttimeout; - do { - /* FIXME: can we actually just yield here ?? */ - for (now = jiffies; now == jiffies;) - cpu_relax(); /* wait a jiffy */ - } while (freescbs < needed && time_before_eq(jiffies, timeout)); - /* - * If we get here with enough free Scbs, we can take them. - * Otherwise, we timed out and didn't get enough. - */ - if (freescbs < needed) { - printk(KERN_ERR "wd7000: can't get enough free SCBs.\n"); - return (NULL); - } - } - - /* Take the lock, then check we didn't get beaten, if so try again */ - spin_lock_irqsave(&scbpool_lock, flags); - if (freescbs < needed) { - spin_unlock_irqrestore(&scbpool_lock, flags); - goto retry; - } - - scb = scbfree; - freescbs -= needed; - for (i = 0; i < needed; i++) { - p = scbfree; - scbfree = p->next; - } - p->next = NULL; - - spin_unlock_irqrestore(&scbpool_lock, flags); - - spin_lock_irq(host->host_lock); - return (scb); -} - - -static inline void free_scb(Scb * scb) -{ - unsigned long flags; - - spin_lock_irqsave(&scbpool_lock, flags); - - memset(scb, 0, sizeof(Scb)); - scb->next = scbfree; - scbfree = scb; - freescbs++; - - spin_unlock_irqrestore(&scbpool_lock, flags); -} - - -static inline void init_scbs(void) -{ - int i; - - spin_lock_init(&scbpool_lock); - - /* This is only ever called before the SCB pool is active */ - - scbfree = &(scbs[0]); - memset(scbs, 0, sizeof(scbs)); - for (i = 0; i < MAX_SCBS - 1; i++) { - scbs[i].next = &(scbs[i + 1]); - scbs[i].SCpnt = NULL; - } - scbs[MAX_SCBS - 1].next = NULL; - scbs[MAX_SCBS - 1].SCpnt = NULL; -} - - -static int mail_out(Adapter * host, Scb * scbptr) -/* - * Note: this can also be used for ICBs; just cast to the parm type. - */ -{ - int i, ogmb; - unsigned long flags; - unchar start_ogmb; - Mailbox *ogmbs = host->mb.ogmb; - int *next_ogmb = &(host->next_ogmb); - - dprintk("wd7000_mail_out: 0x%06lx", (long) scbptr); - - /* We first look for a free outgoing mailbox */ - spin_lock_irqsave(host->sh->host_lock, flags); - ogmb = *next_ogmb; - for (i = 0; i < OGMB_CNT; i++) { - if (ogmbs[ogmb].status == 0) { - dprintk(" using OGMB 0x%x", ogmb); - ogmbs[ogmb].status = 1; - any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr); - - *next_ogmb = (ogmb + 1) % OGMB_CNT; - break; - } else - ogmb = (ogmb + 1) % OGMB_CNT; - } - spin_unlock_irqrestore(host->sh->host_lock, flags); - - dprintk(", scb is 0x%06lx", (long) scbptr); - - if (i >= OGMB_CNT) { - /* - * Alternatively, we might issue the "interrupt on free OGMB", - * and sleep, but it must be ensured that it isn't the init - * task running. Instead, this version assumes that the caller - * will be persistent, and try again. Since it's the adapter - * that marks OGMB's free, waiting even with interrupts off - * should work, since they are freed very quickly in most cases. - */ - dprintk(", no free OGMBs.\n"); - return (0); - } - - wd7000_enable_intr(host); - - start_ogmb = START_OGMB | ogmb; - command_out(host, &start_ogmb, 1); - - dprintk(", awaiting interrupt.\n"); - - return (1); -} - - -static int make_code(unsigned hosterr, unsigned scsierr) -{ -#ifdef WD7000_DEBUG - int in_error = hosterr; -#endif - - switch ((hosterr >> 8) & 0xff) { - case 0: /* Reserved */ - hosterr = DID_ERROR; - break; - case 1: /* Command Complete, no errors */ - hosterr = DID_OK; - break; - case 2: /* Command complete, error logged in scb status (scsierr) */ - hosterr = DID_OK; - break; - case 4: /* Command failed to complete - timeout */ - hosterr = DID_TIME_OUT; - break; - case 5: /* Command terminated; Bus reset by external device */ - hosterr = DID_RESET; - break; - case 6: /* Unexpected Command Received w/ host as target */ - hosterr = DID_BAD_TARGET; - break; - case 80: /* Unexpected Reselection */ - case 81: /* Unexpected Selection */ - hosterr = DID_BAD_INTR; - break; - case 82: /* Abort Command Message */ - hosterr = DID_ABORT; - break; - case 83: /* SCSI Bus Software Reset */ - case 84: /* SCSI Bus Hardware Reset */ - hosterr = DID_RESET; - break; - default: /* Reserved */ - hosterr = DID_ERROR; - } -#ifdef WD7000_DEBUG - if (scsierr || hosterr) - dprintk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", scsierr, in_error, hosterr); -#endif - return (scsierr | (hosterr << 16)); -} - -#define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK) - - -static irqreturn_t wd7000_intr(int irq, void *dev_id) -{ - Adapter *host = (Adapter *) dev_id; - int flag, icmb, errstatus, icmb_status; - int host_error, scsi_error; - Scb *scb; /* for SCSI commands */ - IcbAny *icb; /* for host commands */ - struct scsi_cmnd *SCpnt; - Mailbox *icmbs = host->mb.icmb; - unsigned long flags; - - spin_lock_irqsave(host->sh->host_lock, flags); - host->int_counter++; - - dprintk("wd7000_intr: irq = %d, host = 0x%06lx\n", irq, (long) host); - - flag = inb(host->iobase + ASC_INTR_STAT); - - dprintk("wd7000_intr: intr stat = 0x%02x\n", flag); - - if (!(inb(host->iobase + ASC_STAT) & INT_IM)) { - /* NB: these are _very_ possible if IRQ 15 is being used, since - * it's the "garbage collector" on the 2nd 8259 PIC. Specifically, - * any interrupt signal into the 8259 which can't be identified - * comes out as 7 from the 8259, which is 15 to the host. Thus, it - * is a good thing the WD7000 has an interrupt status port, so we - * can sort these out. Otherwise, electrical noise and other such - * problems would be indistinguishable from valid interrupts... - */ - dprintk("wd7000_intr: phantom interrupt...\n"); - goto ack; - } - - if (!(flag & MB_INTR)) - goto ack; - - /* The interrupt is for a mailbox */ - if (!(flag & IMB_INTR)) { - dprintk("wd7000_intr: free outgoing mailbox\n"); - /* - * If sleep_on() and the "interrupt on free OGMB" command are - * used in mail_out(), wake_up() should correspondingly be called - * here. For now, we don't need to do anything special. - */ - goto ack; - } - - /* The interrupt is for an incoming mailbox */ - icmb = flag & MB_MASK; - icmb_status = icmbs[icmb].status; - if (icmb_status & 0x80) { /* unsolicited - result in ICMB */ - dprintk("wd7000_intr: unsolicited interrupt 0x%02x\n", icmb_status); - goto ack; - } - - /* Aaaargh! (Zaga) */ - scb = isa_bus_to_virt(scsi2int((unchar *) icmbs[icmb].scbptr)); - icmbs[icmb].status = 0; - if (scb->op & ICB_OP_MASK) { /* an SCB is done */ - icb = (IcbAny *) scb; - icb->status = icmb_status; - icb->phase = 0; - goto ack; - } - - SCpnt = scb->SCpnt; - if (--(SCpnt->SCp.phase) <= 0) { /* all scbs are done */ - host_error = scb->vue | (icmb_status << 8); - scsi_error = scb->status; - errstatus = make_code(host_error, scsi_error); - SCpnt->result = errstatus; - - free_scb(scb); - - SCpnt->scsi_done(SCpnt); - } - - ack: - dprintk("wd7000_intr: return from interrupt handler\n"); - wd7000_intr_ack(host); - - spin_unlock_irqrestore(host->sh->host_lock, flags); - return IRQ_HANDLED; -} - -static int wd7000_queuecommand_lck(struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)) -{ - Scb *scb; - Sgb *sgb; - unchar *cdb = (unchar *) SCpnt->cmnd; - unchar idlun; - short cdblen; - int nseg; - Adapter *host = (Adapter *) SCpnt->device->host->hostdata; - - cdblen = SCpnt->cmd_len; - idlun = ((SCpnt->device->id << 5) & 0xe0) | (SCpnt->device->lun & 7); - SCpnt->scsi_done = done; - SCpnt->SCp.phase = 1; - scb = alloc_scbs(SCpnt->device->host, 1); - scb->idlun = idlun; - memcpy(scb->cdb, cdb, cdblen); - scb->direc = 0x40; /* Disable direction check */ - - scb->SCpnt = SCpnt; /* so we can find stuff later */ - SCpnt->host_scribble = (unchar *) scb; - scb->host = host; - - nseg = scsi_sg_count(SCpnt); - if (nseg > 1) { - struct scatterlist *sg; - unsigned i; - - dprintk("Using scatter/gather with %d elements.\n", nseg); - - sgb = scb->sgb; - scb->op = 1; - any2scsi(scb->dataptr, (int) sgb); - any2scsi(scb->maxlen, nseg * sizeof(Sgb)); - - scsi_for_each_sg(SCpnt, sg, nseg, i) { - any2scsi(sgb[i].ptr, isa_page_to_bus(sg_page(sg)) + sg->offset); - any2scsi(sgb[i].len, sg->length); - } - } else { - scb->op = 0; - if (nseg) { - struct scatterlist *sg = scsi_sglist(SCpnt); - any2scsi(scb->dataptr, isa_page_to_bus(sg_page(sg)) + sg->offset); - } - any2scsi(scb->maxlen, scsi_bufflen(SCpnt)); - } - - /* FIXME: drop lock and yield here ? */ - - while (!mail_out(host, scb)) - cpu_relax(); /* keep trying */ - - return 0; -} - -static DEF_SCSI_QCMD(wd7000_queuecommand) - -static int wd7000_diagnostics(Adapter * host, int code) -{ - static IcbDiag icb = { ICB_OP_DIAGNOSTICS }; - static unchar buf[256]; - unsigned long timeout; - - icb.type = code; - any2scsi(icb.len, sizeof(buf)); - any2scsi(icb.ptr, (int) &buf); - icb.phase = 1; - /* - * This routine is only called at init, so there should be OGMBs - * available. I'm assuming so here. If this is going to - * fail, I can just let the timeout catch the failure. - */ - mail_out(host, (struct scb *) &icb); - timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ - while (icb.phase && time_before(jiffies, timeout)) { - cpu_relax(); /* wait for completion */ - barrier(); - } - - if (icb.phase) { - printk("wd7000_diagnostics: timed out.\n"); - return (0); - } - if (make_code(icb.vue | (icb.status << 8), 0)) { - printk("wd7000_diagnostics: failed (0x%02x,0x%02x)\n", icb.vue, icb.status); - return (0); - } - - return (1); -} - - -static int wd7000_adapter_reset(Adapter * host) -{ - InitCmd init_cmd = { - INITIALIZATION, - 7, - host->bus_on, - host->bus_off, - 0, - {0, 0, 0}, - OGMB_CNT, - ICMB_CNT - }; - int diag; - /* - * Reset the adapter - only. The SCSI bus was initialized at power-up, - * and we need to do this just so we control the mailboxes, etc. - */ - outb(ASC_RES, host->iobase + ASC_CONTROL); - udelay(40); /* reset pulse: this is 40us, only need 25us */ - outb(0, host->iobase + ASC_CONTROL); - host->control = 0; /* this must always shadow ASC_CONTROL */ - - if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { - printk(KERN_ERR "wd7000_init: WAIT timed out.\n"); - return -1; /* -1 = not ok */ - } - - if ((diag = inb(host->iobase + ASC_INTR_STAT)) != 1) { - printk("wd7000_init: "); - - switch (diag) { - case 2: - printk(KERN_ERR "RAM failure.\n"); - break; - case 3: - printk(KERN_ERR "FIFO R/W failed\n"); - break; - case 4: - printk(KERN_ERR "SBIC register R/W failed\n"); - break; - case 5: - printk(KERN_ERR "Initialization D-FF failed.\n"); - break; - case 6: - printk(KERN_ERR "Host IRQ D-FF failed.\n"); - break; - case 7: - printk(KERN_ERR "ROM checksum error.\n"); - break; - default: - printk(KERN_ERR "diagnostic code 0x%02Xh received.\n", diag); - } - return -1; - } - /* Clear mailboxes */ - memset(&(host->mb), 0, sizeof(host->mb)); - - /* Execute init command */ - any2scsi((unchar *) & (init_cmd.mailboxes), (int) &(host->mb)); - if (!command_out(host, (unchar *) & init_cmd, sizeof(init_cmd))) { - printk(KERN_ERR "wd7000_adapter_reset: adapter initialization failed.\n"); - return -1; - } - - if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, ASC_INIT, 0)) { - printk("wd7000_adapter_reset: WAIT timed out.\n"); - return -1; - } - return 0; -} - -static int wd7000_init(Adapter * host) -{ - if (wd7000_adapter_reset(host) == -1) - return 0; - - - if (request_irq(host->irq, wd7000_intr, 0, "wd7000", host)) { - printk("wd7000_init: can't get IRQ %d.\n", host->irq); - return (0); - } - if (request_dma(host->dma, "wd7000")) { - printk("wd7000_init: can't get DMA channel %d.\n", host->dma); - free_irq(host->irq, host); - return (0); - } - wd7000_enable_dma(host); - wd7000_enable_intr(host); - - if (!wd7000_diagnostics(host, ICB_DIAG_FULL)) { - free_dma(host->dma); - free_irq(host->irq, NULL); - return (0); - } - - return (1); -} - - -static void wd7000_revision(Adapter * host) -{ - static IcbRevLvl icb = { ICB_OP_GET_REVISION }; - - icb.phase = 1; - /* - * Like diagnostics, this is only done at init time, in fact, from - * wd7000_detect, so there should be OGMBs available. If it fails, - * the only damage will be that the revision will show up as 0.0, - * which in turn means that scatter/gather will be disabled. - */ - mail_out(host, (struct scb *) &icb); - while (icb.phase) { - cpu_relax(); /* wait for completion */ - barrier(); - } - host->rev1 = icb.primary; - host->rev2 = icb.secondary; -} - - -static int wd7000_set_info(struct Scsi_Host *host, char *buffer, int length) -{ - dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length); - - /* - * Currently this is a no-op - */ - dprintk("Sorry, this function is currently out of order...\n"); - return (length); -} - - -static int wd7000_show_info(struct seq_file *m, struct Scsi_Host *host) -{ - Adapter *adapter = (Adapter *)host->hostdata; - unsigned long flags; -#ifdef WD7000_DEBUG - Mailbox *ogmbs, *icmbs; - short count; -#endif - - spin_lock_irqsave(host->host_lock, flags); - seq_printf(m, "Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", host->host_no, adapter->rev1, adapter->rev2); - seq_printf(m, " IO base: 0x%x\n", adapter->iobase); - seq_printf(m, " IRQ: %d\n", adapter->irq); - seq_printf(m, " DMA channel: %d\n", adapter->dma); - seq_printf(m, " Interrupts: %d\n", adapter->int_counter); - seq_printf(m, " BUS_ON time: %d nanoseconds\n", adapter->bus_on * 125); - seq_printf(m, " BUS_OFF time: %d nanoseconds\n", adapter->bus_off * 125); - -#ifdef WD7000_DEBUG - ogmbs = adapter->mb.ogmb; - icmbs = adapter->mb.icmb; - - seq_printf(m, "\nControl port value: 0x%x\n", adapter->control); - seq_puts(m, "Incoming mailbox:\n"); - seq_printf(m, " size: %d\n", ICMB_CNT); - seq_puts(m, " queued messages: "); - - for (i = count = 0; i < ICMB_CNT; i++) - if (icmbs[i].status) { - count++; - seq_printf(m, "0x%x ", i); - } - - seq_puts(m, count ? "\n" : "none\n"); - - seq_puts(m, "Outgoing mailbox:\n"); - seq_printf(m, " size: %d\n", OGMB_CNT); - seq_printf(m, " next message: 0x%x\n", adapter->next_ogmb); - seq_puts(m, " queued messages: "); - - for (i = count = 0; i < OGMB_CNT; i++) - if (ogmbs[i].status) { - count++; - seq_printf(m, "0x%x ", i); - } - - seq_puts(m, count ? "\n" : "none\n"); -#endif - - spin_unlock_irqrestore(host->host_lock, flags); - - return 0; -} - - -/* - * Returns the number of adapters this driver is supporting. - * - * The source for hosts.c says to wait to call scsi_register until 100% - * sure about an adapter. We need to do it a little sooner here; we - * need the storage set up by scsi_register before wd7000_init, and - * changing the location of an Adapter structure is more trouble than - * calling scsi_unregister. - * - */ - -static __init int wd7000_detect(struct scsi_host_template *tpnt) -{ - short present = 0, biosaddr_ptr, sig_ptr, i, pass; - short biosptr[NUM_CONFIGS]; - unsigned iobase; - Adapter *host = NULL; - struct Scsi_Host *sh; - int unit = 0; - - dprintk("wd7000_detect: started\n"); - -#ifdef MODULE - if (wd7000) - wd7000_setup(wd7000); -#endif - - for (i = 0; i < UNITS; wd7000_host[i++] = NULL); - for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1); - - tpnt->proc_name = "wd7000"; - tpnt->show_info = &wd7000_show_info; - tpnt->write_info = wd7000_set_info; - - /* - * Set up SCB free list, which is shared by all adapters - */ - init_scbs(); - - for (pass = 0; pass < NUM_CONFIGS; pass++) { - /* - * First, search for BIOS SIGNATURE... - */ - for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++) - for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) { - for (i = 0; i < pass; i++) - if (biosptr[i] == biosaddr_ptr) - break; - - if (i == pass) { - void __iomem *biosaddr = ioremap(wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs, - signatures[sig_ptr].len); - short bios_match = 1; - - if (biosaddr) - bios_match = check_signature(biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len); - - iounmap(biosaddr); - - if (bios_match) - goto bios_matched; - } - } - - bios_matched: - /* - * BIOS SIGNATURE has been found. - */ -#ifdef WD7000_DEBUG - dprintk("wd7000_detect: pass %d\n", pass + 1); - - if (biosaddr_ptr == NUM_ADDRS) - dprintk("WD-7000 SST BIOS not detected...\n"); - else - dprintk("WD-7000 SST BIOS detected at 0x%lx: checking...\n", wd7000_biosaddr[biosaddr_ptr]); -#endif - - if (configs[pass].irq < 0) - continue; - - if (unit == UNITS) - continue; - - iobase = configs[pass].iobase; - - dprintk("wd7000_detect: check IO 0x%x region...\n", iobase); - - if (request_region(iobase, 4, "wd7000")) { - - dprintk("wd7000_detect: ASC reset (IO 0x%x) ...", iobase); - /* - * ASC reset... - */ - outb(ASC_RES, iobase + ASC_CONTROL); - msleep(10); - outb(0, iobase + ASC_CONTROL); - - if (WAIT(iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { - dprintk("failed!\n"); - goto err_release; - } else - dprintk("ok!\n"); - - if (inb(iobase + ASC_INTR_STAT) == 1) { - /* - * We register here, to get a pointer to the extra space, - * which we'll use as the Adapter structure (host) for - * this adapter. It is located just after the registered - * Scsi_Host structure (sh), and is located by the empty - * array hostdata. - */ - sh = scsi_register(tpnt, sizeof(Adapter)); - if (sh == NULL) - goto err_release; - - host = (Adapter *) sh->hostdata; - - dprintk("wd7000_detect: adapter allocated at 0x%x\n", (int) host); - memset(host, 0, sizeof(Adapter)); - - host->irq = configs[pass].irq; - host->dma = configs[pass].dma; - host->iobase = iobase; - host->int_counter = 0; - host->bus_on = configs[pass].bus_on; - host->bus_off = configs[pass].bus_off; - host->sh = wd7000_host[unit] = sh; - unit++; - - dprintk("wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->iobase, host->irq, host->dma); - - if (!wd7000_init(host)) /* Initialization failed */ - goto err_unregister; - - /* - * OK from here - we'll use this adapter/configuration. - */ - wd7000_revision(host); /* important for scatter/gather */ - - /* - * For boards before rev 6.0, scatter/gather isn't supported. - */ - if (host->rev1 < 6) - sh->sg_tablesize = 1; - - present++; /* count it */ - - if (biosaddr_ptr != NUM_ADDRS) - biosptr[pass] = biosaddr_ptr; - - printk(KERN_INFO "Western Digital WD-7000 (rev %d.%d) ", host->rev1, host->rev2); - printk("using IO 0x%x, IRQ %d, DMA %d.\n", host->iobase, host->irq, host->dma); - printk(" BUS_ON time: %dns, BUS_OFF time: %dns\n", host->bus_on * 125, host->bus_off * 125); - } - } else - dprintk("wd7000_detect: IO 0x%x region already allocated!\n", iobase); - - continue; - - err_unregister: - scsi_unregister(sh); - err_release: - release_region(iobase, 4); - - } - - if (!present) - printk("Failed initialization of WD-7000 SCSI card!\n"); - - return (present); -} - -static int wd7000_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, NULL); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); - return 0; -} - -#if 0 -/* - * I have absolutely NO idea how to do an abort with the WD7000... - */ -static int wd7000_abort(Scsi_Cmnd * SCpnt) -{ - Adapter *host = (Adapter *) SCpnt->device->host->hostdata; - - if (inb(host->iobase + ASC_STAT) & INT_IM) { - printk("wd7000_abort: lost interrupt\n"); - wd7000_intr_handle(host->irq, NULL, NULL); - return FAILED; - } - return FAILED; -} -#endif - -/* - * Last resort. Reinitialize the board. - */ - -static int wd7000_host_reset(struct scsi_cmnd *SCpnt) -{ - Adapter *host = (Adapter *) SCpnt->device->host->hostdata; - - spin_lock_irq(SCpnt->device->host->host_lock); - - if (wd7000_adapter_reset(host) < 0) { - spin_unlock_irq(SCpnt->device->host->host_lock); - return FAILED; - } - - wd7000_enable_intr(host); - - spin_unlock_irq(SCpnt->device->host->host_lock); - return SUCCESS; -} - -/* - * This was borrowed directly from aha1542.c. (Zaga) - */ - -static int wd7000_biosparam(struct scsi_device *sdev, - struct block_device *bdev, sector_t capacity, int *ip) -{ - char b[BDEVNAME_SIZE]; - - dprintk("wd7000_biosparam: dev=%s, size=%llu, ", - bdevname(bdev, b), (u64)capacity); - (void)b; /* unused var warning? */ - - /* - * try default translation - */ - ip[0] = 64; - ip[1] = 32; - ip[2] = capacity >> 11; - - /* - * for disks >1GB do some guessing - */ - if (ip[2] >= 1024) { - int info[3]; - - /* - * try to figure out the geometry from the partition table - */ - if ((scsicam_bios_param(bdev, capacity, info) < 0) || !(((info[0] == 64) && (info[1] == 32)) || ((info[0] == 255) && (info[1] == 63)))) { - printk("wd7000_biosparam: unable to verify geometry for disk with >1GB.\n" " using extended translation.\n"); - - ip[0] = 255; - ip[1] = 63; - ip[2] = (unsigned long) capacity / (255 * 63); - } else { - ip[0] = info[0]; - ip[1] = info[1]; - ip[2] = info[2]; - - if (info[0] == 255) - printk(KERN_INFO "%s: current partition table is " "using extended translation.\n", __func__); - } - } - - dprintk("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]); - dprintk("WARNING: check, if the bios geometry is correct.\n"); - - return (0); -} - -MODULE_AUTHOR("Thomas Wuensche, John Boyd, Miroslav Zagorac"); -MODULE_DESCRIPTION("Driver for the WD7000 series ISA controllers"); -MODULE_LICENSE("GPL"); - -static struct scsi_host_template driver_template = { - .proc_name = "wd7000", - .show_info = wd7000_show_info, - .write_info = wd7000_set_info, - .name = "Western Digital WD-7000", - .detect = wd7000_detect, - .release = wd7000_release, - .queuecommand = wd7000_queuecommand, - .eh_host_reset_handler = wd7000_host_reset, - .bios_param = wd7000_biosparam, - .can_queue = WD7000_Q, - .this_id = 7, - .sg_tablesize = WD7000_SG, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -}; - -#include "scsi_module.c" -- cgit v1.2.3 From 24cbf0f799d3ff8e1f1f6417e9040933acd4b38d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Sep 2016 08:50:50 -0700 Subject: scsi: u14-34f: remove from tree The driver has not seen any maintainer activity or other work that wasn't tree wide conversion or clenaups in the entire history of the git tree. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinicke Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi-parameters.txt | 3 - MAINTAINERS | 6 - drivers/scsi/Kconfig | 49 - drivers/scsi/Makefile | 1 - drivers/scsi/u14-34f.c | 1971 -------------------------------- 5 files changed, 2030 deletions(-) delete mode 100644 drivers/scsi/u14-34f.c (limited to 'MAINTAINERS') diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 2135ff4d1099..083bd934218a 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -123,8 +123,5 @@ parameters may be changed at runtime by the command See comment before function dc390_setup() in drivers/scsi/tmscsim.c. - u14-34f= [HW,SCSI] UltraStor 14F/34F SCSI host adapter - See header of drivers/scsi/u14-34f.c. - wd33c93= [HW,SCSI] See header of drivers/scsi/wd33c93.c. diff --git a/MAINTAINERS b/MAINTAINERS index fdcce6b52cba..6ca763fe0346 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11967,12 +11967,6 @@ S: Maintained F: drivers/tc/ F: include/linux/tc.h -U14-34F SCSI DRIVER -M: Dario Ballabio -L: linux-scsi@vger.kernel.org -S: Maintained -F: drivers/scsi/u14-34f.c - UBI FILE SYSTEM (UBIFS) M: Richard Weinberger M: Artem Bityutskiy diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 57cf77f84ca3..69785315eca3 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1376,55 +1376,6 @@ config SCSI_T128 To compile this driver as a module, choose M here: the module will be called t128. -config SCSI_U14_34F - tristate "UltraStor 14F/34F support" - depends on ISA && SCSI && ISA_DMA_API - ---help--- - This is support for the UltraStor 14F and 34F SCSI-2 host adapters. - The source at contains some - information about this hardware. If the driver doesn't work out of - the box, you may have to change some settings in - . Read the SCSI-HOWTO, available from - . Note that there is also - another driver for the same hardware: "UltraStor SCSI support", - below. You should say Y to both only if you want 24F support as - well. - - To compile this driver as a module, choose M here: the - module will be called u14-34f. - -config SCSI_U14_34F_TAGGED_QUEUE - bool "enable tagged command queueing" - depends on SCSI_U14_34F - help - This is a feature of SCSI-2 which improves performance: the host - adapter can send several SCSI commands to a device's queue even if - previous commands haven't finished yet. - This is equivalent to the "u14-34f=tc:y" boot option. - -config SCSI_U14_34F_LINKED_COMMANDS - bool "enable elevator sorting" - depends on SCSI_U14_34F - help - This option enables elevator sorting for all probed SCSI disks and - CD-ROMs. It definitely reduces the average seek distance when doing - random seeks, but this does not necessarily result in a noticeable - performance improvement: your mileage may vary... - This is equivalent to the "u14-34f=lc:y" boot option. - -config SCSI_U14_34F_MAX_TAGS - int "maximum number of queued commands" - depends on SCSI_U14_34F - default "8" - help - This specifies how many SCSI commands can be maximally queued for - each probed SCSI device. You should reduce the default value of 8 - only if you have disks with buggy or limited tagged command support. - Minimum is 2 and maximum is 14. This value is also the window size - used by the elevator sorting option above. The effective value used - by the driver for each probed SCSI device is reported at boot time. - This is equivalent to the "u14-34f=mq:8" boot option. - config SCSI_NSP32 tristate "Workbit NinjaSCSI-32Bi/UDE support" depends on PCI && SCSI && !64BIT diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2e7d9efd86af..921cf07e9b7b 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -61,7 +61,6 @@ obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o -obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/ obj-$(CONFIG_SCSI_AHA152X) += aha152x.o obj-$(CONFIG_SCSI_AHA1542) += aha1542.o diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c deleted file mode 100644 index 14eb50b95a1e..000000000000 --- a/drivers/scsi/u14-34f.c +++ /dev/null @@ -1,1971 +0,0 @@ -/* - * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. - * - * 03 Jun 2003 Rev. 8.10 for linux-2.5.70 - * + Update for new IRQ API. - * + Use "goto" when appropriate. - * + Drop u14-34f.h. - * + Update for new module_param API. - * + Module parameters can now be specified only in the - * same format as the kernel boot options. - * - * boot option old module param - * ----------- ------------------ - * addr,... io_port=addr,... - * lc:[y|n] linked_comm=[1|0] - * mq:xx max_queue_depth=xx - * tm:[0|1|2] tag_mode=[0|1|2] - * et:[y|n] ext_tran=[1|0] - * of:[y|n] have_old_firmware=[1|0] - * - * A valid example using the new parameter format is: - * modprobe u14-34f "u14-34f=0x340,0x330,lc:y,tm:0,mq:4" - * - * which is equivalent to the old format: - * modprobe u14-34f io_port=0x340,0x330 linked_comm=1 tag_mode=0 \ - * max_queue_depth=4 - * - * With actual module code, u14-34f and u14_34f are equivalent - * as module parameter names. - * - * 12 Feb 2003 Rev. 8.04 for linux 2.5.60 - * + Release irq before calling scsi_register. - * - * 12 Nov 2002 Rev. 8.02 for linux 2.5.47 - * + Release driver_lock before calling scsi_register. - * - * 11 Nov 2002 Rev. 8.01 for linux 2.5.47 - * + Fixed bios_param and scsicam_bios_param calling parameters. - * - * 28 Oct 2002 Rev. 8.00 for linux 2.5.44-ac4 - * + Use new tcq and adjust_queue_depth api. - * + New command line option (tm:[0-2]) to choose the type of tags: - * 0 -> disable tagging ; 1 -> simple tags ; 2 -> ordered tags. - * Default is tm:0 (tagged commands disabled). - * For compatibility the "tc:" option is an alias of the "tm:" - * option; tc:n is equivalent to tm:0 and tc:y is equivalent to - * tm:1. - * - * 10 Oct 2002 Rev. 7.70 for linux 2.5.42 - * + Foreport from revision 6.70. - * - * 25 Jun 2002 Rev. 6.70 for linux 2.4.19 - * + Fixed endian-ness problem due to bitfields. - * - * 21 Feb 2002 Rev. 6.52 for linux 2.4.18 - * + Backport from rev. 7.22 (use io_request_lock). - * - * 20 Feb 2002 Rev. 7.22 for linux 2.5.5 - * + Remove any reference to virt_to_bus(). - * + Fix pio hang while detecting multiple HBAs. - * - * 01 Jan 2002 Rev. 7.20 for linux 2.5.1 - * + Use the dynamic DMA mapping API. - * - * 19 Dec 2001 Rev. 7.02 for linux 2.5.1 - * + Use SCpnt->sc_data_direction if set. - * + Use sglist.page instead of sglist.address. - * - * 11 Dec 2001 Rev. 7.00 for linux 2.5.1 - * + Use host->host_lock instead of io_request_lock. - * - * 1 May 2001 Rev. 6.05 for linux 2.4.4 - * + Fix data transfer direction for opcode SEND_CUE_SHEET (0x5d) - * - * 25 Jan 2001 Rev. 6.03 for linux 2.4.0 - * + "check_region" call replaced by "request_region". - * - * 22 Nov 2000 Rev. 6.02 for linux 2.4.0-test11 - * + Removed old scsi error handling support. - * + The obsolete boot option flag eh:n is silently ignored. - * + Removed error messages while a disk drive is powered up at - * boot time. - * + Improved boot messages: all tagged capable device are - * indicated as "tagged". - * - * 16 Sep 1999 Rev. 5.11 for linux 2.2.12 and 2.3.18 - * + Updated to the new __setup interface for boot command line options. - * + When loaded as a module, accepts the new parameter boot_options - * which value is a string with the same format of the kernel boot - * command line options. A valid example is: - * modprobe u14-34f 'boot_options="0x230,0x340,lc:y,mq:4"' - * - * 22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11 - * + Removed pre-2.2 source code compatibility. - * - * 26 Jul 1998 Rev. 4.33 for linux 2.0.35 and 2.1.111 - * Added command line option (et:[y|n]) to use the existing - * translation (returned by scsicam_bios_param) as disk geometry. - * The default is et:n, which uses the disk geometry jumpered - * on the board. - * The default value et:n is compatible with all previous revisions - * of this driver. - * - * 28 May 1998 Rev. 4.32 for linux 2.0.33 and 2.1.104 - * Increased busy timeout from 10 msec. to 200 msec. while - * processing interrupts. - * - * 18 May 1998 Rev. 4.31 for linux 2.0.33 and 2.1.102 - * Improved abort handling during the eh recovery process. - * - * 13 May 1998 Rev. 4.30 for linux 2.0.33 and 2.1.101 - * The driver is now fully SMP safe, including the - * abort and reset routines. - * Added command line options (eh:[y|n]) to choose between - * new_eh_code and the old scsi code. - * If linux version >= 2.1.101 the default is eh:y, while the eh - * option is ignored for previous releases and the old scsi code - * is used. - * - * 18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97 - * Reworked interrupt handler. - * - * 11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95 - * Major reliability improvement: when a batch with overlapping - * requests is detected, requests are queued one at a time - * eliminating any possible board or drive reordering. - * - * 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95 - * Improved SMP support (if linux version >= 2.1.95). - * - * 9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94 - * Performance improvement: when sequential i/o is detected, - * always use direct sort instead of reverse sort. - * - * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 - * io_port is now unsigned long. - * - * 17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88 - * Use new scsi error handling code (if linux version >= 2.1.88). - * Use new interrupt code. - * - * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 - * Use of udelay inside the wait loops to avoid timeout - * problems with fast cpus. - * Removed check about useless calls to the interrupt service - * routine (reported on SMP systems only). - * At initialization time "sorted/unsorted" is displayed instead - * of "linked/unlinked" to reinforce the fact that "linking" is - * nothing but "elevator sorting" in the actual implementation. - * - * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 - * Use of serial_number_at_timeout in abort and reset processing. - * Use of the __initfunc and __initdata macro in setup code. - * Minor cleanups in the list_statistics code. - * - * 24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26 - * When loading as a module, parameter passing is now supported - * both in 2.0 and in 2.1 style. - * Fixed data transfer direction for some SCSI opcodes. - * Immediate acknowledge to request sense commands. - * Linked commands to each disk device are now reordered by elevator - * sorting. Rare cases in which reordering of write requests could - * cause wrong results are managed. - * - * 18 Jan 1997 rev. 2.60 for linux 2.1.21 and 2.0.28 - * Added command line options to enable/disable linked commands - * (lc:[y|n]), old firmware support (of:[y|n]) and to set the max - * queue depth (mq:xx). Default is "u14-34f=lc:n,of:n,mq:8". - * Improved command linking. - * - * 8 Jan 1997 rev. 2.50 for linux 2.1.20 and 2.0.27 - * Added linked command support. - * - * 3 Dec 1996 rev. 2.40 for linux 2.1.14 and 2.0.27 - * Added queue depth adjustment. - * - * 22 Nov 1996 rev. 2.30 for linux 2.1.12 and 2.0.26 - * The list of i/o ports to be probed can be overwritten by the - * "u14-34f=port0,port1,...." boot command line option. - * Scatter/gather lists are now allocated by a number of kmalloc - * calls, in order to avoid the previous size limit of 64Kb. - * - * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25 - * Added multichannel support. - * - * 27 Sep 1996 rev. 2.12 for linux 2.1.0 - * Portability cleanups (virtual/bus addressing, little/big endian - * support). - * - * 09 Jul 1996 rev. 2.11 for linux 2.0.4 - * "Data over/under-run" no longer implies a redo on all targets. - * Number of internal retries is now limited. - * - * 16 Apr 1996 rev. 2.10 for linux 1.3.90 - * New argument "reset_flags" to the reset routine. - * - * 21 Jul 1995 rev. 2.02 for linux 1.3.11 - * Fixed Data Transfer Direction for some SCSI commands. - * - * 13 Jun 1995 rev. 2.01 for linux 1.2.10 - * HAVE_OLD_UX4F_FIRMWARE should be defined for U34F boards when - * the firmware prom is not the latest one (28008-006). - * - * 11 Mar 1995 rev. 2.00 for linux 1.2.0 - * Fixed a bug which prevented media change detection for removable - * disk drives. - * - * 23 Feb 1995 rev. 1.18 for linux 1.1.94 - * Added a check for scsi_register returning NULL. - * - * 11 Feb 1995 rev. 1.17 for linux 1.1.91 - * U14F qualified to run with 32 sglists. - * Now DEBUG_RESET is disabled by default. - * - * 9 Feb 1995 rev. 1.16 for linux 1.1.90 - * Use host->wish_block instead of host->block. - * - * 8 Feb 1995 rev. 1.15 for linux 1.1.89 - * Cleared target_time_out counter while performing a reset. - * - * 28 Jan 1995 rev. 1.14 for linux 1.1.86 - * Added module support. - * Log and do a retry when a disk drive returns a target status - * different from zero on a recovered error. - * Auto detects if U14F boards have an old firmware revision. - * Max number of scatter/gather lists set to 16 for all boards - * (most installation run fine using 33 sglists, while other - * has problems when using more than 16). - * - * 16 Jan 1995 rev. 1.13 for linux 1.1.81 - * Display a message if check_region detects a port address - * already in use. - * - * 15 Dec 1994 rev. 1.12 for linux 1.1.74 - * The host->block flag is set for all the detected ISA boards. - * - * 30 Nov 1994 rev. 1.11 for linux 1.1.68 - * Redo i/o on target status CHECK_CONDITION for TYPE_DISK only. - * Added optional support for using a single board at a time. - * - * 14 Nov 1994 rev. 1.10 for linux 1.1.63 - * - * 28 Oct 1994 rev. 1.09 for linux 1.1.58 Final BETA release. - * 16 Jul 1994 rev. 1.00 for linux 1.1.29 Initial ALPHA release. - * - * This driver is a total replacement of the original UltraStor - * scsi driver, but it supports ONLY the 14F and 34F boards. - * It can be configured in the same kernel in which the original - * ultrastor driver is configured to allow the original U24F - * support. - * - * Multiple U14F and/or U34F host adapters are supported. - * - * Copyright (C) 1994-2003 Dario Ballabio (ballabio_dario@emc.com) - * - * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that redistributions of source - * code retain the above copyright notice and this comment without - * modification. - * - * WARNING: if your 14/34F board has an old firmware revision (see below) - * you must change "#undef" into "#define" in the following - * statement. - */ -#undef HAVE_OLD_UX4F_FIRMWARE -/* - * The UltraStor 14F, 24F, and 34F are a family of intelligent, high - * performance SCSI-2 host adapters. - * Here is the scoop on the various models: - * - * 14F - ISA first-party DMA HA with floppy support and WD1003 emulation. - * 24F - EISA Bus Master HA with floppy support and WD1003 emulation. - * 34F - VESA Local-Bus Bus Master HA (no WD1003 emulation). - * - * This code has been tested with up to two U14F boards, using both - * firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware - * 28004-006/38004-005 (BIOS rev. 2.01). - * - * The latest firmware is required in order to get reliable operations when - * clustering is enabled. ENABLE_CLUSTERING provides a performance increase - * up to 50% on sequential access. - * - * Since the struct scsi_host_template structure is shared among all 14F and 34F, - * the last setting of use_clustering is in effect for all of these boards. - * - * Here a sample configuration using two U14F boards: - * - U14F0: ISA 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, MB 16, of:n, lc:y, mq:8. - U14F1: ISA 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, MB 16, of:n, lc:y, mq:8. - * - * The boot controller must have its BIOS enabled, while other boards can - * have their BIOS disabled, or enabled to an higher address. - * Boards are named Ux4F0, Ux4F1..., according to the port address order in - * the io_port[] array. - * - * The following facts are based on real testing results (not on - * documentation) on the above U14F board. - * - * - The U14F board should be jumpered for bus on time less or equal to 7 - * microseconds, while the default is 11 microseconds. This is order to - * get acceptable performance while using floppy drive and hard disk - * together. The jumpering for 7 microseconds is: JP13 pin 15-16, - * JP14 pin 7-8 and pin 9-10. - * The reduction has a little impact on scsi performance. - * - * - If scsi bus length exceeds 3m., the scsi bus speed needs to be reduced - * from 10Mhz to 5Mhz (do this by inserting a jumper on JP13 pin 7-8). - * - * - If U14F on board firmware is older than 28004-006/38004-005, - * the U14F board is unable to provide reliable operations if the scsi - * request length exceeds 16Kbyte. When this length is exceeded the - * behavior is: - * - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94; - * - adapter_status equal 0 and target_status equal 2 on for all targets - * in the next operation following the reset. - * This sequence takes a long time (>3 seconds), so in the meantime - * the SD_TIMEOUT in sd.c could expire giving rise to scsi aborts - * (SD_TIMEOUT has been increased from 3 to 6 seconds in 1.1.31). - * Because of this I had to DISABLE_CLUSTERING and to work around the - * bus reset in the interrupt service routine, returning DID_BUS_BUSY - * so that the operations are retried without complains from the scsi.c - * code. - * Any reset of the scsi bus is going to kill tape operations, since - * no retry is allowed for tapes. Bus resets are more likely when the - * scsi bus is under heavy load. - * Requests using scatter/gather have a maximum length of 16 x 1024 bytes - * when DISABLE_CLUSTERING is in effect, but unscattered requests could be - * larger than 16Kbyte. - * - * The new firmware has fixed all the above problems. - * - * For U34F boards the latest bios prom is 38008-002 (BIOS rev. 2.01), - * the latest firmware prom is 28008-006. Older firmware 28008-005 has - * problems when using more than 16 scatter/gather lists. - * - * The list of i/o ports to be probed can be totally replaced by the - * boot command line option: "u14-34f=port0,port1,port2,...", where the - * port0, port1... arguments are ISA/VESA addresses to be probed. - * For example using "u14-34f=0x230,0x340", the driver probes only the two - * addresses 0x230 and 0x340 in this order; "u14-34f=0" totally disables - * this driver. - * - * After the optional list of detection probes, other possible command line - * options are: - * - * et:y use disk geometry returned by scsicam_bios_param; - * et:n use disk geometry jumpered on the board; - * lc:y enables linked commands; - * lc:n disables linked commands; - * tm:0 disables tagged commands (same as tc:n); - * tm:1 use simple queue tags (same as tc:y); - * tm:2 use ordered queue tags (same as tc:2); - * of:y enables old firmware support; - * of:n disables old firmware support; - * mq:xx set the max queue depth to the value xx (2 <= xx <= 8). - * - * The default value is: "u14-34f=lc:n,of:n,mq:8,tm:0,et:n". - * An example using the list of detection probes could be: - * "u14-34f=0x230,0x340,lc:y,tm:2,of:n,mq:4,et:n". - * - * When loading as a module, parameters can be specified as well. - * The above example would be (use 1 in place of y and 0 in place of n): - * - * modprobe u14-34f io_port=0x230,0x340 linked_comm=1 have_old_firmware=0 \ - * max_queue_depth=4 ext_tran=0 tag_mode=2 - * - * ---------------------------------------------------------------------------- - * In this implementation, linked commands are designed to work with any DISK - * or CD-ROM, since this linking has only the intent of clustering (time-wise) - * and reordering by elevator sorting commands directed to each device, - * without any relation with the actual SCSI protocol between the controller - * and the device. - * If Q is the queue depth reported at boot time for each device (also named - * cmds/lun) and Q > 2, whenever there is already an active command to the - * device all other commands to the same device (up to Q-1) are kept waiting - * in the elevator sorting queue. When the active command completes, the - * commands in this queue are sorted by sector address. The sort is chosen - * between increasing or decreasing by minimizing the seek distance between - * the sector of the commands just completed and the sector of the first - * command in the list to be sorted. - * Trivial math assures that the unsorted average seek distance when doing - * random seeks over S sectors is S/3. - * When (Q-1) requests are uniformly distributed over S sectors, the average - * distance between two adjacent requests is S/((Q-1) + 1), so the sorted - * average seek distance for (Q-1) random requests over S sectors is S/Q. - * The elevator sorting hence divides the seek distance by a factor Q/3. - * The above pure geometric remarks are valid in all cases and the - * driver effectively reduces the seek distance by the predicted factor - * when there are Q concurrent read i/o operations on the device, but this - * does not necessarily results in a noticeable performance improvement: - * your mileage may vary.... - * - * Note: command reordering inside a batch of queued commands could cause - * wrong results only if there is at least one write request and the - * intersection (sector-wise) of all requests is not empty. - * When the driver detects a batch including overlapping requests - * (a really rare event) strict serial (pid) order is enforced. - * ---------------------------------------------------------------------------- - * - * The boards are named Ux4F0, Ux4F1,... according to the detection order. - * - * In order to support multiple ISA boards in a reliable way, - * the driver sets host->wish_block = TRUE for all ISA boards. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static int u14_34f_detect(struct scsi_host_template *); -static int u14_34f_release(struct Scsi_Host *); -static int u14_34f_queuecommand(struct Scsi_Host *, struct scsi_cmnd *); -static int u14_34f_eh_abort(struct scsi_cmnd *); -static int u14_34f_eh_host_reset(struct scsi_cmnd *); -static int u14_34f_bios_param(struct scsi_device *, struct block_device *, - sector_t, int *); -static int u14_34f_slave_configure(struct scsi_device *); - -static struct scsi_host_template driver_template = { - .name = "UltraStor 14F/34F rev. 8.10.00 ", - .detect = u14_34f_detect, - .release = u14_34f_release, - .queuecommand = u14_34f_queuecommand, - .eh_abort_handler = u14_34f_eh_abort, - .eh_host_reset_handler = u14_34f_eh_host_reset, - .bios_param = u14_34f_bios_param, - .slave_configure = u14_34f_slave_configure, - .this_id = 7, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, - }; - -#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) -#error "Adjust your defines" -#endif - -/* Values for the PRODUCT_ID ports for the 14/34F */ -#define PRODUCT_ID1 0x56 -#define PRODUCT_ID2 0x40 /* NOTE: Only upper nibble is used */ - -/* Subversion values */ -#define ISA 0 -#define ESA 1 - -#define OP_HOST_ADAPTER 0x1 -#define OP_SCSI 0x2 -#define OP_RESET 0x4 -#define DTD_SCSI 0x0 -#define DTD_IN 0x1 -#define DTD_OUT 0x2 -#define DTD_NONE 0x3 -#define HA_CMD_INQUIRY 0x1 -#define HA_CMD_SELF_DIAG 0x2 -#define HA_CMD_READ_BUFF 0x3 -#define HA_CMD_WRITE_BUFF 0x4 - -#undef DEBUG_LINKED_COMMANDS -#undef DEBUG_DETECT -#undef DEBUG_INTERRUPT -#undef DEBUG_RESET -#undef DEBUG_GENERATE_ERRORS -#undef DEBUG_GENERATE_ABORTS -#undef DEBUG_GEOMETRY - -#define MAX_ISA 3 -#define MAX_VESA 1 -#define MAX_EISA 0 -#define MAX_PCI 0 -#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI) -#define MAX_CHANNEL 1 -#define MAX_LUN 8 -#define MAX_TARGET 8 -#define MAX_MAILBOXES 16 -#define MAX_SGLIST 32 -#define MAX_SAFE_SGLIST 16 -#define MAX_INTERNAL_RETRIES 64 -#define MAX_CMD_PER_LUN 2 -#define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN) - -#define SKIP ULONG_MAX -#define FALSE 0 -#define TRUE 1 -#define FREE 0 -#define IN_USE 1 -#define LOCKED 2 -#define IN_RESET 3 -#define IGNORE 4 -#define READY 5 -#define ABORTING 6 -#define NO_DMA 0xff -#define MAXLOOP 10000 -#define TAG_DISABLED 0 -#define TAG_SIMPLE 1 -#define TAG_ORDERED 2 - -#define REG_LCL_MASK 0 -#define REG_LCL_INTR 1 -#define REG_SYS_MASK 2 -#define REG_SYS_INTR 3 -#define REG_PRODUCT_ID1 4 -#define REG_PRODUCT_ID2 5 -#define REG_CONFIG1 6 -#define REG_CONFIG2 7 -#define REG_OGM 8 -#define REG_ICM 12 -#define REGION_SIZE 13UL -#define BSY_ASSERTED 0x01 -#define IRQ_ASSERTED 0x01 -#define CMD_RESET 0xc0 -#define CMD_OGM_INTR 0x01 -#define CMD_CLR_INTR 0x01 -#define CMD_ENA_INTR 0x81 -#define ASOK 0x00 -#define ASST 0x91 - -#define YESNO(a) ((a) ? 'y' : 'n') -#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) - -#define PACKED __attribute__((packed)) - -struct sg_list { - unsigned int address; /* Segment Address */ - unsigned int num_bytes; /* Segment Length */ - }; - -/* MailBox SCSI Command Packet */ -struct mscp { - -#if defined(__BIG_ENDIAN_BITFIELD) - unsigned char sg:1, ca:1, dcn:1, xdir:2, opcode:3; - unsigned char lun: 3, channel:2, target:3; -#else - unsigned char opcode: 3, /* type of command */ - xdir: 2, /* data transfer direction */ - dcn: 1, /* disable disconnect */ - ca: 1, /* use cache (if available) */ - sg: 1; /* scatter/gather operation */ - unsigned char target: 3, /* SCSI target id */ - channel: 2, /* SCSI channel number */ - lun: 3; /* SCSI logical unit number */ -#endif - - unsigned int data_address PACKED; /* transfer data pointer */ - unsigned int data_len PACKED; /* length in bytes */ - unsigned int link_address PACKED; /* for linking command chains */ - unsigned char clink_id; /* identifies command in chain */ - unsigned char use_sg; /* (if sg is set) 8 bytes per list */ - unsigned char sense_len; - unsigned char cdb_len; /* 6, 10, or 12 */ - unsigned char cdb[12]; /* SCSI Command Descriptor Block */ - unsigned char adapter_status; /* non-zero indicates HA error */ - unsigned char target_status; /* non-zero indicates target error */ - unsigned int sense_addr PACKED; - - /* Additional fields begin here. */ - struct scsi_cmnd *SCpnt; - unsigned int cpp_index; /* cp index */ - - /* All the cp structure is zero filled by queuecommand except the - following CP_TAIL_SIZE bytes, initialized by detect */ - dma_addr_t cp_dma_addr; /* dma handle for this cp structure */ - struct sg_list *sglist; /* pointer to the allocated SG list */ - }; - -#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t)) - -struct hostdata { - struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */ - unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ - unsigned int last_cp_used; /* Index of last mailbox used */ - unsigned int iocount; /* Total i/o done for this board */ - int board_number; /* Number of this board */ - char board_name[16]; /* Name of this board */ - int in_reset; /* True if board is doing a reset */ - int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */ - int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */ - unsigned int retries; /* Number of internal retries */ - unsigned long last_retried_pid; /* Pid of last retried command */ - unsigned char subversion; /* Bus type, either ISA or ESA */ - struct pci_dev *pdev; /* Always NULL */ - unsigned char heads; - unsigned char sectors; - char board_id[256]; /* data from INQUIRY on this board */ - }; - -static struct Scsi_Host *sh[MAX_BOARDS + 1]; -static const char *driver_name = "Ux4F"; -static char sha[MAX_BOARDS]; -static DEFINE_SPINLOCK(driver_lock); - -/* Initialize num_boards so that ihdlr can work while detect is in progress */ -static unsigned int num_boards = MAX_BOARDS; - -static unsigned long io_port[] = { - - /* Space for MAX_INT_PARAM ports usable while loading as a module */ - SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, - SKIP, SKIP, - - /* Possible ISA/VESA ports */ - 0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, - - /* End of list */ - 0x0 - }; - -#define HD(board) ((struct hostdata *) &sh[board]->hostdata) -#define BN(board) (HD(board)->board_name) - -/* Device is Little Endian */ -#define H2DEV(x) cpu_to_le32(x) -#define DEV2H(x) le32_to_cpu(x) - -static irqreturn_t do_interrupt_handler(int, void *); -static void flush_dev(struct scsi_device *, unsigned long, unsigned int, unsigned int); -static int do_trace = FALSE; -static int setup_done = FALSE; -static int link_statistics; -static int ext_tran = FALSE; - -#if defined(HAVE_OLD_UX4F_FIRMWARE) -static int have_old_firmware = TRUE; -#else -static int have_old_firmware = FALSE; -#endif - -#if defined(CONFIG_SCSI_U14_34F_TAGGED_QUEUE) -static int tag_mode = TAG_SIMPLE; -#else -static int tag_mode = TAG_DISABLED; -#endif - -#if defined(CONFIG_SCSI_U14_34F_LINKED_COMMANDS) -static int linked_comm = TRUE; -#else -static int linked_comm = FALSE; -#endif - -#if defined(CONFIG_SCSI_U14_34F_MAX_TAGS) -static int max_queue_depth = CONFIG_SCSI_U14_34F_MAX_TAGS; -#else -static int max_queue_depth = MAX_CMD_PER_LUN; -#endif - -#define MAX_INT_PARAM 10 -#define MAX_BOOT_OPTIONS_SIZE 256 -static char boot_options[MAX_BOOT_OPTIONS_SIZE]; - -#if defined(MODULE) -#include -#include - -module_param_string(u14_34f, boot_options, MAX_BOOT_OPTIONS_SIZE, 0); -MODULE_PARM_DESC(u14_34f, " equivalent to the \"u14-34f=...\" kernel boot " \ -"option." \ -" Example: modprobe u14-34f \"u14_34f=0x340,0x330,lc:y,tm:0,mq:4\""); -MODULE_AUTHOR("Dario Ballabio"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("UltraStor 14F/34F SCSI Driver"); - -#endif - -static int u14_34f_slave_configure(struct scsi_device *dev) { - int j, tqd, utqd; - char *tag_suffix, *link_suffix; - struct Scsi_Host *host = dev->host; - - j = ((struct hostdata *) host->hostdata)->board_number; - - utqd = MAX_CMD_PER_LUN; - tqd = max_queue_depth; - - if (TLDEV(dev->type) && dev->tagged_supported) - - if (tag_mode == TAG_SIMPLE) { - scsi_change_queue_depth(dev, tqd); - tag_suffix = ", simple tags"; - } - else if (tag_mode == TAG_ORDERED) { - scsi_change_queue_depth(dev, tqd); - tag_suffix = ", ordered tags"; - } - else { - scsi_change_queue_depth(dev, tqd); - tag_suffix = ", no tags"; - } - - else if (TLDEV(dev->type) && linked_comm) { - scsi_change_queue_depth(dev, tqd); - tag_suffix = ", untagged"; - } - - else { - scsi_change_queue_depth(dev, utqd); - tag_suffix = ""; - } - - if (TLDEV(dev->type) && linked_comm && dev->queue_depth > 2) - link_suffix = ", sorted"; - else if (TLDEV(dev->type)) - link_suffix = ", unsorted"; - else - link_suffix = ""; - - sdev_printk(KERN_INFO, dev, "cmds/lun %d%s%s.\n", - dev->queue_depth, link_suffix, tag_suffix); - - return FALSE; -} - -static int wait_on_busy(unsigned long iobase, unsigned int loop) { - - while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) { - udelay(1L); - if (--loop == 0) return TRUE; - } - - return FALSE; -} - -static int board_inquiry(unsigned int j) { - struct mscp *cpp; - dma_addr_t id_dma_addr; - unsigned int limit = 0; - unsigned long time; - - id_dma_addr = pci_map_single(HD(j)->pdev, HD(j)->board_id, - sizeof(HD(j)->board_id), PCI_DMA_BIDIRECTIONAL); - cpp = &HD(j)->cp[0]; - cpp->cp_dma_addr = pci_map_single(HD(j)->pdev, cpp, sizeof(struct mscp), - PCI_DMA_BIDIRECTIONAL); - memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE); - cpp->opcode = OP_HOST_ADAPTER; - cpp->xdir = DTD_IN; - cpp->data_address = H2DEV(id_dma_addr); - cpp->data_len = H2DEV(sizeof(HD(j)->board_id)); - cpp->cdb_len = 6; - cpp->cdb[0] = HA_CMD_INQUIRY; - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: board_inquiry, adapter busy.\n", BN(j)); - return TRUE; - } - - HD(j)->cp_stat[0] = IGNORE; - - /* Clear the interrupt indication */ - outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); - - /* Store pointer in OGM address bytes */ - outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM); - - /* Issue OGM interrupt */ - outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); - - spin_unlock_irq(&driver_lock); - time = jiffies; - while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L); - spin_lock_irq(&driver_lock); - - if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) { - HD(j)->cp_stat[0] = FREE; - printk("%s: board_inquiry, err 0x%x.\n", BN(j), cpp->adapter_status); - return TRUE; - } - - pci_unmap_single(HD(j)->pdev, cpp->cp_dma_addr, sizeof(struct mscp), - PCI_DMA_BIDIRECTIONAL); - pci_unmap_single(HD(j)->pdev, id_dma_addr, sizeof(HD(j)->board_id), - PCI_DMA_BIDIRECTIONAL); - return FALSE; -} - -static int port_detect \ - (unsigned long port_base, unsigned int j, struct scsi_host_template *tpnt) { - unsigned char irq, dma_channel, subversion, i; - unsigned char in_byte; - char *bus_type, dma_name[16]; - - /* Allowed BIOS base addresses (NULL indicates reserved) */ - unsigned long bios_segment_table[8] = { - 0, - 0xc4000, 0xc8000, 0xcc000, 0xd0000, - 0xd4000, 0xd8000, 0xdc000 - }; - - /* Allowed IRQs */ - unsigned char interrupt_table[4] = { 15, 14, 11, 10 }; - - /* Allowed DMA channels for ISA (0 indicates reserved) */ - unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; - - /* Head/sector mappings */ - struct { - unsigned char heads; - unsigned char sectors; - } mapping_table[4] = { - { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } - }; - - struct config_1 { - -#if defined(__BIG_ENDIAN_BITFIELD) - unsigned char dma_channel: 2, interrupt:2, - removable_disks_as_fixed:1, bios_segment: 3; -#else - unsigned char bios_segment: 3, removable_disks_as_fixed: 1, - interrupt: 2, dma_channel: 2; -#endif - - } config_1; - - struct config_2 { - -#if defined(__BIG_ENDIAN_BITFIELD) - unsigned char tfr_port: 2, bios_drive_number: 1, - mapping_mode: 2, ha_scsi_id: 3; -#else - unsigned char ha_scsi_id: 3, mapping_mode: 2, - bios_drive_number: 1, tfr_port: 2; -#endif - - } config_2; - - char name[16]; - - sprintf(name, "%s%d", driver_name, j); - - if (!request_region(port_base, REGION_SIZE, driver_name)) { -#if defined(DEBUG_DETECT) - printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base); -#endif - goto fail; - } - - spin_lock_irq(&driver_lock); - - if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) goto freelock; - - in_byte = inb(port_base + REG_PRODUCT_ID2); - - if ((in_byte & 0xf0) != PRODUCT_ID2) goto freelock; - - *(char *)&config_1 = inb(port_base + REG_CONFIG1); - *(char *)&config_2 = inb(port_base + REG_CONFIG2); - - irq = interrupt_table[config_1.interrupt]; - dma_channel = dma_channel_table[config_1.dma_channel]; - subversion = (in_byte & 0x0f); - - /* Board detected, allocate its IRQ */ - if (request_irq(irq, do_interrupt_handler, - (subversion == ESA) ? IRQF_SHARED : 0, - driver_name, (void *) &sha[j])) { - printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); - goto freelock; - } - - if (subversion == ISA && request_dma(dma_channel, driver_name)) { - printk("%s: unable to allocate DMA channel %u, detaching.\n", - name, dma_channel); - goto freeirq; - } - - if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING; - - spin_unlock_irq(&driver_lock); - sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); - spin_lock_irq(&driver_lock); - - if (sh[j] == NULL) { - printk("%s: unable to register host, detaching.\n", name); - goto freedma; - } - - sh[j]->io_port = port_base; - sh[j]->unique_id = port_base; - sh[j]->n_io_port = REGION_SIZE; - sh[j]->base = bios_segment_table[config_1.bios_segment]; - sh[j]->irq = irq; - sh[j]->sg_tablesize = MAX_SGLIST; - sh[j]->this_id = config_2.ha_scsi_id; - sh[j]->can_queue = MAX_MAILBOXES; - sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; - -#if defined(DEBUG_DETECT) - { - unsigned char sys_mask, lcl_mask; - - sys_mask = inb(sh[j]->io_port + REG_SYS_MASK); - lcl_mask = inb(sh[j]->io_port + REG_LCL_MASK); - printk("SYS_MASK 0x%x, LCL_MASK 0x%x.\n", sys_mask, lcl_mask); - } -#endif - - /* Probably a bogus host scsi id, set it to the dummy value */ - if (sh[j]->this_id == 0) sh[j]->this_id = -1; - - /* If BIOS is disabled, force enable interrupts */ - if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK); - - memset(HD(j), 0, sizeof(struct hostdata)); - HD(j)->heads = mapping_table[config_2.mapping_mode].heads; - HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors; - HD(j)->subversion = subversion; - HD(j)->pdev = NULL; - HD(j)->board_number = j; - - if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST; - - if (HD(j)->subversion == ESA) { - sh[j]->unchecked_isa_dma = FALSE; - sh[j]->dma_channel = NO_DMA; - sprintf(BN(j), "U34F%d", j); - bus_type = "VESA"; - } - else { - unsigned long flags; - sh[j]->unchecked_isa_dma = TRUE; - - flags=claim_dma_lock(); - disable_dma(dma_channel); - clear_dma_ff(dma_channel); - set_dma_mode(dma_channel, DMA_MODE_CASCADE); - enable_dma(dma_channel); - release_dma_lock(flags); - - sh[j]->dma_channel = dma_channel; - sprintf(BN(j), "U14F%d", j); - bus_type = "ISA"; - } - - sh[j]->max_channel = MAX_CHANNEL - 1; - sh[j]->max_id = MAX_TARGET; - sh[j]->max_lun = MAX_LUN; - - if (HD(j)->subversion == ISA && !board_inquiry(j)) { - HD(j)->board_id[40] = 0; - - if (strcmp(&HD(j)->board_id[32], "06000600")) { - printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]); - printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n", - BN(j), &HD(j)->board_id[32]); - sh[j]->hostt->use_clustering = DISABLE_CLUSTERING; - sh[j]->sg_tablesize = MAX_SAFE_SGLIST; - } - } - - if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST"); - else sprintf(dma_name, "DMA %u", dma_channel); - - spin_unlock_irq(&driver_lock); - - for (i = 0; i < sh[j]->can_queue; i++) - HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev, - &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); - - for (i = 0; i < sh[j]->can_queue; i++) - if (! ((&HD(j)->cp[i])->sglist = kmalloc( - sh[j]->sg_tablesize * sizeof(struct sg_list), - (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { - printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); - goto release; - } - - if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) - max_queue_depth = MAX_TAGGED_CMD_PER_LUN; - - if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; - - if (tag_mode != TAG_DISABLED && tag_mode != TAG_SIMPLE) - tag_mode = TAG_ORDERED; - - if (j == 0) { - printk("UltraStor 14F/34F: Copyright (C) 1994-2003 Dario Ballabio.\n"); - printk("%s config options -> of:%c, tm:%d, lc:%c, mq:%d, et:%c.\n", - driver_name, YESNO(have_old_firmware), tag_mode, - YESNO(linked_comm), max_queue_depth, YESNO(ext_tran)); - } - - printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d.\n", - BN(j), bus_type, (unsigned long)sh[j]->io_port, (int)sh[j]->base, - sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); - - if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) - printk("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n", - BN(j), sh[j]->max_id, sh[j]->max_lun); - - for (i = 0; i <= sh[j]->max_channel; i++) - printk("%s: SCSI channel %u enabled, host target ID %d.\n", - BN(j), i, sh[j]->this_id); - - return TRUE; - -freedma: - if (subversion == ISA) free_dma(dma_channel); -freeirq: - free_irq(irq, &sha[j]); -freelock: - spin_unlock_irq(&driver_lock); - release_region(port_base, REGION_SIZE); -fail: - return FALSE; - -release: - u14_34f_release(sh[j]); - return FALSE; -} - -static void internal_setup(char *str, int *ints) { - int i, argc = ints[0]; - char *cur = str, *pc; - - if (argc > 0) { - - if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM; - - for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; - - io_port[i] = 0; - setup_done = TRUE; - } - - while (cur && (pc = strchr(cur, ':'))) { - int val = 0, c = *++pc; - - if (c == 'n' || c == 'N') val = FALSE; - else if (c == 'y' || c == 'Y') val = TRUE; - else val = (int) simple_strtoul(pc, NULL, 0); - - if (!strncmp(cur, "lc:", 3)) linked_comm = val; - else if (!strncmp(cur, "of:", 3)) have_old_firmware = val; - else if (!strncmp(cur, "tm:", 3)) tag_mode = val; - else if (!strncmp(cur, "tc:", 3)) tag_mode = val; - else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; - else if (!strncmp(cur, "ls:", 3)) link_statistics = val; - else if (!strncmp(cur, "et:", 3)) ext_tran = val; - - if ((cur = strchr(cur, ','))) ++cur; - } - - return; -} - -static int option_setup(char *str) { - int ints[MAX_INT_PARAM]; - char *cur = str; - int i = 1; - - while (cur && isdigit(*cur) && i < MAX_INT_PARAM) { - ints[i++] = simple_strtoul(cur, NULL, 0); - - if ((cur = strchr(cur, ',')) != NULL) cur++; - } - - ints[0] = i - 1; - internal_setup(cur, ints); - return 1; -} - -static int u14_34f_detect(struct scsi_host_template *tpnt) { - unsigned int j = 0, k; - - tpnt->proc_name = "u14-34f"; - - if(strlen(boot_options)) option_setup(boot_options); - -#if defined(MODULE) - /* io_port could have been modified when loading as a module */ - if(io_port[0] != SKIP) { - setup_done = TRUE; - io_port[MAX_INT_PARAM] = 0; - } -#endif - - for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; - - for (k = 0; io_port[k]; k++) { - - if (io_port[k] == SKIP) continue; - - if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++; - } - - num_boards = j; - return j; -} - -static void map_dma(unsigned int i, unsigned int j) { - unsigned int data_len = 0; - unsigned int k, pci_dir; - int count; - struct scatterlist *sg; - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = SCpnt->sc_data_direction; - - if (SCpnt->sense_buffer) - cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer, - SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE)); - - cpp->sense_len = SCSI_SENSE_BUFFERSIZE; - - if (scsi_bufflen(SCpnt)) { - count = scsi_dma_map(SCpnt); - BUG_ON(count < 0); - - scsi_for_each_sg(SCpnt, sg, count, k) { - cpp->sglist[k].address = H2DEV(sg_dma_address(sg)); - cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg)); - data_len += sg->length; - } - - cpp->sg = TRUE; - cpp->use_sg = scsi_sg_count(SCpnt); - cpp->data_address = - H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist, - cpp->use_sg * sizeof(struct sg_list), - pci_dir)); - cpp->data_len = H2DEV(data_len); - - } else { - pci_dir = PCI_DMA_BIDIRECTIONAL; - cpp->data_len = H2DEV(scsi_bufflen(SCpnt)); - } -} - -static void unmap_dma(unsigned int i, unsigned int j) { - unsigned int pci_dir; - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = SCpnt->sc_data_direction; - - if (DEV2H(cpp->sense_addr)) - pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr), - DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - - scsi_dma_unmap(SCpnt); - - if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; - - if (DEV2H(cpp->data_address)) - pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); -} - -static void sync_dma(unsigned int i, unsigned int j) { - unsigned int pci_dir; - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = SCpnt->sc_data_direction; - - if (DEV2H(cpp->sense_addr)) - pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr), - DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - - if (scsi_sg_count(SCpnt)) - pci_dma_sync_sg_for_cpu(HD(j)->pdev, scsi_sglist(SCpnt), - scsi_sg_count(SCpnt), pci_dir); - - if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; - - if (DEV2H(cpp->data_address)) - pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->data_address), - DEV2H(cpp->data_len), pci_dir); -} - -static void scsi_to_dev_dir(unsigned int i, unsigned int j) { - unsigned int k; - - static const unsigned char data_out_cmds[] = { - 0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e, - 0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, - 0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b, 0x5d - }; - - static const unsigned char data_none_cmds[] = { - 0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e, - 0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47, - 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00 - }; - - struct mscp *cpp; - struct scsi_cmnd *SCpnt; - - cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - - if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { - cpp->xdir = DTD_IN; - return; - } - else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { - cpp->xdir = DTD_OUT; - return; - } - else if (SCpnt->sc_data_direction == DMA_NONE) { - cpp->xdir = DTD_NONE; - return; - } - - if (SCpnt->sc_data_direction != DMA_BIDIRECTIONAL) - panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j)); - - cpp->xdir = DTD_IN; - - for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) - if (SCpnt->cmnd[0] == data_out_cmds[k]) { - cpp->xdir = DTD_OUT; - break; - } - - if (cpp->xdir == DTD_IN) - for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++) - if (SCpnt->cmnd[0] == data_none_cmds[k]) { - cpp->xdir = DTD_NONE; - break; - } - -} - -static int u14_34f_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - unsigned int i, j, k; - struct mscp *cpp; - - /* j is the board number */ - j = ((struct hostdata *) SCpnt->device->host->hostdata)->board_number; - - if (SCpnt->host_scribble) - panic("%s: qcomm, SCpnt %p already active.\n", - BN(j), SCpnt); - - /* i is the mailbox number, look for the first free mailbox - starting from last_cp_used */ - i = HD(j)->last_cp_used + 1; - - for (k = 0; k < sh[j]->can_queue; k++, i++) { - - if (i >= sh[j]->can_queue) i = 0; - - if (HD(j)->cp_stat[i] == FREE) { - HD(j)->last_cp_used = i; - break; - } - } - - if (k == sh[j]->can_queue) { - printk("%s: qcomm, no free mailbox.\n", BN(j)); - return 1; - } - - /* Set pointer to control packet structure */ - cpp = &HD(j)->cp[i]; - - memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE); - SCpnt->scsi_done = done; - cpp->cpp_index = i; - SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index; - - if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%u.\n", - BN(j), i, SCpnt->device->channel, SCpnt->device->id, - (u8)SCpnt->device->lun); - - cpp->opcode = OP_SCSI; - cpp->channel = SCpnt->device->channel; - cpp->target = SCpnt->device->id; - cpp->lun = (u8)SCpnt->device->lun; - cpp->SCpnt = SCpnt; - cpp->cdb_len = SCpnt->cmd_len; - memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); - - /* Use data transfer direction SCpnt->sc_data_direction */ - scsi_to_dev_dir(i, j); - - /* Map DMA buffers and SG list */ - map_dma(i, j); - - if (linked_comm && SCpnt->device->queue_depth > 2 - && TLDEV(SCpnt->device->type)) { - HD(j)->cp_stat[i] = READY; - flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), j, FALSE); - return 0; - } - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - unmap_dma(i, j); - SCpnt->host_scribble = NULL; - scmd_printk(KERN_INFO, SCpnt, - "qcomm, adapter busy.\n"); - return 1; - } - - /* Store pointer in OGM address bytes */ - outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM); - - /* Issue OGM interrupt */ - outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); - - HD(j)->cp_stat[i] = IN_USE; - return 0; -} - -static DEF_SCSI_QCMD(u14_34f_queuecommand) - -static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) { - unsigned int i, j; - - j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; - - if (SCarg->host_scribble == NULL) { - scmd_printk(KERN_INFO, SCarg, "abort, command inactive.\n"); - return SUCCESS; - } - - i = *(unsigned int *)SCarg->host_scribble; - scmd_printk(KERN_INFO, SCarg, "abort, mbox %d.\n", i); - - if (i >= sh[j]->can_queue) - panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: abort, timeout error.\n", BN(j)); - return FAILED; - } - - if (HD(j)->cp_stat[i] == FREE) { - printk("%s: abort, mbox %d is free.\n", BN(j), i); - return SUCCESS; - } - - if (HD(j)->cp_stat[i] == IN_USE) { - printk("%s: abort, mbox %d is in use.\n", BN(j), i); - - if (SCarg != HD(j)->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - BN(j), i, SCarg, HD(j)->cp[i].SCpnt); - - if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) - printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); - - return FAILED; - } - - if (HD(j)->cp_stat[i] == IN_RESET) { - printk("%s: abort, mbox %d is in reset.\n", BN(j), i); - return FAILED; - } - - if (HD(j)->cp_stat[i] == LOCKED) { - printk("%s: abort, mbox %d is locked.\n", BN(j), i); - return SUCCESS; - } - - if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { - unmap_dma(i, j); - SCarg->result = DID_ABORT << 16; - SCarg->host_scribble = NULL; - HD(j)->cp_stat[i] = FREE; - printk("%s, abort, mbox %d ready, DID_ABORT, done.\n", BN(j), i); - SCarg->scsi_done(SCarg); - return SUCCESS; - } - - panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); -} - -static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { - unsigned int i, j, k, c, limit = 0; - unsigned long time; - int arg_done = FALSE; - struct scsi_cmnd *SCpnt; - - j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; - scmd_printk(KERN_INFO, SCarg, "reset, enter.\n"); - - spin_lock_irq(sh[j]->host_lock); - - if (SCarg->host_scribble == NULL) - printk("%s: reset, inactive.\n", BN(j)); - - if (HD(j)->in_reset) { - printk("%s: reset, exit, already in reset.\n", BN(j)); - spin_unlock_irq(sh[j]->host_lock); - return FAILED; - } - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: reset, exit, timeout error.\n", BN(j)); - spin_unlock_irq(sh[j]->host_lock); - return FAILED; - } - - HD(j)->retries = 0; - - for (c = 0; c <= sh[j]->max_channel; c++) - for (k = 0; k < sh[j]->max_id; k++) { - HD(j)->target_redo[k][c] = TRUE; - HD(j)->target_to[k][c] = 0; - } - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == FREE) continue; - - if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); - continue; - } - - if (!(SCpnt = HD(j)->cp[i].SCpnt)) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { - HD(j)->cp_stat[i] = ABORTING; - printk("%s: reset, mbox %d aborting.\n", BN(j), i); - } - - else { - HD(j)->cp_stat[i] = IN_RESET; - printk("%s: reset, mbox %d in reset.\n", BN(j), i); - } - - if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); - - if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); - - if (SCpnt == SCarg) arg_done = TRUE; - } - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: reset, cannot reset, timeout error.\n", BN(j)); - spin_unlock_irq(sh[j]->host_lock); - return FAILED; - } - - outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR); - printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); - -#if defined(DEBUG_RESET) - do_trace = TRUE; -#endif - - HD(j)->in_reset = TRUE; - - spin_unlock_irq(sh[j]->host_lock); - time = jiffies; - while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); - spin_lock_irq(sh[j]->host_lock); - - printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == IN_RESET) { - SCpnt = HD(j)->cp[i].SCpnt; - unmap_dma(i, j); - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox is still waiting for its interrupt */ - HD(j)->cp_stat[i] = LOCKED; - - printk("%s, reset, mbox %d locked, DID_RESET, done.\n", BN(j), i); - } - - else if (HD(j)->cp_stat[i] == ABORTING) { - SCpnt = HD(j)->cp[i].SCpnt; - unmap_dma(i, j); - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox was never queued to the adapter */ - HD(j)->cp_stat[i] = FREE; - - printk("%s, reset, mbox %d aborting, DID_RESET, done.\n", BN(j), i); - } - - else - - /* Any other mailbox has already been set free by interrupt */ - continue; - - SCpnt->scsi_done(SCpnt); - } - - HD(j)->in_reset = FALSE; - do_trace = FALSE; - - if (arg_done) printk("%s: reset, exit, done.\n", BN(j)); - else printk("%s: reset, exit.\n", BN(j)); - - spin_unlock_irq(sh[j]->host_lock); - return SUCCESS; -} - -static int u14_34f_bios_param(struct scsi_device *disk, - struct block_device *bdev, sector_t capacity, int *dkinfo) { - unsigned int j = 0; - unsigned int size = capacity; - - dkinfo[0] = HD(j)->heads; - dkinfo[1] = HD(j)->sectors; - dkinfo[2] = size / (HD(j)->heads * HD(j)->sectors); - - if (ext_tran && (scsicam_bios_param(bdev, capacity, dkinfo) < 0)) { - dkinfo[0] = 255; - dkinfo[1] = 63; - dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); - } - -#if defined (DEBUG_GEOMETRY) - printk ("%s: bios_param, head=%d, sec=%d, cyl=%d.\n", driver_name, - dkinfo[0], dkinfo[1], dkinfo[2]); -#endif - - return FALSE; -} - -static void sort(unsigned long sk[], unsigned int da[], unsigned int n, - unsigned int rev) { - unsigned int i, j, k, y; - unsigned long x; - - for (i = 0; i < n - 1; i++) { - k = i; - - for (j = k + 1; j < n; j++) - if (rev) { - if (sk[j] > sk[k]) k = j; - } - else { - if (sk[j] < sk[k]) k = j; - } - - if (k != i) { - x = sk[k]; sk[k] = sk[i]; sk[i] = x; - y = da[k]; da[k] = da[i]; da[i] = y; - } - } - - return; - } - -static int reorder(unsigned int j, unsigned long cursec, - unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { - struct scsi_cmnd *SCpnt; - struct mscp *cpp; - unsigned int k, n; - unsigned int rev = FALSE, s = TRUE, r = TRUE; - unsigned int input_only = TRUE, overlap = FALSE; - unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; - unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0; - unsigned long ioseek = 0; - - static unsigned int flushcount = 0, batchcount = 0, sortcount = 0; - static unsigned int readycount = 0, ovlcount = 0, inputcount = 0; - static unsigned int readysorted = 0, revcount = 0; - static unsigned long seeksorted = 0, seeknosort = 0; - - if (link_statistics && !(++flushcount % link_statistics)) - printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\ - " av %ldK as %ldK.\n", flushcount, batchcount, inputcount, - ovlcount, readycount, readysorted, sortcount, revcount, - seeknosort / (readycount + 1), - seeksorted / (readycount + 1)); - - if (n_ready <= 1) return FALSE; - - for (n = 0; n < n_ready; n++) { - k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - - if (!(cpp->xdir == DTD_IN)) input_only = FALSE; - - if (blk_rq_pos(SCpnt->request) < minsec) - minsec = blk_rq_pos(SCpnt->request); - if (blk_rq_pos(SCpnt->request) > maxsec) - maxsec = blk_rq_pos(SCpnt->request); - - sl[n] = blk_rq_pos(SCpnt->request); - ioseek += blk_rq_sectors(SCpnt->request); - - if (!n) continue; - - if (sl[n] < sl[n - 1]) s = FALSE; - if (sl[n] > sl[n - 1]) r = FALSE; - - if (link_statistics) { - if (sl[n] > sl[n - 1]) - seek += sl[n] - sl[n - 1]; - else - seek += sl[n - 1] - sl[n]; - } - - } - - if (link_statistics) { - if (cursec > sl[0]) seek += cursec - sl[0]; else seek += sl[0] - cursec; - } - - if (cursec > ((maxsec + minsec) / 2)) rev = TRUE; - - if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE; - - if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev); - - if (!input_only) for (n = 0; n < n_ready; n++) { - k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - ll[n] = blk_rq_sectors(SCpnt->request); pl[n] = SCpnt->serial_number; - - if (!n) continue; - - if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n])) - || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE; - } - - if (overlap) sort(pl, il, n_ready, FALSE); - - if (link_statistics) { - if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; - batchcount++; readycount += n_ready; seeknosort += seek / 1024; - if (input_only) inputcount++; - if (overlap) { ovlcount++; seeksorted += iseek / 1024; } - else seeksorted += (iseek + maxsec - minsec) / 1024; - if (rev && !r) { revcount++; readysorted += n_ready; } - if (!rev && !s) { sortcount++; readysorted += n_ready; } - } - -#if defined(DEBUG_LINKED_COMMANDS) - if (link_statistics && (overlap || !(flushcount % link_statistics))) - for (n = 0; n < n_ready; n++) { - k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - printk("%s %d.%d:%llu mb %d fc %d nr %d sec %ld ns %u"\ - " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", - (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, - (u8)SCpnt->lun, k, flushcount, n_ready, - blk_rq_pos(SCpnt->request), blk_rq_sectors(SCpnt->request), - cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), - YESNO(overlap), cpp->xdir); - } -#endif - return overlap; -} - -static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned int j, - unsigned int ihdlr) { - struct scsi_cmnd *SCpnt; - struct mscp *cpp; - unsigned int k, n, n_ready = 0, il[MAX_MAILBOXES]; - - for (k = 0; k < sh[j]->can_queue; k++) { - - if (HD(j)->cp_stat[k] != READY && HD(j)->cp_stat[k] != IN_USE) continue; - - cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - - if (SCpnt->device != dev) continue; - - if (HD(j)->cp_stat[k] == IN_USE) return; - - il[n_ready++] = k; - } - - if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1; - - for (n = 0; n < n_ready; n++) { - k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - scmd_printk(KERN_INFO, SCpnt, - "%s, mbox %d, adapter" - " busy, will abort.\n", (ihdlr ? "ihdlr" : "qcomm"), - k); - HD(j)->cp_stat[k] = ABORTING; - continue; - } - - outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM); - outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); - HD(j)->cp_stat[k] = IN_USE; - } - -} - -static irqreturn_t ihdlr(unsigned int j) -{ - struct scsi_cmnd *SCpnt; - unsigned int i, k, c, status, tstatus, reg, ret; - struct mscp *spp, *cpp; - int irq = sh[j]->irq; - - /* Check if this board need to be serviced */ - if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) goto none; - - HD(j)->iocount++; - - if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq, - HD(j)->iocount); - - /* Check if this board is still busy */ - if (wait_on_busy(sh[j]->io_port, 20 * MAXLOOP)) { - outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); - printk("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n", - BN(j), irq, reg, HD(j)->iocount); - goto none; - } - - ret = inl(sh[j]->io_port + REG_ICM); - - /* Clear interrupt pending flag */ - outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); - - /* Find the mailbox to be serviced on this board */ - for (i = 0; i < sh[j]->can_queue; i++) - if (H2DEV(HD(j)->cp[i].cp_dma_addr) == ret) break; - - if (i >= sh[j]->can_queue) - panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j), - (void *)ret, (void *)H2DEV(HD(j)->cp[0].cp_dma_addr)); - - cpp = &(HD(j)->cp[i]); - spp = cpp; - -#if defined(DEBUG_GENERATE_ABORTS) - if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) goto handled; -#endif - - if (HD(j)->cp_stat[i] == IGNORE) { - HD(j)->cp_stat[i] = FREE; - goto handled; - } - else if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i, - HD(j)->iocount); - goto handled; - } - else if (HD(j)->cp_stat[i] == FREE) { - printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i, - HD(j)->iocount); - goto handled; - } - else if (HD(j)->cp_stat[i] == IN_RESET) - printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); - else if (HD(j)->cp_stat[i] != IN_USE) - panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", - BN(j), i, HD(j)->cp_stat[i]); - - HD(j)->cp_stat[i] = FREE; - SCpnt = cpp->SCpnt; - - if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (SCpnt->host_scribble == NULL) - panic("%s: ihdlr, mbox %d, SCpnt %p garbled.\n", BN(j), i, - SCpnt); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: ihdlr, mbox %d, index mismatch %d.\n", - BN(j), i, *(unsigned int *)SCpnt->host_scribble); - - sync_dma(i, j); - - if (linked_comm && SCpnt->device->queue_depth > 2 - && TLDEV(SCpnt->device->type)) - flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), j, TRUE); - - tstatus = status_byte(spp->target_status); - -#if defined(DEBUG_GENERATE_ERRORS) - if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 200) < 2)) - spp->adapter_status = 0x01; -#endif - - switch (spp->adapter_status) { - case ASOK: /* status OK */ - - /* Forces a reset if a disk drive keeps returning BUSY */ - if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) - status = DID_ERROR << 16; - - /* If there was a bus reset, redo operation on each target */ - else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK - && HD(j)->target_redo[scmd_id(SCpnt)][scmd_channel(SCpnt)]) - status = DID_BUS_BUSY << 16; - - /* Works around a flaw in scsi.c */ - else if (tstatus == CHECK_CONDITION - && SCpnt->device->type == TYPE_DISK - && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR) - status = DID_BUS_BUSY << 16; - - else - status = DID_OK << 16; - - if (tstatus == GOOD) - HD(j)->target_redo[scmd_id(SCpnt)][scmd_channel(SCpnt)] = FALSE; - - if (spp->target_status && SCpnt->device->type == TYPE_DISK && - (!(tstatus == CHECK_CONDITION && HD(j)->iocount <= 1000 && - (SCpnt->sense_buffer[2] & 0xf) == NOT_READY))) - scmd_printk(KERN_INFO, SCpnt, - "ihdlr, target_status 0x%x, sense key 0x%x.\n", - spp->target_status, - SCpnt->sense_buffer[2]); - - HD(j)->target_to[scmd_id(SCpnt)][scmd_channel(SCpnt)] = 0; - - if (HD(j)->last_retried_pid == SCpnt->serial_number) HD(j)->retries = 0; - - break; - case ASST: /* Selection Time Out */ - - if (HD(j)->target_to[scmd_id(SCpnt)][scmd_channel(SCpnt)] > 1) - status = DID_ERROR << 16; - else { - status = DID_TIME_OUT << 16; - HD(j)->target_to[scmd_id(SCpnt)][scmd_channel(SCpnt)]++; - } - - break; - - /* Perform a limited number of internal retries */ - case 0x93: /* Unexpected bus free */ - case 0x94: /* Target bus phase sequence failure */ - case 0x96: /* Illegal SCSI command */ - case 0xa3: /* SCSI bus reset error */ - - for (c = 0; c <= sh[j]->max_channel; c++) - for (k = 0; k < sh[j]->max_id; k++) - HD(j)->target_redo[k][c] = TRUE; - - - case 0x92: /* Data over/under-run */ - - if (SCpnt->device->type != TYPE_TAPE - && HD(j)->retries < MAX_INTERNAL_RETRIES) { - -#if defined(DID_SOFT_ERROR) - status = DID_SOFT_ERROR << 16; -#else - status = DID_BUS_BUSY << 16; -#endif - - HD(j)->retries++; - HD(j)->last_retried_pid = SCpnt->serial_number; - } - else - status = DID_ERROR << 16; - - break; - case 0x01: /* Invalid command */ - case 0x02: /* Invalid parameters */ - case 0x03: /* Invalid data list */ - case 0x84: /* SCSI bus abort error */ - case 0x9b: /* Auto request sense error */ - case 0x9f: /* Unexpected command complete message error */ - case 0xff: /* Invalid parameter in the S/G list */ - default: - status = DID_ERROR << 16; - break; - } - - SCpnt->result = status | spp->target_status; - -#if defined(DEBUG_INTERRUPT) - if (SCpnt->result || do_trace) -#else - if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || - (spp->adapter_status != ASOK && - spp->adapter_status != ASST && HD(j)->iocount <= 1000) || - do_trace || msg_byte(spp->target_status)) -#endif - scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"\ - " reg 0x%x, count %d.\n", - i, spp->adapter_status, spp->target_status, - reg, HD(j)->iocount); - - unmap_dma(i, j); - - /* Set the command state to inactive */ - SCpnt->host_scribble = NULL; - - SCpnt->scsi_done(SCpnt); - - if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq, - HD(j)->iocount); - -handled: - return IRQ_HANDLED; -none: - return IRQ_NONE; -} - -static irqreturn_t do_interrupt_handler(int irq, void *shap) { - unsigned int j; - unsigned long spin_flags; - irqreturn_t ret; - - /* Check if the interrupt must be processed by this handler */ - if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return IRQ_NONE; - - spin_lock_irqsave(sh[j]->host_lock, spin_flags); - ret = ihdlr(j); - spin_unlock_irqrestore(sh[j]->host_lock, spin_flags); - return ret; -} - -static int u14_34f_release(struct Scsi_Host *shpnt) { - unsigned int i, j; - - for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); - - if (sh[j] == NULL) - panic("%s: release, invalid Scsi_Host pointer.\n", driver_name); - - for (i = 0; i < sh[j]->can_queue; i++) - kfree((&HD(j)->cp[i])->sglist); - - for (i = 0; i < sh[j]->can_queue; i++) - pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr, - sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); - - free_irq(sh[j]->irq, &sha[j]); - - if (sh[j]->dma_channel != NO_DMA) - free_dma(sh[j]->dma_channel); - - release_region(sh[j]->io_port, sh[j]->n_io_port); - scsi_unregister(sh[j]); - return FALSE; -} - -#include "scsi_module.c" - -#ifndef MODULE -__setup("u14-34f=", option_setup); -#endif /* end MODULE */ -- cgit v1.2.3 From 4931a46aef5c0d21422d1344fa8ec9206934e93c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Sep 2016 08:50:51 -0700 Subject: scsi: pas16: remove from tree The driver has not seen any maintainer activity or other work that wasn't tree wide conversion or clenaups in the entire history of the git tree. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinicke Acked-by: Finn Thain Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi-parameters.txt | 3 - MAINTAINERS | 1 - drivers/scsi/Kconfig | 14 - drivers/scsi/Makefile | 1 - drivers/scsi/pas16.c | 565 --------------------------------- drivers/scsi/pas16.h | 121 ------- 6 files changed, 705 deletions(-) delete mode 100644 drivers/scsi/pas16.c delete mode 100644 drivers/scsi/pas16.h (limited to 'MAINTAINERS') diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 083bd934218a..fe77b5a2c926 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -80,9 +80,6 @@ parameters may be changed at runtime by the command Format: , See also Documentation/scsi/st.txt. - pas16= [HW,SCSI] - See header of drivers/scsi/pas16.c. - scsi_debug_*= [SCSI] See drivers/scsi/scsi_debug.c. diff --git a/MAINTAINERS b/MAINTAINERS index 6ca763fe0346..2a0c0567082f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8052,7 +8052,6 @@ F: drivers/scsi/dtc.* F: drivers/scsi/g_NCR5380.* F: drivers/scsi/g_NCR5380_mmio.c F: drivers/scsi/mac_scsi.* -F: drivers/scsi/pas16.* F: drivers/scsi/sun3_scsi.* F: drivers/scsi/sun3_scsi_vme.c F: drivers/scsi/t128.* diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 69785315eca3..ee83d95bc3d6 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1225,20 +1225,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT not allow targets to disconnect is not reasonable if there is more than 1 device on a SCSI bus. The normal answer therefore is N. -config SCSI_PAS16 - tristate "PAS16 SCSI support" - depends on ISA && SCSI - select SCSI_SPI_ATTRS - ---help--- - This is support for a SCSI host adapter. It is explained in section - 3.10 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . - - To compile this driver as a module, choose M here: the - module will be called pas16. - config SCSI_QLOGIC_FAS tristate "Qlogic FAS SCSI support" depends on ISA && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 921cf07e9b7b..be3108c0e476 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -87,7 +87,6 @@ obj-$(CONFIG_SCSI_QLA_ISCSI) += libiscsi.o qla4xxx/ obj-$(CONFIG_SCSI_LPFC) += lpfc/ obj-$(CONFIG_SCSI_BFA_FC) += bfa/ obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor/ -obj-$(CONFIG_SCSI_PAS16) += pas16.o obj-$(CONFIG_SCSI_T128) += t128.o obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o obj-$(CONFIG_SCSI_HPSA) += hpsa.o diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c deleted file mode 100644 index 2f689ae7a803..000000000000 --- a/drivers/scsi/pas16.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * This driver adapted from Drew Eckhardt's Trantor T128 driver - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * ( Based on T128 - DISTRIBUTION RELEASE 3. ) - * - * Modified to work with the Pro Audio Spectrum/Studio 16 - * by John Weidman. - * - * - * For more information, please consult - * - * Media Vision - * (510) 770-8600 - * (800) 348-7116 - */ - -/* - * The card is detected and initialized in one of several ways : - * 1. Autoprobe (default) - There are many different models of - * the Pro Audio Spectrum/Studio 16, and I only have one of - * them, so this may require a little tweaking. An interrupt - * is triggered to autoprobe for the interrupt line. Note: - * with the newer model boards, the interrupt is set via - * software after reset using the default_irq for the - * current board number. - * - * 2. With command line overrides - pas16=port,irq may be - * used on the LILO command line to override the defaults. - * - * 3. With the PAS16_OVERRIDE compile time define. This is - * specified as an array of address, irq tuples. Ie, for - * one board at the default 0x388 address, IRQ10, I could say - * -DPAS16_OVERRIDE={{0x388, 10}} - * NOTE: Untested. - * - * 4. When included as a module, with arguments passed on the command line: - * pas16_irq=xx the interrupt - * pas16_addr=xx the port - * e.g. "modprobe pas16 pas16_addr=0x388 pas16_irq=5" - * - * Note that if the override methods are used, place holders must - * be specified for other boards in the system. - * - * - * Configuration notes : - * The current driver does not support interrupt sharing with the - * sound portion of the card. If you use the same irq for the - * scsi port and sound you will have problems. Either use - * a different irq for the scsi port or don't use interrupts - * for the scsi port. - * - * If you have problems with your card not being recognized, use - * the LILO command line override. Try to get it recognized without - * interrupts. Ie, for a board at the default 0x388 base port, - * boot: linux pas16=0x388,0 - * - * NO_IRQ (0) should be specified for no interrupt, - * IRQ_AUTO (254) to autoprobe for an IRQ line if overridden - * on the command line. - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include "pas16.h" -#include "NCR5380.h" - - -static unsigned short pas16_addr; -static int pas16_irq; - - -static const int scsi_irq_translate[] = - { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 }; - -/* The default_irqs array contains values used to set the irq into the - * board via software (as must be done on newer model boards without - * irq jumpers on the board). The first value in the array will be - * assigned to logical board 0, the next to board 1, etc. - */ -static int default_irqs[] __initdata = - { PAS16_DEFAULT_BOARD_1_IRQ, - PAS16_DEFAULT_BOARD_2_IRQ, - PAS16_DEFAULT_BOARD_3_IRQ, - PAS16_DEFAULT_BOARD_4_IRQ - }; - -static struct override { - unsigned short io_port; - int irq; -} overrides -#ifdef PAS16_OVERRIDE - [] __initdata = PAS16_OVERRIDE; -#else - [4] __initdata = {{0,IRQ_AUTO}, {0,IRQ_AUTO}, {0,IRQ_AUTO}, - {0,IRQ_AUTO}}; -#endif - -#define NO_OVERRIDES ARRAY_SIZE(overrides) - -static struct base { - unsigned short io_port; - int noauto; -} bases[] __initdata = - { {PAS16_DEFAULT_BASE_1, 0}, - {PAS16_DEFAULT_BASE_2, 0}, - {PAS16_DEFAULT_BASE_3, 0}, - {PAS16_DEFAULT_BASE_4, 0} - }; - -#define NO_BASES ARRAY_SIZE(bases) - -static const unsigned short pas16_offset[ 8 ] = - { - 0x1c00, /* OUTPUT_DATA_REG */ - 0x1c01, /* INITIATOR_COMMAND_REG */ - 0x1c02, /* MODE_REG */ - 0x1c03, /* TARGET_COMMAND_REG */ - 0x3c00, /* STATUS_REG ro, SELECT_ENABLE_REG wo */ - 0x3c01, /* BUS_AND_STATUS_REG ro, START_DMA_SEND_REG wo */ - 0x3c02, /* INPUT_DATA_REGISTER ro, (N/A on PAS16 ?) - * START_DMA_TARGET_RECEIVE_REG wo - */ - 0x3c03, /* RESET_PARITY_INTERRUPT_REG ro, - * START_DMA_INITIATOR_RECEIVE_REG wo - */ - }; - - -/* - * Function : enable_board( int board_num, unsigned short port ) - * - * Purpose : set address in new model board - * - * Inputs : board_num - logical board number 0-3, port - base address - * - */ - -static void __init - enable_board( int board_num, unsigned short port ) -{ - outb( 0xbc + board_num, MASTER_ADDRESS_PTR ); - outb( port >> 2, MASTER_ADDRESS_PTR ); -} - - - -/* - * Function : init_board( unsigned short port, int irq ) - * - * Purpose : Set the board up to handle the SCSI interface - * - * Inputs : port - base address of the board, - * irq - irq to assign to the SCSI port - * force_irq - set it even if it conflicts with sound driver - * - */ - -static void __init - init_board( unsigned short io_port, int irq, int force_irq ) -{ - unsigned int tmp; - unsigned int pas_irq_code; - - /* Initialize the SCSI part of the board */ - - outb( 0x30, io_port + P_TIMEOUT_COUNTER_REG ); /* Timeout counter */ - outb( 0x01, io_port + P_TIMEOUT_STATUS_REG_OFFSET ); /* Reset TC */ - outb( 0x01, io_port + WAIT_STATE ); /* 1 Wait state */ - - inb(io_port + pas16_offset[RESET_PARITY_INTERRUPT_REG]); - - /* Set the SCSI interrupt pointer without mucking up the sound - * interrupt pointer in the same byte. - */ - pas_irq_code = ( irq < 16 ) ? scsi_irq_translate[irq] : 0; - tmp = inb( io_port + IO_CONFIG_3 ); - - if( (( tmp & 0x0f ) == pas_irq_code) && pas_irq_code > 0 - && !force_irq ) - { - printk( "pas16: WARNING: Can't use same irq as sound " - "driver -- interrupts disabled\n" ); - /* Set up the drive parameters, disable 5380 interrupts */ - outb( 0x4d, io_port + SYS_CONFIG_4 ); - } - else - { - tmp = ( tmp & 0x0f ) | ( pas_irq_code << 4 ); - outb( tmp, io_port + IO_CONFIG_3 ); - - /* Set up the drive parameters and enable 5380 interrupts */ - outb( 0x6d, io_port + SYS_CONFIG_4 ); - } -} - - -/* - * Function : pas16_hw_detect( unsigned short board_num ) - * - * Purpose : determine if a pas16 board is present - * - * Inputs : board_num - logical board number ( 0 - 3 ) - * - * Returns : 0 if board not found, 1 if found. - */ - -static int __init - pas16_hw_detect( unsigned short board_num ) -{ - unsigned char board_rev, tmp; - unsigned short io_port = bases[ board_num ].io_port; - - /* See if we can find a PAS16 board at the address associated - * with this logical board number. - */ - - /* First, attempt to take a newer model board out of reset and - * give it a base address. This shouldn't affect older boards. - */ - enable_board( board_num, io_port ); - - /* Now see if it looks like a PAS16 board */ - board_rev = inb( io_port + PCB_CONFIG ); - - if( board_rev == 0xff ) - return 0; - - tmp = board_rev ^ 0xe0; - - outb( tmp, io_port + PCB_CONFIG ); - tmp = inb( io_port + PCB_CONFIG ); - outb( board_rev, io_port + PCB_CONFIG ); - - if( board_rev != tmp ) /* Not a PAS-16 */ - return 0; - - if( ( inb( io_port + OPERATION_MODE_1 ) & 0x03 ) != 0x03 ) - return 0; /* return if no SCSI interface found */ - - /* Mediavision has some new model boards that return ID bits - * that indicate a SCSI interface, but they're not (LMS). We'll - * put in an additional test to try to weed them out. - */ - - outb(0x01, io_port + WAIT_STATE); /* 1 Wait state */ - outb(0x20, io_port + pas16_offset[MODE_REG]); /* Is it really SCSI? */ - if (inb(io_port + pas16_offset[MODE_REG]) != 0x20) /* Write to a reg. */ - return 0; /* and try to read */ - outb(0x00, io_port + pas16_offset[MODE_REG]); /* it back. */ - if (inb(io_port + pas16_offset[MODE_REG]) != 0x00) - return 0; - - return 1; -} - - -#ifndef MODULE -/* - * Function : pas16_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -static int __init pas16_setup(char *str) -{ - static int commandline_current; - int i; - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] != 2) - printk("pas16_setup : usage pas16=io_port,irq\n"); - else - if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].io_port = (unsigned short) ints[1]; - overrides[commandline_current].irq = ints[2]; - for (i = 0; i < NO_BASES; ++i) - if (bases[i].io_port == (unsigned short) ints[1]) { - bases[i].noauto = 1; - break; - } - ++commandline_current; - } - return 1; -} - -__setup("pas16=", pas16_setup); -#endif - -/* - * Function : int pas16_detect(struct scsi_host_template * tpnt) - * - * Purpose : detects and initializes PAS16 controllers - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ - -static int __init pas16_detect(struct scsi_host_template *tpnt) -{ - static int current_override; - static unsigned short current_base; - struct Scsi_Host *instance; - unsigned short io_port; - int count; - - if (pas16_addr != 0) { - overrides[0].io_port = pas16_addr; - /* - * This is how we avoid seeing more than - * one host adapter at the same I/O port. - * Cribbed shamelessly from pas16_setup(). - */ - for (count = 0; count < NO_BASES; ++count) - if (bases[count].io_port == pas16_addr) { - bases[count].noauto = 1; - break; - } - } - if (pas16_irq != 0) - overrides[0].irq = pas16_irq; - - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - io_port = 0; - - if (overrides[current_override].io_port) - { - io_port = overrides[current_override].io_port; - enable_board( current_override, io_port ); - init_board( io_port, overrides[current_override].irq, 1 ); - } - else - for (; !io_port && (current_base < NO_BASES); ++current_base) { - dprintk(NDEBUG_INIT, "pas16: probing io_port 0x%04x\n", - (unsigned int)bases[current_base].io_port); - if ( !bases[current_base].noauto && - pas16_hw_detect( current_base ) ){ - io_port = bases[current_base].io_port; - init_board( io_port, default_irqs[ current_base ], 0 ); - dprintk(NDEBUG_INIT, "pas16: detected board\n"); - } - } - - dprintk(NDEBUG_INIT, "pas16: io_port = 0x%04x\n", - (unsigned int)io_port); - - if (!io_port) - break; - - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - if(instance == NULL) - goto out; - - instance->io_port = io_port; - - if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) - goto out_unregister; - - NCR5380_maybe_reset_bus(instance); - - if (overrides[current_override].irq != IRQ_AUTO) - instance->irq = overrides[current_override].irq; - else - instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS); - - /* Compatibility with documented NCR5380 kernel parameters */ - if (instance->irq == 255) - instance->irq = NO_IRQ; - - if (instance->irq != NO_IRQ) - if (request_irq(instance->irq, pas16_intr, 0, - "pas16", instance)) { - printk("scsi%d : IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = NO_IRQ; - } - - if (instance->irq == NO_IRQ) { - printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); - printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); - /* Disable 5380 interrupts, leave drive params the same */ - outb( 0x4d, io_port + SYS_CONFIG_4 ); - outb( (inb(io_port + IO_CONFIG_3) & 0x0f), io_port + IO_CONFIG_3 ); - } - - dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", - instance->host_no, instance->irq); - - ++current_override; - ++count; - } - return count; - -out_unregister: - scsi_unregister(instance); -out: - return count; -} - -/* - * Function : int pas16_biosparam(Disk *disk, struct block_device *dev, int *ip) - * - * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for - * the specified device / size. - * - * Inputs : size = size of device in sectors (512 bytes), dev = block device - * major / minor, ip[] = {heads, sectors, cylinders} - * - * Returns : always 0 (success), initializes ip - * - */ - -/* - * XXX Most SCSI boards use this mapping, I could be incorrect. Some one - * using hard disks on a trantor should verify that this mapping corresponds - * to that used by the BIOS / ASPI driver by running the linux fdisk program - * and matching the H_C_S coordinates to what DOS uses. - */ - -static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev, - sector_t capacity, int *ip) -{ - int size = capacity; - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; /* I think I have it as /(32*64) */ - if( ip[2] > 1024 ) { /* yes, >, not >= */ - ip[0]=255; - ip[1]=63; - ip[2]=size/(63*255); - if( ip[2] > 1023 ) /* yes >1023... */ - ip[2] = 1023; - } - - return 0; -} - -/* - * Function : int pas16_pread (struct Scsi_Host *instance, - * unsigned char *dst, int len) - * - * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to - * dst - * - * Inputs : dst = destination, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int pas16_pread(struct Scsi_Host *instance, - unsigned char *dst, int len) -{ - register unsigned char *d = dst; - register unsigned short reg = (unsigned short) (instance->io_port + - P_DATA_REG_OFFSET); - register int i = len; - int ii = 0; - - while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) ) - ++ii; - - insb( reg, d, i ); - - if ( inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) { - outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET); - printk("scsi%d : watchdog timer fired in NCR5380_pread()\n", - instance->host_no); - return -1; - } - return 0; -} - -/* - * Function : int pas16_pwrite (struct Scsi_Host *instance, - * unsigned char *src, int len) - * - * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from - * src - * - * Inputs : src = source, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int pas16_pwrite(struct Scsi_Host *instance, - unsigned char *src, int len) -{ - register unsigned char *s = src; - register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET); - register int i = len; - int ii = 0; - - while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) ) - ++ii; - - outsb( reg, s, i ); - - if (inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) { - outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET); - printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n", - instance->host_no); - return -1; - } - return 0; -} - -#include "NCR5380.c" - -static int pas16_release(struct Scsi_Host *shost) -{ - if (shost->irq != NO_IRQ) - free_irq(shost->irq, shost); - NCR5380_exit(shost); - scsi_unregister(shost); - return 0; -} - -static struct scsi_host_template driver_template = { - .name = "Pro Audio Spectrum-16 SCSI", - .detect = pas16_detect, - .release = pas16_release, - .proc_name = "pas16", - .info = pas16_info, - .queuecommand = pas16_queue_command, - .eh_abort_handler = pas16_abort, - .eh_bus_reset_handler = pas16_bus_reset, - .bios_param = pas16_biosparam, - .can_queue = 32, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING, - .cmd_size = NCR5380_CMD_SIZE, - .max_sectors = 128, -}; -#include "scsi_module.c" - -#ifdef MODULE -module_param(pas16_addr, ushort, 0); -module_param(pas16_irq, int, 0); -#endif -MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h deleted file mode 100644 index 9fe7f33660b4..000000000000 --- a/drivers/scsi/pas16.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This driver adapted from Drew Eckhardt's Trantor T128 driver - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * ( Based on T128 - DISTRIBUTION RELEASE 3. ) - * - * Modified to work with the Pro Audio Spectrum/Studio 16 - * by John Weidman. - * - * - * For more information, please consult - * - * Media Vision - * (510) 770-8600 - * (800) 348-7116 - */ - - -#ifndef PAS16_H -#define PAS16_H - -#define PAS16_DEFAULT_BASE_1 0x388 -#define PAS16_DEFAULT_BASE_2 0x384 -#define PAS16_DEFAULT_BASE_3 0x38c -#define PAS16_DEFAULT_BASE_4 0x288 - -#define PAS16_DEFAULT_BOARD_1_IRQ 10 -#define PAS16_DEFAULT_BOARD_2_IRQ 12 -#define PAS16_DEFAULT_BOARD_3_IRQ 14 -#define PAS16_DEFAULT_BOARD_4_IRQ 15 - - -/* - * The Pro Audio Spectrum boards are I/O mapped. They use a Zilog 5380 - * SCSI controller, which is the equivalent of NCR's 5380. "Pseudo-DMA" - * architecture is used, where a PAL drives the DMA signals on the 5380 - * allowing fast, blind transfers with proper handshaking. - */ - - -/* The Time-out Counter register is used to safe-guard against a stuck - * bus (in the case of RDY driven handshake) or a stuck byte (if 16-Bit - * DMA conversion is used). The counter uses a 28.224MHz clock - * divided by 14 as its clock source. In the case of a stuck byte in - * the holding register, an interrupt is generated (and mixed with the - * one with the drive) using the CD-ROM interrupt pointer. - */ - -#define P_TIMEOUT_COUNTER_REG 0x4000 -#define P_TC_DISABLE 0x80 /* Set to 0 to enable timeout int. */ - /* Bits D6-D0 contain timeout count */ - - -#define P_TIMEOUT_STATUS_REG_OFFSET 0x4001 -#define P_TS_TIM 0x80 /* check timeout status */ - /* Bits D6-D4 N/U */ -#define P_TS_ARM_DRQ_INT 0x08 /* Arm DRQ Int. When set high, - * the next rising edge will - * cause a CD-ROM interrupt. - * When set low, the interrupt - * will be cleared. There is - * no status available for - * this interrupt. - */ -#define P_TS_ENABLE_TO_ERR_INTERRUPT /* Enable timeout error int. */ -#define P_TS_ENABLE_WAIT /* Enable Wait */ - -#define P_TS_CT 0x01 /* clear timeout. Note: writing - * to this register clears the - * timeout error int. or status - */ - - -/* - * The data register reads/writes to/from the 5380 in pseudo-DMA mode - */ - -#define P_DATA_REG_OFFSET 0x5c00 /* rw */ - -#define P_STATUS_REG_OFFSET 0x5c01 /* ro */ -#define P_ST_RDY 0x80 /* 5380 DDRQ Status */ - -#define P_IRQ_STATUS 0x5c03 -#define P_IS_IRQ 0x80 /* DIRQ status */ - -#define PCB_CONFIG 0x803 -#define MASTER_ADDRESS_PTR 0x9a01 /* Fixed position - no relo */ -#define SYS_CONFIG_4 0x8003 -#define WAIT_STATE 0xbc00 -#define OPERATION_MODE_1 0xec03 -#define IO_CONFIG_3 0xf002 - -#define NCR5380_implementation_fields /* none */ - -#define PAS16_io_port(reg) (instance->io_port + pas16_offset[(reg)]) - -#define NCR5380_read(reg) ( inb(PAS16_io_port(reg)) ) -#define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) - -#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) -#define NCR5380_dma_recv_setup pas16_pread -#define NCR5380_dma_send_setup pas16_pwrite -#define NCR5380_dma_residual(instance) (0) - -#define NCR5380_intr pas16_intr -#define NCR5380_queue_command pas16_queue_command -#define NCR5380_abort pas16_abort -#define NCR5380_bus_reset pas16_bus_reset -#define NCR5380_info pas16_info - -/* 15 14 12 10 7 5 3 - 1101 0100 1010 1000 */ - -#define PAS16_IRQS 0xd4a8 - -#endif /* PAS16_H */ -- cgit v1.2.3 From f95819a09c2d6ff2e8a784ff46ba8836f937d07b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Sep 2016 08:50:52 -0700 Subject: scsi: t128: remove from tree The driver has not seen any maintainer activity or other work that wasn't tree wide conversion or clenaups in the entire history of the git tree. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinicke Acked-by: Finn Thain Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi-parameters.txt | 3 - MAINTAINERS | 1 - drivers/scsi/Kconfig | 17 -- drivers/scsi/Makefile | 1 - drivers/scsi/t128.c | 407 --------------------------------- drivers/scsi/t128.h | 97 -------- 6 files changed, 526 deletions(-) delete mode 100644 drivers/scsi/t128.c delete mode 100644 drivers/scsi/t128.h (limited to 'MAINTAINERS') diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index fe77b5a2c926..00a03c0cd8c2 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -113,9 +113,6 @@ parameters may be changed at runtime by the command sym53c416= [HW,SCSI] See header of drivers/scsi/sym53c416.c. - t128= [HW,SCSI] - See header of drivers/scsi/t128.c. - tmscsim= [HW,SCSI] See comment before function dc390_setup() in drivers/scsi/tmscsim.c. diff --git a/MAINTAINERS b/MAINTAINERS index 2a0c0567082f..e4ec1b8abbb7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8054,7 +8054,6 @@ F: drivers/scsi/g_NCR5380_mmio.c F: drivers/scsi/mac_scsi.* F: drivers/scsi/sun3_scsi.* F: drivers/scsi/sun3_scsi_vme.c -F: drivers/scsi/t128.* NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) M: "James E.J. Bottomley" diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index ee83d95bc3d6..a38e37cd722c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1345,23 +1345,6 @@ config SCSI_AM53C974 To compile this driver as a module, choose M here: the module will be called am53c974. -config SCSI_T128 - tristate "Trantor T128/T128F/T228 SCSI support" - depends on ISA && SCSI - select SCSI_SPI_ATTRS - select CHECK_SIGNATURE - ---help--- - This is support for a SCSI host adapter. It is explained in section - 3.11 of the SCSI-HOWTO, available from - . If it doesn't work out - of the box, you may have to change some settings in - . Note that Trantor was purchased by - Adaptec, and some former Trantor products are being sold under the - Adaptec name. - - To compile this driver as a module, choose M here: the - module will be called t128. - config SCSI_NSP32 tristate "Workbit NinjaSCSI-32Bi/UDE support" depends on PCI && SCSI && !64BIT diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index be3108c0e476..392609a1190a 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -87,7 +87,6 @@ obj-$(CONFIG_SCSI_QLA_ISCSI) += libiscsi.o qla4xxx/ obj-$(CONFIG_SCSI_LPFC) += lpfc/ obj-$(CONFIG_SCSI_BFA_FC) += bfa/ obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor/ -obj-$(CONFIG_SCSI_T128) += t128.o obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o obj-$(CONFIG_SCSI_HPSA) += hpsa.o obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi/ diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c deleted file mode 100644 index 8a8608ac62e6..000000000000 --- a/drivers/scsi/t128.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Trantor T128/T128F/T228 driver - * Note : architecturally, the T100 and T130 are different and won't - * work - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - * - * For more information, please consult - * - * Trantor Systems, Ltd. - * T128/T128F/T228 SCSI Host Adapter - * Hardware Specifications - * - * Trantor Systems, Ltd. - * 5415 Randall Place - * Fremont, CA 94538 - * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 - */ - -/* - * The card is detected and initialized in one of several ways : - * 1. Autoprobe (default) - since the board is memory mapped, - * a BIOS signature is scanned for to locate the registers. - * An interrupt is triggered to autoprobe for the interrupt - * line. - * - * 2. With command line overrides - t128=address,irq may be - * used on the LILO command line to override the defaults. - * - * 3. With the T128_OVERRIDE compile time define. This is - * specified as an array of address, irq tuples. Ie, for - * one board at the default 0xcc000 address, IRQ5, I could say - * -DT128_OVERRIDE={{0xcc000, 5}} - * - * Note that if the override methods are used, place holders must - * be specified for other boards in the system. - * - * T128/T128F jumper/dipswitch settings (note : on my sample, the switches - * were epoxy'd shut, meaning I couldn't change the 0xcc000 base address) : - * - * T128 Sw7 Sw8 Sw6 = 0ws Sw5 = boot - * T128F Sw6 Sw7 Sw5 = 0ws Sw4 = boot Sw8 = floppy disable - * cc000 off off - * c8000 off on - * dc000 on off - * d8000 on on - * - * - * Interrupts - * There is a 12 pin jumper block, jp1, numbered as follows : - * T128 (JP1) T128F (J5) - * 2 4 6 8 10 12 11 9 7 5 3 1 - * 1 3 5 7 9 11 12 10 8 6 4 2 - * - * 3 2-4 - * 5 1-3 - * 7 3-5 - * T128F only - * 10 8-10 - * 12 7-9 - * 14 10-12 - * 15 9-11 - */ - -#include -#include -#include -#include -#include - -#include -#include "t128.h" -#include "NCR5380.h" - -static struct override { - unsigned long address; - int irq; -} overrides -#ifdef T128_OVERRIDE - [] __initdata = T128_OVERRIDE; -#else - [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, - {0 ,IRQ_AUTO}, {0, IRQ_AUTO}}; -#endif - -#define NO_OVERRIDES ARRAY_SIZE(overrides) - -static struct base { - unsigned int address; - int noauto; -} bases[] __initdata = { - { 0xcc000, 0}, { 0xc8000, 0}, { 0xdc000, 0}, { 0xd8000, 0} -}; - -#define NO_BASES ARRAY_SIZE(bases) - -static struct signature { - const char *string; - int offset; -} signatures[] __initdata = { -{"TSROM: SCSI BIOS, Version 1.12", 0x36}, -}; - -#define NO_SIGNATURES ARRAY_SIZE(signatures) - -#ifndef MODULE -/* - * Function : t128_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -static int __init t128_setup(char *str) -{ - static int commandline_current; - int i; - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] != 2) - printk("t128_setup : usage t128=address,irq\n"); - else - if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].address = ints[1]; - overrides[commandline_current].irq = ints[2]; - for (i = 0; i < NO_BASES; ++i) - if (bases[i].address == ints[1]) { - bases[i].noauto = 1; - break; - } - ++commandline_current; - } - return 1; -} - -__setup("t128=", t128_setup); -#endif - -/* - * Function : int t128_detect(struct scsi_host_template * tpnt) - * - * Purpose : detects and initializes T128,T128F, or T228 controllers - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ - -static int __init t128_detect(struct scsi_host_template *tpnt) -{ - static int current_override, current_base; - struct Scsi_Host *instance; - unsigned long base; - void __iomem *p; - int sig, count; - - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - base = 0; - p = NULL; - - if (overrides[current_override].address) { - base = overrides[current_override].address; - p = ioremap(bases[current_base].address, 0x2000); - if (!p) - base = 0; - } else - for (; !base && (current_base < NO_BASES); ++current_base) { - dprintk(NDEBUG_INIT, "t128: probing address 0x%08x\n", - bases[current_base].address); - if (bases[current_base].noauto) - continue; - p = ioremap(bases[current_base].address, 0x2000); - if (!p) - continue; - for (sig = 0; sig < NO_SIGNATURES; ++sig) - if (check_signature(p + signatures[sig].offset, - signatures[sig].string, - strlen(signatures[sig].string))) { - base = bases[current_base].address; - dprintk(NDEBUG_INIT, "t128: detected board\n"); - goto found; - } - iounmap(p); - } - - dprintk(NDEBUG_INIT, "t128: base = 0x%08x\n", (unsigned int)base); - - if (!base) - break; - -found: - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - if(instance == NULL) - goto out_unmap; - - instance->base = base; - ((struct NCR5380_hostdata *)instance->hostdata)->base = p; - - if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) - goto out_unregister; - - NCR5380_maybe_reset_bus(instance); - - if (overrides[current_override].irq != IRQ_AUTO) - instance->irq = overrides[current_override].irq; - else - instance->irq = NCR5380_probe_irq(instance, T128_IRQS); - - /* Compatibility with documented NCR5380 kernel parameters */ - if (instance->irq == 255) - instance->irq = NO_IRQ; - - if (instance->irq != NO_IRQ) - if (request_irq(instance->irq, t128_intr, 0, "t128", - instance)) { - printk("scsi%d : IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = NO_IRQ; - } - - if (instance->irq == NO_IRQ) { - printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); - printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); - } - - dprintk(NDEBUG_INIT, "scsi%d: irq = %d\n", - instance->host_no, instance->irq); - - ++current_override; - ++count; - } - return count; - -out_unregister: - scsi_unregister(instance); -out_unmap: - iounmap(p); - return count; -} - -static int t128_release(struct Scsi_Host *shost) -{ - struct NCR5380_hostdata *hostdata = shost_priv(shost); - - if (shost->irq != NO_IRQ) - free_irq(shost->irq, shost); - NCR5380_exit(shost); - scsi_unregister(shost); - iounmap(hostdata->base); - return 0; -} - -/* - * Function : int t128_biosparam(Disk * disk, struct block_device *dev, int *ip) - * - * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for - * the specified device / size. - * - * Inputs : size = size of device in sectors (512 bytes), dev = block device - * major / minor, ip[] = {heads, sectors, cylinders} - * - * Returns : always 0 (success), initializes ip - * - */ - -/* - * XXX Most SCSI boards use this mapping, I could be incorrect. Some one - * using hard disks on a trantor should verify that this mapping corresponds - * to that used by the BIOS / ASPI driver by running the linux fdisk program - * and matching the H_C_S coordinates to what DOS uses. - */ - -static int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *ip) -{ - ip[0] = 64; - ip[1] = 32; - ip[2] = capacity >> 11; - return 0; -} - -/* - * Function : int t128_pread (struct Scsi_Host *instance, - * unsigned char *dst, int len) - * - * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to - * dst - * - * Inputs : dst = destination, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int t128_pread(struct Scsi_Host *instance, - unsigned char *dst, int len) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - void __iomem *reg, *base = hostdata->base; - unsigned char *d = dst; - register int i = len; - - reg = base + T_DATA_REG_OFFSET; - -#if 0 - for (; i; --i) { - while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); -#else - while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); - for (; i; --i) { -#endif - *d++ = readb(reg); - } - - if (readb(base + T_STATUS_REG_OFFSET) & T_ST_TIM) { - unsigned char tmp; - void __iomem *foo = base + T_CONTROL_REG_OFFSET; - tmp = readb(foo); - writeb(tmp | T_CR_CT, foo); - writeb(tmp, foo); - printk("scsi%d : watchdog timer fired in NCR5380_pread()\n", - instance->host_no); - return -1; - } else - return 0; -} - -/* - * Function : int t128_pwrite (struct Scsi_Host *instance, - * unsigned char *src, int len) - * - * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from - * src - * - * Inputs : src = source, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int t128_pwrite(struct Scsi_Host *instance, - unsigned char *src, int len) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - void __iomem *reg, *base = hostdata->base; - unsigned char *s = src; - register int i = len; - - reg = base + T_DATA_REG_OFFSET; - -#if 0 - for (; i; --i) { - while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); -#else - while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); - for (; i; --i) { -#endif - writeb(*s++, reg); - } - - if (readb(base + T_STATUS_REG_OFFSET) & T_ST_TIM) { - unsigned char tmp; - void __iomem *foo = base + T_CONTROL_REG_OFFSET; - tmp = readb(foo); - writeb(tmp | T_CR_CT, foo); - writeb(tmp, foo); - printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n", - instance->host_no); - return -1; - } else - return 0; -} - -MODULE_LICENSE("GPL"); - -#include "NCR5380.c" - -static struct scsi_host_template driver_template = { - .name = "Trantor T128/T128F/T228", - .detect = t128_detect, - .release = t128_release, - .proc_name = "t128", - .info = t128_info, - .queuecommand = t128_queue_command, - .eh_abort_handler = t128_abort, - .eh_bus_reset_handler = t128_bus_reset, - .bios_param = t128_biosparam, - .can_queue = 32, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING, - .cmd_size = NCR5380_CMD_SIZE, - .max_sectors = 128, -}; -#include "scsi_module.c" diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h deleted file mode 100644 index c95bcd839109..000000000000 --- a/drivers/scsi/t128.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Trantor T128/T128F/T228 defines - * Note : architecturally, the T100 and T128 are different and won't work - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - * - * For more information, please consult - * - * Trantor Systems, Ltd. - * T128/T128F/T228 SCSI Host Adapter - * Hardware Specifications - * - * Trantor Systems, Ltd. - * 5415 Randall Place - * Fremont, CA 94538 - * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 - */ - -#ifndef T128_H -#define T128_H - -/* - * The trantor boards are memory mapped. They use an NCR5380 or - * equivalent (my sample board had part second sourced from ZILOG). - * NCR's recommended "Pseudo-DMA" architecture is used, where - * a PAL drives the DMA signals on the 5380 allowing fast, blind - * transfers with proper handshaking. - */ - -/* - * Note : a boot switch is provided for the purpose of informing the - * firmware to boot or not boot from attached SCSI devices. So, I imagine - * there are fewer people who've yanked the ROM like they do on the Seagate - * to make bootup faster, and I'll probably use this for autodetection. - */ -#define T_ROM_OFFSET 0 - -/* - * Note : my sample board *WAS NOT* populated with the SRAM, so this - * can't be used for autodetection without a ROM present. - */ -#define T_RAM_OFFSET 0x1800 - -/* - * All of the registers are allocated 32 bytes of address space, except - * for the data register (read/write to/from the 5380 in pseudo-DMA mode) - */ -#define T_CONTROL_REG_OFFSET 0x1c00 /* rw */ -#define T_CR_INT 0x10 /* Enable interrupts */ -#define T_CR_CT 0x02 /* Reset watchdog timer */ - -#define T_STATUS_REG_OFFSET 0x1c20 /* ro */ -#define T_ST_BOOT 0x80 /* Boot switch */ -#define T_ST_S3 0x40 /* User settable switches, */ -#define T_ST_S2 0x20 /* read 0 when switch is on, 1 off */ -#define T_ST_S1 0x10 -#define T_ST_PS2 0x08 /* Set for Microchannel 228 */ -#define T_ST_RDY 0x04 /* 5380 DRQ */ -#define T_ST_TIM 0x02 /* indicates 40us watchdog timer fired */ -#define T_ST_ZERO 0x01 /* Always zero */ - -#define T_5380_OFFSET 0x1d00 /* 8 registers here, see NCR5380.h */ - -#define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ - -#define NCR5380_implementation_fields \ - void __iomem *base - -#define T128_address(reg) \ - (((struct NCR5380_hostdata *)shost_priv(instance))->base + T_5380_OFFSET + ((reg) * 0x20)) - -#define NCR5380_read(reg) readb(T128_address(reg)) -#define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) - -#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) -#define NCR5380_dma_recv_setup t128_pread -#define NCR5380_dma_send_setup t128_pwrite -#define NCR5380_dma_residual(instance) (0) - -#define NCR5380_intr t128_intr -#define NCR5380_queue_command t128_queue_command -#define NCR5380_abort t128_abort -#define NCR5380_bus_reset t128_bus_reset -#define NCR5380_info t128_info - -#define NCR5380_io_delay(x) udelay(x) - -/* 15 14 12 10 7 5 3 - 1101 0100 1010 1000 */ - -#define T128_IRQS 0xc4a8 - -#endif /* T128_H */ -- cgit v1.2.3 From 92efbb8500230c883ca6966b0ef9f3e18c1e29ba Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Sep 2016 08:50:53 -0700 Subject: scsi: dtc: remove from tree The driver has not seen any maintainer activity or other work that wasn't tree wide conversion or clenaups in the entire history of the git tree. Signed-off-by: Christoph Hellwig Reviewed-by: Hannes Reinicke Acked-by: Finn Thain Signed-off-by: Martin K. Petersen --- Documentation/scsi/dtc3x80.txt | 43 ---- Documentation/scsi/scsi-parameters.txt | 3 - MAINTAINERS | 2 - drivers/scsi/Kconfig | 14 -- drivers/scsi/Makefile | 1 - drivers/scsi/dtc.c | 447 --------------------------------- drivers/scsi/dtc.h | 42 ---- 7 files changed, 552 deletions(-) delete mode 100644 Documentation/scsi/dtc3x80.txt delete mode 100644 drivers/scsi/dtc.c delete mode 100644 drivers/scsi/dtc.h (limited to 'MAINTAINERS') diff --git a/Documentation/scsi/dtc3x80.txt b/Documentation/scsi/dtc3x80.txt deleted file mode 100644 index 1d7af9f9a8ed..000000000000 --- a/Documentation/scsi/dtc3x80.txt +++ /dev/null @@ -1,43 +0,0 @@ -README file for the Linux DTC3180/3280 scsi driver. -by Ray Van Tassle (rayvt@comm.mot.com) March 1996 -Based on the generic & core NCR5380 code by Drew Eckhard - -SCSI device driver for the DTC 3180/3280. -Data Technology Corp---a division of Qume. - -The 3280 has a standard floppy interface. - -The 3180 does not. Otherwise, they are identical. - -The DTC3x80 does not support DMA but it does have Pseudo-DMA which is -supported by the driver. - -Its DTC406 scsi chip is supposedly compatible with the NCR 53C400. -It is memory mapped, uses an IRQ, but no dma or io-port. There is -internal DMA, between SCSI bus and an on-chip 128-byte buffer. Double -buffering is done automagically by the chip. Data is transferred -between the on-chip buffer and CPU/RAM via memory moves. - -The driver detects the possible memory addresses (jumper selectable): - CC00, DC00, C800, and D800 -The possible IRQ's (jumper selectable) are: - IRQ 10, 11, 12, 15 -Parity is supported by the chip, but not by this driver. -Information can be obtained from /proc/scsi/dtc3c80/N. - -Note on interrupts: - -The documentation says that it can be set to interrupt whenever the -on-chip buffer needs CPU attention. I couldn't get this to work. So -the driver polls for data-ready in the pseudo-DMA transfer routine. -The interrupt support routines in the NCR3280.c core modules handle -scsi disconnect/reconnect, and this (mostly) works. However..... I -have tested it with 4 totally different hard drives (both SCSI-1 and -SCSI-2), and one CDROM drive. Interrupts works great for all but one -specific hard drive. For this one, the driver will eventually hang in -the transfer state. I have tested with: "dd bs=4k count=2k -of=/dev/null if=/dev/sdb". It reads ok for a while, then hangs. -After beating my head against this for a couple of weeks, getting -nowhere, I give up. So.....This driver does NOT use interrupts, even -if you have the card jumpered to an IRQ. Probably nobody will ever -care. diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt index 00a03c0cd8c2..8e66dafa41e1 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.txt @@ -34,9 +34,6 @@ parameters may be changed at runtime by the command See drivers/scsi/BusLogic.c, comment before function BusLogic_ParseDriverOptions(). - dtc3181e= [HW,SCSI] - See Documentation/scsi/g_NCR5380.txt. - eata= [HW,SCSI] fdomain= [HW,SCSI] diff --git a/MAINTAINERS b/MAINTAINERS index e4ec1b8abbb7..48f2b480ac6e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8042,13 +8042,11 @@ M: Michael Schmitz L: linux-scsi@vger.kernel.org S: Maintained F: Documentation/scsi/g_NCR5380.txt -F: Documentation/scsi/dtc3x80.txt F: drivers/scsi/NCR5380.* F: drivers/scsi/arm/cumana_1.c F: drivers/scsi/arm/oak.c F: drivers/scsi/atari_scsi.* F: drivers/scsi/dmx3191d.c -F: drivers/scsi/dtc.* F: drivers/scsi/g_NCR5380.* F: drivers/scsi/g_NCR5380_mmio.c F: drivers/scsi/mac_scsi.* diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a38e37cd722c..3e2bdb90813c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -637,20 +637,6 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. -config SCSI_DTC3280 - tristate "DTC3180/3280 SCSI support" - depends on ISA && SCSI - select SCSI_SPI_ATTRS - select CHECK_SIGNATURE - help - This is support for DTC 3180/3280 SCSI Host Adapters. Please read - the SCSI-HOWTO, available from - , and the file - . - - To compile this driver as a module, choose M here: the - module will be called dtc. - config SCSI_EATA tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support" depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 392609a1190a..38d938d7fe67 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -90,7 +90,6 @@ obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor/ obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o obj-$(CONFIG_SCSI_HPSA) += hpsa.o obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi/ -obj-$(CONFIG_SCSI_DTC3280) += dtc.o obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c deleted file mode 100644 index 459863f94e46..000000000000 --- a/drivers/scsi/dtc.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * DTC 3180/3280 driver, by - * Ray Van Tassle rayvt@comm.mot.com - * - * taken from ... - * Trantor T128/T128F/T228 driver by... - * - * Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - */ - -/* - * The card is detected and initialized in one of several ways : - * 1. Autoprobe (default) - since the board is memory mapped, - * a BIOS signature is scanned for to locate the registers. - * An interrupt is triggered to autoprobe for the interrupt - * line. - * - * 2. With command line overrides - dtc=address,irq may be - * used on the LILO command line to override the defaults. - * -*/ - -/*----------------------------------------------------------------*/ -/* the following will set the monitor border color (useful to find - where something crashed or gets stuck at */ -/* 1 = blue - 2 = green - 3 = cyan - 4 = red - 5 = magenta - 6 = yellow - 7 = white -*/ -#if 0 -#define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);} -#else -#define rtrc(i) {} -#endif - - -#include -#include -#include -#include -#include -#include -#include - -#include "dtc.h" -#include "NCR5380.h" - -/* - * The DTC3180 & 3280 boards are memory mapped. - * - */ - -/* - */ -/* Offset from DTC_5380_OFFSET */ -#define DTC_CONTROL_REG 0x100 /* rw */ -#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ -#define CSR_DIR_READ 0x40 /* rw direction, 1 = read 0 = write */ - -#define CSR_RESET 0x80 /* wo Resets 53c400 */ -#define CSR_5380_REG 0x80 /* ro 5380 registers can be accessed */ -#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */ -#define CSR_SCSI_BUFF_INTR 0x20 /* rw Enable int on transfer ready */ -#define CSR_5380_INTR 0x10 /* rw Enable 5380 interrupts */ -#define CSR_SHARED_INTR 0x08 /* rw Interrupt sharing */ -#define CSR_HOST_BUF_NOT_RDY 0x04 /* ro Host buffer not ready */ -#define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer ready */ -#define CSR_GATED_5380_IRQ 0x01 /* ro Last block xferred */ -#define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR) - - -#define DTC_BLK_CNT 0x101 /* rw - * # of 128-byte blocks to transfer */ - - -#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ - -#define DTC_SWITCH_REG 0x3982 /* ro - DIP switches */ -#define DTC_RESUME_XFER 0x3982 /* wo - resume data xfer - * after disconnect/reconnect*/ - -#define DTC_5380_OFFSET 0x3880 /* 8 registers here, see NCR5380.h */ - -/*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */ -#define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */ - -static struct override { - unsigned int address; - int irq; -} overrides -#ifdef OVERRIDE -[] __initdata = OVERRIDE; -#else -[4] __initdata = { - { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO } -}; -#endif - -#define NO_OVERRIDES ARRAY_SIZE(overrides) - -static struct base { - unsigned long address; - int noauto; -} bases[] __initdata = { - { 0xcc000, 0 }, - { 0xc8000, 0 }, - { 0xdc000, 0 }, - { 0xd8000, 0 } -}; - -#define NO_BASES ARRAY_SIZE(bases) - -static const struct signature { - const char *string; - int offset; -} signatures[] = { - {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, -}; - -#define NO_SIGNATURES ARRAY_SIZE(signatures) - -#ifndef MODULE -/* - * Function : dtc_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -static int __init dtc_setup(char *str) -{ - static int commandline_current; - int i; - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] != 2) - printk("dtc_setup: usage dtc=address,irq\n"); - else if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].address = ints[1]; - overrides[commandline_current].irq = ints[2]; - for (i = 0; i < NO_BASES; ++i) - if (bases[i].address == ints[1]) { - bases[i].noauto = 1; - break; - } - ++commandline_current; - } - return 1; -} - -__setup("dtc=", dtc_setup); -#endif - -/* - * Function : int dtc_detect(struct scsi_host_template * tpnt) - * - * Purpose : detects and initializes DTC 3180/3280 controllers - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * -*/ - -static int __init dtc_detect(struct scsi_host_template * tpnt) -{ - static int current_override, current_base; - struct Scsi_Host *instance; - unsigned int addr; - void __iomem *base; - int sig, count; - - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - addr = 0; - base = NULL; - - if (overrides[current_override].address) { - addr = overrides[current_override].address; - base = ioremap(addr, 0x2000); - if (!base) - addr = 0; - } else - for (; !addr && (current_base < NO_BASES); ++current_base) { - dprintk(NDEBUG_INIT, "dtc: probing address 0x%08x\n", - (unsigned int)bases[current_base].address); - if (bases[current_base].noauto) - continue; - base = ioremap(bases[current_base].address, 0x2000); - if (!base) - continue; - for (sig = 0; sig < NO_SIGNATURES; ++sig) { - if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { - addr = bases[current_base].address; - dprintk(NDEBUG_INIT, "dtc: detected board\n"); - goto found; - } - } - iounmap(base); - } - - dprintk(NDEBUG_INIT, "dtc: addr = 0x%08x\n", addr); - - if (!addr) - break; - -found: - instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); - if (instance == NULL) - goto out_unmap; - - instance->base = addr; - ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; - - if (NCR5380_init(instance, FLAG_LATE_DMA_SETUP)) - goto out_unregister; - - NCR5380_maybe_reset_bus(instance); - - NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */ - if (overrides[current_override].irq != IRQ_AUTO) - instance->irq = overrides[current_override].irq; - else - instance->irq = NCR5380_probe_irq(instance, DTC_IRQS); - - /* Compatibility with documented NCR5380 kernel parameters */ - if (instance->irq == 255) - instance->irq = NO_IRQ; - - /* With interrupts enabled, it will sometimes hang when doing heavy - * reads. So better not enable them until I finger it out. */ - instance->irq = NO_IRQ; - - if (instance->irq != NO_IRQ) - if (request_irq(instance->irq, dtc_intr, 0, - "dtc", instance)) { - printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); - instance->irq = NO_IRQ; - } - - if (instance->irq == NO_IRQ) { - printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); - printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); - } - - dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", - instance->host_no, instance->irq); - - ++current_override; - ++count; - } - return count; - -out_unregister: - scsi_unregister(instance); -out_unmap: - iounmap(base); - return count; -} - -/* - * Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip) - * - * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for - * the specified device / size. - * - * Inputs : size = size of device in sectors (512 bytes), dev = block device - * major / minor, ip[] = {heads, sectors, cylinders} - * - * Returns : always 0 (success), initializes ip - * -*/ - -/* - * XXX Most SCSI boards use this mapping, I could be incorrect. Some one - * using hard disks on a trantor should verify that this mapping corresponds - * to that used by the BIOS / ASPI driver by running the linux fdisk program - * and matching the H_C_S coordinates to what DOS uses. -*/ - -static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev, - sector_t capacity, int *ip) -{ - int size = capacity; - - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; - return 0; -} - - -/**************************************************************** - * Function : int NCR5380_pread (struct Scsi_Host *instance, - * unsigned char *dst, int len) - * - * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to - * dst - * - * Inputs : dst = destination, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. -*/ - -static inline int dtc_pread(struct Scsi_Host *instance, - unsigned char *dst, int len) -{ - unsigned char *d = dst; - int i; /* For counting time spent in the poll-loop */ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - i = 0; - if (instance->irq == NO_IRQ) - NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); - else - NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE); - NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ - rtrc(1); - while (len > 0) { - rtrc(2); - while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) - ++i; - rtrc(3); - memcpy_fromio(d, hostdata->base + DTC_DATA_BUF, 128); - d += 128; - len -= 128; - rtrc(7); - /*** with int's on, it sometimes hangs after here. - * Looks like something makes HBNR go away. */ - } - rtrc(4); - while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) - ++i; - rtrc(0); - return (0); -} - -/**************************************************************** - * Function : int NCR5380_pwrite (struct Scsi_Host *instance, - * unsigned char *src, int len) - * - * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from - * src - * - * Inputs : src = source, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. -*/ - -static inline int dtc_pwrite(struct Scsi_Host *instance, - unsigned char *src, int len) -{ - int i; - struct NCR5380_hostdata *hostdata = shost_priv(instance); - - if (instance->irq == NO_IRQ) - NCR5380_write(DTC_CONTROL_REG, 0); - else - NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); - NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ - for (i = 0; len > 0; ++i) { - rtrc(5); - /* Poll until the host buffer can accept data. */ - while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) - ++i; - rtrc(3); - memcpy_toio(hostdata->base + DTC_DATA_BUF, src, 128); - src += 128; - len -= 128; - } - rtrc(4); - while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) - ++i; - rtrc(6); - /* Wait until the last byte has been sent to the disk */ - while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) - ++i; - rtrc(7); - /* Check for parity error here. fixme. */ - rtrc(0); - return (0); -} - -static int dtc_dma_xfer_len(struct scsi_cmnd *cmd) -{ - int transfersize = cmd->transfersize; - - /* Limit transfers to 32K, for xx400 & xx406 - * pseudoDMA that transfers in 128 bytes blocks. - */ - if (transfersize > 32 * 1024 && cmd->SCp.this_residual && - !(cmd->SCp.this_residual % transfersize)) - transfersize = 32 * 1024; - - return transfersize; -} - -MODULE_LICENSE("GPL"); - -#include "NCR5380.c" - -static int dtc_release(struct Scsi_Host *shost) -{ - struct NCR5380_hostdata *hostdata = shost_priv(shost); - - if (shost->irq != NO_IRQ) - free_irq(shost->irq, shost); - NCR5380_exit(shost); - scsi_unregister(shost); - iounmap(hostdata->base); - return 0; -} - -static struct scsi_host_template driver_template = { - .name = "DTC 3180/3280", - .detect = dtc_detect, - .release = dtc_release, - .proc_name = "dtc3x80", - .info = dtc_info, - .queuecommand = dtc_queue_command, - .eh_abort_handler = dtc_abort, - .eh_bus_reset_handler = dtc_bus_reset, - .bios_param = dtc_biosparam, - .can_queue = 32, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING, - .cmd_size = NCR5380_CMD_SIZE, - .max_sectors = 128, -}; -#include "scsi_module.c" diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h deleted file mode 100644 index fcb0a8ea7bda..000000000000 --- a/drivers/scsi/dtc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * DTC controller, taken from T128 driver by... - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - */ - -#ifndef DTC3280_H -#define DTC3280_H - -#define NCR5380_implementation_fields \ - void __iomem *base - -#define DTC_address(reg) \ - (((struct NCR5380_hostdata *)shost_priv(instance))->base + DTC_5380_OFFSET + reg) - -#define NCR5380_read(reg) (readb(DTC_address(reg))) -#define NCR5380_write(reg, value) (writeb(value, DTC_address(reg))) - -#define NCR5380_dma_xfer_len(instance, cmd, phase) \ - dtc_dma_xfer_len(cmd) -#define NCR5380_dma_recv_setup dtc_pread -#define NCR5380_dma_send_setup dtc_pwrite -#define NCR5380_dma_residual(instance) (0) - -#define NCR5380_intr dtc_intr -#define NCR5380_queue_command dtc_queue_command -#define NCR5380_abort dtc_abort -#define NCR5380_bus_reset dtc_bus_reset -#define NCR5380_info dtc_info - -#define NCR5380_io_delay(x) udelay(x) - -/* 15 12 11 10 - 1001 1100 0000 0000 */ - -#define DTC_IRQS 0x9c00 - - -#endif /* DTC3280_H */ -- cgit v1.2.3