Parent repository is bk://linux-scsi.bkbits.net/scsi-misc-2.6 jejb@mulgrave.(none)|ChangeSet|20040311043103|02905 jejb diff -Nru a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt --- a/Documentation/scsi/st.txt Wed Mar 10 21:09:42 2004 +++ b/Documentation/scsi/st.txt Wed Mar 10 21:09:42 2004 @@ -2,7 +2,7 @@ The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) -Last modified: Thu Feb 19 21:57:30 2004 by makisara +Last modified: Wed Feb 25 14:09:08 2004 by makisara BASICS @@ -36,8 +36,9 @@ manager. The changes persist until the defaults again come into effect. -3. Up to four modes can be defined and selected using the minor number -(bits 5 and 6). Mode 0 corresponds to the defaults discussed +3. By default, up to four modes can be defined and selected using the minor +number (bits 5 and 6). The number of modes can be changed by changing +ST_NBR_MODE_BITS in st.h. Mode 0 corresponds to the defaults discussed above. Additional modes are dormant until they are defined by the system manager (root). When specification of a new mode is started, the configuration of mode 0 is used to provide a starting point for @@ -107,7 +108,7 @@ dev_upper non-rew mode dev-lower 20 - 8 7 6 5 4 0 The non-rewind bit is always bit 7 (the uppermost bit in the lowermost -byte). The bits defining the mode are next to the non-rewind bits. The +byte). The bits defining the mode are below the non-rewind bit. The remaining bits define the tape device number. This numbering is backward compatible with the numbering used when the minor number was only 8 bits wide. @@ -117,10 +118,10 @@ The driver creates the directory /sys/class/scsi_tape and populates it with directories corresponding to the existing tape devices. There are autorewind -and non-rewind entries for each mode. The names are stxmy and stxmyn, where x -is the tape number and y is the mode. For example, the directories for the -first tape device are (assuming four modes): st0m0 st0m0n st0m1 st0m1n -st0m2 st0m2n st0m3 st0m3n. +and non-rewind entries for each mode. The names are stxy and nstxy, where x +is the tape number and y a character corresponding to the mode (none, l, m, +a). For example, the directories for the first tape device are (assuming four +modes): st0 nst0 st0l nst0l st0m nst0m st0a nst0a. Each directory contains the entries: default_blksize default_compression default_density defined dev device driver. The file 'defined' contains 1 @@ -130,7 +131,7 @@ 'device' and 'driver' point to the SCSI device and driver entries. A link named 'tape' is made from the SCSI device directory to the class -directory corresponding to the mode 0 auto-rewind device (e.g., st0m0). +directory corresponding to the mode 0 auto-rewind device (e.g., st0). BSD AND SYS V SEMANTICS diff -Nru a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig --- a/drivers/message/fusion/Kconfig Wed Mar 10 21:09:43 2004 +++ b/drivers/message/fusion/Kconfig Wed Mar 10 21:09:43 2004 @@ -3,7 +3,7 @@ config FUSION tristate "Fusion MPT (base + ScsiHost) drivers" - depends on BLK_DEV_SD && PCI + depends on PCI ---help--- LSI Logic Fusion(TM) Message Passing Technology (MPT) device support provides high performance SCSI host initiator, and LAN [1] interface @@ -14,41 +14,6 @@ [1] LAN is not supported on parallel SCSI medium. - These drivers require a Fusion MPT compatible PCI adapter installed - in the host system. MPT adapters contain specialized I/O processors - to handle I/O workload, and more importantly to offload this work - from the host CPU(s). - - If you have Fusion MPT hardware and want to use it, you can say - Y or M here to add MPT (base + ScsiHost) drivers. - = build lib (fusion), and link [static] into the kernel [2] - proper - = compiled as [dynamic] modules [3] named: (mptbase, - mptscsih) - - [2] In order enable capability to boot the linux kernel - natively from a Fusion MPT target device, you MUST - answer Y here! (currently requires CONFIG_BLK_DEV_SD) - [3] To compile this support as modules, choose M here. - - If unsure, say N. - - If you say Y or M here you will get a choice of these - additional protocol and support module options: Module Name: - Enhanced SCSI error reporting (isense) - Fusion MPT misc device (ioctl) driver (mptctl) - Fusion MPT LAN driver (mptlan) - - --- - Fusion MPT is trademark of LSI Logic Corporation, and its - architecture is based on LSI Logic's Message Passing Interface (MPI) - specification. - -config FUSION_BOOT - bool - depends on FUSION=y - default y - config FUSION_MAX_SGE int "Maximum number of scatter gather entries" depends on FUSION @@ -62,7 +27,6 @@ necessary (or recommended) unless the user will be running large I/O's via the raw interface. -# How can we force these options to module or nothing? config FUSION_ISENSE tristate "Enhanced SCSI error reporting" depends on MODULES && FUSION && m @@ -132,17 +96,4 @@ If unsure whether you really want or need this, say N. - NOTES: This feature is NOT available nor supported for linux-2.2.x - kernels. You must be building a linux-2.3.x or linux-2.4.x kernel - in order to configure this option. - Support for building this feature into the linux kernel is not - yet available. - -# if [ "$CONFIG_FUSION_LAN" != "n" ]; then -# define_bool CONFIG_NET_FC y -# fi -# These be define_tristate, but we leave them define_bool -# for backward compatibility with pre-linux-2.2.15 kernels. -# (Bugzilla:fibrebugs, #384) endmenu - diff -Nru a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile --- a/drivers/message/fusion/Makefile Wed Mar 10 21:09:43 2004 +++ b/drivers/message/fusion/Makefile Wed Mar 10 21:09:43 2004 @@ -17,10 +17,16 @@ # Fusion MPT drivers; recognized debug defines... # MPT general: -#EXTRA_CFLAGS += -DDEBUG +#EXTRA_CFLAGS += -DMPT_DEBUG_SCSI #EXTRA_CFLAGS += -DMPT_DEBUG #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME #EXTRA_CFLAGS += -DMPT_DEBUG_SG + +# This is a temporary fix for the reply/request fifo +# for some 64bit archs. Uncommenting this line +# will place the fifo's in 32bit space +#EXTRA_CFLAGS += -DMPTBASE_MEM_ALLOC_FIFO_FIX + # # driver/module specifics... # diff -Nru a/drivers/message/fusion/isense.c b/drivers/message/fusion/isense.c --- a/drivers/message/fusion/isense.c Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/isense.c Wed Mar 10 21:09:42 2004 @@ -5,7 +5,7 @@ * Error Report logging output. This module implements SCSI-3 * Opcode lookup and a sorted table of SCSI-3 ASC/ASCQ strings. * - * Copyright (c) 1991-2003 Steven J. Ralston + * Copyright (c) 1991-2004 Steven J. Ralston * Written By: Steven J. Ralston * (yes I wrote some of the orig. code back in 1991!) * (mailto:sjralston1@netscape.net) @@ -66,7 +66,7 @@ #endif #define MODULEAUTHOR "Steven J. Ralston" -#define COPYRIGHT "Copyright (c) 2001-2003 " MODULEAUTHOR +#define COPYRIGHT "Copyright (c) 2001-2004 " MODULEAUTHOR #include "mptbase.h" #include "isense.h" diff -Nru a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h --- a/drivers/message/fusion/linux_compat.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/linux_compat.h Wed Mar 10 21:09:42 2004 @@ -15,25 +15,7 @@ #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#define SET_NICE(current,x) do {(current)->nice = (x);} while (0) -#else -#define SET_NICE(current,x) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#define pci_enable_device(pdev) (0) -#define SCSI_DATA_UNKNOWN 0 -#define SCSI_DATA_WRITE 1 -#define SCSI_DATA_READ 2 -#define SCSI_DATA_NONE 3 -#endif - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) -#define pci_set_dma_mask(pdev, mask) (0) -#define scsi_set_pci_device(sh, pdev) (0) -#endif +#define SET_NICE(current,x) do {(current)->nice = (x);} while (0) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) # if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) @@ -147,31 +129,9 @@ /* PCI/driver subsystem { */ -#if 0 /* FIXME Don't know what to use to check for the proper kernel version */ -#define DEVICE_COUNT_RESOURCE 6 -#define PCI_BASEADDR_FLAGS(idx) base_address[idx] -#define PCI_BASEADDR_START(idx) base_address[idx] & ~0xFUL -/* - * We have to keep track of the original value using - * a temporary, and not by just sticking pdev->base_address[x] - * back. pdev->base_address[x] is an opaque cookie that can - * be used by the PCI implementation on a given Linux port - * for any purpose. -DaveM - */ -#define PCI_BASEADDR_SIZE(__pdev, __idx) \ -({ unsigned int size, tmp; \ - pci_read_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), &tmp); \ - pci_write_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), 0xffffffff); \ - pci_read_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), &size); \ - pci_write_config_dword(__pdev, PCI_BASE_ADDRESS_0 + (4*(__idx)), tmp); \ - (4 - size); \ -}) -#else #define PCI_BASEADDR_FLAGS(idx) resource[idx].flags #define PCI_BASEADDR_START(idx) resource[idx].start #define PCI_BASEADDR_SIZE(dev,idx) (dev)->resource[idx].end - (dev)->resource[idx].start + 1 -#endif /* } ifndef 0 */ - /* Compatability for the 2.3.x PCI DMA API. */ #ifndef PCI_DMA_BIDIRECTIONAL @@ -227,54 +187,10 @@ /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* PCI_DMA_BIDIRECTIONAL */ -/* - * With the new command queuing code in the SCSI mid-layer we no longer have - * to hold the io_request_lock spin lock when calling the scsi_done routine. - * For now we only do this with the 2.5.1 kernel or newer. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) - #define MPT_HOST_LOCK(flags) - #define MPT_HOST_UNLOCK(flags) -#else - #define MPT_HOST_LOCK(flags) \ - spin_lock_irqsave(&io_request_lock, flags) - #define MPT_HOST_UNLOCK(flags) \ - spin_unlock_irqrestore(&io_request_lock, flags) -#endif - -/* - * We use our new error handling code if the kernel version is 2.4.18 or newer. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,18) - #define MPT_SCSI_USE_NEW_EH -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41) #define mpt_work_struct work_struct #define MPT_INIT_WORK(_task, _func, _data) INIT_WORK(_task, _func, _data) -#else -#define mpt_work_struct tq_struct -#define MPT_INIT_WORK(_task, _func, _data) \ -({ (_task)->sync = 0; \ - (_task)->routine = (_func); \ - (_task)->data = (void *) (_data); \ -}) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) -#define mptscsih_sync_irq(_irq) synchronize_irq(_irq) -#else -#define mptscsih_sync_irq(_irq) synchronize_irq() -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,58) -#define mpt_inc_use_count() -#define mpt_dec_use_count() -#else -#define mpt_inc_use_count() MOD_INC_USE_COUNT -#define mpt_dec_use_count() MOD_DEC_USE_COUNT -#endif - +#define mpt_sync_irq(_irq) synchronize_irq(_irq) /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* _LINUX_COMPAT_H */ diff -Nru a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h --- a/drivers/message/fusion/lsi/mpi.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/lsi/mpi.h Wed Mar 10 21:09:42 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI.H + * Name: mpi.h * Title: MPI Message independent structures and definitions * Creation Date: July 27, 2000 * - * MPI.H Version: 01.02.07 + * mpi.h Version: 01.05.xx * * Version History * --------------- @@ -48,6 +48,10 @@ * 05-31-02 01.02.05 Bumped MPI_HEADER_VERSION_UNIT. * 07-12-02 01.02.06 Added define for MPI_FUNCTION_MAILBOX. * 09-16-02 01.02.07 Bumped value for MPI_HEADER_VERSION_UNIT. + * 11-15-02 01.02.08 Added define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX and + * obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX. + * 04-01-03 01.02.09 New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED + * 06-26-03 01.02.10 Bumped MPI_HEADER_VERSION_UNIT value. * -------------------------------------------------------------------------- */ @@ -62,7 +66,7 @@ *****************************************************************************/ #define MPI_VERSION_MAJOR (0x01) -#define MPI_VERSION_MINOR (0x02) +#define MPI_VERSION_MINOR (0x05) #define MPI_VERSION_MAJOR_MASK (0xFF00) #define MPI_VERSION_MAJOR_SHIFT (8) #define MPI_VERSION_MINOR_MASK (0x00FF) @@ -73,10 +77,12 @@ #define MPI_VERSION_01_00 (0x0100) #define MPI_VERSION_01_01 (0x0101) #define MPI_VERSION_01_02 (0x0102) +#define MPI_VERSION_01_03 (0x0103) +#define MPI_VERSION_01_05 (0x0105) /* Note: The major versions of 0xe0 through 0xff are reserved */ /* versioning for this MPI header set */ -#define MPI_HEADER_VERSION_UNIT (0x09) +#define MPI_HEADER_VERSION_UNIT (0x00) #define MPI_HEADER_VERSION_DEV (0x00) #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI_HEADER_VERSION_UNIT_SHIFT (8) @@ -171,6 +177,8 @@ #define MPI_REPLY_POST_FIFO_OFFSET (0x00000044) #define MPI_REPLY_FREE_FIFO_OFFSET (0x00000044) +#define MPI_HI_PRI_REQUEST_QUEUE_OFFSET (0x00000048) + /***************************************************************************** @@ -230,10 +238,6 @@ #define MPI_FUNCTION_TARGET_ASSIST (0x0B) #define MPI_FUNCTION_TARGET_STATUS_SEND (0x0C) #define MPI_FUNCTION_TARGET_MODE_ABORT (0x0D) -#define MPI_FUNCTION_TARGET_FC_BUF_POST_LINK_SRVC (0x0E) /* obsolete name */ -#define MPI_FUNCTION_TARGET_FC_RSP_LINK_SRVC (0x0F) /* obsolete name */ -#define MPI_FUNCTION_TARGET_FC_EX_SEND_LINK_SRVC (0x10) /* obsolete name */ -#define MPI_FUNCTION_TARGET_FC_ABORT (0x11) /* obsolete name */ #define MPI_FUNCTION_FC_LINK_SRVC_BUF_POST (0x0E) #define MPI_FUNCTION_FC_LINK_SRVC_RSP (0x0F) #define MPI_FUNCTION_FC_EX_LINK_SRVC_SEND (0x10) @@ -251,16 +255,46 @@ #define MPI_FUNCTION_MAILBOX (0x19) +#define MPI_FUNCTION_SMP_PASSTHROUGH (0x1A) +#define MPI_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) + +#define MPI_DIAG_BUFFER_POST (0x1D) +#define MPI_DIAG_RELEASE (0x1E) + +#define MPI_FUNCTION_SCSI_IO_32 (0x1F) + #define MPI_FUNCTION_LAN_SEND (0x20) #define MPI_FUNCTION_LAN_RECEIVE (0x21) #define MPI_FUNCTION_LAN_RESET (0x22) +#define MPI_FUNCTION_INBAND_BUFFER_POST (0x28) +#define MPI_FUNCTION_INBAND_SEND (0x29) +#define MPI_FUNCTION_INBAND_RSP (0x2A) +#define MPI_FUNCTION_INBAND_ABORT (0x2B) + #define MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) #define MPI_FUNCTION_IO_UNIT_RESET (0x41) #define MPI_FUNCTION_HANDSHAKE (0x42) #define MPI_FUNCTION_REPLY_FRAME_REMOVAL (0x43) +/* standard version format */ +typedef struct _MPI_VERSION_STRUCT +{ + U8 Dev; /* 00h */ + U8 Unit; /* 01h */ + U8 Minor; /* 02h */ + U8 Major; /* 03h */ +} MPI_VERSION_STRUCT, MPI_POINTER PTR_MPI_VERSION_STRUCT, + MpiVersionStruct_t, MPI_POINTER pMpiVersionStruct; + +typedef union _MPI_VERSION_FORMAT +{ + MPI_VERSION_STRUCT Struct; + U32 Word; +} MPI_VERSION_FORMAT, MPI_POINTER PTR_MPI_VERSION_FORMAT, + MpiVersionFormat_t, MPI_POINTER pMpiVersionFormat_t; + /***************************************************************************** * @@ -573,44 +607,54 @@ /* Common IOCStatus values for all replies */ /****************************************************************************/ -#define MPI_IOCSTATUS_SUCCESS (0x0000) -#define MPI_IOCSTATUS_INVALID_FUNCTION (0x0001) -#define MPI_IOCSTATUS_BUSY (0x0002) -#define MPI_IOCSTATUS_INVALID_SGL (0x0003) -#define MPI_IOCSTATUS_INTERNAL_ERROR (0x0004) -#define MPI_IOCSTATUS_RESERVED (0x0005) -#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) -#define MPI_IOCSTATUS_INVALID_FIELD (0x0007) -#define MPI_IOCSTATUS_INVALID_STATE (0x0008) +#define MPI_IOCSTATUS_SUCCESS (0x0000) +#define MPI_IOCSTATUS_INVALID_FUNCTION (0x0001) +#define MPI_IOCSTATUS_BUSY (0x0002) +#define MPI_IOCSTATUS_INVALID_SGL (0x0003) +#define MPI_IOCSTATUS_INTERNAL_ERROR (0x0004) +#define MPI_IOCSTATUS_RESERVED (0x0005) +#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) +#define MPI_IOCSTATUS_INVALID_FIELD (0x0007) +#define MPI_IOCSTATUS_INVALID_STATE (0x0008) +#define MPI_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) /****************************************************************************/ /* Config IOCStatus values */ /****************************************************************************/ -#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) -#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) -#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) -#define MPI_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) -#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) -#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) +#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) +#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) +#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) +#define MPI_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) +#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) +#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) /****************************************************************************/ /* SCSIIO Reply (SPI & FCP) initiator values */ /****************************************************************************/ -#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) -#define MPI_IOCSTATUS_SCSI_INVALID_BUS (0x0041) -#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID (0x0042) -#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) -#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) -#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) -#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) -#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) -#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) -#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) -#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) -#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) -#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) +#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) +#define MPI_IOCSTATUS_SCSI_INVALID_BUS (0x0041) +#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID (0x0042) +#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) +#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) +#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) +#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) +#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) +#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) +#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) +#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) +#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) +#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) + +/****************************************************************************/ +/* For use by SCSI Initiator and SCSI Target end-to-end data protection */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_EEDP_CRC_ERROR (0x004D) +#define MPI_IOCSTATUS_EEDP_LBA_TAG_ERROR (0x004E) +#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) + /****************************************************************************/ /* SCSI (SPI & FCP) target values */ @@ -618,7 +662,8 @@ #define MPI_IOCSTATUS_TARGET_PRIORITY_IO (0x0060) #define MPI_IOCSTATUS_TARGET_INVALID_PORT (0x0061) -#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) +#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete */ +#define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) #define MPI_IOCSTATUS_TARGET_ABORTED (0x0063) #define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) #define MPI_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) @@ -626,7 +671,7 @@ #define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT (0x006B) /****************************************************************************/ -/* Additional FCP target values */ +/* Additional FCP target values (obsolete) */ /****************************************************************************/ #define MPI_IOCSTATUS_TARGET_FC_ABORTED (0x0066) /* obsolete */ @@ -642,6 +687,7 @@ #define MPI_IOCSTATUS_FC_RX_ID_INVALID (0x0067) #define MPI_IOCSTATUS_FC_DID_INVALID (0x0068) #define MPI_IOCSTATUS_FC_NODE_LOGGED_OUT (0x0069) +#define MPI_IOCSTATUS_FC_EXCHANGE_CANCELED (0x006C) /****************************************************************************/ /* LAN values */ @@ -656,6 +702,25 @@ #define MPI_IOCSTATUS_LAN_PARTIAL_PACKET (0x0086) #define MPI_IOCSTATUS_LAN_CANCELED (0x0087) +/****************************************************************************/ +/* Serial Attached SCSI values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) + +/****************************************************************************/ +/* Inband values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_INBAND_ABORTED (0x0098) +#define MPI_IOCSTATUS_INBAND_NO_CONNECTION (0x0099) + +/****************************************************************************/ +/* Diagnostic Tools values */ +/****************************************************************************/ + +#define MPI_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) + /****************************************************************************/ /* IOCStatus flag to indicate that log info is available */ @@ -669,9 +734,12 @@ /****************************************************************************/ #define MPI_IOCLOGINFO_TYPE_MASK (0xF0000000) +#define MPI_IOCLOGINFO_TYPE_SHIFT (28) #define MPI_IOCLOGINFO_TYPE_NONE (0x0) #define MPI_IOCLOGINFO_TYPE_SCSI (0x1) #define MPI_IOCLOGINFO_TYPE_FC (0x2) +#define MPI_IOCLOGINFO_TYPE_SAS (0x3) +#define MPI_IOCLOGINFO_TYPE_ISCSI (0x4) #define MPI_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) diff -Nru a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h --- a/drivers/message/fusion/lsi/mpi_cnfg.h Wed Mar 10 21:09:43 2004 +++ b/drivers/message/fusion/lsi/mpi_cnfg.h Wed Mar 10 21:09:43 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI_CNFG.H + * Name: mpi_cnfg.h * Title: MPI Config message, structures, and Pages * Creation Date: July 27, 2000 * - * MPI_CNFG.H Version: 01.02.09 + * mpi_cnfg.h Version: 01.05.xx * * Version History * --------------- @@ -127,7 +127,24 @@ * MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE. * Added new config page: CONFIG_PAGE_SCSI_DEVICE_3. * Modified MPI_FCPORTPAGE5_FLAGS_ defines. - * 09-16-02 01.02.09 Added more MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG define. + * 09-16-02 01.02.09 Added MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG define. + * 11-15-02 01.02.10 Added ConnectedID defines for CONFIG_PAGE_SCSI_PORT_0. + * Added more Flags defines for CONFIG_PAGE_FC_PORT_1. + * Added more Flags defines for CONFIG_PAGE_FC_DEVICE_0. + * 04-01-03 01.02.11 Added RR_TOV field and additional Flags defines for + * CONFIG_PAGE_FC_PORT_1. + * Added define MPI_FCPORTPAGE5_FLAGS_DISABLE to disable + * an alias. + * Added more device id defines. + * 06-26-03 01.02.12 Added MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID define. + * Added TargetConfig and IDConfig fields to + * CONFIG_PAGE_SCSI_PORT_1. + * Added more PortFlags defines for CONFIG_PAGE_SCSI_PORT_2 + * to control DV. + * Added more Flags defines for CONFIG_PAGE_FC_PORT_1. + * In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field + * with ADISCHardALPA. + * Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define. * -------------------------------------------------------------------------- */ @@ -159,6 +176,19 @@ } ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion, fCONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION; +typedef struct _CONFIG_EXTENDED_PAGE_HEADER +{ + U8 PageVersion; /* 00h */ + U8 Reserved1; /* 01h */ + U8 PageNumber; /* 02h */ + U8 PageType; /* 03h */ + U16 ExtPageLength; /* 04h */ + U8 ExtPageType; /* 06h */ + U8 Reserved2; /* 07h */ +} fCONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER, + ConfigExtendedPageHeader_t, MPI_POINTER pConfigExtendedPageHeader_t; + + /**************************************************************************** * PageType field values @@ -180,12 +210,23 @@ #define MPI_CONFIG_PAGETYPE_RAID_VOLUME (0x08) #define MPI_CONFIG_PAGETYPE_MANUFACTURING (0x09) #define MPI_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) +#define MPI_CONFIG_PAGETYPE_INBAND (0x0B) +#define MPI_CONFIG_PAGETYPE_EXTENDED (0x0F) #define MPI_CONFIG_PAGETYPE_MASK (0x0F) #define MPI_CONFIG_TYPENUM_MASK (0x0FFF) /**************************************************************************** +* ExtPageType field values +****************************************************************************/ +#define MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10) +#define MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) +#define MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) +#define MPI_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) + + +/**************************************************************************** * PageAddress field values ****************************************************************************/ #define MPI_SCSI_PORT_PGAD_PORT_MASK (0x000000FF) @@ -219,6 +260,24 @@ #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_SHIFT (0) +#define MPI_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_DEVICE_PGAD_FORM_SHIFT (28) +#define MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID (0x00000001) +#define MPI_SAS_DEVICE_PGAD_FORM_HANDLE (0x00000002) +#define MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_DEVICE_PGAD_GNH_HANDLE_SHIFT (0) +#define MPI_SAS_DEVICE_PGAD_BT_BUS_MASK (0x0000FF00) +#define MPI_SAS_DEVICE_PGAD_BT_BUS_SHIFT (8) +#define MPI_SAS_DEVICE_PGAD_BT_TID_MASK (0x000000FF) +#define MPI_SAS_DEVICE_PGAD_BT_TID_SHIFT (0) +#define MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_DEVICE_PGAD_H_HANDLE_SHIFT (0) + +#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x00FF0000) +#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT (16) +#define MPI_SAS_PHY_PGAD_DEVHANDLE_MASK (0x0000FFFF) +#define MPI_SAS_PHY_PGAD_DEVHANDLE_SHIFT (0) /**************************************************************************** @@ -230,7 +289,8 @@ U8 Reserved; /* 01h */ U8 ChainOffset; /* 02h */ U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ + U16 ExtPageLength; /* 04h */ + U8 ExtPageType; /* 06h */ U8 MsgFlags; /* 07h */ U32 MsgContext; /* 08h */ U8 Reserved2[8]; /* 0Ch */ @@ -260,7 +320,8 @@ U8 Reserved; /* 01h */ U8 MsgLength; /* 02h */ U8 Function; /* 03h */ - U8 Reserved1[3]; /* 04h */ + U16 ExtPageLength; /* 04h */ + U8 ExtPageType; /* 06h */ U8 MsgFlags; /* 07h */ U32 MsgContext; /* 08h */ U8 Reserved2[2]; /* 0Ch */ @@ -281,23 +342,22 @@ /**************************************************************************** * Manufacturing Config pages ****************************************************************************/ +#define MPI_MANUFACTPAGE_VENDORID_LSILOGIC (0x1000) +/* Fibre Channel */ #define MPI_MANUFACTPAGE_DEVICEID_FC909 (0x0621) #define MPI_MANUFACTPAGE_DEVICEID_FC919 (0x0624) #define MPI_MANUFACTPAGE_DEVICEID_FC929 (0x0622) #define MPI_MANUFACTPAGE_DEVICEID_FC919X (0x0628) #define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) - +/* SCSI */ #define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) #define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) #define MPI_MANUFACTPAGE_DEVID_1030_53C1035 (0x0032) #define MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035 (0x0033) #define MPI_MANUFACTPAGE_DEVID_53C1035 (0x0040) #define MPI_MANUFACTPAGE_DEVID_53C1035ZC (0x0041) - -#define MPI_MANUFACTPAGE_DEVID_SA2010 (0x0804) -#define MPI_MANUFACTPAGE_DEVID_SA2010ZC (0x0805) -#define MPI_MANUFACTPAGE_DEVID_SA2020 (0x0806) -#define MPI_MANUFACTPAGE_DEVID_SA2020ZC (0x0807) +/* SAS */ +#define MPI_MANUFACTPAGE_DEVID_SAS1064 (0x0050) typedef struct _CONFIG_PAGE_MANUFACTURING_0 @@ -381,8 +441,8 @@ U8 InfoOffset1; /* 0Ah */ U8 InfoSize1; /* 0Bh */ U8 InquirySize; /* 0Ch */ - U8 Reserved2; /* 0Dh */ - U16 Reserved3; /* 0Eh */ + U8 Flags; /* 0Dh */ + U16 Reserved2; /* 0Eh */ U8 InquiryData[56]; /* 10h */ U32 ISVolumeSettings; /* 48h */ U32 IMEVolumeSettings; /* 4Ch */ @@ -390,7 +450,30 @@ } fCONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; -#define MPI_MANUFACTURING4_PAGEVERSION (0x00) +#define MPI_MANUFACTURING4_PAGEVERSION (0x01) + +/* defines for the Flags field */ +#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_5 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + U64 BaseWWID; /* 04h */ +} fCONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5, + ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t; + +#define MPI_MANUFACTURING5_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_6 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} fCONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6, + ManufacturingPage6_t, MPI_POINTER pManufacturingPage6_t; + +#define MPI_MANUFACTURING6_PAGEVERSION (0x00) /**************************************************************************** @@ -414,16 +497,18 @@ } fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; -#define MPI_IOUNITPAGE1_PAGEVERSION (0x00) +#define MPI_IOUNITPAGE1_PAGEVERSION (0x01) /* IO Unit Page 1 Flags defines */ - #define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000) #define MPI_IOUNITPAGE1_SINGLE_FUNCTION (0x00000001) #define MPI_IOUNITPAGE1_MULTI_PATHING (0x00000002) #define MPI_IOUNITPAGE1_SINGLE_PATHING (0x00000000) +#define MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004) +#define MPI_IOUNITPAGE1_DISABLE_QUEUE_FULL_HANDLING (0x00000020) #define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040) #define MPI_IOUNITPAGE1_FORCE_32 (0x00000080) +#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) typedef struct _MPI_ADAPTER_INFO @@ -453,6 +538,11 @@ #define MPI_IOUNITPAGE2_FLAGS_COLOR_VIDEO_DISABLE (0x00000008) #define MPI_IOUNITPAGE2_FLAGS_DONT_HOOK_INT_40 (0x00000010) +#define MPI_IOUNITPAGE2_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0) +#define MPI_IOUNITPAGE2_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000) +#define MPI_IOUNITPAGE2_FLAGS_ADAPTER_DISPLAY (0x00000020) +#define MPI_IOUNITPAGE2_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040) + /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to @@ -515,6 +605,12 @@ #define MPI_IOCPAGE1_PAGEVERSION (0x01) +/* defines for the Flags field */ +#define MPI_IOCPAGE1_EEDP_HOST_SUPPORTS_DIF (0x08000000) +#define MPI_IOCPAGE1_EEDP_MODE_MASK (0x07000000) +#define MPI_IOCPAGE1_EEDP_MODE_OFF (0x00000000) +#define MPI_IOCPAGE1_EEDP_MODE_T10 (0x01000000) +#define MPI_IOCPAGE1_EEDP_MODE_LSI_1 (0x02000000) #define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001) #define MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) @@ -655,7 +751,7 @@ typedef struct _CONFIG_PAGE_IOC_5 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + fCONFIG_PAGE_HEADER Header; /* 00h */ U32 Reserved1; /* 04h */ U8 NumHotSpares; /* 08h */ U8 Reserved2; /* 09h */ @@ -667,6 +763,57 @@ #define MPI_IOCPAGE5_PAGEVERSION (0x00) +/**************************************************************************** +* BIOS Port Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_BIOS_1 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + U32 BiosOptions; /* 04h */ + U32 IOCSettings; /* 08h */ + U32 Reserved1; /* 0Ch */ + U32 DeviceSettings; /* 10h */ + U16 NumberOfDevices; /* 14h */ + U16 Reserved2; /* 16h */ + U16 IOTimeoutBlockDevicesNonRM; /* 18h */ + U16 IOTimeoutSequential; /* 1Ah */ + U16 IOTimeoutOther; /* 1Ch */ + U16 IOTimeoutBlockDevicesRM; /* 1Eh */ +} fCONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, + BIOSPage1_t, MPI_POINTER pBIOSPage1_t; + +#define MPI_BIOSPAGE1_PAGEVERSION (0x00) + +/* values for the BiosOptions field */ +#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) +#define MPI_BIOSPAGE1_OPTIONS_FC_ENABLE (0x00000200) +#define MPI_BIOSPAGE1_OPTIONS_SAS_ENABLE (0x00000100) +#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) + +/* values for the IOCSettings field */ +#define MPI_BIOSPAGE1_IOCSET_MASK_SPINUP_DELAY (0x00000F00) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_SPINUP_DELAY (8) + +#define MPI_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0) +#define MPI_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000) +#define MPI_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040) +#define MPI_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080) + +#define MPI_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030) +#define MPI_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000) +#define MPI_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010) +#define MPI_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020) +#define MPI_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030) + +#define MPI_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008) + +/* values for the DeviceSettings field */ +#define MPI_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008) +#define MPI_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004) +#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) +#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) + /**************************************************************************** * SCSI Port Config Pages @@ -686,7 +833,27 @@ #define MPI_SCSIPORTPAGE0_CAP_DT (0x00000002) #define MPI_SCSIPORTPAGE0_CAP_QAS (0x00000004) #define MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK (0x0000FF00) +#define MPI_SCSIPORTPAGE0_SYNC_ASYNC (0x00) +#define MPI_SCSIPORTPAGE0_SYNC_5 (0x32) +#define MPI_SCSIPORTPAGE0_SYNC_10 (0x19) +#define MPI_SCSIPORTPAGE0_SYNC_20 (0x0C) +#define MPI_SCSIPORTPAGE0_SYNC_33_33 (0x0B) +#define MPI_SCSIPORTPAGE0_SYNC_40 (0x0A) +#define MPI_SCSIPORTPAGE0_SYNC_80 (0x09) +#define MPI_SCSIPORTPAGE0_SYNC_160 (0x08) +#define MPI_SCSIPORTPAGE0_SYNC_UNKNOWN (0xFF) + +#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8) +#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \ + ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \ + >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \ + ) #define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000) +#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16) +#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \ + ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \ + >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \ + ) #define MPI_SCSIPORTPAGE0_CAP_WIDE (0x20000000) #define MPI_SCSIPORTPAGE0_CAP_AIP (0x80000000) @@ -694,6 +861,10 @@ #define MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD (0x01) #define MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE (0x02) #define MPI_SCSIPORTPAGE0_PHY_SIGNAL_LVD (0x03) +#define MPI_SCSIPORTPAGE0_PHY_MASK_CONNECTED_ID (0xFF000000) +#define MPI_SCSIPORTPAGE0_PHY_SHIFT_CONNECTED_ID (24) +#define MPI_SCSIPORTPAGE0_PHY_BUS_FREE_CONNECTED_ID (0xFE) +#define MPI_SCSIPORTPAGE0_PHY_UNKNOWN_CONNECTED_ID (0xFF) typedef struct _CONFIG_PAGE_SCSI_PORT_1 @@ -701,13 +872,22 @@ fCONFIG_PAGE_HEADER Header; /* 00h */ U32 Configuration; /* 04h */ U32 OnBusTimerValue; /* 08h */ + U8 TargetConfig; /* 0Ch */ + U8 Reserved1; /* 0Dh */ + U16 IDConfig; /* 0Eh */ } fCONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1, SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t; -#define MPI_SCSIPORTPAGE1_PAGEVERSION (0x02) +#define MPI_SCSIPORTPAGE1_PAGEVERSION (0x03) +/* Configuration values */ #define MPI_SCSIPORTPAGE1_CFG_PORT_SCSI_ID_MASK (0x000000FF) #define MPI_SCSIPORTPAGE1_CFG_PORT_RESPONSE_ID_MASK (0xFFFF0000) +#define MPI_SCSIPORTPAGE1_CFG_SHIFT_PORT_RESPONSE_ID (16) + +/* TargetConfig values */ +#define MPI_SCSIPORTPAGE1_TARGCONFIG_TARG_ONLY (0x01) +#define MPI_SCSIPORTPAGE1_TARGCONFIG_INIT_TARG (0x02) typedef struct _MPI_DEVICE_INFO @@ -727,13 +907,21 @@ } fCONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2, SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t; -#define MPI_SCSIPORTPAGE2_PAGEVERSION (0x01) +#define MPI_SCSIPORTPAGE2_PAGEVERSION (0x02) +/* PortFlags values */ #define MPI_SCSIPORTPAGE2_PORT_FLAGS_SCAN_HIGH_TO_LOW (0x00000001) #define MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET (0x00000004) #define MPI_SCSIPORTPAGE2_PORT_FLAGS_ALTERNATE_CHS (0x00000008) #define MPI_SCSIPORTPAGE2_PORT_FLAGS_TERMINATION_DISABLE (0x00000010) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK (0x00000060) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_FULL_DV (0x00000000) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY (0x00000020) +#define MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV (0x00000060) + + +/* PortSettings values */ #define MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK (0x0000000F) #define MPI_SCSIPORTPAGE2_PORT_MASK_INIT_HBA (0x00000030) #define MPI_SCSIPORTPAGE2_PORT_DISABLE_INIT_HBA (0x00000000) @@ -741,7 +929,11 @@ #define MPI_SCSIPORTPAGE2_PORT_OS_INIT_HBA (0x00000020) #define MPI_SCSIPORTPAGE2_PORT_BIOS_OS_INIT_HBA (0x00000030) #define MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA (0x000000C0) +#define MPI_SCSIPORTPAGE2_PORT_RM_NONE (0x00000000) +#define MPI_SCSIPORTPAGE2_PORT_RM_BOOT_ONLY (0x00000040) +#define MPI_SCSIPORTPAGE2_PORT_RM_WITH_MEDIA (0x00000080) #define MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK (0x00000F00) +#define MPI_SCSIPORTPAGE2_PORT_SHIFT_SPINUP_DELAY (8) #define MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS (0x00003000) #define MPI_SCSIPORTPAGE2_PORT_NEGO_MASTER_SETTINGS (0x00000000) #define MPI_SCSIPORTPAGE2_PORT_NONE_MASTER_SETTINGS (0x00001000) @@ -778,7 +970,9 @@ #define MPI_SCSIDEVPAGE0_NP_RTI (0x00000040) #define MPI_SCSIDEVPAGE0_NP_PCOMP_EN (0x00000080) #define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK (0x0000FF00) +#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD (8) #define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK (0x00FF0000) +#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET (16) #define MPI_SCSIDEVPAGE0_NP_WIDE (0x20000000) #define MPI_SCSIDEVPAGE0_NP_AIP (0x80000000) @@ -808,7 +1002,9 @@ #define MPI_SCSIDEVPAGE1_RP_RTI (0x00000040) #define MPI_SCSIDEVPAGE1_RP_PCOMP_EN (0x00000080) #define MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK (0x0000FF00) +#define MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD (8) #define MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK (0x00FF0000) +#define MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET (16) #define MPI_SCSIDEVPAGE1_RP_WIDE (0x20000000) #define MPI_SCSIDEVPAGE1_RP_AIP (0x80000000) @@ -915,7 +1111,7 @@ #define MPI_FCPORTPAGE0_FLAGS_ALIAS_ALPA_SUPPORTED (0x00000010) #define MPI_FCPORTPAGE0_FLAGS_ALIAS_WWN_SUPPORTED (0x00000020) -#define MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID (0x00000030) +#define MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID (0x00000040) #define MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK (0x00000F00) #define MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT (0x00000000) @@ -954,13 +1150,19 @@ #define MPI_FCPORTPAGE0_SUPPORT_CLASS_2 (0x00000002) #define MPI_FCPORTPAGE0_SUPPORT_CLASS_3 (0x00000004) -#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT 1 1 GBit/sec */ -#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT 2 2 GBit/sec */ -#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT 4 10 GBit/sec */ +#define MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN (0x00000000) /* (SNIA)HBA_PORTSPEED_UNKNOWN 0 Unknown - transceiver incapable of reporting */ +#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT 1 1 GBit/sec */ +#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT 2 2 GBit/sec */ +#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT 4 10 GBit/sec */ +#define MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED (0x00000008) /* (SNIA)HBA_PORTSPEED_4GBIT 8 4 GBit/sec */ +#define MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN #define MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED #define MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED #define MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED +#define MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED +#define MPI_FCPORTPAGE0_CURRENT_SPEED_NOT_NEGOTIATED (0x00008000) /* (SNIA)HBA_PORTSPEED_NOT_NEGOTIATED (1<<15) Speed not established */ + typedef struct _CONFIG_PAGE_FC_PORT_1 @@ -974,15 +1176,25 @@ U8 TopologyConfig; /* 1Ah */ U8 AltConnector; /* 1Bh */ U8 NumRequestedAliases; /* 1Ch */ - U8 Reserved1; /* 1Dh */ - U16 Reserved2; /* 1Eh */ + U8 RR_TOV; /* 1Dh */ + U8 InitiatorDeviceTimeout; /* 1Eh */ + U8 InitiatorIoPendTimeout; /* 1Fh */ } fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1, FCPortPage1_t, MPI_POINTER pFCPortPage1_t; -#define MPI_FCPORTPAGE1_PAGEVERSION (0x04) +#define MPI_FCPORTPAGE1_PAGEVERSION (0x06) #define MPI_FCPORTPAGE1_FLAGS_EXT_FCP_STATUS_EN (0x08000000) #define MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY (0x04000000) +#define MPI_FCPORTPAGE1_FLAGS_FORCE_USE_NOSEEPROM_WWNS (0x02000000) +#define MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS (0x01000000) +#define MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID (0x00800000) +#define MPI_FCPORTPAGE1_FLAGS_PORT_OFFLINE (0x00400000) +#define MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK (0x00200000) +#define MPI_FCPORTPAGE1_FLAGS_MASK_RR_TOV_UNITS (0x00000070) +#define MPI_FCPORTPAGE1_FLAGS_SUPPRESS_PROT_REG (0x00000008) +#define MPI_FCPORTPAGE1_FLAGS_PLOGI_ON_LOGO (0x00000004) +#define MPI_FCPORTPAGE1_FLAGS_MAINTAIN_LOGINS (0x00000002) #define MPI_FCPORTPAGE1_FLAGS_SORT_BY_DID (0x00000001) #define MPI_FCPORTPAGE1_FLAGS_SORT_BY_WWN (0x00000000) @@ -993,6 +1205,11 @@ #define MPI_FCPORTPAGE1_FLAGS_PROT_LAN ((U32)MPI_PORTFACTS_PROTOCOL_LAN << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) #define MPI_FCPORTPAGE1_FLAGS_PROT_LOGBUSADDR ((U32)MPI_PORTFACTS_PROTOCOL_LOGBUSADDR << MPI_FCPORTPAGE1_FLAGS_PROT_SHIFT) +#define MPI_FCPORTPAGE1_FLAGS_NONE_RR_TOV_UNITS (0x00000000) +#define MPI_FCPORTPAGE1_FLAGS_THOUSANDTH_RR_TOV_UNITS (0x00000010) +#define MPI_FCPORTPAGE1_FLAGS_TENTH_RR_TOV_UNITS (0x00000030) +#define MPI_FCPORTPAGE1_FLAGS_TEN_RR_TOV_UNITS (0x00000050) + #define MPI_FCPORTPAGE1_HARD_ALPA_NOT_USED (0xFF) #define MPI_FCPORTPAGE1_LCONFIG_SPEED_MASK (0x0F) @@ -1009,6 +1226,8 @@ #define MPI_FCPORTPAGE1_ALT_CONN_UNKNOWN (0x00) +#define MPI_FCPORTPAGE1_INITIATOR_DEV_TIMEOUT_MASK (0x7F) + typedef struct _CONFIG_PAGE_FC_PORT_2 { @@ -1108,12 +1327,13 @@ } fCONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5, FCPortPage5_t, MPI_POINTER pFCPortPage5_t; -#define MPI_FCPORTPAGE5_PAGEVERSION (0x01) +#define MPI_FCPORTPAGE5_PAGEVERSION (0x02) #define MPI_FCPORTPAGE5_FLAGS_ALPA_ACQUIRED (0x01) #define MPI_FCPORTPAGE5_FLAGS_HARD_ALPA (0x02) #define MPI_FCPORTPAGE5_FLAGS_HARD_WWNN (0x04) #define MPI_FCPORTPAGE5_FLAGS_HARD_WWPN (0x08) +#define MPI_FCPORTPAGE5_FLAGS_DISABLE (0x10) typedef struct _CONFIG_PAGE_FC_PORT_6 { @@ -1322,7 +1542,7 @@ U8 Flags; /* 19h */ U16 BBCredit; /* 1Ah */ U16 MaxRxFrameSize; /* 1Ch */ - U8 Reserved1; /* 1Eh */ + U8 ADISCHardALPA; /* 1Eh */ U8 PortNumber; /* 1Fh */ U8 FcPhLowestVersion; /* 20h */ U8 FcPhHighestVersion; /* 21h */ @@ -1331,13 +1551,16 @@ } fCONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0, FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t; -#define MPI_FC_DEVICE_PAGE0_PAGEVERSION (0x02) +#define MPI_FC_DEVICE_PAGE0_PAGEVERSION (0x03) #define MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID (0x01) +#define MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID (0x02) +#define MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID (0x04) #define MPI_FC_DEVICE_PAGE0_PROT_IP (0x01) #define MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET (0x02) #define MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR (0x04) +#define MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY (0x08) #define MPI_FC_DEVICE_PAGE0_PGAD_PORT_MASK (MPI_FC_DEVICE_PGAD_PORT_MASK) #define MPI_FC_DEVICE_PAGE0_PGAD_FORM_MASK (MPI_FC_DEVICE_PGAD_FORM_MASK) @@ -1348,6 +1571,7 @@ #define MPI_FC_DEVICE_PAGE0_PGAD_BUS_SHIFT (MPI_FC_DEVICE_PGAD_BT_BUS_SHIFT) #define MPI_FC_DEVICE_PAGE0_PGAD_TID_MASK (MPI_FC_DEVICE_PGAD_BT_TID_MASK) +#define MPI_FC_DEVICE_PAGE0_HARD_ALPA_UNKNOWN (0xFF) /**************************************************************************** * RAID Volume Config Pages @@ -1564,6 +1788,318 @@ #define MPI_LAN_PAGE1_DEV_STATE_RESET (0x00) #define MPI_LAN_PAGE1_DEV_STATE_OPERATIONAL (0x01) + + +/**************************************************************************** +* Inband Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_INBAND_0 +{ + fCONFIG_PAGE_HEADER Header; /* 00h */ + MPI_VERSION_FORMAT InbandVersion; /* 04h */ + U16 MaximumBuffers; /* 08h */ + U16 Reserved1; /* 0Ah */ +} fCONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0, + InbandPage0_t, MPI_POINTER pInbandPage0_t; + +#define MPI_INBAND_PAGEVERSION (0x00) + + + +/**************************************************************************** +* SAS IO Unit Config Pages +****************************************************************************/ + +typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA +{ + U8 Port; /* 00h */ + U8 PortFlags; /* 01h */ + U8 PhyFlags; /* 02h */ + U8 NegotiatedLinkRate; /* 03h */ + U32 ControllerPhyDeviceInfo;/* 04h */ + U16 AttachedDeviceHandle; /* 08h */ + U16 ControllerDevHandle; /* 0Ah */ + U32 Reserved2; /* 0Ch */ +} MPI_SAS_IO_UNIT0_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT0_PHY_DATA, + SasIOUnit0PhyData, MPI_POINTER pSasIOUnit0PhyData; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_SAS_IOUNIT0_PHY_MAX +#define MPI_SAS_IOUNIT0_PHY_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U8 NumPhys; /* 0Ch */ + U8 Reserved2; /* 0Dh */ + U16 Reserved3; /* 0Eh */ + MPI_SAS_IO_UNIT0_PHY_DATA PhyData[MPI_SAS_IOUNIT0_PHY_MAX]; /* 10h */ +} fCONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0, + SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t; + +#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x00) + +/* values for SAS IO Unit Page 0 PortFlags */ +#define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS (0x08) +#define MPI_SAS_IOUNIT0_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) +#define MPI_SAS_IOUNIT0_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) +#define MPI_SAS_IOUNIT0_PORT_FLAGS_WAIT_FOR_PORTENABLE (0x02) +#define MPI_SAS_IOUNIT0_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 0 PhyFlags */ +#define MPI_SAS_IOUNIT0_PHY_FLAGS_PHY_DISABLED (0x04) +#define MPI_SAS_IOUNIT0_PHY_FLAGS_TX_INVERT (0x02) +#define MPI_SAS_IOUNIT0_PHY_FLAGS_RX_INVERT (0x01) + +/* values for SAS IO Unit Page 0 NegotiatedLinkRate */ +#define MPI_SAS_IOUNIT0_RATE_UNKNOWN (0x00) +#define MPI_SAS_IOUNIT0_RATE_PHY_DISABLED (0x01) +#define MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION (0x02) +#define MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI_SAS_IOUNIT0_RATE_1_5 (0x08) +#define MPI_SAS_IOUNIT0_RATE_3_0 (0x09) + +/* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ + + +typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA +{ + U8 Port; /* 00h */ + U8 PortFlags; /* 01h */ + U8 PhyFlags; /* 02h */ + U8 MaxMinLinkRate; /* 03h */ + U32 ControllerPhyDeviceInfo;/* 04h */ + U32 Reserved1; /* 08h */ +} MPI_SAS_IO_UNIT1_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT1_PHY_DATA, + SasIOUnit1PhyData, MPI_POINTER pSasIOUnit1PhyData; + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check Header.PageLength at runtime. + */ +#ifndef MPI_SAS_IOUNIT1_PHY_MAX +#define MPI_SAS_IOUNIT1_PHY_MAX (1) +#endif + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U8 NumPhys; /* 0Ch */ + U8 Reserved2; /* 0Dh */ + U16 Reserved3; /* 0Eh */ + MPI_SAS_IO_UNIT1_PHY_DATA PhyData[MPI_SAS_IOUNIT1_PHY_MAX]; /* 10h */ +} fCONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, + SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; + +#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x00) + +/* values for SAS IO Unit Page 0 PortFlags */ +#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_WAIT_FOR_PORTENABLE (0x02) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) + +/* values for SAS IO Unit Page 0 PhyFlags */ +#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04) +#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02) +#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01) + +/* values for SAS IO Unit Page 0 MaxMinLinkRate */ +#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0) +#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80) +#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90) +#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F) +#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08) +#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09) + +/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ + + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U16 MaxPersistentIDs; /* 0Ch */ + U16 NumPersistentIDsUsed; /* 0Eh */ + U8 Status; /* 10h */ + U8 Flags; /* 11h */ + U16 Reserved2; /* 12h */ +} fCONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, + SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; + +#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x00) + +/* values for SAS IO Unit Page 2 Status field */ +#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) +#define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS (0x01) + +/* values for SAS IO Unit Page 2 Flags field */ +#define MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS (0x01) + + +typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U32 MaxInvalidDwordCount; /* 0Ch */ + U32 InvalidDwordCountTime; /* 10h */ + U32 MaxRunningDisparityErrorCount; /* 14h */ + U32 RunningDisparityErrorTime; /* 18h */ + U32 MaxLossDwordSynchCount; /* 1Ch */ + U32 LossDwordSynchCountTime; /* 20h */ + U32 MaxPhyResetProblemCount; /* 24h */ + U32 PhyResetProblemTime; /* 28h */ +} fCONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3, + SasIOUnitPage3_t, MPI_POINTER pSasIOUnitPage3_t; + +#define MPI_SASIOUNITPAGE3_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U64 SASAddress; /* 0Ch */ + U32 Reserved2; /* 14h */ + U16 DevHandle; /* 18h */ + U16 ParentDevHandle; /* 1Ah */ + U16 ExpanderChangeCount; /* 1Ch */ + U16 ExpanderRouteIndexes; /* 1Eh */ + U8 NumPhys; /* 20h */ + U8 SASLevel; /* 21h */ + U8 Flags; /* 22h */ + U8 Reserved3; /* 23h */ +} fCONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, + SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t; + +#define MPI_SASEXPANDER0_PAGEVERSION (0x00) + +/* values for SAS Expander Page 0 Flags field */ +#define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x02) +#define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x01) + + +typedef struct _CONFIG_PAGE_SAS_DEVICE_0 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U64 SASAddress; /* 0Ch */ + U32 Reserved2; /* 14h */ + U16 DevHandle; /* 18h */ + U8 TargetID; /* 1Ah */ + U8 Bus; /* 1Bh */ + U32 DeviceInfo; /* 1Ch */ + U16 Flags; /* 20h */ + U8 PhysicalPort; /* 22h */ + U8 Reserved3; /* 23h */ +} fCONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0, + SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t; + +#define MPI_SASDEVICE0_PAGEVERSION (0x00) + +/* values for SAS Device Page 0 Flags field */ +#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x04) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x02) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x01) + +/* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */ + + +typedef struct _CONFIG_PAGE_SAS_DEVICE_1 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U64 SASAddress; /* 0Ch */ + U32 Reserved2; /* 14h */ + U16 DevHandle; /* 18h */ + U8 TargetID; /* 1Ah */ + U8 Bus; /* 1Bh */ + U8 InitialRegDeviceFIS[20];/* 1Ch */ +} fCONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1, + SasDevicePage1_t, MPI_POINTER pSasDevicePage1_t; + +#define MPI_SASDEVICE1_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_SAS_PHY_0 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U64 SASAddress; /* 0Ch */ + U16 AttachedDevHandle; /* 14h */ + U8 AttachedPhyIdentifier; /* 16h */ + U8 Reserved2; /* 17h */ + U32 AttachedDeviceInfo; /* 18h */ + U8 ProgrammedLinkRate; /* 20h */ + U8 HwLinkRate; /* 21h */ + U8 ChangeCount; /* 22h */ + U8 Reserved3; /* 23h */ + U32 PhyInfo; /* 24h */ +} fCONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0, + SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t; + +#define MPI_SASPHY0_PAGEVERSION (0x00) + +/* values for SAS PHY Page 0 ProgrammedLinkRate field */ +#define MPI_SAS_PHY0_PRATE_MAX_RATE_MASK (0xF0) +#define MPI_SAS_PHY0_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI_SAS_PHY0_PRATE_MAX_RATE_1_5 (0x80) +#define MPI_SAS_PHY0_PRATE_MAX_RATE_3_0 (0x90) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_MASK (0x0F) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_1_5 (0x08) +#define MPI_SAS_PHY0_PRATE_MIN_RATE_3_0 (0x09) + +/* values for SAS PHY Page 0 HwLinkRate field */ +#define MPI_SAS_PHY0_HWRATE_MAX_RATE_MASK (0xF0) +#define MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5 (0x80) +#define MPI_SAS_PHY0_HWRATE_MAX_RATE_3_0 (0x90) +#define MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK (0x0F) +#define MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5 (0x08) +#define MPI_SAS_PHY0_HWRATE_MIN_RATE_3_0 (0x09) + +/* values for SAS PHY Page 0 PhyInfo field */ +#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE (0x00004000) +#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR (0x00002000) +#define MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY (0x00001000) + +#define MPI_SAS_PHY0_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00) +#define MPI_SAS_PHY0_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8) + +#define MPI_SAS_PHY0_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0) +#define MPI_SAS_PHY0_PHYINFO_DIRECT_ROUTING (0x00000000) +#define MPI_SAS_PHY0_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010) +#define MPI_SAS_PHY0_PHYINFO_TABLE_ROUTING (0x00000020) + +#define MPI_SAS_PHY0_PHYINFO_MASK_LINK_RATE (0x0000000F) +#define MPI_SAS_PHY0_PHYINFO_UNKNOWN_LINK_RATE (0x00000000) +#define MPI_SAS_PHY0_PHYINFO_PHY_DISABLED (0x00000001) +#define MPI_SAS_PHY0_PHYINFO_NEGOTIATION_FAILED (0x00000002) +#define MPI_SAS_PHY0_PHYINFO_SATA_OOB_COMPLETE (0x00000003) +#define MPI_SAS_PHY0_PHYINFO_RATE_1_5 (0x00000008) +#define MPI_SAS_PHY0_PHYINFO_RATE_3_0 (0x00000009) + + +typedef struct _CONFIG_PAGE_SAS_PHY_1 +{ + fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U32 InvalidDwordCount; /* 0Ch */ + U32 RunningDisparityErrorCount; /* 10h */ + U32 LossDwordSynchCount; /* 14h */ + U32 PhyResetProblemCount; /* 18h */ +} fCONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1, + SasPhyPage1_t, MPI_POINTER pSasPhyPage1_t; + +#define MPI_SASPHY1_PAGEVERSION (0x00) + #endif diff -Nru a/drivers/message/fusion/lsi/mpi_fc.h b/drivers/message/fusion/lsi/mpi_fc.h --- a/drivers/message/fusion/lsi/mpi_fc.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/lsi/mpi_fc.h Wed Mar 10 21:09:42 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI_FC.H + * Name: mpi_fc.h * Title: MPI Fibre Channel messages and structures * Creation Date: June 12, 2000 * - * MPI_FC.H Version: 01.02.03 + * mpi_fc.h Version: 01.05.xx * * Version History * --------------- @@ -45,7 +45,7 @@ /***************************************************************************** * -* F C T a r g e t M o d e M e s s a g e s +* F C D i r e c t A c c e s s M e s s a g e s * *****************************************************************************/ @@ -334,6 +334,7 @@ FcPrimitiveSendRequest_t, MPI_POINTER pFcPrimitiveSendRequest_t; #define MPI_FC_PRIM_SEND_FLAGS_PORT_MASK (0x01) +#define MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK (0x02) #define MPI_FC_PRIM_SEND_FLAGS_RESET_LINK (0x04) #define MPI_FC_PRIM_SEND_FLAGS_STOP_SEND (0x08) #define MPI_FC_PRIM_SEND_FLAGS_SEND_ONCE (0x10) diff -Nru a/drivers/message/fusion/lsi/mpi_inb.h b/drivers/message/fusion/lsi/mpi_inb.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/message/fusion/lsi/mpi_inb.h Wed Mar 10 21:09:43 2004 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2003 LSI Logic Corporation. + * + * + * Name: mpi_inb.h + * Title: MPI Inband structures and definitions + * Creation Date: September 30, 2003 + * + * mpi_inb.h Version: 01.03.xx + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * ??-??-?? 01.03.01 Original release. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_INB_H +#define MPI_INB_H + +/****************************************************************************** +* +* I n b a n d M e s s a g e s +* +*******************************************************************************/ + + +/****************************************************************************/ +/* Inband Buffer Post Request */ +/****************************************************************************/ + +typedef struct _MSG_INBAND_BUFFER_POST_REQUEST +{ + U8 Reserved1; /* 00h */ + U8 BufferCount; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved4; /* 0Ch */ + SGE_TRANS_SIMPLE_UNION SGL; /* 10h */ +} MSG_INBAND_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REQUEST, + MpiInbandBufferPostRequest_t , MPI_POINTER pMpiInbandBufferPostRequest_t; + + +typedef struct _WWN_FC_FORMAT +{ + U64 NodeName; /* 00h */ + U64 PortName; /* 08h */ +} WWN_FC_FORMAT, MPI_POINTER PTR_WWN_FC_FORMAT, + WwnFcFormat_t, MPI_POINTER pWwnFcFormat_t; + +typedef struct _WWN_SAS_FORMAT +{ + U64 WorldWideID; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ +} WWN_SAS_FORMAT, MPI_POINTER PTR_WWN_SAS_FORMAT, + WwnSasFormat_t, MPI_POINTER pWwnSasFormat_t; + +typedef union _WWN_INBAND_FORMAT +{ + WWN_FC_FORMAT Fc; + WWN_SAS_FORMAT Sas; +} WWN_INBAND_FORMAT, MPI_POINTER PTR_WWN_INBAND_FORMAT, + WwnInbandFormat, MPI_POINTER pWwnInbandFormat; + + +/* Inband Buffer Post reply message */ + +typedef struct _MSG_INBAND_BUFFER_POST_REPLY +{ + U16 Reserved1; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferLength; /* 14h */ + U32 TransactionContext; /* 18h */ + WWN_INBAND_FORMAT Wwn; /* 1Ch */ + U32 IOCIdentifier[4]; /* 2Ch */ +} MSG_INBAND_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REPLY, + MpiInbandBufferPostReply_t, MPI_POINTER pMpiInbandBufferPostReply_t; + + +/****************************************************************************/ +/* Inband Send Request */ +/****************************************************************************/ + +typedef struct _MSG_INBAND_SEND_REQUEST +{ + U16 Reserved1; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved4; /* 0Ch */ + WWN_INBAND_FORMAT Wwn; /* 10h */ + U32 Reserved5; /* 20h */ + SGE_IO_UNION SGL; /* 24h */ +} MSG_INBAND_SEND_REQUEST, MPI_POINTER PTR_MSG_INBAND_SEND_REQUEST, + MpiInbandSendRequest_t , MPI_POINTER pMpiInbandSendRequest_t; + + +/* Inband Send reply message */ + +typedef struct _MSG_INBAND_SEND_REPLY +{ + U16 Reserved1; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ResponseLength; /* 14h */ +} MSG_INBAND_SEND_REPLY, MPI_POINTER PTR_MSG_INBAND_SEND_REPLY, + MpiInbandSendReply_t, MPI_POINTER pMpiInbandSendReply_t; + + +/****************************************************************************/ +/* Inband Response Request */ +/****************************************************************************/ + +typedef struct _MSG_INBAND_RSP_REQUEST +{ + U16 Reserved1; /* 00h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved4; /* 0Ch */ + WWN_INBAND_FORMAT Wwn; /* 10h */ + U32 IOCIdentifier[4]; /* 20h */ + U32 ResponseLength; /* 30h */ + SGE_IO_UNION SGL; /* 34h */ +} MSG_INBAND_RSP_REQUEST, MPI_POINTER PTR_MSG_INBAND_RSP_REQUEST, + MpiInbandRspRequest_t , MPI_POINTER pMpiInbandRspRequest_t; + + +/* Inband Response reply message */ + +typedef struct _MSG_INBAND_RSP_REPLY +{ + U16 Reserved1; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_INBAND_RSP_REPLY, MPI_POINTER PTR_MSG_INBAND_RSP_REPLY, + MpiInbandRspReply_t, MPI_POINTER pMpiInbandRspReply_t; + + +/****************************************************************************/ +/* Inband Abort Request */ +/****************************************************************************/ + +typedef struct _MSG_INBAND_ABORT_REQUEST +{ + U8 Reserved1; /* 00h */ + U8 AbortType; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved4; /* 0Ch */ + U32 ContextToAbort; /* 10h */ +} MSG_INBAND_ABORT_REQUEST, MPI_POINTER PTR_MSG_INBAND_ABORT_REQUEST, + MpiInbandAbortRequest_t , MPI_POINTER pMpiInbandAbortRequest_t; + +#define MPI_INBAND_ABORT_TYPE_ALL_BUFFERS (0x00) +#define MPI_INBAND_ABORT_TYPE_EXACT_BUFFER (0x01) +#define MPI_INBAND_ABORT_TYPE_SEND_REQUEST (0x02) +#define MPI_INBAND_ABORT_TYPE_RESPONSE_REQUEST (0x03) + + +/* Inband Abort reply message */ + +typedef struct _MSG_INBAND_ABORT_REPLY +{ + U8 Reserved1; /* 00h */ + U8 AbortType; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_INBAND_ABORT_REPLY, MPI_POINTER PTR_MSG_INBAND_ABORT_REPLY, + MpiInbandAbortReply_t, MPI_POINTER pMpiInbandAbortReply_t; + + +#endif + diff -Nru a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h --- a/drivers/message/fusion/lsi/mpi_init.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/lsi/mpi_init.h Wed Mar 10 21:09:42 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI_INIT.H + * Name: mpi_init.h * Title: MPI initiator mode messages and structures * Creation Date: June 8, 2000 * - * MPI_INIT.H Version: 01.02.05 + * mpi_init.h Version: 01.05.xx * * Version History * --------------- @@ -31,6 +31,8 @@ * 10-04-01 01.02.04 Added defines for SEP request Action field. * 05-31-02 01.02.05 Added MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR define * for SCSI IO requests. + * 11-15-02 01.02.06 Added special extended SCSI Status defines for FCP. + * 06-26-03 01.02.07 Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define. * -------------------------------------------------------------------------- */ @@ -45,7 +47,7 @@ *****************************************************************************/ /****************************************************************************/ -/* SCSI IO messages and assocaited structures */ +/* SCSI IO messages and associated structures */ /****************************************************************************/ typedef struct _MSG_SCSI_IO_REQUEST @@ -78,6 +80,16 @@ #define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST (0x00) #define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC (0x02) #define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04) +#define MPI_SCSIIO_MSGFLGS_EEDP_TYPE_MASK (0xE0) +#define MPI_SCSIIO_MSGFLGS_EEDP_NONE (0x00) +#define MPI_SCSIIO_MSGFLGS_EEDP_RDPROTECT_T10 (0x20) +#define MPI_SCSIIO_MSGFLGS_EEDP_VRPROTECT_T10 (0x40) +#define MPI_SCSIIO_MSGFLGS_EEDP_WRPROTECT_T10 (0x60) +#define MPI_SCSIIO_MSGFLGS_EEDP_520_READ_MODE1 (0x20) +#define MPI_SCSIIO_MSGFLGS_EEDP_520_WRITE_MODE1 (0x40) +#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_READ_MODE1 (0x60) +#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_WRITE_MODE1 (0x80) + /* SCSI IO LUN fields */ @@ -153,6 +165,10 @@ #define MPI_SCSI_STATUS_TASK_SET_FULL (0x28) #define MPI_SCSI_STATUS_ACA_ACTIVE (0x30) +#define MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT (0x80) +#define MPI_SCSI_STATUS_FCPEXT_NO_LINK (0x81) +#define MPI_SCSI_STATUS_FCPEXT_UNASSIGNED (0x82) + /* SCSI IO Reply SCSIState values */ @@ -176,6 +192,33 @@ /****************************************************************************/ +/* SCSI IO 32 Request message structure */ +/****************************************************************************/ + +typedef struct _MSG_SCSI_IO32_REQUEST +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U8 CDBLength; /* 04h */ + U8 SenseBufferLength; /* 05h */ + U8 Reserved; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 LUN[8]; /* 0Ch */ + U32 Control; /* 14h */ + U8 CDB[32]; /* 18h */ + U32 DataLength; /* 38h */ + U32 SenseBufferLowAddr; /* 3Ch */ + SGE_IO_UNION SGL; /* 40h */ +} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST, + SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t; + +/* SCSI IO 32 uses the same defines as above for SCSI IO */ + + +/****************************************************************************/ /* SCSI Task Management messages */ /****************************************************************************/ @@ -203,6 +246,7 @@ #define MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) #define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x04) #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) +#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) /* MsgFlags bits */ #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00) diff -Nru a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h --- a/drivers/message/fusion/lsi/mpi_ioc.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/lsi/mpi_ioc.h Wed Mar 10 21:09:42 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI_IOC.H + * Name: mpi_ioc.h * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: August 11, 2000 * - * MPI_IOC.H Version: 01.02.06 + * mpi_ioc.h Version: 01.05.xx * * Version History * --------------- @@ -55,6 +55,8 @@ * 05-31-02 01.02.06 Added define for * MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID. * Added AliasIndex to EVENT_DATA_LOGOUT structure. + * 04-01-03 01.02.07 Added defines for MPI_FW_HEADER_SIGNATURE_. + * 06-26-03 01.02.08 Added new values to the product family defines. * -------------------------------------------------------------------------- */ @@ -87,19 +89,21 @@ U8 Reserved1[2]; /* 0Eh */ U32 HostMfaHighAddr; /* 10h */ U32 SenseBufferHighAddr; /* 14h */ + U32 ReplyFifoHostSignalingAddr; /* 18h */ } MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT, IOCInit_t, MPI_POINTER pIOCInit_t; /* WhoInit values */ -#define MPI_WHOINIT_NO_ONE (0x00) -#define MPI_WHOINIT_SYSTEM_BIOS (0x01) -#define MPI_WHOINIT_ROM_BIOS (0x02) -#define MPI_WHOINIT_PCI_PEER (0x03) -#define MPI_WHOINIT_HOST_DRIVER (0x04) -#define MPI_WHOINIT_MANUFACTURER (0x05) +#define MPI_WHOINIT_NO_ONE (0x00) +#define MPI_WHOINIT_SYSTEM_BIOS (0x01) +#define MPI_WHOINIT_ROM_BIOS (0x02) +#define MPI_WHOINIT_PCI_PEER (0x03) +#define MPI_WHOINIT_HOST_DRIVER (0x04) +#define MPI_WHOINIT_MANUFACTURER (0x05) /* Flags values */ -#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01) +#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01) +#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02) typedef struct _MSG_IOC_INIT_REPLY { @@ -179,8 +183,10 @@ U8 MaxDevices; /* 2Eh */ U8 MaxBuses; /* 2Fh */ U32 FWImageSize; /* 30h */ - U32 Reserved4; /* 34h */ + U32 IOCCapabilities; /* 34h */ MPI_FW_VERSION FWVersion; /* 38h */ + U16 HighPriorityQueueDepth; /* 3Ch */ + U16 Reserved2; /* 3Eh */ } MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY, IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t; @@ -192,12 +198,22 @@ #define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) #define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) +#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) +#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008) #define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01) #define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00) #define MPI_IOCFACTS_EVENTSTATE_ENABLED (0x01) +#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q (0x00000001) +#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL (0x00000002) +#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004) +#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) +#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) +#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) +#define MPI_IOCFACTS_CAPABILITY_EEDP (0x00000040) + /***************************************************************************** @@ -253,6 +269,8 @@ #define MPI_PORTFACTS_PORTTYPE_INACTIVE (0x00) #define MPI_PORTFACTS_PORTTYPE_SCSI (0x01) #define MPI_PORTFACTS_PORTTYPE_FC (0x10) +#define MPI_PORTFACTS_PORTTYPE_ISCSI (0x20) +#define MPI_PORTFACTS_PORTTYPE_SAS (0x30) /* ProtocolFlags values */ @@ -386,6 +404,10 @@ #define MPI_EVENT_INTEGRATED_RAID (0x0000000B) #define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C) #define MPI_EVENT_ON_BUS_TIMER_EXPIRED (0x0000000D) +#define MPI_EVENT_QUEUE_FULL (0x0000000E) +#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F) +#define MPI_EVENT_SAS_SES (0x00000010) +#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011) /* AckRequired field values */ @@ -433,6 +455,39 @@ #define MPI_EVENT_SCSI_DEV_STAT_RC_NOT_RESPONDING (0x04) #define MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA (0x05) +/* SAS Device Status Change Event data */ + +typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 Reserved; /* 03h */ + U8 ASC; /* 04h */ + U8 ASCQ; /* 05h */ + U16 DevHandle; /* 06h */ + U32 DeviceInfo; /* 08h */ +} EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, + MpiEventDataSasDeviceStatusChange_t, + MPI_POINTER pMpiEventDataSasDeviceStatusChange_t; + +/* MPI SAS Device Status Change Event data ReasonCode values */ +#define MPI_EVENT_SAS_DEV_STAT_RC_ADDED (0x03) +#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING (0x04) +#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) +#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06) + +/* SCSI Event data for Queue Full event */ + +typedef struct _EVENT_DATA_QUEUE_FULL +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U16 CurrentDepth; /* 02h */ +} EVENT_DATA_QUEUE_FULL, MPI_POINTER PTR_EVENT_DATA_QUEUE_FULL, + EventDataQueueFull_t, MPI_POINTER pEventDataQueueFull_t; + /* MPI Link Status Change Event data */ typedef struct _EVENT_DATA_LINK_STATUS @@ -538,6 +593,7 @@ #define MPI_FW_DOWNLOAD_ITYPE_FW (0x01) #define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02) #define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03) +#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04) typedef struct _FWDownloadTCSGE @@ -590,6 +646,7 @@ #define MPI_FW_UPLOAD_ITYPE_FW_FLASH (0x01) #define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) #define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03) +#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04) typedef struct _FWUploadTCSGE { @@ -653,6 +710,11 @@ #define MPI_FW_HEADER_PID_TYPE_MASK (0xF000) #define MPI_FW_HEADER_PID_TYPE_SCSI (0x0000) #define MPI_FW_HEADER_PID_TYPE_FC (0x1000) +#define MPI_FW_HEADER_PID_TYPE_SAS (0x2000) + +#define MPI_FW_HEADER_SIGNATURE_0 (0x5AEAA55A) +#define MPI_FW_HEADER_SIGNATURE_1 (0xA55AEAA5) +#define MPI_FW_HEADER_SIGNATURE_2 (0x5AA55AEA) #define MPI_FW_HEADER_PID_PROD_MASK (0x0F00) #define MPI_FW_HEADER_PID_PROD_INITIATOR_SCSI (0x0100) @@ -663,6 +725,7 @@ #define MPI_FW_HEADER_PID_PROD_CTX_SCSI (0x0600) #define MPI_FW_HEADER_PID_FAMILY_MASK (0x00FF) +/* SCSI */ #define MPI_FW_HEADER_PID_FAMILY_1030A0_SCSI (0x0001) #define MPI_FW_HEADER_PID_FAMILY_1030B0_SCSI (0x0002) #define MPI_FW_HEADER_PID_FAMILY_1030B1_SCSI (0x0003) @@ -673,9 +736,17 @@ #define MPI_FW_HEADER_PID_FAMILY_1020C0_SCSI (0x0008) #define MPI_FW_HEADER_PID_FAMILY_1035A0_SCSI (0x0009) #define MPI_FW_HEADER_PID_FAMILY_1035B0_SCSI (0x000A) +#define MPI_FW_HEADER_PID_FAMILY_1030TA0_SCSI (0x000B) +#define MPI_FW_HEADER_PID_FAMILY_1020TA0_SCSI (0x000C) +/* Fibre Channel */ #define MPI_FW_HEADER_PID_FAMILY_909_FC (0x0000) #define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001) #define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002) +#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) +#define MPI_FW_HEADER_PID_FAMILY_949_FC (0x0004) +#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005) +/* SAS */ +#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001) typedef struct _MPI_EXT_IMAGE_HEADER { @@ -694,5 +765,6 @@ #define MPI_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) #define MPI_EXT_IMAGE_TYPE_FW (0x01) #define MPI_EXT_IMAGE_TYPE_NVDATA (0x03) +#define MPI_EXT_IMAGE_TYPE_BOOTLOADER (0x04) #endif diff -Nru a/drivers/message/fusion/lsi/mpi_lan.h b/drivers/message/fusion/lsi/mpi_lan.h --- a/drivers/message/fusion/lsi/mpi_lan.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/lsi/mpi_lan.h Wed Mar 10 21:09:42 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI_LAN.H + * Name: mpi_lan.h * Title: MPI LAN messages and structures * Creation Date: June 30, 2000 * - * MPI_LAN.H Version: 01.02.01 + * mpi_lan.h Version: 01.05.xx * * Version History * --------------- diff -Nru a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h --- a/drivers/message/fusion/lsi/mpi_raid.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/lsi/mpi_raid.h Wed Mar 10 21:09:42 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2001-2002 LSI Logic Corporation. + * Copyright (c) 2001-2003 LSI Logic Corporation. * * - * Name: MPI_RAID.H + * Name: mpi_raid.h * Title: MPI RAID message and structures * Creation Date: February 27, 2001 * - * MPI_RAID.H Version: 01.02.07 + * mpi_raid.h Version: 01.05.xx * * Version History * --------------- @@ -25,6 +25,9 @@ * MPI_RAID_ACTION_INACTIVATE_VOLUME, and * MPI_RAID_ACTION_ADATA_INACTIVATE_ALL. * 07-12-02 01.02.07 Added structures for Mailbox request and reply. + * 11-15-02 01.02.08 Added missing MsgContext field to MSG_MAILBOX_REQUEST. + * 04-01-03 01.02.09 New action data option flag for + * MPI_RAID_ACTION_DELETE_VOLUME. * -------------------------------------------------------------------------- */ @@ -40,7 +43,7 @@ /****************************************************************************/ -/* RAID Volume Request */ +/* RAID Action Request */ /****************************************************************************/ typedef struct _MSG_RAID_ACTION @@ -90,6 +93,9 @@ #define MPI_RAID_ACTION_ADATA_KEEP_PHYS_DISKS (0x00000000) #define MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS (0x00000001) +#define MPI_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000) +#define MPI_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000002) + /* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */ #define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL (0x00000001) @@ -184,7 +190,7 @@ /****************************************************************************/ -/* Mailbox request structure */ +/* Mailbox reqeust structure */ /****************************************************************************/ typedef struct _MSG_MAILBOX_REQUEST @@ -195,6 +201,7 @@ U16 Reserved2; U8 Reserved3; U8 MsgFlags; + U32 MsgContext; U8 Command[10]; U16 Reserved4; SGE_IO_UNION SGL; diff -Nru a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/message/fusion/lsi/mpi_sas.h Wed Mar 10 21:09:43 2004 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2003 LSI Logic Corporation. + * + * + * Name: mpi_sas.h + * Title: MPI Serial Attached SCSI structures and definitions + * Creation Date: April 23, 2003 + * + * mpi_sas.h Version: 01.05.xx + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * xx-yy-zz 01.05.01 Original release. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_SAS_H +#define MPI_SAS_H + +/***************************************************************************** +* +* S e r i a l A t t a c h e d S C S I M e s s a g e s +* +*****************************************************************************/ + +/****************************************************************************/ +/* Serial Management Protocol Passthrough Request */ +/****************************************************************************/ + +typedef struct _MSG_SMP_PASSTHROUGH_REQUEST +{ + U8 PassthroughFlags; /* 00h */ + U8 PhysicalPort; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 RequestDataLength; /* 04h */ + U8 ConnectionRate; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved1; /* 0Ch */ + U64 SASAddress; /* 10h */ + U32 Reserved2; /* 18h */ + U32 Reserved3; /* 1Ch */ + SGE_SIMPLE_UNION SGL; /* 20h */ +} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST, + SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t; + +#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) + +#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00) +#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5 (0x08) +#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0 (0x09) + + +/* Serial Management Protocol Passthrough Reply */ +typedef struct _MSG_SMP_PASSTHROUGH_REPLY +{ + U8 PassthroughFlags; /* 00h */ + U8 PhysicalPort; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 ResponseDataLength; /* 04h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2; /* 0Ch */ + U8 SASStatus; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 Reserved3; /* 14h */ + U8 ResponseData[4]; /* 18h */ +} MSG_SMP_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REPLY, + SmpPassthroughReply_t, MPI_POINTER pSmpPassthroughReply_t; + +#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80) + +/* values for the SASStatus field */ +#define MPI_SASSTATUS_SUCCESS (0x00) +#define MPI_SASSTATUS_UNKNOWN_ERROR (0x01) +#define MPI_SASSTATUS_INVALID_FRAME (0x02) +#define MPI_SASSTATUS_UTC_BAD_DEST (0x03) +#define MPI_SASSTATUS_UTC_BREAK_RECEIVED (0x04) +#define MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05) +#define MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06) +#define MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07) +#define MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08) +#define MPI_SASSTATUS_UTC_WRONG_DESTINATION (0x09) +#define MPI_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A) +#define MPI_SASSTATUS_LONG_INFORMATION_UNIT (0x0B) +#define MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C) +#define MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D) +#define MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E) +#define MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F) +#define MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10) +#define MPI_SASSTATUS_DATA_OFFSET_ERROR (0x11) +#define MPI_SASSTATUS_SDSF_NAK_RECEIVED (0x12) +#define MPI_SASSTATUS_SDSF_CONNECTION_FAILED (0x13) +#define MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14) + + +/* + * Values for the SAS DeviceInfo field used in SAS Device Status Change Event + * data and SAS IO Unit Configuration pages. + */ +#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) +#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) +#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) +#define MPI_SAS_DEVICE_INFO_SSP_TARGET (0x00000400) +#define MPI_SAS_DEVICE_INFO_STP_TARGET (0x00000200) +#define MPI_SAS_DEVICE_INFO_SMP_TARGET (0x00000100) +#define MPI_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080) +#define MPI_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040) +#define MPI_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020) +#define MPI_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010) +#define MPI_SAS_DEVICE_INFO_SATA_HOST (0x00000008) + +#define MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) +#define MPI_SAS_DEVICE_INFO_NO_DEVICE (0x00000000) +#define MPI_SAS_DEVICE_INFO_END_DEVICE (0x00000001) +#define MPI_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002) +#define MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) + + +/****************************************************************************/ +/* SAS IO Unit Control Request */ +/****************************************************************************/ + +typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST +{ + U8 Operation; /* 00h */ + U8 Reserved1; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 TargetID; /* 0Ch */ + U8 Bus; /* 0Dh */ + U8 PhyNum; /* 0Eh */ + U8 Reserved4; /* 0Fh */ + U32 Reserved5; /* 10h */ + U64 SASAddress; /* 14h */ + U32 Reserved6; /* 1Ch */ +} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST, + SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t; + +/* values for the ... field */ +#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01) +#define MPI_SAS_OP_CLEAR_ALL (0x02) +#define MPI_SAS_OP_MAP (0x03) +#define MPI_SAS_OP_MOVE (0x04) +#define MPI_SAS_OP_CLEAR (0x05) +#define MPI_SAS_OP_PHY_LINK_RESET (0x06) +#define MPI_SAS_OP_PHY_HARD_RESET (0x07) +#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) + + +/* SAS IO Unit Control Reply */ +typedef struct _MSG_SAS_IOUNIT_CONTROL_REPLY +{ + U8 Operation; /* 00h */ + U8 Reserved1; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_SAS_IOUNIT_CONTROL_REPLY, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REPLY, + SasIoUnitControlReply_t, MPI_POINTER pSasIoUnitControlReply_t; + +#endif + + diff -Nru a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h --- a/drivers/message/fusion/lsi/mpi_targ.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/lsi/mpi_targ.h Wed Mar 10 21:09:42 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI_TARG.H + * Name: mpi_targ.h * Title: MPI Target mode messages and structures * Creation Date: June 22, 2000 * - * MPI_TARG.H Version: 01.02.07 + * mpi_targ.h Version: 01.05.xx * * Version History * --------------- @@ -41,6 +41,8 @@ * Added AliasIndex field to MPI_TARGET_FCP_CMD_BUFFER. * 09-16-02 01.02.07 Added flags for confirmed completion. * Added PRIORITY_REASON_TARGET_BUSY. + * 11-15-02 01.02.08 Added AliasID field to MPI_TARGET_SCSI_SPI_CMD_BUFFER. + * 04-01-03 01.02.09 Added OptionalOxid field to MPI_TARGET_FCP_CMD_BUFFER. * -------------------------------------------------------------------------- */ @@ -171,7 +173,7 @@ U32 FcpDl; /* 1Ch */ U8 AliasIndex; /* 20h */ U8 Reserved1; /* 21h */ - U16 Reserved2; /* 22h */ + U16 OptionalOxid; /* 22h */ } MPI_TARGET_FCP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_FCP_CMD_BUFFER, MpiTargetFcpCmdBuffer, MPI_POINTER pMpiTargetFcpCmdBuffer; @@ -190,6 +192,10 @@ U8 TaskManagementFlags; /* 12h */ U8 AdditionalCDBLength; /* 13h */ U8 CDB[16]; /* 14h */ + /* Alias ID */ + U8 AliasID; /* 24h */ + U8 Reserved1; /* 25h */ + U16 Reserved2; /* 26h */ } MPI_TARGET_SCSI_SPI_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER, MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer; diff -Nru a/drivers/message/fusion/lsi/mpi_tool.h b/drivers/message/fusion/lsi/mpi_tool.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/message/fusion/lsi/mpi_tool.h Wed Mar 10 21:09:43 2004 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2001-2003 LSI Logic Corporation. + * + * + * Name: mpi_tool.h + * Title: MPI Toolbox structures and definitions + * Creation Date: July 30, 2001 + * + * mpi_tool.h Version: 01.05.xx + * + * Version History + * --------------- + * + * Date Version Description + * -------- -------- ------------------------------------------------------ + * 08-08-01 01.02.01 Original release. + * 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines. + * -------------------------------------------------------------------------- + */ + +#ifndef MPI_TOOL_H +#define MPI_TOOL_H + +#define MPI_TOOLBOX_CLEAN_TOOL (0x00) +#define MPI_TOOLBOX_MEMORY_MOVE_TOOL (0x01) +#define MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) +#define MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) +#define MPI_TOOLBOX_FC_MANAGEMENT_TOOL (0x04) + + +/****************************************************************************/ +/* Toolbox reply */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_REPLY +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved3; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_TOOLBOX_REPLY, MPI_POINTER PTR_MSG_TOOLBOX_REPLY, + ToolboxReply_t, MPI_POINTER pToolboxReply_t; + + +/****************************************************************************/ +/* Toolbox Clean Tool request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_CLEAN_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Flags; /* 0Ch */ +} MSG_TOOLBOX_CLEAN_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_CLEAN_REQUEST, + ToolboxCleanRequest_t, MPI_POINTER pToolboxCleanRequest_t; + +#define MPI_TOOLBOX_CLEAN_NVSRAM (0x00000001) +#define MPI_TOOLBOX_CLEAN_SEEPROM (0x00000002) +#define MPI_TOOLBOX_CLEAN_FLASH (0x00000004) +#define MPI_TOOLBOX_CLEAN_BOOTLOADER (0x04000000) +#define MPI_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) +#define MPI_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) +#define MPI_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) +#define MPI_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000) +#define MPI_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000) + + +/****************************************************************************/ +/* Toolbox Memory Move request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_MEM_MOVE_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + SGE_SIMPLE_UNION SGL; /* 0Ch */ +} MSG_TOOLBOX_MEM_MOVE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_MEM_MOVE_REQUEST, + ToolboxMemMoveRequest_t, MPI_POINTER pToolboxMemMoveRequest_t; + + +/****************************************************************************/ +/* Toolbox Diagnostic Data Upload request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Flags; /* 0Ch */ + U32 Reserved3; /* 10h */ + SGE_SIMPLE_UNION SGL; /* 14h */ +} MSG_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, + ToolboxDiagDataUploadRequest_t, MPI_POINTER pToolboxDiagDataUploadRequest_t; + +typedef struct _DIAG_DATA_UPLOAD_HEADER +{ + U32 DiagDataLength; /* 00h */ + U8 FormatCode; /* 04h */ + U8 Reserved; /* 05h */ + U16 Reserved1; /* 06h */ +} DIAG_DATA_UPLOAD_HEADER, MPI_POINTER PTR_DIAG_DATA_UPLOAD_HEADER, + DiagDataUploadHeader_t, MPI_POINTER pDiagDataUploadHeader_t; + +#define MPI_TB_DIAG_FORMAT_SCSI_PRINTF_1 (0x01) +#define MPI_TB_DIAG_FORMAT_SCSI_2 (0x02) +#define MPI_TB_DIAG_FORMAT_SCSI_3 (0x03) +#define MPI_TB_DIAG_FORMAT_FC_TRACE_1 (0x04) + + +/****************************************************************************/ +/* Toolbox ISTWI Read Write request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Flags; /* 0Ch */ + U8 BusNum; /* 0Dh */ + U16 Reserved3; /* 0Eh */ + U8 NumAddressBytes; /* 10h */ + U8 Reserved4; /* 11h */ + U16 DataLength; /* 12h */ + U8 DeviceAddr; /* 14h */ + U8 Addr1; /* 15h */ + U8 Addr2; /* 16h */ + U8 Addr3; /* 17h */ + U32 Reserved5; /* 18h */ + SGE_SIMPLE_UNION SGL; /* 1Ch */ +} MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST, + ToolboxIstwiReadWriteRequest_t, MPI_POINTER pToolboxIstwiReadWriteRequest_t; + +#define MPI_TB_ISTWI_FLAGS_WRITE (0x00) +#define MPI_TB_ISTWI_FLAGS_READ (0x01) + + +/****************************************************************************/ +/* Toolbox FC Management request */ +/****************************************************************************/ + +/* ActionInfo for Bus and TargetId */ +typedef struct _MPI_TB_FC_MANAGE_BUS_TID_AI +{ + U16 Reserved; /* 00h */ + U8 Bus; /* 02h */ + U8 TargetId; /* 03h */ +} MPI_TB_FC_MANAGE_BUS_TID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_BUS_TID_AI, + MpiTbFcManageBusTidAi_t, MPI_POINTER pMpiTbFcManageBusTidAi_t; + +/* ActionInfo for port identifier */ +typedef struct _MPI_TB_FC_MANAGE_PID_AI +{ + U32 PortIdentifier; /* 00h */ +} MPI_TB_FC_MANAGE_PID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_PID_AI, + MpiTbFcManagePidAi_t, MPI_POINTER pMpiTbFcManagePidAi_t; + +/* union of ActionInfo */ +typedef union _MPI_TB_FC_MANAGE_AI_UNION +{ + MPI_TB_FC_MANAGE_BUS_TID_AI BusTid; + MPI_TB_FC_MANAGE_PID_AI Port; +} MPI_TB_FC_MANAGE_AI_UNION, MPI_POINTER PTR_MPI_TB_FC_MANAGE_AI_UNION, + MpiTbFcManageAiUnion_t, MPI_POINTER pMpiTbFcManageAiUnion_t; + +typedef struct _MSG_TOOLBOX_FC_MANAGE_REQUEST +{ + U8 Tool; /* 00h */ + U8 Reserved; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Action; /* 0Ch */ + U8 Reserved3; /* 0Dh */ + U16 Reserved4; /* 0Eh */ + MPI_TB_FC_MANAGE_AI_UNION ActionInfo; /* 10h */ +} MSG_TOOLBOX_FC_MANAGE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_FC_MANAGE_REQUEST, + ToolboxFcManageRequest_t, MPI_POINTER pToolboxFcManageRequest_t; + +/* defines for the Action field */ +#define MPI_TB_FC_MANAGE_ACTION_DISC_ALL (0x00) +#define MPI_TB_FC_MANAGE_ACTION_DISC_PID (0x01) +#define MPI_TB_FC_MANAGE_ACTION_DISC_BUS_TID (0x02) + + +/****************************************************************************/ +/* Diagnostic Buffer Post request */ +/****************************************************************************/ + +typedef struct _MSG_DIAG_BUFFER_POST_REQUEST +{ + U8 TraceLevel; /* 00h */ + U8 BufferType; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 ExtendedType; /* 0Ch */ + U32 BufferLength; /* 10h */ + U32 ProductSpecific[4]; /* 14h */ + U32 Reserved3; /* 18h */ + SGE_SIMPLE_UNION SGL; /* 28h */ +} MSG_DIAG_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REQUEST, + DiagBufferPostRequest_t, MPI_POINTER pDiagBufferPostRequest_t; + +#define MPI_DIAG_BUF_TYPE_TRACE (0x00) +#define MPI_DIAG_BUF_TYPE_SNAPSHOT (0x01) +#define MPI_DIAG_BUF_TYPE_EXTENDED (0x02) + +#define MPI_DIAG_EXTENDED_QTAG (0x00000001) + + +/* Diagnostic Buffer Post reply */ +typedef struct _MSG_DIAG_BUFFER_POST_REPLY +{ + U8 Reserved1; /* 00h */ + U8 BufferType; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 TransferLength; /* 14h */ +} MSG_DIAG_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REPLY, + DiagBufferPostReply_t, MPI_POINTER pDiagBufferPostReply_t; + + +/****************************************************************************/ +/* Diagnostic Release request */ +/****************************************************************************/ + +typedef struct _MSG_DIAG_RELEASE_REQUEST +{ + U8 Reserved1; /* 00h */ + U8 BufferType; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ +} MSG_DIAG_RELEASE_REQUEST, MPI_POINTER PTR_MSG_DIAG_RELEASE_REQUEST, + DiagReleaseRequest_t, MPI_POINTER pDiagReleaseRequest_t; + + +/* Diagnostic Release reply */ +typedef struct _MSG_DIAG_RELEASE_REPLY +{ + U8 Reserved1; /* 00h */ + U8 BufferType; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved2; /* 04h */ + U8 Reserved3; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U16 Reserved4; /* 0Ch */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ +} MSG_DIAG_RELEASE_REPLY, MPI_POINTER PTR_MSG_DIAG_RELEASE_REPLY, + DiagReleaseReply_t, MPI_POINTER pDiagReleaseReply_t; + + +#endif + + diff -Nru a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h --- a/drivers/message/fusion/lsi/mpi_type.h Wed Mar 10 21:09:43 2004 +++ b/drivers/message/fusion/lsi/mpi_type.h Wed Mar 10 21:09:43 2004 @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2002 LSI Logic Corporation. + * Copyright (c) 2000-2003 LSI Logic Corporation. * * - * Name: MPI_TYPE.H + * Name: mpi_type.h * Title: MPI Basic type definitions * Creation Date: June 6, 2000 * - * MPI Version: 01.02.01 + * mpi_type.h Version: 01.05.xx * * Version History * --------------- diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c --- a/drivers/message/fusion/mptbase.c Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/mptbase.c Wed Mar 10 21:09:42 2004 @@ -44,7 +44,7 @@ * for gobs of hard work fixing and optimizing LAN code. * THANK YOU! * - * Copyright (c) 1999-2003 LSI Logic Corporation + * Copyright (c) 1999-2004 LSI Logic Corporation * Originally By: Steven J. Ralston * (mailto:sjralston1@netscape.net) * (mailto:mpt_linux_developer@lsil.com) @@ -209,8 +209,8 @@ static int GetIoUnitPage2(MPT_ADAPTER *ioc); static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); -static int mpt_findImVolumes(MPT_ADAPTER *ioc); static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); +static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); static void mpt_timer_expired(unsigned long data); static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); @@ -347,14 +347,14 @@ MPT_FRAME_HDR *mf; MPT_FRAME_HDR *mr; u32 pa; - int req_idx = -1; + int req_idx; int cb_idx; int type; int freeme; - int count = 0; ioc = bus_id; +#ifdef MPT_DEBUG_IRQ /* * Verify ioc pointer is ok */ @@ -369,6 +369,7 @@ return IRQ_NONE; } } +#endif /* * Drain the reply FIFO! @@ -521,17 +522,7 @@ spin_unlock_irqrestore(&ioc->FreeQlock, flags); } - count++; - dirqprintk((MYIOC_s_INFO_FMT "ISR processed frame #%d\n", ioc->name, count)); mb(); - - if (count >= MPT_MAX_REPLIES_PER_ISR) { - dirqprintk((MYIOC_s_INFO_FMT "ISR processed %d replies.", - ioc->name, count)); - dirqprintk((" Giving this ISR a break!\n")); - return IRQ_HANDLED; - } - } /* drain reply FIFO */ return IRQ_HANDLED; @@ -605,7 +596,8 @@ } else if (func == MPI_FUNCTION_EVENT_ACK) { dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n", ioc->name)); - } else if (func == MPI_FUNCTION_CONFIG) { + } else if (func == MPI_FUNCTION_CONFIG || + func == MPI_FUNCTION_TOOLBOX) { CONFIGPARMS *pCfg; unsigned long flags; @@ -714,11 +706,7 @@ MptCallbacks[i] = cbfunc; MptDriverClass[i] = dclass; MptEvHandlers[i] = NULL; - MptDeviceDriverHandlers[i] = NULL; last_drv_idx = i; - if (cbfunc != mpt_base_reply) { - mpt_inc_use_count(); - } break; } } @@ -745,10 +733,6 @@ last_drv_idx++; if (isense_idx != -1 && isense_idx <= cb_idx) isense_idx++; - - if (cb_idx != mpt_base_index) { - mpt_dec_use_count(); - } } } @@ -890,7 +874,7 @@ MPT_FRAME_HDR* mpt_get_msg_frame(int handle, int iocid) { - MPT_FRAME_HDR *mf = NULL; + MPT_FRAME_HDR *mf; MPT_ADAPTER *iocp; unsigned long flags; @@ -922,6 +906,8 @@ iocp->mfcnt++; #endif } + else + mf = NULL; spin_unlock_irqrestore(&iocp->FreeQlock, flags); #ifdef MFCNT @@ -986,7 +972,11 @@ mf_dma_addr = iocp->req_frames_low_dma + req_offset; CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr); + } else { + printk (KERN_ERR + "mpt_put_msg_frame: Invalid iocid=%d\n", iocid); } + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1135,7 +1125,7 @@ ((reqBytes/4)<chip->IntStatus, 0); - if ((r = WaitForDoorbellAck(iocp, 1, sleepFlag)) < 0) { + if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) { return -2; } @@ -1162,7 +1152,7 @@ (req_as_bytes[(ii*4) + 2] << 16) | (req_as_bytes[(ii*4) + 3] << 24)); CHIPREG_WRITE32(&iocp->chip->Doorbell, word); - if ((r = WaitForDoorbellAck(iocp, 1, sleepFlag)) < 0) { + if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) { r = -3; break; } @@ -1190,10 +1180,12 @@ MPT_ADAPTER * mpt_adapter_find_first(void) { - MPT_ADAPTER *this = NULL; + MPT_ADAPTER *this; if (! Q_IS_EMPTY(&MptAdapters)) this = MptAdapters.head; + else + this = NULL; return this; } @@ -1208,10 +1200,12 @@ MPT_ADAPTER * mpt_adapter_find_next(MPT_ADAPTER *prev) { - MPT_ADAPTER *next = NULL; + MPT_ADAPTER *next; if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head)) next = prev->forw; + else + next = NULL; return next; } @@ -1272,10 +1266,12 @@ int ii; int r = -ENODEV; u64 mask = 0xffffffffffffffffULL; + u8 revision; + u8 pcixcmd; if (pci_enable_device(pdev)) return r; - + if (!pci_set_dma_mask(pdev, mask)) { dprintk((KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); @@ -1296,12 +1292,30 @@ printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } - memset(ioc, 0, sizeof(*ioc)); + memset(ioc, 0, sizeof(MPT_ADAPTER)); ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ - ioc->reply_sz = ioc->req_sz; + ioc->reply_sz = MPT_REPLY_FRAME_SIZE; ioc->pcidev = pdev; + +#if defined(MPTBASE_MEM_ALLOC_FIFO_FIX) + memcpy(&ioc->pcidev32,ioc->pcidev,sizeof(struct pci_dev)); + if (pci_set_dma_mask(&ioc->pcidev32, 0xFFFFFFFF)) { + dprintk((KERN_INFO MYNAM + ": error setting 32bit mask\n")); + kfree(ioc); + return -ENODEV; + } + + if (pci_set_consistent_dma_mask(&ioc->pcidev32, 0xFFFFFFFF)) { + dprintk((KERN_INFO MYNAM + ": error setting 32bit mask\n")); + kfree(ioc); + return -ENODEV; + } +#endif + ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); @@ -1412,48 +1426,45 @@ } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { ioc->chip_type = FC929X; - ioc->prod_name = "LSIFC929X"; - { + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + if (revision < XL_929) { + ioc->prod_name = "LSIFC929X"; /* 929X Chip Fix. Set Split transactions level - * for PCIX. Set bits 5 - 6 to zero, turn on bit 4. - */ - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF9F; - pcixcmd |= 0x0010; - pci_write_config_word(pdev, 0x6a, pcixcmd); + * for PCIX. Set MOST bits to zero. + */ + pci_read_config_byte(pdev, 0x6a, &pcixcmd); + pcixcmd &= 0x8F; + pci_write_config_byte(pdev, 0x6a, pcixcmd); + } else { + ioc->prod_name = "LSIFC929XL"; + /* 929XL Chip Fix. Set MMRBC to 0x08. + */ + pci_read_config_byte(pdev, 0x6a, &pcixcmd); + pcixcmd |= 0x08; + pci_write_config_byte(pdev, 0x6a, pcixcmd); } } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { ioc->chip_type = FC919X; ioc->prod_name = "LSIFC919X"; - { - /* 919X Chip Fix. Set Split transactions level - * for PCIX. Set bits 5 - 6 to zero, turn on bit 4. - */ - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF9F; - pcixcmd |= 0x0010; - pci_write_config_word(pdev, 0x6a, pcixcmd); - } + /* 919X Chip Fix. Set Split transactions level + * for PCIX. Set MOST bits to zero. + */ + pci_read_config_byte(pdev, 0x6a, &pcixcmd); + pcixcmd &= 0x8F; + pci_write_config_byte(pdev, 0x6a, pcixcmd); } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; - { - u8 revision; - - /* 1030 Chip Fix. Disable Split transactions - * for PCIX. Set bits 4 - 6 to zero if Rev < C0( = 8) - */ - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - if (revision < 0x08) { - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF8F; - pci_write_config_word(pdev, 0x6a, pcixcmd); - } + /* 1030 Chip Fix. Disable Split transactions + * for PCIX. Set MOST bits to zero if Rev < C0( = 8). + */ + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + if (revision < C0_1030) { + pci_read_config_byte(pdev, 0x6a, &pcixcmd); + pcixcmd &= 0x8F; + pci_write_config_byte(pdev, 0x6a, pcixcmd); } } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { @@ -1515,17 +1526,18 @@ || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X)) mpt_detect_bound_ports(ioc, pdev); - if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { - printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", - ioc->name, r); - } + if ((r = mpt_do_ioc_recovery(ioc, + MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { + printk(KERN_WARNING MYNAM + ": WARNING - %s did not initialize properly! (%d)\n", + ioc->name, r); - if(r != 0 ) { Q_DEL_ITEM(ioc); mpt_adapters[ioc->id] = NULL; free_irq(ioc->pci_irq, ioc); iounmap(mem); kfree(ioc); + pci_set_drvdata(pdev, NULL); return r; } @@ -1565,6 +1577,7 @@ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; + mpt_sync_irq(pdev->irq); /* Clear any lingering interrupt */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -1574,7 +1587,6 @@ Q_DEL_ITEM(ioc); mpt_adapter_dispose(ioc); - mptscsih_sync_irq(pdev->irq); pci_set_drvdata(pdev, NULL); } @@ -1755,20 +1767,23 @@ int r; int ii; int handlers; + int ret = 0; + int reset_alt_ioc_active = 0; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); - /* Disable reply interrupts */ + /* Disable reply interrupts (also blocks FreeQ) */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; - /* NOTE: Access to IOC's request FreeQ is now blocked! */ if (ioc->alt_ioc) { - /* Disable alt-IOC's reply interrupts for a bit ... */ + if (ioc->alt_ioc->active) + reset_alt_ioc_active = 1; + + /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); ioc->alt_ioc->active = 0; - /* NOTE: Access to alt-IOC's request FreeQ is now blocked! */ } hard = 1; @@ -1776,15 +1791,29 @@ hard = 0; if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) { - printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", - ioc->name); + if (hard_reset_done == -4) { + printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n", + ioc->name); + + if (reset_alt_ioc_active && ioc->alt_ioc) { + /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ + dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", + ioc->alt_ioc->name)); + CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); + ioc->alt_ioc->active = 1; + } + + } else { + printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", + ioc->name); + } return -1; } /* hard_reset_done = 0 if a soft reset was performed * and 1 if a hard reset was performed. */ - if (hard_reset_done && ioc->alt_ioc) { + if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) { if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) alt_ioc_ready = 1; else @@ -1793,42 +1822,55 @@ ioc->alt_ioc->name, r); } - /* Get IOC facts! */ + /* Get IOC facts! Allow 1 retry */ if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) - return -2; - if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { + r = GetIocFacts(ioc, sleepFlag, reason); + + if (r) { + ret = -2; + } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); } if (alt_ioc_ready) { - if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) - return -2; - if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { + if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { + /* Retry - alt IOC was initialized once + */ + r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); + } + if (r) { + alt_ioc_ready = 0; + reset_alt_ioc_active = 0; + } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc->alt_ioc); } } - /* - * Prime reply & request queues! + /* Prime reply & request queues! * (mucho alloc's) Must be done prior to * init as upper addresses are needed for init. + * If fails, continue with alt-ioc processing */ - if ((r = PrimeIocFifos(ioc)) != 0) - return -3; + if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0)) + ret = -3; - // May need to check/upload firmware & data here! - if ((r = SendIocInit(ioc, sleepFlag)) != 0) - return -4; + /* May need to check/upload firmware & data here! + * If fails, continue with alt-ioc processing + */ + if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0)) + ret = -4; // NEW! if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) { printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", ioc->alt_ioc->name, r); alt_ioc_ready = 0; + reset_alt_ioc_active = 0; } if (alt_ioc_ready) { if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { alt_ioc_ready = 0; + reset_alt_ioc_active = 0; printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n", ioc->alt_ioc->name, r); @@ -1840,9 +1882,14 @@ ddlprintk((MYIOC_s_INFO_FMT "firmware upload required!\n", ioc->name)); - r = mpt_do_upload(ioc, sleepFlag); - if (r != 0) - printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); + /* Controller is not operational, cannot do upload + */ + if (ret == 0) { + r = mpt_do_upload(ioc, sleepFlag); + if (r != 0) + printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); + } + /* Handle the alt IOC too */ if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){ ddlprintk((MYIOC_s_INFO_FMT @@ -1855,12 +1902,13 @@ } } + if (ret == 0) { + /* Enable! (reply interrupt) */ + CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); + ioc->active = 1; + } - /* Enable! (reply interrupt) */ - CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); - ioc->active = 1; - - if (ioc->alt_ioc) { + if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt) */ dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); @@ -1872,7 +1920,7 @@ * Enable MPT base driver management of EventNotification * and EventAck handling. */ - if (!ioc->facts.EventState) + if ((ret == 0) && (!ioc->facts.EventState)) (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) @@ -1886,7 +1934,7 @@ * routine calls HardResetHandler, which calls into here again, * and we try GetLanConfigPages again... */ - if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { + if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { if ((int)ioc->chip_type <= (int)FC929) { /* * Pre-fetch FC port WWN and stuff... @@ -1928,6 +1976,8 @@ /* Check, and possibly reset, the coalescing value */ mpt_read_ioc_pg_1(ioc); + + mpt_read_ioc_pg_4(ioc); } GetIoUnitPage2(ioc); @@ -1942,24 +1992,24 @@ if (hard_reset_done) { r = handlers = 0; for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if (MptResetHandlers[ii]) { + if ((ret == 0) && MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", ioc->name, ii)); r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); handlers++; + } - if (alt_ioc_ready) { - dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); - handlers++; - } + if (alt_ioc_ready && MptResetHandlers[ii]) { + dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", + ioc->name, ioc->alt_ioc->name, ii)); + r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); + handlers++; } } /* FIXME? Examine results here? */ } - return 0; + return ret; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2114,6 +2164,15 @@ kfree(this->spi_data.pIocPg3); this->spi_data.pIocPg3 = NULL; } + + if (freeup && this->spi_data.pIocPg4 != NULL) { + sz = this->spi_data.IocPg4Sz; + pci_free_consistent(this->pcidev, sz, + this->spi_data.pIocPg4, + this->spi_data.IocPg4_dma); + this->spi_data.pIocPg4 = NULL; + this->alloc_total -= sz; + } } } @@ -2429,7 +2488,7 @@ * 1 byte in size, so we can just fire it off as is. */ r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts, - reply_sz, (u16*)facts, 3 /*seconds*/, sleepFlag); + reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag); if (r != 0) return r; @@ -2510,7 +2569,7 @@ */ ioc->req_sz = MIN(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4); ioc->req_depth = MIN(MPT_MAX_REQ_DEPTH, facts->GlobalCredits); - ioc->reply_sz = ioc->req_sz; + ioc->reply_sz = MPT_REPLY_FRAME_SIZE; ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", @@ -2578,7 +2637,7 @@ * 1 byte in size, so we can just fire it off as is. */ ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts, - reply_sz, (u16*)pfacts, 3 /*seconds*/, sleepFlag); + reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag); if (ii != 0) return ii; @@ -2651,6 +2710,8 @@ /* ioc_init.MsgFlags = 0; */ /* ioc_init.MsgContext = cpu_to_le32(0x00000000); */ ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ + + ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize; if (sizeof(dma_addr_t) == sizeof(u64)) { /* Save the upper 32-bits of the request @@ -2663,6 +2724,9 @@ ioc_init.HostMfaHighAddr = cpu_to_le32(0); ioc_init.SenseBufferHighAddr = cpu_to_le32(0); } + + ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr; + ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr; dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init)); @@ -2773,8 +2837,8 @@ void * mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz) { - fw_image_t **cached_fw = NULL; - u8 *mem = NULL; + fw_image_t **cached_fw; + u8 *mem; dma_addr_t fw_dma; int alloc_total = 0; int bytes_left, bytes, num_frags; @@ -2922,7 +2986,7 @@ u8 reply[sizeof(FWUploadReply_t)]; FWUpload_t *prequest; FWUploadReply_t *preply; - FWUploadTCSGE_t *ptcsge = NULL; + FWUploadTCSGE_t *ptcsge; int sgeoffset; int ii, sz, reply_sz; int cmdStatus, freeMem = 0; @@ -3054,16 +3118,16 @@ static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) { - MpiFwHeader_t *FwHdr = NULL; + MpiFwHeader_t *FwHdr; MpiExtImageHeader_t *ExtHdr; - fw_image_t **pCached = NULL; + fw_image_t **pCached=NULL; int fw_sz; u32 diag0val; #ifdef MPT_DEBUG u32 diag1val = 0; #endif int count = 0; - u32 *ptru32 = NULL; + u32 *ptru32; u32 diagRwData; u32 nextImage; u32 ext_offset; @@ -3097,11 +3161,11 @@ pCached = (fw_image_t **)ioc->cached_fw; else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL)) pCached = (fw_image_t **)ioc->alt_ioc->cached_fw; + else + return -2; ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n", ioc->name, pCached)); - if (!pCached) - return -2; /* Write magic sequence to WriteSequence register * until enter diagnostic mode @@ -3351,6 +3415,7 @@ SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); if (sleepFlag == CAN_SLEEP) { + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); } else { mdelay (1000); @@ -3551,11 +3616,11 @@ } else { /* Wait for FW to reload and for board * to go to the READY state. - * Maximum wait is 30 seconds. + * Maximum wait is 60 seconds. * If fail, no error will check again * with calling program. */ - for (count = 0; count < 30; count ++) { + for (count = 0; count < 60; count ++) { doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); doorbell &= MPI_IOC_STATE_MASK; @@ -3673,7 +3738,7 @@ dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n", ioc->name, reset_type)); CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<reply_frames == NULL) { sz = (ioc->reply_sz * ioc->reply_depth) + 128; +#if defined(MPTBASE_MEM_ALLOC_FIFO_FIX) + mem = pci_alloc_consistent(&ioc->pcidev32, sz, &ioc->reply_alloc_dma); +#else mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->reply_alloc_dma); +#endif if (mem == NULL) goto out_fail; @@ -3778,7 +3847,11 @@ */ sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; +#if defined(MPTBASE_MEM_ALLOC_FIFO_FIX) + mem = pci_alloc_consistent(&ioc->pcidev32, sz, &ioc->req_alloc_dma); +#else mem = pci_alloc_consistent(ioc->pcidev, sz, &ioc->req_alloc_dma); +#endif if (mem == NULL) goto out_fail; @@ -3894,8 +3967,8 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mpt_handshake_req_reply_wait - Send MPT request to and receive reply from - * IOC via doorbell handshake method. + * mpt_handshake_req_reply_wait - Send MPT request to and receive reply + * from IOC via doorbell handshake method. * @ioc: Pointer to MPT_ADAPTER structure * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame @@ -3955,7 +4028,7 @@ * our handshake request. */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - if (!failcnt && (t = WaitForDoorbellAck(ioc, 2, sleepFlag)) < 0) + if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) failcnt++; if (!failcnt) { @@ -3973,7 +4046,7 @@ (req_as_bytes[(ii*4) + 3] << 24)); CHIPREG_WRITE32(&ioc->chip->Doorbell, word); - if ((t = WaitForDoorbellAck(ioc, 2, sleepFlag)) < 0) + if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) failcnt++; } @@ -4137,7 +4210,7 @@ } else { hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0) + if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) failcnt++; else { hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); @@ -4154,7 +4227,7 @@ * reply 16 bits at a time. */ for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) { - if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0) + if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) failcnt++; hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); /* don't overflow our IOC hs_reply[] buffer! */ @@ -4163,7 +4236,7 @@ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); } - if (!failcnt && (t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0) + if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) failcnt++; CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -4466,7 +4539,7 @@ static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) { - u8 *pbuf = NULL; + u8 *pbuf; dma_addr_t buf_dma; CONFIGPARMS cfg; ConfigPageHeader_t header; @@ -4528,6 +4601,9 @@ pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities); pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface); + if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) + ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; + ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK; if (data) { @@ -4552,7 +4628,6 @@ } if (pbuf) { pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma); - pbuf = NULL; } } } @@ -4589,6 +4664,8 @@ /* Save the Port Page 2 data * (reformat into a 32bit quantity) */ + data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK; + ioc->spi_data.PortFlags = data; for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { pdevice = &pPP2->DeviceSettings[ii]; data = (le16_to_cpu(pdevice->DeviceFlags) << 16) | @@ -4598,7 +4675,6 @@ } pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma); - pbuf = NULL; } } @@ -4671,11 +4747,12 @@ * -EFAULT if read of config page header fails or data pointer not NULL * -ENOMEM if pci_alloc failed */ -static int +int mpt_findImVolumes(MPT_ADAPTER *ioc) { - IOCPage2_t *pIoc2 = NULL; - ConfigPageIoc2RaidVol_t *pIocRv = NULL; + IOCPage2_t *pIoc2; + u8 *mem; + ConfigPageIoc2RaidVol_t *pIocRv; dma_addr_t ioc2_dma; CONFIGPARMS cfg; ConfigPageHeader_t header; @@ -4685,9 +4762,6 @@ u8 nVols, nPhys; u8 vid, vbus, vioc; - if (ioc->spi_data.pIocPg3) - return -EFAULT; - /* Read IOCP2 header then the page. */ header.PageVersion = 0; @@ -4716,11 +4790,22 @@ if (mpt_config(ioc, &cfg) != 0) goto done_and_free; + if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) { + mem = kmalloc(iocpage2sz, GFP_ATOMIC); + if (mem) { + ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem; + } else { + goto done_and_free; + } + } + memcpy(mem, (u8 *)pIoc2, iocpage2sz); + /* Identify RAID Volume Id's */ nVols = pIoc2->NumActiveVolumes; if ( nVols == 0) { - /* No RAID Volumes. Done. + /* No RAID Volume. */ + goto done_and_free; } else { /* At least 1 RAID Volume */ @@ -4745,17 +4830,14 @@ /* Identify Hidden Physical Disk Id's */ nPhys = pIoc2->NumActivePhysDisks; if (nPhys == 0) { - /* No physical disks. Done. + /* No physical disks. */ } else { mpt_read_ioc_pg_3(ioc); } done_and_free: - if (pIoc2) { - pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); - pIoc2 = NULL; - } + pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); return rc; } @@ -4763,7 +4845,7 @@ int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) { - IOCPage3_t *pIoc3 = NULL; + IOCPage3_t *pIoc3; u8 *mem; CONFIGPARMS cfg; ConfigPageHeader_t header; @@ -4816,18 +4898,66 @@ } } - if (pIoc3) { - pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma); - pIoc3 = NULL; - } + pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma); return 0; } static void +mpt_read_ioc_pg_4(MPT_ADAPTER *ioc) +{ + IOCPage4_t *pIoc4; + CONFIGPARMS cfg; + ConfigPageHeader_t header; + dma_addr_t ioc4_dma; + int iocpage4sz; + + /* Read and save IOC Page 4 + */ + header.PageVersion = 0; + header.PageLength = 0; + header.PageNumber = 4; + header.PageType = MPI_CONFIG_PAGETYPE_IOC; + cfg.hdr = &header; + cfg.physAddr = -1; + cfg.pageAddr = 0; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.timeout = 0; + if (mpt_config(ioc, &cfg) != 0) + return; + + if (header.PageLength == 0) + return; + + if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) { + iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */ + pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma); + if (!pIoc4) + return; + } else { + ioc4_dma = ioc->spi_data.IocPg4_dma; + iocpage4sz = ioc->spi_data.IocPg4Sz; + } + + /* Read the Page into dma memory. + */ + cfg.physAddr = ioc4_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + if (mpt_config(ioc, &cfg) == 0) { + ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4; + ioc->spi_data.IocPg4_dma = ioc4_dma; + ioc->spi_data.IocPg4Sz = iocpage4sz; + } else { + pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma); + ioc->spi_data.pIocPg4 = NULL; + } +} + +static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) { - IOCPage1_t *pIoc1 = NULL; + IOCPage1_t *pIoc1; CONFIGPARMS cfg; ConfigPageHeader_t header; dma_addr_t ioc1_dma; @@ -4903,10 +5033,7 @@ } } - if (pIoc1) { - pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma); - pIoc1 = NULL; - } + pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma); return; } @@ -5022,9 +5149,8 @@ pReq->Reserved = 0; pReq->ChainOffset = 0; pReq->Function = MPI_FUNCTION_CONFIG; - pReq->Reserved1[0] = 0; - pReq->Reserved1[1] = 0; - pReq->Reserved1[2] = 0; + pReq->ExtPageLength = 0; + pReq->ExtPageType = 0; pReq->MsgFlags = 0; for (ii=0; ii < 8; ii++) pReq->Reserved2[ii] = 0; @@ -5083,6 +5209,112 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_toolbox - Generic function to issue toolbox message + * @ioc - Pointer to an adapter structure + * @cfg - Pointer to a toolbox structure. Struct contains + * action, page address, direction, physical address + * and pointer to a configuration page header + * Page header is updated. + * + * Returns 0 for success + * -EPERM if not allowed due to ISR context + * -EAGAIN if no msg frames currently available + * -EFAULT for non-successful reply or no reply (timeout) + */ +int +mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) +{ + ToolboxIstwiReadWriteRequest_t *pReq; + MPT_FRAME_HDR *mf; + unsigned long flags; + int rc; + int flagsLength; + int in_isr; + + /* (Bugzilla:fibrebugs, #513) + * Bug fix (part 1)! 20010905 -sralston + * Prevent calling wait_event() (below), if caller happens + * to be in ISR context, because that is fatal! + */ + in_isr = in_interrupt(); + if (in_isr) { + dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n", + ioc->name)); + return -EPERM; + } + + /* Get and Populate a free Frame + */ + if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) { + dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n", + ioc->name)); + return -EAGAIN; + } + pReq = (ToolboxIstwiReadWriteRequest_t *)mf; + pReq->Tool = pCfg->action; + pReq->Reserved = 0; + pReq->ChainOffset = 0; + pReq->Function = MPI_FUNCTION_TOOLBOX; + pReq->Reserved1 = 0; + pReq->Reserved2 = 0; + pReq->MsgFlags = 0; + pReq->Flags = pCfg->dir; + pReq->BusNum = 0; + pReq->Reserved3 = 0; + pReq->NumAddressBytes = 0x01; + pReq->Reserved4 = 0; + pReq->DataLength = 0x04; + pReq->DeviceAddr = 0xB0; + pReq->Addr1 = 0; + pReq->Addr2 = 0; + pReq->Addr3 = 0; + pReq->Reserved5 = 0; + + /* Add a SGE to the config request. + */ + + flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4; + + mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr); + + dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n", + ioc->name, pReq->Tool)); + + /* Append pCfg pointer to end of mf + */ + *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg; + + /* Initalize the timer + */ + init_timer(&pCfg->timer); + pCfg->timer.data = (unsigned long) ioc; + pCfg->timer.function = mpt_timer_expired; + pCfg->wait_done = 0; + + /* Set the timer; ensure 10 second minimum */ + if (pCfg->timeout < 10) + pCfg->timer.expires = jiffies + HZ*10; + else + pCfg->timer.expires = jiffies + HZ*pCfg->timeout; + + /* Add to end of Q, set timer and then issue this command */ + spin_lock_irqsave(&ioc->FreeQlock, flags); + Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + + add_timer(&pCfg->timer); + mpt_put_msg_frame(mpt_base_index, ioc->id, mf); + wait_event(mpt_waitq, pCfg->wait_done); + + /* mf has been freed - do not access */ + + rc = pCfg->status; + + return rc; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_timer_expired - Call back for timer process. * Used only internal config functionality. @@ -5124,9 +5356,12 @@ dprintk((KERN_WARNING MYNAM ": IOC %s_reset routed to MPT base driver!\n", - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")); + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); - if (reset_phase == MPT_IOC_PRE_RESET) { + if (reset_phase == MPT_IOC_SETUP_RESET) { + ; + } else if (reset_phase == MPT_IOC_PRE_RESET) { /* If the internal config Q is not empty - * delete timer. MF resources will be freed when * the FIFO's are primed. @@ -5590,7 +5825,7 @@ int rc; unsigned long flags; - dprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name)); + dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name)); #ifdef MFCNT printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name); printk("MF count 0x%x !\n", ioc->mfcnt); @@ -5611,6 +5846,29 @@ /* FIXME: If do_ioc_recovery fails, repeat.... */ + /* The SCSI driver needs to adjust timeouts on all current + * commands prior to the diagnostic reset being issued. + * Prevents timeouts occuring during a diagnostic reset...very bad. + * For all other protocol drivers, this is a no-op. + */ + { + int ii; + int r = 0; + + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + if (MptResetHandlers[ii]) { + dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n", + ioc->name, ii)); + r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET); + if (ioc->alt_ioc) { + dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n", + ioc->name, ioc->alt_ioc->name, ii)); + r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET); + } + } + } + } + if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) { printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n", rc, ioc->name); @@ -5625,7 +5883,7 @@ ioc->alt_ioc->diagPending = 0; spin_unlock_irqrestore(&ioc->diagLock, flags); - dprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); + dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); return rc; } @@ -5634,7 +5892,7 @@ static char * EventDescriptionStr(u8 event, u32 evData0) { - char *ds = NULL; + char *ds; switch(event) { case MPI_EVENT_NONE: @@ -5839,109 +6097,11 @@ "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer", "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info" }; - char *desc = "unknown"; u8 subcl = (log_info >> 24) & 0x7; - u32 SubCl = log_info & 0x27000000; - - switch(log_info) { -/* FCP Initiator */ - case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME: - desc = "Received an out of order frame - unsupported"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME: - desc = "Bad start of frame primative"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME: - desc = "Bad end of frame primative"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN: - desc = "Receiver hardware detected overrun"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER: - desc = "Other errors caught by IOC which require retries"; - break; - case MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD: - desc = "Main processor could not initialize sub-processor"; - break; -/* FC Target */ - case MPI_IOCLOGINFO_FC_TARGET_NO_PDISC: - desc = "Not sent because we are waiting for a PDISC from the initiator"; - break; - case MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN: - desc = "Not sent because we are not logged in to the remote node"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP: - desc = "Data Out, Auto Response, not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP: - desc = "Data In, Auto Response, not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA: - desc = "Data In, Auto Response, missing data frames"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP: - desc = "Data Out, No Response, not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP: - desc = "Auto-response after a write not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP: - desc = "Data In, No Response, not completed due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA: - desc = "Data In, No Response, missing data frames"; - break; - case MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP: - desc = "Manual Response not sent due to a LIP"; - break; - case MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3: - desc = "Not sent because remote node does not support Class 3"; - break; - case MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID: - desc = "Not sent because login to remote node not validated"; - break; - case MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND: - desc = "Cleared from the outbound queue after a logout"; - break; - case MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN: - desc = "Cleared waiting for data after a logout"; - break; -/* LAN */ - case MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING: - desc = "Transaction Context Sgl Missing"; - break; - case MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE: - desc = "Transaction Context found before an EOB"; - break; - case MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET: - desc = "Transaction Context value has reserved bits set"; - break; - case MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG: - desc = "Invalid SGL Flags"; - break; -/* FC Link */ - case MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT: - desc = "Loop initialization timed out"; - break; - case MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED: - desc = "Another system controller already initialized the loop"; - break; - case MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED: - desc = "Not synchronized to signal or still negotiating (possible cable problem)"; - break; - case MPI_IOCLOGINFO_FC_LINK_CRC_ERROR: - desc = "CRC check detected error on received frame"; - break; - } +// u32 SubCl = log_info & 0x27000000; printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}", ioc->name, log_info, subcl_str[subcl]); - if (SubCl == MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET) - printk(", byte_offset=%d\n", log_info & MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET); - else if (SubCl == MPI_IOCLOGINFO_FC_STATE_CHANGE) - printk("\n"); /* StateChg in LogInfo & 0x00FFFFFF, above */ - else - printk("\n" KERN_INFO " %s\n", desc); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -6021,7 +6181,6 @@ isense_idx = last_drv_idx; r = 1; } - mpt_inc_use_count(); return r; } @@ -6040,7 +6199,6 @@ mpt_ScsiOpcodesPtr = NULL; printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n"); isense_idx = -1; - mpt_dec_use_count(); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -6072,6 +6230,8 @@ EXPORT_SYMBOL(mpt_stm_index); EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_config); +EXPORT_SYMBOL(mpt_toolbox); +EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h --- a/drivers/message/fusion/mptbase.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/mptbase.h Wed Mar 10 21:09:42 2004 @@ -8,7 +8,7 @@ * Credits: * (see mptbase.c) * - * Copyright (c) 1999-2003 LSI Logic Corporation + * Copyright (c) 1999-2004 LSI Logic Corporation * Originally By: Steven J. Ralston * (mailto:sjralston1@netscape.net) * (mailto:mpt_linux_developer@lsil.com) @@ -68,6 +68,7 @@ #include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ #include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ +#include "lsi/mpi_tool.h" /* Tools support */ #include "lsi/fc_log.h" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -77,11 +78,11 @@ #endif #ifndef COPYRIGHT -#define COPYRIGHT "Copyright (c) 1999-2003 " MODULEAUTHOR +#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.00.03" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.00.03" +#define MPT_LINUX_VERSION_COMMON "3.01.00" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.00" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -93,10 +94,10 @@ */ #define MPT_MAX_ADAPTERS 18 #define MPT_MAX_PROTOCOL_DRIVERS 16 -#define MPT_MAX_BUS 1 +#define MPT_MAX_BUS 1 /* Do not change */ #define MPT_MAX_FC_DEVICES 255 #define MPT_MAX_SCSI_DEVICES 16 -#define MPT_LAST_LUN 31 +#define MPT_LAST_LUN 255 #define MPT_SENSE_BUFFER_ALLOC 64 /* allow for 256 max sense alloc, but only 255 max request */ #if MPT_SENSE_BUFFER_ALLOC >= 256 @@ -127,6 +128,8 @@ #define MPT_MAX_FRAME_SIZE 128 #define MPT_DEFAULT_FRAME_SIZE 128 +#define MPT_REPLY_FRAME_SIZE 0x40 /* Must be a multiple of 8 */ + #define MPT_SG_REQ_128_SCALE 1 #define MPT_SG_REQ_96_SCALE 2 #define MPT_SG_REQ_64_SCALE 4 @@ -150,6 +153,9 @@ #define MPT_NARROW 0 #define MPT_WIDE 1 +#define C0_1030 0x08 +#define XL_929 0x01 + #ifdef __KERNEL__ /* { */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -185,8 +191,8 @@ void (*remove) (struct pci_dev *dev); void (*shutdown) (struct device * dev); #ifdef CONFIG_PM - int (*suspend) (struct pci_dev *dev, u32 state); int (*resume) (struct pci_dev *dev); + int (*suspend) (struct pci_dev *dev, u32 state); #endif }; @@ -201,9 +207,6 @@ u32 arg1; u32 pad; void *argp1; -#ifndef MPT_SCSI_USE_NEW_EH - void *argp2; -#endif } linkage; /* * NOTE: When request frames are free, on the linkage structure @@ -255,6 +258,7 @@ MPIHeader_t hdr; SCSIIORequest_t scsireq; SCSIIOReply_t sreply; + ConfigReply_t configreply; MPIDefaultReply_t reply; MPT_FRAME_TRACKER frame; } u; @@ -408,12 +412,9 @@ ScsiCmndTracker SentQ; ScsiCmndTracker DoneQ; u32 num_luns; -//--- LUN split here? - u32 luns; /* Max LUNs is 32 */ - u8 inq_data[SCSI_STD_INQUIRY_BYTES]; /* 36 */ - u8 pad0[4]; - u8 inq00_data[20]; - u8 pad1[4]; + u32 luns[8]; /* Max LUNs is 256 */ + u8 pad[4]; + u8 inq_data[8]; /* IEEE Registered Extended Identifier obtained via INQUIRY VPD page 0x83 */ /* NOTE: Do not separate uniq_prepad and uniq_data @@ -421,26 +422,17 @@ u8 uniq_prepad[8]; u8 uniq_data[20]; u8 pad2[4]; - u8 inqC3_data[12]; - u8 pad3[4]; - u8 inqC9_data[12]; - u8 pad4[4]; - u8 dev_vol_name[64]; } VirtDevice; /* * Fibre Channel (SCSI) target device and associated defines... */ -#define MPT_TARGET_DEFAULT_DV_STATUS 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,55) -#define MPT_TARGET_FLAGS_CONFIGURED 0x02 -#define MPT_TARGET_FLAGS_Q_YES 0x08 -#else +#define MPT_TARGET_DEFAULT_DV_STATUS 0x00 #define MPT_TARGET_FLAGS_VALID_NEGO 0x01 #define MPT_TARGET_FLAGS_VALID_INQUIRY 0x02 #define MPT_TARGET_FLAGS_Q_YES 0x08 #define MPT_TARGET_FLAGS_VALID_56 0x10 -#endif +#define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 #define MPT_TARGET_NO_NEGO_WIDE 0x01 #define MPT_TARGET_NO_NEGO_SYNC 0x02 @@ -539,8 +531,13 @@ /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ typedef struct _ScsiCfgData { + u32 PortFlags; int *nvram; /* table of device NVRAM values */ + IOCPage2_t *pIocPg2; /* table of Raid Volumes */ IOCPage3_t *pIocPg3; /* table of physical disks */ + IOCPage4_t *pIocPg4; /* SEP devices addressing */ + dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ + int IocPg4Sz; /* IOCPage4 size */ u8 dvStatus[MPT_MAX_SCSI_DEVICES]; int isRaid; /* bit field, 1 if RAID */ u8 minSyncFactor; /* 0xFF if async */ @@ -554,7 +551,8 @@ u8 dvScheduled; /* 1 if scheduled */ u8 forceDv; /* 1 to force DV scheduling */ u8 noQas; /* Disable QAS for this adapter */ - u8 rsvd[2]; + u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */ + u8 rsvd[1]; } ScsiCfgData; typedef struct _fw_image { @@ -610,6 +608,9 @@ u32 sense_buf_low_dma; int mtrr_reg; struct pci_dev *pcidev; /* struct pci_dev pointer */ +#if defined(MPTBASE_MEM_ALLOC_FIFO_FIX) + struct pci_dev pcidev32; /* struct pci_dev pointer */ +#endif u8 *memmap; /* mmap address */ struct Scsi_Host *sh; /* Scsi Host pointer */ ScsiCfgData spi_data; /* Scsi config. data */ @@ -622,6 +623,12 @@ int eventTypes; /* Event logging parameters */ int eventContext; /* Next event context */ int eventLogSize; /* Max number of cached events */ +#ifdef MPTSCSIH_DBG_TIMEOUT + int timeout_hard; + int timeout_delta; + int timeout_cnt; + int timeout_maxcnt; +#endif struct _mpt_ioctl_events *events; /* pointer to event log */ fw_image_t **cached_fw; /* Pointer to FW SG List */ Q_TRACKER configQ; /* linked list of config. requests */ @@ -665,6 +672,7 @@ /* reset_phase defs */ #define MPT_IOC_PRE_RESET 0 #define MPT_IOC_POST_RESET 1 +#define MPT_IOC_SETUP_RESET 2 /* * Invent MPT host event (super-set of MPI Events) @@ -880,14 +888,12 @@ #define MPT_NVRAM_WIDE_DISABLE (0x00100000) #define MPT_NVRAM_BOOT_CHOICE (0x00200000) -#ifdef MPT_SCSI_USE_NEW_EH /* The TM_STATE variable is used to provide strict single threading of TM * requests as well as communicate TM error conditions. */ #define TM_STATE_NONE (0) #define TM_STATE_IN_PROGRESS (1) #define TM_STATE_ERROR (2) -#endif typedef struct _MPT_SCSI_HOST { MPT_ADAPTER *ioc; @@ -928,12 +934,8 @@ u8 is_spi; /* Parallel SCSI i/f */ u8 negoNvram; /* DV disabled, nego NVRAM */ u8 is_multipath; /* Multi-path compatible */ -#ifdef MPT_SCSI_USE_NEW_EH u8 tmState; u8 rsvd[1]; -#else - u8 rsvd[2]; -#endif MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/ MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ struct scsi_cmnd *abortSCpnt; @@ -1033,8 +1035,10 @@ extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); +extern int mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); extern void *mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img); +extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); /* diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c --- a/drivers/message/fusion/mptctl.c Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/mptctl.c Wed Mar 10 21:09:42 2004 @@ -29,7 +29,7 @@ * * (see also mptbase.c) * - * Copyright (c) 1999-2003 LSI Logic Corporation + * Copyright (c) 1999-2004 LSI Logic Corporation * Originally By: Steven J. Ralston, Noah Romer * (mailto:sjralston1@netscape.net) * (mailto:mpt_linux_developer@lsil.com) @@ -82,6 +82,7 @@ #include #include #include +#include #include #include @@ -91,7 +92,7 @@ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" -#define COPYRIGHT "Copyright (c) 1999-2003 LSI Logic Corporation" +#define COPYRIGHT "Copyright (c) 1999-2004 LSI Logic Corporation" #define MODULEAUTHOR "Steven J. Ralston, Noah Romer, Pamela Delaney" #include "mptbase.h" #include "mptctl.h" @@ -260,6 +261,7 @@ iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK; if (iocStatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED) { if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) { + ioc->ioctl->reset &= ~MPTCTL_RESET_OK; del_timer (&ioc->ioctl->timer); ioc->ioctl->timer.expires = jiffies + HZ; add_timer(&ioc->ioctl->timer); @@ -456,7 +458,7 @@ unsigned long flags; spin_lock_irqsave(&hd->ioc->FreeQlock, flags); -#ifdef MPT_SCSI_USE_NEW_EH + if (hd->tmState == TM_STATE_NONE) { hd->tmState = TM_STATE_IN_PROGRESS; hd->tmPending = 1; @@ -465,15 +467,7 @@ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); return -EBUSY; } -#else - if (hd->tmPending) { - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - return -EBUSY; - } else { - hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - } -#endif + return 0; } @@ -488,14 +482,10 @@ return; spin_lock_irqsave(&ioc->FreeQlock, flags); -#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_ERROR; hd->tmPending = 0; spin_unlock_irqrestore(&ioc->FreeQlock, flags); -#else - hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); -#endif return; } @@ -513,9 +503,12 @@ { MPT_IOCTL *ioctl = ioc->ioctl; dctlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to IOCTL driver!\n", - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")); + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); - if (reset_phase == MPT_IOC_PRE_RESET){ + if (reset_phase == MPT_IOC_SETUP_RESET){ + ; + } else if (reset_phase == MPT_IOC_PRE_RESET){ /* Someone has called the reset handler to * do a hard reset. No more replies from the FW. @@ -532,13 +525,15 @@ } } else { + ioctl->tmPtr = NULL; + /* Set the status and continue IOCTL * processing. All memory will be free'd * by originating thread after wake_up is * called. */ if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){ - ioctl->status = MPT_IOCTL_STATUS_DID_IOCRESET; + ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET; /* Wake up the calling process */ @@ -620,7 +615,11 @@ return -ENODEV; } - + if (!iocp->active) { + printk(KERN_ERR "%s::mptctl_ioctl() @%d - Controller disabled.\n", + __FILE__, __LINE__); + return -EFAULT; + } /* Handle those commands that are just returning * information stored in the driver. @@ -691,7 +690,7 @@ return -ENODEV; /* (-6) No such device or address */ } - if (mpt_HardResetHandler(iocp, NO_SLEEP) != 0) { + if (mpt_HardResetHandler(iocp, CAN_SLEEP) != 0) { printk (KERN_ERR "%s@%d::mptctl_do_reset - reset failed.\n", __FILE__, __LINE__); return -1; @@ -1254,10 +1253,10 @@ /* Fill in the data and return the structure to the calling * program */ - if (ioc->chip_type == C1030) - karg.adapterType = MPT_IOCTL_INTERFACE_SCSI; - else + if ((int)ioc->chip_type <= (int) FC929) karg.adapterType = MPT_IOCTL_INTERFACE_FC; + else + karg.adapterType = MPT_IOCTL_INTERFACE_SCSI; port = karg.hdr.port; @@ -1307,7 +1306,8 @@ /* Set the Version Strings. */ - strlcpy (karg.driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH); + strncpy (karg.driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH); + karg.driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0'; karg.busChangeEvent = 0; karg.hostId = ioc->pfacts[port].PortSCSIID; @@ -1343,15 +1343,18 @@ MPT_ADAPTER *ioc; struct Scsi_Host *sh; MPT_SCSI_HOST *hd; + VirtDevice *vdev; char *pmem; int *pdata; + IOCPage2_t *pIoc2; int iocnum; int numDevices = 0; unsigned int max_id; - int ii, jj, lun; + int id, jj, indexed_lun, lun_index; + u32 lun; int maxWordsLeft; int numBytes; - u8 port; + u8 port, devType, bus_id; dctlprintk(("mptctl_gettargetinfo called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { @@ -1418,27 +1421,59 @@ * sh->max_id = maximum target ID + 1 */ if (hd && hd->Targets) { - ii = 0; - while (ii <= max_id) { - if (hd->Targets[ii]) { - for (jj = 0; jj <= MPT_LAST_LUN; jj++) { - lun = (1 << jj); - if (hd->Targets[ii]->luns & lun) { - numDevices++; - *pdata = (jj << 16) | ii; - --maxWordsLeft; - - pdata++; - - if (maxWordsLeft <= 0) - break; + mpt_findImVolumes(ioc); + pIoc2 = ioc->spi_data.pIocPg2; + for ( id = 0; id <= max_id; id++ ) { + if ( pIoc2 && pIoc2->NumActiveVolumes && + ( id == pIoc2->RaidVolume[0].VolumeID ) ) { + if (maxWordsLeft <= 0) { + printk(KERN_ERR "mptctl_gettargetinfo - " + "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices); + goto data_space_full; + } + if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 ) + devType = 0x80; + else + devType = 0xC0; + bus_id = pIoc2->RaidVolume[0].VolumeBus; + numDevices++; + *pdata = ( (devType << 24) | (bus_id << 8) | id ); + dctlprintk((KERN_ERR "mptctl_gettargetinfo - " + "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); + pdata++; + --maxWordsLeft; + } else { + vdev = hd->Targets[id]; + if (vdev) { + for (jj = 0; jj <= MPT_LAST_LUN; jj++) { + lun_index = (jj >> 5); + indexed_lun = (jj % 32); + lun = (1 << indexed_lun); + if (vdev->luns[lun_index] & lun) { + if (maxWordsLeft <= 0) { + printk(KERN_ERR + "mptctl_gettargetinfo - " + "buffer is full but more targets are available on ioc %d numDevices=%d\n", + iocnum, numDevices); + goto data_space_full; + } + bus_id = vdev->bus_id; + numDevices++; + *pdata = ( (jj << 16) | (bus_id << 8) | id ); + dctlprintk((KERN_ERR + "mptctl_gettargetinfo - " + "target ioc=%d target=%x numDevices=%d pdata=%p\n", + iocnum, *pdata, numDevices, pdata)); + pdata++; + --maxWordsLeft; + } } } } - ii++; } } } +data_space_full: karg.numDevices = numDevices; /* Copy part of the data from kernel memory to user memory @@ -1507,8 +1542,10 @@ #else karg.chip_type = ioc->chip_type; #endif - strlcpy (karg.name, ioc->name, MPT_MAX_NAME); - strlcpy (karg.product, ioc->prod_name, MPT_PRODUCT_LENGTH); + strncpy (karg.name, ioc->name, MPT_MAX_NAME); + karg.name[MPT_MAX_NAME-1]='\0'; + strncpy (karg.product, ioc->prod_name, MPT_PRODUCT_LENGTH); + karg.product[MPT_PRODUCT_LENGTH-1]='\0'; /* Copy the data from kernel memory to user memory */ @@ -1806,22 +1843,20 @@ MPT_FRAME_HDR *mf = NULL; MPIHeader_t *hdr; char *psge; - MptSge_t *this_sge = NULL; - MptSge_t *sglbuf = NULL; struct buflist bufIn; /* data In buffer */ struct buflist bufOut; /* data Out buffer */ - dma_addr_t sglbuf_dma; - dma_addr_t dma_addr; + dma_addr_t dma_addr_in; + dma_addr_t dma_addr_out; int dir; /* PCI data direction */ int sgSize = 0; /* Num SG elements */ - int this_alloc; - int iocnum, flagsLength; - int sz, rc = 0; - int msgContext; + int iocnum, flagsLength; + int sz, rc = 0; + int msgContext; int tm_flags_set = 0; u16 req_idx; dctlprintk(("mptctl_do_mpt_command called.\n")); + bufIn.kptr = bufOut.kptr = NULL; if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { @@ -1848,7 +1883,7 @@ if (karg.dataOutSize > 0) sz += sizeof(dma_addr_t) + sizeof(u32); - if ( sz > ioc->req_sz) { + if (sz > ioc->req_sz) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Request frame too large (%d) maximum (%d)\n", __FILE__, __LINE__, sz, ioc->req_sz); @@ -1891,6 +1926,9 @@ switch (hdr->Function) { case MPI_FUNCTION_IOC_FACTS: case MPI_FUNCTION_PORT_FACTS: + karg.dataOutSize = karg.dataInSize = 0; + break; + case MPI_FUNCTION_CONFIG: case MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND: case MPI_FUNCTION_FC_EX_LINK_SRVC_SEND: @@ -1928,12 +1966,14 @@ */ if (karg.maxSenseBytes > MPT_SENSE_BUFFER_SIZE) pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; + else + pScsiReq->SenseBufferLength = karg.maxSenseBytes; pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + (req_idx * MPT_SENSE_BUFFER_ALLOC)); - if ( (hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) { + if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) { if (hd->Targets) pTarget = hd->Targets[target]; } @@ -1944,11 +1984,10 @@ /* Have the IOCTL driver set the direction based * on the dataOutSize (ordering issue with Sparc). */ - if (karg.dataOutSize > 0 ) { + if (karg.dataOutSize > 0) { scsidir = MPI_SCSIIO_CONTROL_WRITE; dataSize = karg.dataOutSize; - } - else { + } else { scsidir = MPI_SCSIIO_CONTROL_READ; dataSize = karg.dataInSize; } @@ -1990,6 +2029,8 @@ */ if (karg.maxSenseBytes > MPT_SENSE_BUFFER_SIZE) pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; + else + pScsiReq->SenseBufferLength = karg.maxSenseBytes; pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma @@ -2001,11 +2042,10 @@ /* Have the IOCTL driver set the direction based * on the dataOutSize (ordering issue with Sparc). */ - if (karg.dataOutSize > 0 ) { + if (karg.dataOutSize > 0) { scsidir = MPI_SCSIIO_CONTROL_WRITE; dataSize = karg.dataOutSize; - } - else { + } else { scsidir = MPI_SCSIIO_CONTROL_READ; dataSize = karg.dataInSize; } @@ -2033,7 +2073,7 @@ __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; - } else if (mptctl_set_tm_flags(hd) != 0) { + } else if (mptctl_set_tm_flags(hd) != 0) { rc = -EPERM; goto done_free_mem; } @@ -2107,7 +2147,7 @@ * preceede the data in (read) SGE. psgList is used to free the * allocated memory. */ - psge = (char *) ( ((int *) mf) + karg.dataSgeOffset); + psge = (char *) (((int *) mf) + karg.dataSgeOffset); flagsLength = 0; /* bufIn and bufOut are used for user to kernel space transfers @@ -2115,30 +2155,18 @@ bufIn.kptr = bufOut.kptr = NULL; bufIn.len = bufOut.len = 0; - if (karg.dataOutSize > 0 ) + if (karg.dataOutSize > 0) sgSize ++; - if (karg.dataInSize > 0 ) + if (karg.dataInSize > 0) sgSize ++; if (sgSize > 0) { - /* Allocate memory for the SGL. - * Used to free kernel memory once - * the MF is freed. - */ - sglbuf = pci_alloc_consistent (ioc->pcidev, - sgSize*sizeof(MptSge_t), &sglbuf_dma); - if (sglbuf == NULL) { - rc = -ENOMEM; - goto done_free_mem; - } - this_sge = sglbuf; - /* Set up the dataOut memory allocation */ if (karg.dataOutSize > 0) { dir = PCI_DMA_TODEVICE; - if (karg.dataInSize > 0 ) { + if (karg.dataInSize > 0) { flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_DIRECTION | mpt_addr_size() ) @@ -2147,22 +2175,25 @@ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; } flagsLength |= karg.dataOutSize; - - this_alloc = karg.dataOutSize; - bufOut.len = this_alloc; + bufOut.len = karg.dataOutSize; bufOut.kptr = pci_alloc_consistent( - ioc->pcidev, this_alloc, &dma_addr); + ioc->pcidev, bufOut.len, &dma_addr_out); if (bufOut.kptr == NULL) { rc = -ENOMEM; goto done_free_mem; } else { + /* Set up this SGE. + * Copy to MF and to sglbuf + */ + mpt_add_sge(psge, flagsLength, dma_addr_out); + psge += (sizeof(u32) + sizeof(dma_addr_t)); + /* Copy user data to kernel space. */ if (copy_from_user(bufOut.kptr, karg.dataOutBufPtr, bufOut.len)) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - Unable " "to read user data " @@ -2171,16 +2202,6 @@ rc = -EFAULT; goto done_free_mem; } - - /* Set up this SGE. - * Copy to MF and to sglbuf - */ - mpt_add_sge(psge, flagsLength, dma_addr); - psge += (sizeof(u32) + sizeof(dma_addr_t)); - - this_sge->FlagsLength = flagsLength; - this_sge->Address = dma_addr; - this_sge++; } } @@ -2189,10 +2210,10 @@ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; flagsLength |= karg.dataInSize; - this_alloc = karg.dataInSize; - bufIn.len = this_alloc; + bufIn.len = karg.dataInSize; bufIn.kptr = pci_alloc_consistent(ioc->pcidev, - this_alloc, &dma_addr); + bufIn.len, &dma_addr_in); + if (bufIn.kptr == NULL) { rc = -ENOMEM; goto done_free_mem; @@ -2200,11 +2221,7 @@ /* Set up this SGE * Copy to MF and to sglbuf */ - mpt_add_sge(psge, flagsLength, dma_addr); - - this_sge->FlagsLength = flagsLength; - this_sge->Address = dma_addr; - this_sge++; + mpt_add_sge(psge, flagsLength, dma_addr_in); } } } else { @@ -2228,7 +2245,7 @@ if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { rc = mpt_send_handshake_request(mptctl_id, ioc->id, - sizeof(SCSITaskMgmt_t), (u32*)mf, NO_SLEEP); + sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP); if (rc == 0) { wait_event(mptctl_wait, ioc->ioctl->wait_done); } else { @@ -2236,45 +2253,41 @@ tm_flags_set= 0; del_timer(&ioc->ioctl->timer); ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE; - ioc->ioctl->status = MPT_IOCTL_STATUS_TM_FAILED; + ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED; + mpt_free_msg_frame(mptctl_id, ioc->id, mf); } } else { mpt_put_msg_frame(mptctl_id, ioc->id, mf); wait_event(mptctl_wait, ioc->ioctl->wait_done); } - /* The command is complete. * Return data to the user. + mf = NULL; + + /* MF Cleanup: + * If command failed and failure triggered a diagnostic reset + * OR a diagnostic reset happens during command processing, + * no data, messaging queues are reset (mf cannot be accessed), + * and status is DID_IOCRESET * - * If command completed, mf has been freed so cannot - * use this memory. + * If a user-requested bus reset fails to be handshaked, then + * mf is returned to free queue and status is TM_FAILED. * - * If timeout, a recovery mechanism has been called. - * Need to free the mf. + * Otherise, the command completed and the mf was freed + # by ISR (mf cannot be touched). */ if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { - - /* A timeout - there is no data to return to the - * the user other than an error. - * The timer callback deleted the + /* The timer callback deleted the * timer and reset the adapter queues. */ printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - " "Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__); tm_flags_set= 0; rc = -ETIME; - - /* Free memory and return to the calling function - */ - goto done_free_mem; } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) { - /* User TM request failed! + /* User TM request failed! mf has not been freed. */ rc = -ENODATA; } else { - /* Callback freed request frame. - */ - mf = NULL; - /* If a valid reply frame, copy to the user. * Offset 2: reply length in U32's */ @@ -2332,42 +2345,31 @@ } done_free_mem: - /* Clear status bits. - */ - ioc->ioctl->status = 0; + /* Clear all status bits except TMTIMER_ACTIVE, this bit is cleared + * upon completion of the TM command. + * ioc->ioctl->status = 0; + */ + ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TIMER_ACTIVE | MPT_IOCTL_STATUS_TM_FAILED | + MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | + MPT_IOCTL_STATUS_RF_VALID | MPT_IOCTL_STATUS_DID_IOCRESET); if (tm_flags_set) mptctl_free_tm_flags(ioc); - if (sglbuf) { - this_sge = sglbuf; - - /* Free the allocated memory. - */ - if (bufOut.kptr != NULL ) { - dma_addr = this_sge->Address; - this_sge++; /* go to next structure */ - this_alloc = bufOut.len; - pci_free_consistent(ioc->pcidev, - this_alloc, (void *) bufOut.kptr, dma_addr); - } - - if (bufIn.kptr != NULL ) { - dma_addr = this_sge->Address; - this_alloc = bufIn.len; - - pci_free_consistent(ioc->pcidev, - this_alloc, (void *) bufIn.kptr, dma_addr); - } - - this_alloc = sgSize * sizeof(MptSge_t); + /* Free the allocated memory. + */ + if (bufOut.kptr != NULL) { pci_free_consistent(ioc->pcidev, - this_alloc, (void *) sglbuf, sglbuf_dma); + bufOut.len, (void *) bufOut.kptr, dma_addr_out); + } + if (bufIn.kptr != NULL) { + pci_free_consistent(ioc->pcidev, + bufIn.len, (void *) bufIn.kptr, dma_addr_in); } - /* mf will be null if allocation failed OR - * if command completed OK (callback freed) + /* mf is null if command issued successfully + * otherwise, failure occured after mf acquired. */ if (mf) mpt_free_msg_frame(mptctl_id, ioc->id, mf); @@ -2405,7 +2407,7 @@ */ if (data_size == sizeof(hp_host_info_t)) cim_rev = 1; - else if (data_size == (sizeof(hp_host_info_t) + 12)) + else if (data_size == sizeof(hp_host_info_rev0_t)) cim_rev = 0; /* obsolete */ else return -EFAULT; @@ -2478,7 +2480,7 @@ cfg.dir = 0; /* read */ cfg.timeout = 10; - strlcpy(karg.serial_number, " ", sizeof(karg.serial_number)); + strncpy(karg.serial_number, " ", 24); if (mpt_config(ioc, &cfg) == 0) { if (cfg.hdr->PageLength > 0) { /* Issue the second config page request */ @@ -2489,9 +2491,10 @@ cfg.physAddr = buf_dma; if (mpt_config(ioc, &cfg) == 0) { ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf; - if (strlen(pdata->BoardTracerNumber) > 1) - strlcpy(karg.serial_number, pdata->BoardTracerNumber, - sizeof(karg.serial_number)); + if (strlen(pdata->BoardTracerNumber) > 1) { + strncpy(karg.serial_number, pdata->BoardTracerNumber, 24); + karg.serial_number[24-1]='\0'; + } } pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); pbuf = NULL; @@ -2535,6 +2538,20 @@ } } + cfg.pageAddr = 0; + cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL; + cfg.dir = MPI_TB_ISTWI_FLAGS_READ; + cfg.timeout = 10; + pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); + if (pbuf) { + cfg.physAddr = buf_dma; + if ((mpt_toolbox(ioc, &cfg)) == 0) { + karg.rsvd = *(u32 *)pbuf; + } + pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); + pbuf = NULL; + } + /* Copy the data from kernel memory to user memory */ if (copy_to_user((char *)arg, &karg, @@ -2736,6 +2753,19 @@ * to ensure the structure contents is properly processed by mptctl. */ static int +compat_mptctl_ioctl(unsigned int fd, unsigned int cmd, + unsigned long arg, struct file *filp) +{ + int ret; + + lock_kernel(); + dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n")); + ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + unlock_kernel(); + return ret; +} + +static int compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp) { @@ -2875,30 +2905,30 @@ } #ifdef CONFIG_COMPAT - err = register_ioctl32_conversion(MPTIOCINFO, NULL); + err = register_ioctl32_conversion(MPTIOCINFO, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTIOCINFO1, NULL); + err = register_ioctl32_conversion(MPTIOCINFO1, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTTARGETINFO, NULL); + err = register_ioctl32_conversion(MPTTARGETINFO, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTTEST, NULL); + err = register_ioctl32_conversion(MPTTEST, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTEVENTQUERY, NULL); + err = register_ioctl32_conversion(MPTEVENTQUERY, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTEVENTENABLE, NULL); + err = register_ioctl32_conversion(MPTEVENTENABLE, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTEVENTREPORT, NULL); + err = register_ioctl32_conversion(MPTEVENTREPORT, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(MPTHARDRESET, NULL); + err = register_ioctl32_conversion(MPTHARDRESET, compat_mptctl_ioctl); if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTCOMMAND32, compat_mpt_command); if (++where && err) goto out_fail; err = register_ioctl32_conversion(MPTFWDOWNLOAD32, compat_mptfwxfer_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(HP_GETHOSTINFO, NULL); + err = register_ioctl32_conversion(HP_GETHOSTINFO, compat_mptctl_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(HP_GETTARGETINFO, NULL); + err = register_ioctl32_conversion(HP_GETTARGETINFO, compat_mptctl_ioctl); if (++where && err) goto out_fail; #endif diff -Nru a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h --- a/drivers/message/fusion/mptctl.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/mptctl.h Wed Mar 10 21:09:42 2004 @@ -15,7 +15,7 @@ * * (see also mptbase.c) * - * Copyright (c) 1999-2003 LSI Logic Corporation + * Copyright (c) 1999-2004 LSI Logic Corporation * Originally By: Steven J. Ralston * (mailto:sjralston1@netscape.net) * (mailto:mpt_linux_developer@lsil.com) @@ -342,6 +342,7 @@ #define CPQFCTS_IOC_MAGIC 'Z' #define HP_IOC_MAGIC 'Z' #define HP_GETHOSTINFO _IOR(HP_IOC_MAGIC, 20, hp_host_info_t) +#define HP_GETHOSTINFO1 _IOR(HP_IOC_MAGIC, 20, hp_host_info_rev0_t) #define HP_GETTARGETINFO _IOR(HP_IOC_MAGIC, 21, hp_target_info_t) /* All HP IOCTLs must include this header @@ -357,7 +358,7 @@ /* * Header: * iocnum required (input) - * host ignored + * host ignored * channe ignored * id ignored * lun ignored @@ -371,9 +372,9 @@ u8 devfn; u8 bus; ushort host_no; /* SCSI Host number, if scsi driver not loaded*/ - u8 fw_version[16]; /* string */ + u8 fw_version[16]; /* string */ u8 serial_number[24]; /* string */ - u32 ioc_status; + u32 ioc_status; u32 bus_phys_width; u32 base_io_addr; u32 rsvd; @@ -382,10 +383,33 @@ unsigned int timeouts; /* num timeouts */ } hp_host_info_t; +/* replace ulongs with uints, need to preserve backwards + * compatibility. + */ +typedef struct _hp_host_info_rev0 { + hp_header_t hdr; + u16 vendor; + u16 device; + u16 subsystem_vendor; + u16 subsystem_id; + u8 devfn; + u8 bus; + ushort host_no; /* SCSI Host number, if scsi driver not loaded*/ + u8 fw_version[16]; /* string */ + u8 serial_number[24]; /* string */ + u32 ioc_status; + u32 bus_phys_width; + u32 base_io_addr; + u32 rsvd; + unsigned long hard_resets; /* driver initiated resets */ + unsigned long soft_resets; /* ioc, external resets */ + unsigned long timeouts; /* num timeouts */ +} hp_host_info_rev0_t; + /* * Header: * iocnum required (input) - * host required + * host required * channel required (bus number) * id required * lun ignored diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c --- a/drivers/message/fusion/mptlan.c Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/mptlan.c Wed Mar 10 21:09:42 2004 @@ -23,7 +23,7 @@ * * (see also mptbase.c) * - * Copyright (c) 2000-2003 LSI Logic Corporation + * Copyright (c) 2000-2004 LSI Logic Corporation * Originally By: Noah Romer * (mailto:mpt_linux_developer@lsil.com) * @@ -340,12 +340,15 @@ struct mpt_lan_priv *priv = (struct mpt_lan_priv *) dev->priv; dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")); + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); if (priv->mpt_rxfidx == NULL) return (1); - if (reset_phase == MPT_IOC_PRE_RESET) { + if (reset_phase == MPT_IOC_SETUP_RESET) { + ; + } else if (reset_phase == MPT_IOC_PRE_RESET) { int i; unsigned long flags; diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c Wed Mar 10 21:09:43 2004 +++ b/drivers/message/fusion/mptscsih.c Wed Mar 10 21:09:43 2004 @@ -21,7 +21,7 @@ * * (see mptbase.c) * - * Copyright (c) 1999-2003 LSI Logic Corporation + * Copyright (c) 1999-2004 LSI Logic Corporation * Original author: Steven J. Ralston * (mailto:sjralston1@netscape.net) * (mailto:mpt_linux_developer@lsil.com) @@ -165,17 +165,19 @@ static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx); static void post_pendingQ_commands(MPT_SCSI_HOST *hd); -static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); -static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); +static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); +static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); -static void mptscsih_target_settings(MPT_SCSI_HOST *hd, VirtDevice *target, Scsi_Device *sdev); +static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen); +void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56); static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq); static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id); static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags); +static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static void mptscsih_timer_expired(unsigned long data); static void mptscsih_taskmgmt_timeout(unsigned long data); @@ -190,18 +192,18 @@ static void mptscsih_domainValidation(void *hd); static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); -static int mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int target); +static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); static void mptscsih_fillbuf(char *buffer, int size, int index, int width); #endif static int mptscsih_setup(char *str); /* module entry point */ -static int __init mptscsih_init (void); -static void __exit mptscsih_exit (void); +static int __init mptscsih_init (void); +static void __exit mptscsih_exit (void); -static int __devinit mptscsih_probe (struct pci_dev *, const struct pci_device_id *); -static void __devexit mptscsih_remove(struct pci_dev *); +static int mptscsih_probe (struct pci_dev *, const struct pci_device_id *); +static void mptscsih_remove(struct pci_dev *); static void mptscsih_shutdown(struct device *); #ifdef CONFIG_PM static int mptscsih_suspend(struct pci_dev *pdev, u32 state); @@ -214,7 +216,6 @@ */ static int mpt_scsi_hosts = 0; -static atomic_t queue_depth; static int ScsiDoneCtx = -1; static int ScsiTaskCtx = -1; @@ -243,6 +244,10 @@ static struct mptscsih_driver_setup driver_setup = MPTSCSIH_DRIVER_SETUP; +#ifdef MPTSCSIH_DBG_TIMEOUT +static Scsi_Cmnd *foo_to[8]; +#endif + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* see mptscsih.h */ @@ -438,10 +443,10 @@ static inline int mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex) { - MPT_FRAME_HDR *chainBuf = NULL; + MPT_FRAME_HDR *chainBuf; unsigned long flags; - int rc = FAILED; - int chain_idx = MPT_HOST_NO_CHAIN; + int rc; + int chain_idx; spin_lock_irqsave(&hd->ioc->FreeQlock, flags); if (!Q_IS_EMPTY(&hd->FreeChainQ)) { @@ -454,6 +459,10 @@ chain_idx = offset / hd->ioc->req_sz; rc = SUCCESS; } + else { + rc = FAILED; + chain_idx = MPT_HOST_NO_CHAIN; + } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); @@ -506,13 +515,12 @@ /* Map the data portion, if any. * sges_left = 0 if no data transfer. */ - sges_left = SCpnt->use_sg; - if (SCpnt->use_sg) { + if ( (sges_left = SCpnt->use_sg) ) { sges_left = pci_map_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); - if (sges_left == 0) + if (sges_left == 0) return FAILED; } else if (SCpnt->request_bufflen) { dma_addr_t buf_dma_addr; @@ -729,50 +737,67 @@ hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if ((mf == NULL) || - (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { - printk(MYIOC_s_ERR_FMT "%s req frame ptr! (=%p)!\n", - ioc->name, mf?"BAD":"NULL", (void *) mf); - return 0; - } - req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); sc = hd->ScsiLookup[req_idx]; if (sc == NULL) { + MPIHeader_t *hdr = (MPIHeader_t *)mf; + /* Remark: writeSDP1 will use the ScsiDoneCtx * If a SCSI I/O cmd, device disabled by OS and * completion done. Cannot touch sc struct. Just free mem. */ - atomic_dec(&queue_depth); + if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) + printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n", + ioc->name); mptscsih_freeChainBuffers(hd, req_idx); return 1; } - dmfprintk((MYIOC_s_INFO_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n", - ioc->name, mf, mr, sc, req_idx)); - - atomic_dec(&queue_depth); + dmfprintk((MYIOC_s_INFO_FMT + "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n", + ioc->name, mf, mr, sc, req_idx)); sc->result = DID_OK << 16; /* Set default reply as OK */ pScsiReq = (SCSIIORequest_t *) mf; pScsiReply = (SCSIIOReply_t *) mr; +#ifdef MPTSCSIH_DBG_TIMEOUT + if (ioc->timeout_cnt > 0) { + int ii, left = 0; + + for (ii=0; ii < 8; ii++) { + if (sc == foo_to[ii]) { + printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n", + ioc->name, sc, jiffies); + foo_to[ii] = NULL; + } + if (foo_to[ii] != NULL) + left++; + } + + if (left == 0) { + ioc->timeout_maxcnt = 0; + ioc->timeout_cnt = 0; + } + } +#endif + if (pScsiReply == NULL) { /* special context reply handling */ ; } else { u32 xfer_cnt; u16 status; - u8 scsi_state; + u8 scsi_state, scsi_status; status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; scsi_state = pScsiReply->SCSIState; - dsprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n", + dprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n", ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], mf, mr, sc)); - dsprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh" + dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh" ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n", status, scsi_state, pScsiReply->SCSIStatus, le32_to_cpu(pScsiReply->IOCLogInfo))); @@ -780,14 +805,6 @@ if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) copy_sense_data(sc, hd, mf, pScsiReply); - /* - * Look for + dump FCP ResponseInfo[]! - */ - if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) { - dprintk((KERN_NOTICE " FCP_ResponseInfo=%08xh\n", - le32_to_cpu(pScsiReply->ResponseInfo))); - } - switch(status) { case MPI_IOCSTATUS_BUSY: /* 0x0002 */ /* CHECKME! @@ -827,52 +844,45 @@ case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ /* - * YIKES! I just discovered that SCSI IO which - * returns check condition, SenseKey=05 (ILLEGAL REQUEST) - * and ASC/ASCQ=94/01 (LSI Logic RAID vendor specific), - * comes down this path! * Do upfront check for valid SenseData and give it * precedence! */ - sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus; - if (scsi_state == 0) { - ; - } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { + scsi_status = pScsiReply->SCSIStatus; + sc->result = (DID_OK << 16) | scsi_status; + xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); + if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { /* Have already saved the status and sense data */ ; - } else if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { - /* What to do? - */ - sc->result = DID_SOFT_ERROR << 16; - } - else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { - /* Not real sure here either... */ - sc->result = DID_RESET << 16; + } else { + if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) { + sc->result = DID_SOFT_ERROR << 16; + } + if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { + /* What to do? + */ + sc->result = DID_SOFT_ERROR << 16; + } + else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { + /* Not real sure here either... */ + sc->result = DID_RESET << 16; + } } /* Give report and update residual count. */ - xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); dprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", sc->underflow)); dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt)); sc->resid = sc->request_bufflen - xfer_cnt; dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid)); - - if(sc->underflow > xfer_cnt) { - printk(MYIOC_s_INFO_FMT - "SCSI data underrun: underflow=%02x, xfercnt=%02x\n", - ioc->name, sc->underflow, xfer_cnt); - sc->result = DID_SOFT_ERROR << 16; - } - + /* Report Queue Full */ - if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL) + if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); - + break; case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ @@ -965,9 +975,7 @@ hd->ScsiLookup[req_idx] = NULL; - MPT_HOST_LOCK(flags); sc->scsi_done(sc); /* Issue the command callback */ - MPT_HOST_UNLOCK(flags); /* Free Chain buffers */ mptscsih_freeChainBuffers(hd, req_idx); @@ -988,7 +996,7 @@ /* Flush the doneQ. */ - dprintk((KERN_INFO MYNAM ": flush_doneQ called\n")); + dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n")); while (1) { spin_lock_irqsave(&hd->freedoneQlock, flags); if (Q_IS_EMPTY(&hd->doneQ)) { @@ -1013,9 +1021,7 @@ /* Do the OS callback. */ - MPT_HOST_LOCK(flags); SCpnt->scsi_done(SCpnt); - MPT_HOST_UNLOCK(flags); } return; @@ -1055,6 +1061,22 @@ return; } +static void +mptscsih_reset_timeouts (MPT_SCSI_HOST *hd) +{ + Scsi_Cmnd *SCpnt; + int ii; + int max = hd->ioc->req_depth; + + for (ii= 0; ii < max; ii++) { + if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { + mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60)); + dtmprintk((MYIOC_s_WARN_FMT "resetting SCpnt=%p timeout + 60HZ", + (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); + } + } +} + /* * mptscsih_flush_running_cmds - For each command found, search * Scsi_Host instance taskQ and reply to OS. @@ -1068,23 +1090,24 @@ static void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) { - Scsi_Cmnd *SCpnt = NULL; - MPT_FRAME_HDR *mf = NULL; + Scsi_Cmnd *SCpnt; + MPT_FRAME_HDR *mf; + MPT_DONE_Q *buffer; int ii; int max = hd->ioc->req_depth; + unsigned long flags; dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n")); for (ii= 0; ii < max; ii++) { if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { /* Command found. - * - * Search pendingQ, if found, - * delete from Q. If found, do not decrement - * queue_depth, command never posted. */ - if (mptscsih_search_pendingQ(hd, ii) == NULL) - atomic_dec(&queue_depth); + + /* Search pendingQ, if found, + * delete from Q. + */ + mptscsih_search_pendingQ(hd, ii); /* Null ScsiLookup index */ @@ -1111,15 +1134,39 @@ } SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; - MPT_HOST_LOCK(flags); - SCpnt->scsi_done(SCpnt); /* Issue the command callback */ - MPT_HOST_UNLOCK(flags); /* Free Chain buffers */ mptscsih_freeChainBuffers(hd, ii); /* Free Message frames */ mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); + +#if 1 + /* Post to doneQ, do not reply until POST phase + * of reset handler....prevents new commands from + * being queued. + */ + spin_lock_irqsave(&hd->freedoneQlock, flags); + if (!Q_IS_EMPTY(&hd->freeQ)) { + buffer = hd->freeQ.head; + Q_DEL_ITEM(buffer); + + /* Set the Scsi_Cmnd pointer + */ + buffer->argp = (void *)SCpnt; + + /* Add to the doneQ + */ + Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q); + spin_unlock_irqrestore(&hd->freedoneQlock, flags); + } else { + spin_unlock_irqrestore(&hd->freedoneQlock, flags); + SCpnt->scsi_done(SCpnt); + } +#else + SCpnt->scsi_done(SCpnt); /* Issue the command callback */ +#endif + } } @@ -1147,8 +1194,8 @@ int ii; int max = hd->ioc->req_depth; - dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d numIos %d\n", - target, lun, max, atomic_read(&queue_depth))); + dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", + target, lun, max)); for (ii=0; ii < max; ii++) { if (hd->ScsiLookup[ii] != NULL) { @@ -1161,11 +1208,6 @@ if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun))) continue; - /* If cmd pended, do not decrement queue_depth, command never posted. - */ - if (mptscsih_search_pendingQ(hd, ii) == NULL) - atomic_dec(&queue_depth); - /* Cleanup */ hd->ScsiLookup[ii] = NULL; @@ -1177,73 +1219,6 @@ return; } -#ifdef DROP_TEST -/* mptscsih_flush_drop_test - Free resources and do callback if - * DROP_TEST enabled. - * - * @hd: Pointer to a SCSI HOST structure - * - * Returns: None. - * - * Must be called while new I/Os are being queued. - */ -static void -mptscsih_flush_drop_test (MPT_SCSI_HOST *hd) -{ - Scsi_Cmnd *sc; - unsigned long flags; - u16 req_idx; - - /* Free resources for the drop test MF - * and chain buffers. - */ - if (dropMfPtr) { - req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx); - sc = hd->ScsiLookup[req_idx]; - if (sc == NULL) { - printk(MYIOC_s_ERR_FMT "Drop Test: NULL ScsiCmd ptr!\n", - ioc->name); - } else { - /* unmap OS resources, set status, do callback - * free driver resources - */ - if (sc->use_sg) { - pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer, - sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction)); - } else if (sc->request_bufflen) { - scPrivate *my_priv; - - my_priv = (scPrivate *) &sc->SCp; - pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, - sc->request_bufflen, - scsi_to_pci_dma_dir(sc->sc_data_direction)); - } - - sc->host_scribble = NULL; - sc->result = DID_RESET << 16; - hd->ScsiLookup[req_idx] = NULL; - atomic_dec(&queue_depth); - MPT_HOST_LOCK(flags); - sc->scsi_done(sc); /* Issue callback */ - MPT_HOST_UNLOCK(flags); - } - - mptscsih_freeChainBuffers(hd, req_idx); - mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr); - printk(MYIOC_s_INFO_FMT "Free'd Dropped cmd (%p)\n", - hd->ioc->name, sc); - printk(MYIOC_s_INFO_FMT "mf (%p) reqidx (%4x)\n", - hd->ioc->name, dropMfPtr, req_idx); - printk(MYIOC_s_INFO_FMT "Num Tot (%d) Good (%d) Bad (%d) \n", - hd->ioc->name, dropTestNum, - dropTestOK, dropTestBad); - } - dropMfPtr = NULL; - - return; -} -#endif - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptscsih_initChainBuffers - Allocate memory for and initialize @@ -1263,18 +1238,15 @@ /* ReqToChain size must equal the req_depth * index = req_idx */ - sz = hd->ioc->req_depth * sizeof(int); if (hd->ReqToChain == NULL) { + sz = hd->ioc->req_depth * sizeof(int); mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) return -1; hd->ReqToChain = (int *) mem; - } else { - mem = (u8 *) hd->ReqToChain; } -/* memset(mem, 0xFF, sz); */ - for(ii=0;iiioc->req_depth;ii++) + for (ii = 0; ii < hd->ioc->req_depth; ii++) hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN; /* ChainToChain size must equal the total number @@ -1322,7 +1294,11 @@ if (hd->ChainBuffer == NULL) { /* Allocate free chain buffer pool */ +#if defined(MPTBASE_MEM_ALLOC_FIFO_FIX) + mem = pci_alloc_consistent(&hd->ioc->pcidev32, sz, &hd->ChainBufferDMA); +#else mem = pci_alloc_consistent(hd->ioc->pcidev, sz, &hd->ChainBufferDMA); +#endif if (mem == NULL) return -1; @@ -1405,310 +1381,333 @@ * */ -static int __devinit +static int mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct Scsi_Host *sh = NULL; - MPT_SCSI_HOST *hd = NULL; + struct Scsi_Host *sh; + MPT_SCSI_HOST *hd; MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - int portnum; MPT_DONE_Q *freedoneQ; unsigned long flags; int sz, ii; int numSGE = 0; int scale; + int ioc_cap; u8 *mem; int error=0; - for (portnum=0; portnum < ioc->facts.NumberOfPorts; portnum++) { - - /* 20010215 -sralston - * Added sanity check on SCSI Initiator-mode enabled - * for this MPT adapter. - */ - if (!(ioc->pfacts[portnum].ProtocolFlags & - MPI_PORTFACTS_PROTOCOL_INITIATOR)) { - printk(MYIOC_s_WARN_FMT - "Skipping because SCSI Initiator mode is NOT enabled!\n", - ioc->name); - continue; - } - - /* 20010202 -sralston - * Added sanity check on readiness of the MPT adapter. - */ - if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { - printk(MYIOC_s_WARN_FMT - "Skipping because it's not operational!\n", - ioc->name); - continue; - } - - sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST)); - if (sh != NULL) { - spin_lock_irqsave(&ioc->FreeQlock, flags); - - /* Attach the SCSI Host to the IOC structure - */ - ioc->sh = sh; - - sh->io_port = 0; - sh->n_io_port = 0; - sh->irq = 0; - - /* set 16 byte cdb's */ - sh->max_cmd_len = 16; - - /* Yikes! This is important! - * Otherwise, by default, linux - * only scans target IDs 0-7! - * pfactsN->MaxDevices unreliable - * (not supported in early - * versions of the FW). - * max_id = 1 + actual max id, - * max_lun = 1 + actual last lun, - * see hosts.h :o( - */ - if ((int)ioc->chip_type > (int)FC929) { - sh->max_id = MPT_MAX_SCSI_DEVICES; - } else { - /* For FC, increase the queue depth - * from MPT_SCSI_CAN_QUEUE (31) - * to MPT_FC_CAN_QUEUE (63). - */ - sh->can_queue = MPT_FC_CAN_QUEUE; - sh->max_id = - MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; - } - - sh->max_lun = MPT_LAST_LUN + 1; - sh->max_sectors = MPT_SCSI_MAX_SECTORS; - sh->this_id = ioc->pfacts[portnum].PortSCSIID; - - /* Required entry. - */ - sh->unique_id = ioc->id; - - /* Verify that we won't exceed the maximum - * number of chain buffers - * We can optimize: ZZ = req_sz/sizeof(SGE) - * For 32bit SGE's: - * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ - * + (req_sz - 64)/sizeof(SGE) - * A slightly different algorithm is required for - * 64bit SGEs. - */ - scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); - if (sizeof(dma_addr_t) == sizeof(u64)) { - numSGE = (scale - 1) * - (ioc->facts.MaxChainDepth-1) + scale + - (ioc->req_sz - 60) / (sizeof(dma_addr_t) + - sizeof(u32)); - } else { - numSGE = 1 + (scale - 1) * - (ioc->facts.MaxChainDepth-1) + scale + - (ioc->req_sz - 64) / (sizeof(dma_addr_t) + - sizeof(u32)); - } - - if (numSGE < sh->sg_tablesize) { - /* Reset this value */ - dprintk((MYIOC_s_INFO_FMT - "Resetting sg_tablesize to %d from %d\n", - ioc->name, numSGE, sh->sg_tablesize)); - sh->sg_tablesize = numSGE; - } - - /* Set the pci device pointer in Scsi_Host structure. - */ - scsi_set_device(sh, &ioc->pcidev->dev); - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - hd = (MPT_SCSI_HOST *) sh->hostdata; - hd->ioc = ioc; - hd->max_sge = sh->sg_tablesize; - - if ((int)ioc->chip_type > (int)FC929) - hd->is_spi = 1; + /* 20010202 -sralston + * Added sanity check on readiness of the MPT adapter. + */ + if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { + printk(MYIOC_s_WARN_FMT + "Skipping because it's not operational!\n", + ioc->name); + return -ENODEV; + } - if (DmpService && (ioc->chip_type == FC919 || - ioc->chip_type == FC929)) { - hd->is_multipath = 1; - } - hd->port = 0; /* FIXME! */ + if (!ioc->active) { + printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", + ioc->name); + return -ENODEV; + } - /* SCSI needs Scsi_Cmnd lookup table! - * (with size equal to req_depth*PtrSz!) - */ - sz = hd->ioc->req_depth * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { - error = -ENOMEM; - goto mptscsih_probe_failed; - } + /* Sanity check - ensure at least 1 port is INITIATOR capable + */ + ioc_cap = 0; + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { + if (ioc->pfacts[ii].ProtocolFlags & + MPI_PORTFACTS_PROTOCOL_INITIATOR) + ioc_cap ++; + } - memset(mem, 0, sz); - hd->ScsiLookup = (struct scsi_cmnd **) mem; + if (!ioc_cap) { + printk(MYIOC_s_WARN_FMT + "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", + ioc->name, ioc); + return -ENODEV; + } - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", - ioc->name, hd->ScsiLookup, sz)); + sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST)); + + if (!sh) { + printk(MYIOC_s_WARN_FMT + "Unable to register controller with SCSI subsystem\n", + ioc->name); + return -1; + } + + spin_lock_irqsave(&ioc->FreeQlock, flags); - if (mptscsih_initChainBuffers(hd, 1) < 0) { - error = -EINVAL; - goto mptscsih_probe_failed; - } + /* Attach the SCSI Host to the IOC structure + */ + ioc->sh = sh; - /* Allocate memory for free and doneQ's - */ - sz = sh->can_queue * sizeof(MPT_DONE_Q); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { - error = -ENOMEM; - goto mptscsih_probe_failed; - } + sh->io_port = 0; + sh->n_io_port = 0; + sh->irq = 0; + + /* set 16 byte cdb's */ + sh->max_cmd_len = 16; + + /* Yikes! This is important! + * Otherwise, by default, linux + * only scans target IDs 0-7! + * pfactsN->MaxDevices unreliable + * (not supported in early + * versions of the FW). + * max_id = 1 + actual max id, + * max_lun = 1 + actual last lun, + * see hosts.h :o( + */ + if ((int)ioc->chip_type > (int)FC929) { + sh->max_id = MPT_MAX_SCSI_DEVICES; + } else { + /* For FC, increase the queue depth + * from MPT_SCSI_CAN_QUEUE (31) + * to MPT_FC_CAN_QUEUE (63). + */ + sh->can_queue = MPT_FC_CAN_QUEUE; + sh->max_id = + MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; + } + + sh->max_lun = MPT_LAST_LUN + 1; + sh->max_sectors = MPT_SCSI_MAX_SECTORS; + sh->max_channel = 0; + sh->this_id = ioc->pfacts[0].PortSCSIID; + + /* Required entry. + */ + sh->unique_id = ioc->id; + + /* Verify that we won't exceed the maximum + * number of chain buffers + * We can optimize: ZZ = req_sz/sizeof(SGE) + * For 32bit SGE's: + * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ + * + (req_sz - 64)/sizeof(SGE) + * A slightly different algorithm is required for + * 64bit SGEs. + */ + scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); + if (sizeof(dma_addr_t) == sizeof(u64)) { + numSGE = (scale - 1) * + (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + + sizeof(u32)); + } else { + numSGE = 1 + (scale - 1) * + (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + + sizeof(u32)); + } + + if (numSGE < sh->sg_tablesize) { + /* Reset this value */ + dprintk((MYIOC_s_INFO_FMT + "Resetting sg_tablesize to %d from %d\n", + ioc->name, numSGE, sh->sg_tablesize)); + sh->sg_tablesize = numSGE; + } - memset(mem, 0xFF, sz); - hd->memQ = mem; + /* Set the pci device pointer in Scsi_Host structure. + */ + scsi_set_device(sh, &ioc->pcidev->dev); - /* Initialize the free, done and pending Qs. - */ - Q_INIT(&hd->freeQ, MPT_DONE_Q); - Q_INIT(&hd->doneQ, MPT_DONE_Q); - Q_INIT(&hd->pendingQ, MPT_DONE_Q); - spin_lock_init(&hd->freedoneQlock); - - mem = hd->memQ; - for (ii=0; ii < sh->can_queue; ii++) { - freedoneQ = (MPT_DONE_Q *) mem; - Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q); - mem += sizeof(MPT_DONE_Q); - } + spin_unlock_irqrestore(&ioc->FreeQlock, flags); - /* Initialize this Scsi_Host - * internal task Q. - */ - Q_INIT(&hd->taskQ, MPT_FRAME_HDR); - hd->taskQcnt = 0; + hd = (MPT_SCSI_HOST *) sh->hostdata; + hd->ioc = ioc; + hd->max_sge = sh->sg_tablesize; + + if ((int)ioc->chip_type > (int)FC929) + hd->is_spi = 1; + + if (DmpService && (ioc->chip_type == FC919 || + ioc->chip_type == FC929)) { + hd->is_multipath = 1; + } + + /* SCSI needs Scsi_Cmnd lookup table! + * (with size equal to req_depth*PtrSz!) + */ + sz = hd->ioc->req_depth * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptscsih_probe_failed; + } - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - sz = sh->max_id * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { - error = -ENOMEM; - goto mptscsih_probe_failed; - } + memset(mem, 0, sz); + hd->ScsiLookup = (struct scsi_cmnd **) mem; - memset(mem, 0, sz); - hd->Targets = (VirtDevice **) mem; + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", + ioc->name, hd->ScsiLookup, sz)); + + if (mptscsih_initChainBuffers(hd, 1) < 0) { + error = -EINVAL; + goto mptscsih_probe_failed; + } + + /* Allocate memory for free and doneQ's + */ + sz = sh->can_queue * sizeof(MPT_DONE_Q); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptscsih_probe_failed; + } - dprintk((KERN_INFO - " Targets @ %p, sz=%d\n", hd->Targets, sz)); + memset(mem, 0xFF, sz); + hd->memQ = mem; + /* Initialize the free, done and pending Qs. + */ + Q_INIT(&hd->freeQ, MPT_DONE_Q); + Q_INIT(&hd->doneQ, MPT_DONE_Q); + Q_INIT(&hd->pendingQ, MPT_DONE_Q); + spin_lock_init(&hd->freedoneQlock); + + mem = hd->memQ; + for (ii=0; ii < sh->can_queue; ii++) { + freedoneQ = (MPT_DONE_Q *) mem; + Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q); + mem += sizeof(MPT_DONE_Q); + } + + /* Initialize this Scsi_Host + * internal task Q. + */ + Q_INIT(&hd->taskQ, MPT_FRAME_HDR); + hd->taskQcnt = 0; + + /* Allocate memory for the device structures. + * A non-Null pointer at an offset + * indicates a device exists. + * max_id = 1 + maximum id (hosts.h) + */ + sz = sh->max_id * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptscsih_probe_failed; + } - /* Clear the TM flags - */ - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - hd->resetPending = 0; - hd->abortSCpnt = NULL; - hd->tmPtr = NULL; - hd->numTMrequests = 0; + memset(mem, 0, sz); + hd->Targets = (VirtDevice **) mem; - /* Clear the pointer used to store - * single-threaded commands, i.e., those - * issued during a bus scan, dv and - * configuration pages. - */ - hd->cmdPtr = NULL; + dprintk((KERN_INFO + " Targets @ %p, sz=%d\n", hd->Targets, sz)); - /* Initialize this SCSI Hosts' timers - * To use, set the timer expires field - * and add_timer - */ - init_timer(&hd->timer); - hd->timer.data = (unsigned long) hd; - hd->timer.function = mptscsih_timer_expired; - - init_timer(&hd->TMtimer); - hd->TMtimer.data = (unsigned long) hd; - hd->TMtimer.function = mptscsih_taskmgmt_timeout; - hd->qtag_tick = jiffies; + /* Clear the TM flags + */ + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + hd->resetPending = 0; + hd->abortSCpnt = NULL; + hd->tmPtr = NULL; + hd->numTMrequests = 0; + + /* Clear the pointer used to store + * single-threaded commands, i.e., those + * issued during a bus scan, dv and + * configuration pages. + */ + hd->cmdPtr = NULL; - /* Moved Earlier Pam D */ - /* ioc->sh = sh; */ + /* Initialize this SCSI Hosts' timers + * To use, set the timer expires field + * and add_timer + */ + init_timer(&hd->timer); + hd->timer.data = (unsigned long) hd; + hd->timer.function = mptscsih_timer_expired; + + init_timer(&hd->TMtimer); + hd->TMtimer.data = (unsigned long) hd; + hd->TMtimer.function = mptscsih_taskmgmt_timeout; + hd->qtag_tick = jiffies; + + /* Moved Earlier Pam D */ + /* ioc->sh = sh; */ + +#ifdef MPTSCSIH_DBG_TIMEOUT + hd->ioc->timeout_hard = 0; + hd->ioc->timeout_delta = 30 * HZ; + hd->ioc->timeout_maxcnt = 0; + hd->ioc->timeout_cnt = 0; + for (ii=0; ii < 8; ii++) + foo_to[ii] = NULL; +#endif + if (hd->is_spi) { + /* Update with the driver setup + * values. + */ + if (hd->ioc->spi_data.maxBusWidth > + driver_setup.max_width) { + hd->ioc->spi_data.maxBusWidth = + driver_setup.max_width; + } - if (hd->is_spi) { - /* Update with the driver setup - * values. - */ - if (hd->ioc->spi_data.maxBusWidth > - driver_setup.max_width) { - hd->ioc->spi_data.maxBusWidth = - driver_setup.max_width; - } + if (hd->ioc->spi_data.minSyncFactor < + driver_setup.min_sync_fac) { + hd->ioc->spi_data.minSyncFactor = + driver_setup.min_sync_fac; + } - if (hd->ioc->spi_data.minSyncFactor < - driver_setup.min_sync_fac) { - hd->ioc->spi_data.minSyncFactor = - driver_setup.min_sync_fac; - } + if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) { + hd->ioc->spi_data.maxSyncOffset = 0; + } - if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) { - hd->ioc->spi_data.maxSyncOffset = 0; - } + hd->ioc->spi_data.Saf_Te = driver_setup.saf_te; - hd->negoNvram = 0; + hd->negoNvram = 0; #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - hd->negoNvram = MPT_SCSICFG_USE_NVRAM; + hd->negoNvram = MPT_SCSICFG_USE_NVRAM; #endif - if (driver_setup.dv == 0) { - hd->negoNvram = MPT_SCSICFG_USE_NVRAM; - } - - hd->ioc->spi_data.forceDv = 0; - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - hd->ioc->spi_data.dvStatus[ii] = - MPT_SCSICFG_NEGOTIATE; - } - - if (hd->negoNvram == 0) { - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) - hd->ioc->spi_data.dvStatus[ii] |= - MPT_SCSICFG_DV_NOT_DONE; - } + if (driver_setup.dv == 0) { + hd->negoNvram = MPT_SCSICFG_USE_NVRAM; + } - ddvprintk((MYIOC_s_INFO_FMT - "dv %x width %x factor %x \n", - hd->ioc->name, driver_setup.dv, - driver_setup.max_width, - driver_setup.min_sync_fac)); + hd->ioc->spi_data.forceDv = 0; + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { + hd->ioc->spi_data.dvStatus[ii] = + MPT_SCSICFG_NEGOTIATE; + } - } + if (hd->negoNvram == 0) { + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) + hd->ioc->spi_data.dvStatus[ii] |= + MPT_SCSICFG_DV_NOT_DONE; + } - mpt_scsi_hosts++; + ddvprintk((MYIOC_s_INFO_FMT + "dv %x width %x factor %x saf_te %x\n", + hd->ioc->name, driver_setup.dv, + driver_setup.max_width, + driver_setup.min_sync_fac, + driver_setup.saf_te)); + } - error = scsi_add_host (sh, &ioc->pcidev->dev); - if(error) { - dprintk((KERN_ERR MYNAM, - "scsi_add_host failed\n")); - goto mptscsih_probe_failed; - } + mpt_scsi_hosts++; - scsi_scan_host(sh); - return 0; - } /* scsi_host_alloc */ + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { + dprintk((KERN_ERR MYNAM + "scsi_add_host failed\n")); + goto mptscsih_probe_failed; + } - } /* for each adapter port */ + scsi_scan_host(sh); + return 0; mptscsih_probe_failed: mptscsih_remove(pdev); return error; + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1718,7 +1717,7 @@ * * */ -static void __devexit +static void mptscsih_remove(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); @@ -1920,7 +1919,7 @@ static struct mpt_pci_driver mptscsih_driver = { .probe = mptscsih_probe, - .remove = __devexit_p(mptscsih_remove), + .remove = mptscsih_remove, .shutdown = mptscsih_shutdown, #ifdef CONFIG_PM .suspend = mptscsih_suspend, @@ -1979,8 +1978,8 @@ * mptscsih_exit - Unregisters MPT adapter(s) * */ -static void __exit -mptscsih_exit(void) +static void +__exit mptscsih_exit(void) { MPT_ADAPTER *ioc; @@ -2023,7 +2022,7 @@ const char * mptscsih_info(struct Scsi_Host *SChost) { - MPT_SCSI_HOST *h = NULL; + MPT_SCSI_HOST *h; int size = 0; if (info_kbuf == NULL) @@ -2099,101 +2098,20 @@ return ((info.pos > info.offset) ? info.pos - info.offset : 0); } -struct mptscsih_usrcmd { - ulong target; - ulong lun; - ulong data; - ulong cmd; -}; - -#define UC_GET_SPEED 0x10 - -static void mptscsih_exec_user_cmd(MPT_ADAPTER *ioc, struct mptscsih_usrcmd *uc) +#ifndef MPTSCSIH_DBG_TIMEOUT +static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len) { - CONFIGPARMS cfg; - dma_addr_t cfg_dma_addr = -1; - ConfigPageHeader_t header; - - dprintk(("exec_user_command: ioc %p cmd %ld target=%ld\n", - ioc, uc->cmd, uc->target)); - - switch (uc->cmd) { - case UC_GET_SPEED: - { - SCSIDevicePage0_t *pData = NULL; - - if (ioc->spi_data.sdp0length == 0) - return; - - pData = (SCSIDevicePage0_t *)pci_alloc_consistent(ioc->pcidev, - ioc->spi_data.sdp0length * 4, &cfg_dma_addr); - - if (pData == NULL) - return; - - header.PageVersion = ioc->spi_data.sdp0version; - header.PageLength = ioc->spi_data.sdp0length; - header.PageNumber = 0; - header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; - - cfg.hdr = &header; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - cfg.dir = 0; - cfg.pageAddr = (u32) uc->target; /* bus << 8 | target */ - cfg.physAddr = cfg_dma_addr; - - if (mpt_config(ioc, &cfg) == 0) { - u32 np = le32_to_cpu(pData->NegotiatedParameters); - u32 tmp = np & MPI_SCSIDEVPAGE0_NP_WIDE; - - printk("Target %d: %s;", - (u32) uc->target, - tmp ? "Wide" : "Narrow"); - - tmp = np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK; - if (tmp) { - u32 speed = 0; - printk(" Synchronous"); - tmp = (tmp >> 16); - printk(" (Offset=0x%x", tmp); - tmp = np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK; - tmp = (tmp >> 8); - printk(" Factor=0x%x)", tmp); - if (tmp <= MPT_ULTRA320) - speed=160; - else if (tmp <= MPT_ULTRA160) - speed=80; - else if (tmp <= MPT_ULTRA2) - speed=40; - else if (tmp <= MPT_ULTRA) - speed=20; - else if (tmp <= MPT_FAST) - speed=10; - else if (tmp <= MPT_SCSI) - speed=5; - - if (np & MPI_SCSIDEVPAGE0_NP_WIDE) - speed*=2; - - printk(" %dMB/sec\n", speed); - - } else - printk(" Asynchronous.\n"); - } else { - printk("failed\n" ); - } - - pci_free_consistent(ioc->pcidev, ioc->spi_data.sdp0length * 4, - pData, cfg_dma_addr); - } - break; - } + /* Not yet implemented */ + return len; } - +#else #define is_digit(c) ((c) >= '0' && (c) <= '9') #define digit_to_bin(c) ((c) - '0') #define is_space(c) ((c) == ' ' || (c) == '\t') +#define UC_DBG_TIMEOUT 0x01 +#define UC_DBG_HARDRESET 0x02 + static int skip_spaces(char *ptr, int len) { int cnt, c; @@ -2242,50 +2160,66 @@ static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length) { - char *ptr = buffer; - struct mptscsih_usrcmd cmd, *uc = &cmd; - ulong target; - int arg_len; - int len = length; + char *ptr = buffer; + char btmp[24]; /* REMOVE */ + int arg_len; + int len = length; + int cmd; + ulong number = 1; + ulong delta = 10; - uc->target = uc->cmd = uc->lun = uc->data = 0; - if ((len > 0) && (ptr[len -1] == '\n')) --len; - if ((arg_len = is_keyword(ptr, len, "getspeed")) != 0) - uc->cmd = UC_GET_SPEED; - else - arg_len = 0; - - dprintk(("user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd)); + if (len < 22) { + strncpy(btmp, buffer, len); + btmp[len+1]='\0'; + } else { + strncpy(btmp, buffer, 22); + btmp[23]='\0'; + } + printk("user_command: ioc %d, buffer %s, length %d\n", + ioc->id, btmp, length); - if (!arg_len) + if ((arg_len = is_keyword(ptr, len, "timeout")) != 0) + cmd = UC_DBG_TIMEOUT; + else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0) + cmd = UC_DBG_HARDRESET; + else return -EINVAL; ptr += arg_len; len -= arg_len; - switch(uc->cmd) { - case UC_GET_SPEED: + switch(cmd) { + case UC_DBG_TIMEOUT: + SKIP_SPACES(1); + GET_INT_ARG(number); SKIP_SPACES(1); - GET_INT_ARG(target); - uc->target = target; + GET_INT_ARG(delta); break; } - dprintk(("user_command: target=%ld len=%d\n", uc->target, len)); + printk("user_command: cnt=%ld delta=%ld\n", number, delta); if (len) return -EINVAL; else { - /* process this command ... - */ - mptscsih_exec_user_cmd(ioc, uc); + if (cmd == UC_DBG_HARDRESET) { + ioc->timeout_hard = 1; + } else if (cmd == UC_DBG_TIMEOUT) { + /* process this command ... + */ + ioc->timeout_maxcnt = 0; + ioc->timeout_delta = delta < 2 ? 2 : delta; + ioc->timeout_cnt = 0; + ioc->timeout_maxcnt = number < 8 ? number: 8; + } } /* Not yet implemented */ return length; } +#endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** @@ -2303,7 +2237,7 @@ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func) { - MPT_ADAPTER *ioc = NULL; + MPT_ADAPTER *ioc; MPT_SCSI_HOST *hd = NULL; int size = 0; @@ -2334,49 +2268,8 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - static int max_qd = 1; #define ADD_INDEX_LOG(req_ent) do { } while(0) -#ifdef DROP_TEST -#define DROP_IOC 1 /* IOC to force failures */ -#define DROP_TARGET 3 /* Target ID to force failures */ -#define DROP_THIS_CMD 10000 /* iteration to drop command */ -static int dropCounter = 0; -static int dropTestOK = 0; /* num did good */ -static int dropTestBad = 0; /* num did bad */ -static int dropTestNum = 0; /* total = good + bad + incomplete */ -static int numTotCmds = 0; -static MPT_FRAME_HDR *dropMfPtr = NULL; -static int numTMrequested = 0; -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_put_msgframe - Wrapper routine to post message frame to F/W. - * @context: Call back context (ScsiDoneCtx, ScsiScanDvCtx) - * @id: IOC id number - * @mf: Pointer to message frame - * - * Handles the call to mptbase for posting request and queue depth - * tracking. - * - * Returns none. - */ -static inline void -mptscsih_put_msgframe(int context, int id, MPT_FRAME_HDR *mf) -{ - /* Main banana... */ - atomic_inc(&queue_depth); - if (atomic_read(&queue_depth) > max_qd) { - max_qd = atomic_read(&queue_depth); - dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd)); - } - - mpt_put_msg_frame(context, id, mf); - - return; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine. @@ -2396,7 +2289,7 @@ MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; VirtDevice *pTarget; - MPT_DONE_Q *buffer = NULL; + MPT_DONE_Q *buffer; unsigned long flags; int target; int lun; @@ -2424,9 +2317,14 @@ if (hd->resetPending) { /* Prevent new commands from being issued - * while reloading the FW. + * while reloading the FW. Reset timer to 60 seconds, + * as the FW can take some time to come ready. + * For New EH, cmds on doneQ posted to FW. */ did_errcode = 1; + mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60)); + dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", + (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); goto did_error; } @@ -2481,8 +2379,8 @@ /* Use the above information to set up the message frame */ - pScsiReq->TargetID = target; - pScsiReq->Bus = hd->port; + pScsiReq->TargetID = (u8) target; + pScsiReq->Bus = (u8) SCpnt->device->channel; pScsiReq->ChainOffset = 0; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; pScsiReq->CDBLength = SCpnt->cmd_len; @@ -2501,12 +2399,14 @@ /* * Write SCSI CDB into the message - * Should write from cmd_len up to 16, but skip for performance reasons. */ cmd_len = SCpnt->cmd_len; for (ii=0; ii < cmd_len; ii++) pScsiReq->CDB[ii] = SCpnt->cmnd[ii]; + for (ii=cmd_len; ii < 16; ii++) + pScsiReq->CDB[ii] = 0; + /* DataLength */ pScsiReq->DataLength = cpu_to_le32(datalen); @@ -2532,39 +2432,6 @@ hd->ScsiLookup[my_idx] = SCpnt; SCpnt->host_scribble = NULL; -#ifdef DROP_TEST - numTotCmds++; - /* If the IOC number and target match, increment - * counter. If counter matches DROP_THIS, do not - * issue command to FW to force a reset. - * Save the MF pointer so we can free resources - * when task mgmt completes. - */ - if ((hd->ioc->id == DROP_IOC) && (target == DROP_TARGET)) { - dropCounter++; - - if (dropCounter == DROP_THIS_CMD) { - dropCounter = 0; - - /* If global is set, then we are already - * doing something - so keep issuing commands. - */ - if (dropMfPtr == NULL) { - dropTestNum++; - dropMfPtr = mf; - atomic_inc(&queue_depth); - printk(MYIOC_s_INFO_FMT - "Dropped SCSI cmd (%p)\n", - hd->ioc->name, SCpnt); - printk("mf (%p) req (%4x) tot cmds (%d)\n", - mf, my_idx, numTotCmds); - - return 0; - } - } - } -#endif - /* SCSI specific processing */ issueCmd = 1; if (hd->is_spi) { @@ -2617,8 +2484,20 @@ } } +#ifdef MPTSCSIH_DBG_TIMEOUT + if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) { + foo_to[hd->ioc->timeout_cnt] = SCpnt; + hd->ioc->timeout_cnt++; + //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta); + issueCmd = 0; + printk(MYIOC_s_WARN_FMT + "to pendingQ: (sc=%p, mf=%p, time=%ld)\n", + hd->ioc->name, SCpnt, mf, jiffies); + } +#endif + if (issueCmd) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); + mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", hd->ioc->name, SCpnt, mf, my_idx)); } else { @@ -2660,6 +2539,8 @@ SCpnt->result = (DID_BUS_BUSY << 16); spin_lock_irqsave(&hd->freedoneQlock, flags); if (!Q_IS_EMPTY(&hd->freeQ)) { + dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n", + (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); buffer = hd->freeQ.head; Q_DEL_ITEM(buffer); @@ -2692,7 +2573,7 @@ static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx) { - MPT_FRAME_HDR *chain = NULL; + MPT_FRAME_HDR *chain; unsigned long flags; int chain_idx; int next; @@ -2755,9 +2636,9 @@ * Returns 0 for SUCCESS or -1 if FAILED. */ static int -mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag) +mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag) { - MPT_ADAPTER *ioc = NULL; + MPT_ADAPTER *ioc; int rc = -1; int doTask = 1; u32 ioc_raw_state; @@ -2770,19 +2651,18 @@ return 0; ioc = hd->ioc; - dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); - if (ioc == NULL) { printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n"); - return 0; + return FAILED; } + dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); // SJR - CHECKME - Can we avoid this here? // (mpt_HardResetHandler has this check...) spin_lock_irqsave(&ioc->diagLock, flags); if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) { spin_unlock_irqrestore(&ioc->diagLock, flags); - return 0; + return FAILED; } spin_unlock_irqrestore(&ioc->diagLock, flags); @@ -2792,6 +2672,37 @@ if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM) doTask = 0; + /* Wait a fixed amount of time for the TM pending flag to be cleared. + * If we time out and not bus reset, then we return a FAILED status to the caller. + * The call to mptscsih_tm_pending_wait() will set the pending flag if we are + * successful. Otherwise, reload the FW. + */ + if (mptscsih_tm_pending_wait(hd) == FAILED) { + if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { + dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: " + "Timed out waiting for last TM (%d) to complete! \n", + hd->ioc->name, hd->tmPending)); + return FAILED; + } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { + dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: " + "Timed out waiting for last TM (%d) to complete! \n", + hd->ioc->name, hd->tmPending)); + return FAILED; + } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { + dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: " + "Timed out waiting for last TM (%d) to complete! \n", + hd->ioc->name, hd->tmPending)); + if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)) + return FAILED; + + doTask = 0; + } + } else { + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + hd->tmPending |= (1 << type); + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + } + /* Is operational? */ ioc_raw_state = mpt_GetIocState(hd->ioc, 0); @@ -2799,7 +2710,7 @@ #ifdef MPT_DEBUG_RESET if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { printk(MYIOC_s_WARN_FMT - "TM Handler: IOC Not operational! state 0x%x Calling HardResetHandler\n", + "TM Handler: IOC Not operational(0x%x)!\n", hd->ioc->name, ioc_raw_state); } #endif @@ -2811,23 +2722,24 @@ */ if (hd->hard_resets < -1) hd->hard_resets++; - rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, timeout, sleepFlag); + rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag); if (rc) { printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); } else { dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); } } -#ifdef DROP_TEST - numTMrequested++; - if (numTMrequested > 5) { - rc = 0; /* set to 1 to force a hard reset */ - numTMrequested = 0; - } + +#ifdef MPTSCSIH_DBG_TIMEOUT + if (hd->ioc->timeout_hard) + rc = 1; #endif - if (rc || ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw)) { - dtmprintk((MYIOC_s_INFO_FMT "Falling through to HardReset! \n", + /* Only fall through to the HRH if this is a bus reset + */ + if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || + ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { + dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", hd->ioc->name)); rc = mpt_HardResetHandler(hd->ioc, sleepFlag); } @@ -2857,7 +2769,7 @@ * else other non-zero value returned. */ static int -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag) +mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; @@ -2879,7 +2791,7 @@ */ pScsiTm = (SCSITaskMgmt_t *) mf; pScsiTm->TargetID = target; - pScsiTm->Bus = hd->port; + pScsiTm->Bus = channel; pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; @@ -2953,8 +2865,11 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p, numIOs=%d)\n", - hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + if (hd->resetPending) + return FAILED; + + printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n", + hd->ioc->name, SCpnt); if (hd->timeouts < -1) hd->timeouts++; @@ -2968,38 +2883,21 @@ search_doneQ_for_cmd(hd, SCpnt); SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " "Command not in the active list! (sc=%p)\n", hd->ioc->name, SCpnt)); return SUCCESS; } - /* Wait a fixed amount of time for the TM pending flag to be cleared. - * If we time out, then we return a FAILED status to the caller. This - * call to mptscsih_tm_pending_wait() will set the pending flag if we are - * successful. - */ - spin_unlock_irq(host_lock); - if (mptscsih_tm_pending_wait(hd) == FAILED){ - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "Timed out waiting for previous TM to complete! " - "(sc = %p)\n", - hd->ioc->name, SCpnt)); - spin_lock_irq(host_lock); - return FAILED; - } - spin_lock_irq(host_lock); - /* If this command is pended, then timeout/hang occurred * during DV. Post command and flush pending Q * and then following up with the reset request. */ if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); + mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); post_pendingQ_commands(hd); dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "Found command in pending queue! (sc=%p)\n", + "Posting pended cmd! (sc=%p)\n", hd->ioc->name, SCpnt)); } @@ -3017,7 +2915,7 @@ spin_unlock_irq(host_lock); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - SCpnt->device->id, SCpnt->device->lun, + SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP) < 0) { @@ -3064,31 +2962,21 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p, numIOs=%d)\n", - hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + if (hd->resetPending) + return FAILED; - /* Unsupported for SCSI. Suppored for FCP + printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", + hd->ioc->name, SCpnt); + + /* Unsupported for SCSI. Supported for FCP */ if (hd->is_spi) return FAILED; - /* Wait a fixed amount of time for the TM pending flag to be cleared. - * If we time out, then we return a FAILED status to the caller. This - * call to mptscsih_tm_pending_wait() will set the pending flag if we are - * successful. - */ spin_unlock_irq(host_lock); - if (mptscsih_tm_pending_wait(hd) == FAILED) { - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " - "Timed out waiting for previous TM to complete! " - "(sc = %p)\n", - hd->ioc->name, SCpnt)); - spin_lock_irq(host_lock); - return FAILED; - } - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - SCpnt->device->id, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP) + SCpnt->device->channel, SCpnt->device->id, + 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP) < 0){ /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. @@ -3129,30 +3017,19 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p, numIOs=%d)\n", - hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n", + hd->ioc->name, SCpnt); if (hd->timeouts < -1) hd->timeouts++; - /* Wait a fixed amount of time for the TM pending flag to be cleared. - * If we time out, then we return a FAILED status to the caller. This - * call to mptscsih_tm_pending_wait() will set the pending flag if we are - * successful. - */ - spin_unlock_irq(host_lock); - if (mptscsih_tm_pending_wait(hd) == FAILED) { - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " - "Timed out waiting for previous TM to complete! " - "(sc = %p)\n", - hd->ioc->name, SCpnt)); - spin_lock_irq(host_lock); - return FAILED; - } - /* We are now ready to execute the task management request. */ + spin_unlock_irq(host_lock); +// printk("testing start : mptscsih_schedule_reset\n"); +// mptscsih_schedule_reset(hd); +// printk("testing end: mptscsih_schedule_reset\n"); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP) + SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP) < 0){ /* The TM request failed and the subsequent FW-reload failed! @@ -3197,8 +3074,6 @@ printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n", hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); /* If our attempts to reset the host failed, then return a failed * status. The host will be taken off line by the SCSI mid-layer. @@ -3274,7 +3149,7 @@ { SCSITaskMgmtReply_t *pScsiTmReply; SCSITaskMgmt_t *pScsiTmReq; - MPT_SCSI_HOST *hd = NULL; + MPT_SCSI_HOST *hd; unsigned long flags; u8 tmType = 0; @@ -3325,10 +3200,7 @@ */ if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) hd->abortSCpnt = NULL; -#ifdef DROP_TEST - if (dropMfPtr) - dropTestBad++; -#endif + /* If an internal command is present * or the TM failed - reload the FW. * FC FW may respond FAILED to an ABORT @@ -3349,17 +3221,9 @@ hd->abortSCpnt = NULL; flush_doneQ(hd); -#ifdef DROP_TEST - if (dropMfPtr) - dropTestOK++; -#endif } } -#ifdef DROP_TEST - mptscsih_flush_drop_test(hd); -#endif - hd->tmPtr = NULL; spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; @@ -3438,15 +3302,14 @@ hd = (MPT_SCSI_HOST *)host->hostdata; - if (hd == NULL) - return ENODEV; + return -ENODEV; if ((vdev = hd->Targets[device->id]) == NULL) { if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n", - hd->ioc->name, (int)sizeof(VirtDevice)); - return ENOMEM; + hd->ioc->name, (int)sizeof(VirtDevice)); + return -ENOMEM; } else { memset(vdev, 0, sizeof(VirtDevice)); rwlock_init(&vdev->VdevLock); @@ -3478,7 +3341,7 @@ VirtDevice *vdev; hd = (MPT_SCSI_HOST *)host->hostdata; - + if (hd == NULL) return; @@ -3489,8 +3352,8 @@ if ((vdev = hd->Targets[device->id]) != NULL) { vdev->num_luns--; - if (vdev->luns & (1 << device->lun)) - vdev->luns &= ~(1 << device->lun); + if (vdev->luns[0] & (1 << device->lun)) + vdev->luns[0] &= ~(1 << device->lun); /* Free device structure only if number of luns is 0. */ @@ -3499,16 +3362,20 @@ hd->Targets[device->id] = NULL; if (hd->is_spi) { - hd->ioc->spi_data.dvStatus[device->id] = MPT_SCSICFG_NEGOTIATE; + hd->ioc->spi_data.dvStatus[device->id] = + MPT_SCSICFG_NEGOTIATE; if (hd->negoNvram == 0) - hd->ioc->spi_data.dvStatus[device->id] |= MPT_SCSICFG_DV_NOT_DONE; + hd->ioc->spi_data.dvStatus[device->id] + |= MPT_SCSICFG_DV_NOT_DONE; /* Don't alter isRaid, not allowed to move * volumes on a running system. */ - if (hd->ioc->spi_data.isRaid & (1 << (device->id))) - hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; + if (hd->ioc->spi_data.isRaid & (1 << + (device->id))) + hd->ioc->spi_data.forceDv |= + MPT_SCSICFG_RELOAD_IOC_PG3; } } } @@ -3525,205 +3392,76 @@ int mptscsih_slave_configure(Scsi_Device *device) { - struct Scsi_Host *host = device->host; - VirtDevice *vdev; - MPT_SCSI_HOST *hd; - - hd = (MPT_SCSI_HOST *)host->hostdata; - - dsprintk((KERN_INFO "slave_configure: device @ %p, id=%d, LUN=%d, channel=%d\n", - device, device->id, device->lun, device->channel)); - dsprintk((KERN_INFO "sdtr %d wdtr %d ppr %d inq length=%d\n", - device->sdtr, device->wdtr, device->ppr, device->inquiry_len)); - dsprintk(("tagged %d simple %d ordered %d\n", - device->tagged_supported, device->simple_tags, device->ordered_tags)); - - /* set target parameters, queue depths, set dv flags ? */ - if (hd && (hd->Targets != NULL)) { - vdev = hd->Targets[device->id]; - - if (vdev && !(vdev->tflags & MPT_TARGET_FLAGS_CONFIGURED)) { - /* Configure only the first discovered LUN - */ - vdev->raidVolume = 0; - if (hd->is_spi && (hd->ioc->spi_data.isRaid & (1 << (device->id)))) { - vdev->raidVolume = 1; - ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", device->id)); - } - - mptscsih_target_settings(hd, vdev, device); + struct Scsi_Host *sh = device->host; + VirtDevice *pTarget; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata; - vdev->tflags |= MPT_TARGET_FLAGS_CONFIGURED; - } + if ((hd == NULL) || (hd->Targets == NULL)) { + return 0; + } - if (vdev) { - /* set the queue depth for all devices - */ - if (!device->tagged_supported || - !(vdev->tflags & MPT_TARGET_FLAGS_Q_YES)) { + dsprintk((MYIOC_s_INFO_FMT + "device @ %p, id=%d, LUN=%d, channel=%d\n", + hd->ioc->name, device, device->id, device->lun, device->channel)); + dsprintk((MYIOC_s_INFO_FMT + "sdtr %d wdtr %d ppr %d inq length=%d\n", + hd->ioc->name, device->sdtr, device->wdtr, + device->ppr, device->inquiry_len)); + + if (device->id > sh->max_id) { + /* error case, should never happen */ + scsi_adjust_queue_depth(device, 0, 1); + goto slave_configure_exit; + } + + pTarget = hd->Targets[device->id]; + + if (pTarget == NULL) { + /* error case - don't know about this device */ + scsi_adjust_queue_depth(device, 0, 1); + goto slave_configure_exit; + } + + mptscsih_initTarget(hd, device->channel, device->id, device->lun, + device->inquiry, device->inquiry_len ); + scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, + MPT_SCSI_CMD_PER_DEV_HIGH); + if ( hd->is_spi ) { + if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { + if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) scsi_adjust_queue_depth(device, 0, 1); - } else if (vdev->type == 0x00 - && (vdev->minSyncFactor <= MPT_ULTRA160 || !hd->is_spi)) { + else if (((pTarget->inq_data[0] & 0x1f) == 0x00) + && (pTarget->minSyncFactor <= MPT_ULTRA160 )) scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, - MPT_SCSI_CMD_PER_DEV_HIGH); - } else { + MPT_SCSI_CMD_PER_DEV_HIGH); + else scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, - MPT_SCSI_CMD_PER_DEV_LOW); - } - - vdev->luns |= (1 << device->lun); - vdev->tflags |= MPT_TARGET_FLAGS_CONFIGURED; - } - } - return 0; -} -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Update the target negotiation parameters based on the - * the Inquiry data, adapter capabilities, and NVRAM settings. - * - */ -static void -mptscsih_target_settings(MPT_SCSI_HOST *hd, VirtDevice *target, Scsi_Device *sdev) -{ - ScsiCfgData *pspi_data = &hd->ioc->spi_data; - int id = (int) target->target_id; - int nvram; - u8 width = MPT_NARROW; - u8 factor = MPT_ASYNC; - u8 offset = 0; - u8 nfactor; - u8 noQas = 1; - - ddvtprintk((KERN_INFO "set Target: (id %d) \n", id)); - - if (!hd->is_spi) { - /* FC - only care about QTag support - */ - if (sdev->tagged_supported) - target->tflags |= MPT_TARGET_FLAGS_Q_YES; - return; - } - - /* SCSI - Set flags based on Inquiry data - */ - if (sdev->scsi_level < 2) { - width = 0; - factor = MPT_ULTRA2; - offset = pspi_data->maxSyncOffset; - } else { - width = sdev->wdtr; - if (sdev->sdtr) { - if (sdev->ppr) { - /* U320 requires IU capability */ - if ((sdev->inquiry_len > 56) && (sdev->inquiry[56] & 0x01)) - factor = MPT_ULTRA320; - else - factor = MPT_ULTRA160; - } else - factor = MPT_ULTRA2; - - /* If RAID, never disable QAS - * else if non RAID, do not disable - * QAS if bit 1 is set - * bit 1 QAS support, non-raid only - * bit 0 IU support - */ - if ((target->raidVolume == 1) || - ((sdev->inquiry_len > 56) && (sdev->inquiry[56] & 0x02))) - noQas = 0; - - offset = pspi_data->maxSyncOffset; - + MPT_SCSI_CMD_PER_DEV_LOW); } else { - factor = MPT_ASYNC; - offset = 0; + /* error case - No Inq. Data */ + scsi_adjust_queue_depth(device, 0, 1); } } - /* Update tflags based on NVRAM settings. (SCSI only) - */ - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = pspi_data->nvram[id]; - nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - - if (width) - width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - - if (offset > 0) { - /* Ensure factor is set to the - * maximum of: adapter, nvram, inquiry - */ - if (nfactor) { - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; - - factor = MAX (factor, nfactor); - if (factor == MPT_ASYNC) - offset = 0; - } else { - offset = 0; - factor = MPT_ASYNC; - } - } else - factor = MPT_ASYNC; - } + dsprintk((MYIOC_s_INFO_FMT + "Queue depth=%d, tflags=%x\n", + hd->ioc->name, device->queue_depth, pTarget->tflags)); - /* Make sure data is consistent - */ - if ((!width) && (factor < MPT_ULTRA2)) - factor = MPT_ULTRA2; - - /* Save the data to the target structure. - */ - target->minSyncFactor = factor; - target->maxOffset = offset; - target->maxWidth = width; - if (sdev->tagged_supported) - target->tflags |= MPT_TARGET_FLAGS_Q_YES; - - /* Disable unused features. - */ - target->negoFlags = pspi_data->noQas; - if (!width) - target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; + dsprintk((MYIOC_s_INFO_FMT + "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n", + hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor)); - if (!offset) - target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; +slave_configure_exit: - if (noQas) - target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - - /* GEM, processor WORKAROUND - */ - target->type = sdev->inquiry[0] & 0x1F; - if ((target->type == 0x03) || (target->type > 0x08)){ - target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); - pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; - } - - /* Disable QAS if mixed configuration case - */ - if ((noQas) && (!pspi_data->noQas) && (target->type == 0x00)){ - VirtDevice *vdev; - int ii; + dsprintk((MYIOC_s_INFO_FMT + "tagged %d, simple %d, ordered %d\n", + hd->ioc->name,device->tagged_supported, device->simple_tags, + device->ordered_tags)); - ddvtprintk((KERN_INFO "Disabling QAS!\n")); - pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS; - for (ii = 0; ii < id; ii++) { - vdev = hd->Targets[id]; - if (vdev != NULL) - vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - } - } - - ddvtprintk((KERN_INFO "Final settings id %d: dvstatus 0x%x\n", sdev->id, pspi_data->dvStatus[id])); - ddvtprintk(("wide %d, factor 0x%x offset 0x%x neg flags 0x%x flags 0x%x\n", - width, factor, offset, target->negoFlags, target->tflags)); - - return; + return 0; } + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Private routines... @@ -3789,11 +3527,10 @@ thisIo.SCSIStatus = pScsiReply->SCSIStatus; thisIo.DoDisplay = 1; if (hd->is_multipath) - sprintf(devFoo, "%d:%d:%d \"%s\"", + sprintf(devFoo, "%d:%d:%d", hd->ioc->id, pReq->TargetID, - pReq->LUN[1], - target->dev_vol_name); + pReq->LUN[1]); else sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun); thisIo.DevIDStr = devFoo; @@ -3842,7 +3579,7 @@ unsigned long flags; MPT_DONE_Q *buffer; MPT_FRAME_HDR *mf = NULL; - MPT_FRAME_HDR *cmdMfPtr = NULL; + MPT_FRAME_HDR *cmdMfPtr; ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name)); cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); @@ -3911,7 +3648,7 @@ continue; } - mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf); + mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) { @@ -3930,12 +3667,13 @@ static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { - MPT_SCSI_HOST *hd = NULL; + MPT_SCSI_HOST *hd; unsigned long flags; dtmprintk((KERN_WARNING MYNAM ": IOC %s_reset routed to SCSI host driver!\n", - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")); + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); /* If a FW reload request arrives after base installed but * before all scsi hosts have been attached, then an alt_ioc @@ -3946,9 +3684,8 @@ else hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (reset_phase == MPT_IOC_PRE_RESET) { - dtmprintk((MYIOC_s_WARN_FMT "Do Pre-Diag Reset handling\n", - ioc->name)); + if (reset_phase == MPT_IOC_SETUP_RESET) { + dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name)); /* Clean Up: * 1. Set Hard Reset Pending Flag @@ -3956,6 +3693,15 @@ */ hd->resetPending = 1; +#if 0 + /* calling mod_timer() panics in 2.6 kernel... + * need to investigate + */ + mptscsih_reset_timeouts (hd); +#endif + } else if (reset_phase == MPT_IOC_PRE_RESET) { + dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name)); + /* 2. Flush running commands * Clean drop test code - if compiled * Clean ScsiLookup (and associated memory) @@ -3964,9 +3710,6 @@ /* 2a. Drop Test Command. */ -#ifdef DROP_TEST - mptscsih_flush_drop_test(hd); -#endif /* 2b. Reply to OS all known outstanding I/O commands. */ @@ -3979,7 +3722,6 @@ if (hd->cmdPtr) { del_timer(&hd->timer); mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr); - atomic_dec(&queue_depth); } /* 2d. If a task management has not completed, @@ -3990,12 +3732,14 @@ mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr); } - dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset handling complete.\n", - ioc->name)); +#ifdef MPTSCSIH_DBG_TIMEOUT + ioc->timeout_hard = 0; +#endif + + dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); } else { - dtmprintk((MYIOC_s_WARN_FMT "Do Post-Diag Reset handling\n", - ioc->name)); + dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name)); /* Once a FW reload begins, all new OS commands are * redirected to the doneQ w/ a reset status. @@ -4052,10 +3796,6 @@ */ flush_doneQ(hd); - dtmprintk((MYIOC_s_WARN_FMT "Post-Reset handling complete.\n", - ioc->name)); - - /* 8. Set flag to force DV and re-read IOC Page 3 */ if (hd->is_spi) { @@ -4063,6 +3803,8 @@ ddvtprintk(("Set reload IOC Pg3 Flag\n")); } + dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); + } return 1; /* currently means nothing really */ @@ -4571,6 +4313,268 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mptscsih_initTarget - Target, LUN alloc/free functionality. + * @hd: Pointer to MPT_SCSI_HOST structure + * @bus_id: Bus number (?) + * @target_id: SCSI target id + * @lun: SCSI LUN id + * @data: Pointer to data + * @dlen: Number of INQUIRY bytes + * + * NOTE: It's only SAFE to call this routine if data points to + * sane & valid STANDARD INQUIRY data! + * + * Allocate and initialize memory for this target. + * Save inquiry data. + * + */ +static void +mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen) +{ + int indexed_lun, lun_index; + VirtDevice *vdev; + char data_56; + + dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", + hd->ioc->name, bus_id, target_id, lun, hd)); + + /* Is LUN supported? If so, upper 3 bits will be 0 + * in first byte of inquiry data. + */ + if (data[0] & 0xe0) + return; + + vdev = hd->Targets[target_id]; + + lun_index = (lun >> 5); /* 32 luns per lun_index */ + indexed_lun = (lun % 32); + vdev->luns[lun_index] |= (1 << indexed_lun); + + vdev->raidVolume = 0; + if (hd->is_spi) { + if (hd->ioc->spi_data.isRaid & (1 << target_id)) { + vdev->raidVolume = 1; + ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id)); + } + } + + if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { + if ( dlen > 8 ) { + memcpy (vdev->inq_data, data, 8); + } else { + memcpy (vdev->inq_data, data, dlen); + } + vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; + + /* If LUN 0, tape and have not done DV, set the DV flag. + */ + if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) { + ScsiCfgData *pSpi = &hd->ioc->spi_data; + if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE) + pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV; + } + + if ( (data[0] == SCSI_TYPE_PROC) && + !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { + if ( dlen > 49 ) { + vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; + if ( data[44] == 'S' && + data[45] == 'A' && + data[46] == 'F' && + data[47] == '-' && + data[48] == 'T' && + data[49] == 'E' ) { + vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; + mptscsih_writeIOCPage4(hd, target_id, bus_id); + } + } else { + /* Treat all Processors as SAF-TE if + * command line option is set */ + if ( hd->ioc->spi_data.Saf_Te ) { + vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; + mptscsih_writeIOCPage4(hd, target_id, bus_id); + } + } + } + + data_56 = 0; + if (dlen > 56) { + if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) { + /* Update the target capabilities + */ + data_56 = data[56]; + vdev->tflags |= MPT_TARGET_FLAGS_VALID_56; + } + } + mptscsih_setTargetNegoParms(hd, vdev, data_56); + } + + dprintk((KERN_INFO " target = %p\n", vdev)); + return; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * Update the target negotiation parameters based on the + * the Inquiry data, adapter capabilities, and NVRAM settings. + * + */ +void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) +{ + ScsiCfgData *pspi_data = &hd->ioc->spi_data; + int id = (int) target->target_id; + int nvram; + char canQ = 0; + VirtDevice *vdev; + int ii; + u8 width = MPT_NARROW; + u8 factor = MPT_ASYNC; + u8 offset = 0; + u8 version, nfactor; + u8 noQas = 1; + + if (!hd->is_spi) { + if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { + if (target->inq_data[7] & 0x02) + target->tflags |= MPT_TARGET_FLAGS_Q_YES; + } + return; + } + + target->negoFlags = pspi_data->noQas; + + /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine + * support. If available, default QAS to off and allow enabling. + * If not available, default QAS to on, turn off for non-disks. + */ + + /* Set flags based on Inquiry data + */ + if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { + version = target->inq_data[2] & 0x07; + if (version < 2) { + width = 0; + factor = MPT_ULTRA2; + offset = pspi_data->maxSyncOffset; + } else { + if (target->inq_data[7] & 0x20) { + width = 1; + } + + if (target->inq_data[7] & 0x10) { + /* bits 2 & 3 show DT support + */ + if ((byte56 & 0x04) == 0) + factor = MPT_ULTRA2; + else if ((byte56 & 0x03) == 0) + factor = MPT_ULTRA160; + else + factor = MPT_ULTRA320; + offset = pspi_data->maxSyncOffset; + + /* If RAID, never disable QAS + * else if non RAID, do not disable + * QAS if bit 1 is set + * bit 1 QAS support, non-raid only + * bit 0 IU support + */ + if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0)) + noQas = 0; + } else { + factor = MPT_ASYNC; + offset = 0; + } + } + + if (target->inq_data[7] & 0x02) { + canQ = 1; + } + + /* Update tflags based on NVRAM settings. (SCSI only) + */ + if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { + nvram = pspi_data->nvram[id]; + nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; + + if (width) + width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; + + if (offset > 0) { + /* Ensure factor is set to the + * maximum of: adapter, nvram, inquiry + */ + if (nfactor) { + if (nfactor < pspi_data->minSyncFactor ) + nfactor = pspi_data->minSyncFactor; + + factor = MAX (factor, nfactor); + if (factor == MPT_ASYNC) + offset = 0; + } else { + offset = 0; + factor = MPT_ASYNC; + } + } else { + factor = MPT_ASYNC; + } + } + + /* Make sure data is consistent + */ + if ((!width) && (factor < MPT_ULTRA2)) { + factor = MPT_ULTRA2; + } + + /* Save the data to the target structure. + */ + target->minSyncFactor = factor; + target->maxOffset = offset; + target->maxWidth = width; + if (canQ) { + target->tflags |= MPT_TARGET_FLAGS_Q_YES; + } + + target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; + + /* Disable unused features. + */ + if (!width) + target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; + + if (!offset) + target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; + + /* GEM, processor WORKAROUND + */ + if (((target->inq_data[0] & 0x1F) == 0x03) + || ((target->inq_data[0] & 0x1F) > 0x08)) { + target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); + pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; + } else { + if (noQas && (pspi_data->noQas == 0)) { + pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; + target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + + /* Disable QAS in a mixed configuration case + */ + +// ddvtprintk((KERN_INFO "Disabling QAS!\n")); + for (ii = 0; ii < id; ii++) { + if ( (vdev = hd->Targets[ii]) ) { + vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + } + } + } + } + } + + return; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return. * Else set the NEED_DV flag after Read Capacity Issued (disks) * or Mode Sense (cdroms). @@ -4581,7 +4585,7 @@ static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) { u8 cmd; - + if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) return; @@ -4609,16 +4613,14 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * If no Target (old) or Target unconfigured (new) and bus reset on 1st I/O, - * set the flag to prevent any future negotiations to this device. + * If no Target, bus reset on 1st I/O. Set the flag to + * prevent any future negotiations to this device. */ static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id) { - if (hd->Targets) { - VirtDevice *vdev = hd->Targets[target_id]; - if ((vdev == NULL) || !(vdev->tflags & MPT_TARGET_FLAGS_CONFIGURED)) - hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO; - } + + if ((hd->Targets) && (hd->Targets[target_id] == NULL)) + hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO; return; } @@ -4691,9 +4693,9 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) { MPT_ADAPTER *ioc = hd->ioc; - Config_t *pReq = NULL; - SCSIDevicePage1_t *pData = NULL; - VirtDevice *pTarget = NULL; + Config_t *pReq; + SCSIDevicePage1_t *pData; + VirtDevice *pTarget; MPT_FRAME_HDR *mf; dma_addr_t dataDma; u16 req_idx; @@ -4784,13 +4786,11 @@ /* If id is not a raid volume, get the updated * transmission settings from the target structure. */ - if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume - && (pTarget->tflags & MPT_TARGET_FLAGS_CONFIGURED)) { + if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) { width = pTarget->maxWidth; factor = pTarget->minSyncFactor; offset = pTarget->maxOffset; negoFlags = pTarget->negoFlags; - pTarget = NULL; } if (flags & MPT_SCSICFG_BLK_NEGO) @@ -4832,9 +4832,8 @@ pReq->Reserved = 0; pReq->ChainOffset = 0; pReq->Function = MPI_FUNCTION_CONFIG; - pReq->Reserved1[0] = 0; - pReq->Reserved1[1] = 0; - pReq->Reserved1[2] = 0; + pReq->ExtPageLength = 0; + pReq->ExtPageType = 0; pReq->MsgFlags = 0; for (ii=0; ii < 8; ii++) { pReq->Reserved2[ii] = 0; @@ -4861,18 +4860,97 @@ pData->Reserved = 0; pData->Configuration = cpu_to_le32(configuration); - dsprintk((MYIOC_s_INFO_FMT + dprintk((MYIOC_s_INFO_FMT "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n", ioc->name, id, (id | (bus<<8)), requested, configuration)); - mptscsih_put_msgframe(ScsiDoneCtx, ioc->id, mf); + mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf); } return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* mptscsih_writeIOCPage4 - write IOC Page 4 + * @hd: Pointer to a SCSI Host Structure + * @target_id: write IOC Page4 for this ID & Bus + * + * Return: -EAGAIN if unable to obtain a Message Frame + * or 0 if success. + * + * Remark: We do not wait for a return, write pages sequentially. + */ +static int +mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) +{ + MPT_ADAPTER *ioc = hd->ioc; + Config_t *pReq; + IOCPage4_t *IOCPage4Ptr; + MPT_FRAME_HDR *mf; + dma_addr_t dataDma; + u16 req_idx; + u32 frameOffset; + u32 flagsLength; + int ii; + + /* Get a MF for this command. + */ + if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) { + dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", + ioc->name)); + return -EAGAIN; + } + + ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n", + ioc->name, mf, target_id)); + + /* Set the request and the data pointers. + * Place data at end of MF. + */ + pReq = (Config_t *)mf; + + req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); + frameOffset = ioc->req_sz - sizeof(IOCPage4_t); + + /* Complete the request frame (same for all requests). + */ + pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + pReq->Reserved = 0; + pReq->ChainOffset = 0; + pReq->Function = MPI_FUNCTION_CONFIG; + pReq->ExtPageLength = 0; + pReq->ExtPageType = 0; + pReq->MsgFlags = 0; + for (ii=0; ii < 8; ii++) { + pReq->Reserved2[ii] = 0; + } + + IOCPage4Ptr = ioc->spi_data.pIocPg4; + dataDma = ioc->spi_data.IocPg4_dma; + ii = IOCPage4Ptr->ActiveSEP++; + IOCPage4Ptr->SEP[ii].SEPTargetID = target_id; + IOCPage4Ptr->SEP[ii].SEPBus = bus; + pReq->Header = IOCPage4Ptr->Header; + pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 )); + + /* Add a SGE to the config request. + */ + flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | + (IOCPage4Ptr->Header.PageLength + ii) * 4; + + mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); + + dsprintk((MYIOC_s_INFO_FMT + "writeIOCPage4: pgaddr 0x%x\n", + ioc->name, (target_id | (bus<<8)))); + + mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf); + + return 0; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* mptscsih_taskmgmt_timeout - Call back for timeout on a * task management request. * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long @@ -4982,8 +5060,6 @@ ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", hd->ioc->name, mf, mr, req_idx)); - atomic_dec(&queue_depth); - hd->pLocal = &hd->localReply; hd->pLocal->scsiStatus = 0; @@ -5042,7 +5118,7 @@ u8 *sense_data; int sz; - /* save sense data in global & target structure + /* save sense data in global structure */ completionCode = MPT_SCANDV_SENSE; hd->pLocal->scsiStatus = pReply->SCSIStatus; @@ -5215,7 +5291,7 @@ hd->cmdPtr = mf; add_timer(&hd->timer); - mptscsih_put_msgframe(ScsiScanDvCtx, hd->ioc->id, mf); + mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf); wait_event(scandv_waitq, scandv_wait_done); if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD)) @@ -5452,7 +5528,7 @@ hd->cmdPtr = mf; add_timer(&hd->timer); - mptscsih_put_msgframe(ScsiScanDvCtx, hd->ioc->id, mf); + mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf); wait_event(scandv_waitq, scandv_wait_done); if (hd->pLocal) { @@ -5490,7 +5566,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) { MPT_ADAPTER *ioc= hd->ioc; - VirtDevice *pTarget = NULL; + VirtDevice *pTarget; SCSIDevicePage1_t *pcfg1Data = NULL; INTERNAL_CMD iocmd; CONFIGPARMS cfg; @@ -5498,7 +5574,8 @@ ConfigPageHeader_t header1; int bus = 0; int id = 0; - int lun = 0; + int lun; + int indexed_lun, lun_index; int hostId = ioc->pfacts[portnum].PortSCSIID; int max_id; int requested, configuration, data; @@ -5593,7 +5670,9 @@ for (lun=0; lun <= MPT_LAST_LUN; lun++) { /* If LUN present, issue the command */ - if (pTarget->luns & (1<> 5); /* 32 luns per lun_index */ + indexed_lun = (lun % 32); + if (pTarget->luns[lun_index] & (1<Targets == NULL) @@ -5843,15 +5922,15 @@ * Return: None. */ static int -mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int id) +mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) { MPT_ADAPTER *ioc = hd->ioc; - VirtDevice *pTarget = NULL; - SCSIDevicePage1_t *pcfg1Data = NULL; - SCSIDevicePage0_t *pcfg0Data = NULL; - u8 *pbuf1 = NULL; - u8 *pbuf2 = NULL; - u8 *pDvBuf = NULL; + VirtDevice *pTarget; + SCSIDevicePage1_t *pcfg1Data; + SCSIDevicePage0_t *pcfg0Data; + u8 *pbuf1; + u8 *pbuf2; + u8 *pDvBuf; dma_addr_t dvbuf_dma = -1; dma_addr_t buf1_dma = -1; dma_addr_t buf2_dma = -1; @@ -5871,6 +5950,7 @@ int patt; int repeat; int retcode = 0; + int nfactor = MPT_ULTRA320; char firstPass = 1; char doFallback = 0; char readPage0; @@ -5883,14 +5963,17 @@ if (ioc->spi_data.sdp0length == 0) return 0; - if (id == ioc->pfacts[portnum].PortSCSIID) + /* If multiple buses are used, require that the initiator + * id be the same on all buses. + */ + if (id == ioc->pfacts[0].PortSCSIID) return 0; lun = 0; - bus = 0; + bus = (u8) bus_number; ddvtprintk((MYIOC_s_NOTE_FMT - "DV started: numIOs %d bus=%d, id %d dv @ %p\n", - ioc->name, atomic_read(&queue_depth), bus, id, &dv)); + "DV started: bus=%d, id %d dv @ %p\n", + ioc->name, bus, id, &dv)); /* Prep DV structure */ @@ -5916,11 +5999,11 @@ iocmd.rsvd = iocmd.rsvd2 = 0; pTarget = hd->Targets[id]; - if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_CONFIGURED)) { + if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { /* Another GEM workaround. Check peripheral device type, * if PROCESSOR, quit DV. */ - if ((pTarget->type == 0x03) || (pTarget->type > 0x08)) { + if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) { pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); return 0; } @@ -5992,24 +6075,34 @@ /* Skip this ID? Set cfg.hdr to force config page write */ - if ((ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID) && - (!(ioc->spi_data.nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE))) { + { + ScsiCfgData *pspi_data = &hd->ioc->spi_data; + if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { + /* Set the factor from nvram */ + nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; + if (nfactor < pspi_data->minSyncFactor ) + nfactor = pspi_data->minSyncFactor; - ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", - ioc->name, bus, id, lun)); + if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) || + (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) { - dv.cmd = MPT_SET_MAX; - mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); - cfg.hdr = &header1; - /* Double writes to SDP1 can cause problems, - * skip save of the final negotiated settings to - * SCSI device page 1. - */ - cfg.physAddr = cfg1_dma_addr; - cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfg.dir = 1; - mpt_config(hd->ioc, &cfg); - goto target_done; + ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", + ioc->name, bus, id, lun)); + + dv.cmd = MPT_SET_MAX; + mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); + cfg.hdr = &header1; + + /* Save the final negotiated settings to + * SCSI device page 1. + */ + cfg.physAddr = cfg1_dma_addr; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; + mpt_config(hd->ioc, &cfg); + goto target_done; + } + } } /* Finish iocmd inititialization - hidden or visible disk? */ @@ -6059,7 +6152,7 @@ sz = SCSI_STD_INQUIRY_BYTES; rc = MPT_SCANDV_GOOD; while (1) { - ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test.\n", ioc->name)); + ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id)); retcode = 0; dv.cmd = MPT_SET_MIN; mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); @@ -6131,6 +6224,14 @@ } } + /* Reset the size for disks + */ + inq0 = (*pbuf1) & 0x1F; + if ((inq0 == 0) && pTarget && !pTarget->raidVolume) { + sz = 0x40; + iocmd.size = sz; + } + /* Another GEM workaround. Check peripheral device type, * if PROCESSOR, quit DV. */ @@ -6140,6 +6241,28 @@ if (mptscsih_do_cmd(hd, &iocmd) < 0) goto target_done; + if (sz == 0x40) { + if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A) + && (pTarget->minSyncFactor > 0x09)) { + if ((pbuf1[56] & 0x04) == 0) + ; + else if ((pbuf1[56] & 0x01) == 1) { + pTarget->minSyncFactor = + nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320; + } else { + pTarget->minSyncFactor = + nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160; + } + + dv.max.factor = pTarget->minSyncFactor; + + if ((pbuf1[56] & 0x02) == 0) { + pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; + } + } + } + if (doFallback) dv.cmd = MPT_FALLBACK; else @@ -6223,7 +6346,7 @@ firstPass = 0; } } - ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test completed OK.\n", ioc->name)); + ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); inq0 = (*pbuf1) & 0x1F; /* Continue only for disks @@ -6231,6 +6354,9 @@ if (inq0 != 0) goto target_done; + if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY ) + goto target_done; + /* Start the Enhanced Test. * 0) issue TUR to clear out check conditions * 1) read capacity of echo (regular) buffer @@ -6671,8 +6797,8 @@ if (pDvBuf) pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); - ddvtprintk((MYIOC_s_INFO_FMT "DV Done. IOs outstanding = %d\n", - ioc->name, atomic_read(&queue_depth))); + ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n", + ioc->name)); return retcode; } @@ -6687,9 +6813,9 @@ static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) { - VirtDevice *pTarget = NULL; - SCSIDevicePage0_t *pPage0 = NULL; - SCSIDevicePage1_t *pPage1 = NULL; + VirtDevice *pTarget; + SCSIDevicePage0_t *pPage0; + SCSIDevicePage1_t *pPage1; int val = 0, data, configuration; u8 width = 0; u8 offset = 0; @@ -6841,7 +6967,6 @@ factor = MPT_ULTRA; width = MPT_WIDE; } else if ((factor == MPT_ULTRA) && width) { - factor = MPT_ULTRA; width = MPT_NARROW; } else if (factor < MPT_FAST) { factor = MPT_FAST; @@ -7072,9 +7197,9 @@ /* Commandline Parsing routines and defines. * * insmod format: - * insmod mptscsih mptscsih="width:1 dv:n factor:0x09" + * insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1" * boot format: - * mptscsih=width:1,dv:n,factor:0x8 + * mptscsih=width:1,dv:n,factor:0x8,saf-te:1 * */ #ifdef MODULE @@ -7087,11 +7212,13 @@ "dv:" "width:" "factor:" - ; /* DONNOT REMOVE THIS ';' */ + "saf-te:" + ; /* DO NOT REMOVE THIS ';' */ #define OPT_DV 1 #define OPT_MAX_WIDTH 2 #define OPT_MIN_SYNC_FACTOR 3 +#define OPT_SAF_TE 4 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int @@ -7146,6 +7273,10 @@ case OPT_MIN_SYNC_FACTOR: driver_setup.min_sync_fac = val; + break; + + case OPT_SAF_TE: + driver_setup.saf_te = val; break; default: diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h --- a/drivers/message/fusion/mptscsih.h Wed Mar 10 21:09:43 2004 +++ b/drivers/message/fusion/mptscsih.h Wed Mar 10 21:09:43 2004 @@ -15,7 +15,7 @@ * * (see also mptbase.c) * - * Copyright (c) 1999-2003 LSI Logic Corporation + * Copyright (c) 1999-2004 LSI Logic Corporation * Originally By: Steven J. Ralston * (mailto:netscape.net) * (mailto:mpt_linux_developer@lsil.com) @@ -70,11 +70,7 @@ * Try to keep these at 2^N-1 */ #define MPT_FC_CAN_QUEUE 127 -#if defined MPT_SCSI_USE_NEW_EH - #define MPT_SCSI_CAN_QUEUE 127 -#else - #define MPT_SCSI_CAN_QUEUE 63 -#endif +#define MPT_SCSI_CAN_QUEUE 127 #define MPT_SCSI_CMD_PER_DEV_HIGH 31 #define MPT_SCSI_CMD_PER_DEV_LOW 7 @@ -98,7 +94,7 @@ #define MPT_SCSI_SG_DEPTH 40 #endif -/* To disable domain validation, comment the +/* To disable domain validation, uncomment the * following line. No effect for FC devices. * For SCSI devices, driver will negotiate to * NVRAM settings (if available) or to maximum adapter @@ -114,12 +110,14 @@ #define MPTSCSIH_DOMAIN_VALIDATION 1 #define MPTSCSIH_MAX_WIDTH 1 #define MPTSCSIH_MIN_SYNC 0x08 +#define MPTSCSIH_SAF_TE 0 struct mptscsih_driver_setup { u8 dv; u8 max_width; u8 min_sync_fac; + u8 saf_te; }; @@ -128,6 +126,7 @@ MPTSCSIH_DOMAIN_VALIDATION, \ MPTSCSIH_MAX_WIDTH, \ MPTSCSIH_MIN_SYNC, \ + MPTSCSIH_SAF_TE, \ } diff -Nru a/drivers/message/fusion/scsi3.h b/drivers/message/fusion/scsi3.h --- a/drivers/message/fusion/scsi3.h Wed Mar 10 21:09:42 2004 +++ b/drivers/message/fusion/scsi3.h Wed Mar 10 21:09:42 2004 @@ -4,7 +4,7 @@ * (Ultimately) SCSI-3 definitions; for now, inheriting * SCSI-2 definitions. * - * Copyright (c) 1996-2003 Steven J. Ralston + * Copyright (c) 1996-2004 Steven J. Ralston * Written By: Steven J. Ralston (19960517) * (mailto:sjralston1@netscape.net) * (mailto:mpt_linux_developer@lsil.com) diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c --- a/drivers/scsi/53c700.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/53c700.c Wed Mar 10 21:09:42 2004 @@ -137,6 +137,9 @@ #include "scsi.h" #include "hosts.h" +#include +#include + #include "53c700.h" /* NOTE: For 64 bit drivers there are points in the code where we use @@ -173,6 +176,8 @@ STATIC struct device_attribute *NCR_700_dev_attrs[]; +STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; + static char *NCR_700_phase[] = { "", "after selection", @@ -236,6 +241,53 @@ NCR_700_MAX_OFFSET }; +/* This translates the SDTR message offset and period to a value + * which can be loaded into the SXFER_REG. + * + * NOTE: According to SCSI-2, the true transfer period (in ns) is + * actually four times this period value */ +static inline __u8 +NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, + __u8 offset, __u8 period) +{ + int XFERP; + + __u8 min_xferp = (hostdata->chip710 + ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP); + __u8 max_offset = (hostdata->chip710 + ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET); + + if(offset == 0) + return 0; + + if(period < hostdata->min_period) { + printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_SDTR_msg[3]*4); + period = hostdata->min_period; + } + XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; + if(offset > max_offset) { + printk(KERN_WARNING "53c700: Offset %d exceeds chip maximum, setting to %d\n", + offset, max_offset); + offset = max_offset; + } + if(XFERP < min_xferp) { + printk(KERN_WARNING "53c700: XFERP %d is less than minium, setting to %d\n", + XFERP, min_xferp); + XFERP = min_xferp; + } + return (offset & 0x0f) | (XFERP & 0x07)<<4; +} + +static inline __u8 +NCR_700_get_SXFER(Scsi_Device *SDp) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + + return NCR_700_offset_period_to_sxfer(hostdata, spi_offset(SDp), + spi_period(SDp)); +} + struct Scsi_Host * NCR_700_detect(Scsi_Host_Template *tpnt, struct NCR_700_Host_Parameters *hostdata) @@ -326,6 +378,8 @@ hostdata->cmd = NULL; host->max_id = 7; host->max_lun = NCR_700_MAX_LUNS; + BUG_ON(NCR_700_transport_template == NULL); + host->transportt = NCR_700_transport_template; host->unique_id = hostdata->base; host->base = hostdata->base; hostdata->eh_complete = NULL; @@ -520,40 +574,6 @@ hostdata->cmd = NULL; } -/* This translates the SDTR message offset and period to a value - * which can be loaded into the SXFER_REG. - * - * NOTE: According to SCSI-2, the true transfer period (in ns) is - * actually four times this period value */ -STATIC inline __u8 -NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, - __u8 offset, __u8 period) -{ - int XFERP; - __u8 min_xferp = (hostdata->chip710 - ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP); - __u8 max_offset = (hostdata->chip710 - ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET); - /* NOTE: NCR_700_SDTR_msg[3] contains our offer of the minimum - * period. It is set in NCR_700_chip_setup() */ - if(period < NCR_700_SDTR_msg[3]) { - printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_SDTR_msg[3]*4); - period = NCR_700_SDTR_msg[3]; - } - XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; - if(offset > max_offset) { - printk(KERN_WARNING "53c700: Offset %d exceeds chip maximum, setting to %d\n", - offset, max_offset); - offset = max_offset; - } - if(XFERP < min_xferp) { - printk(KERN_WARNING "53c700: XFERP %d is less than minium, setting to %d\n", - XFERP, min_xferp); - XFERP = min_xferp; - } - return (offset & 0x0f) | (XFERP & 0x07)<<4; -} - STATIC inline void NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp, struct NCR_700_command_slot *slot) @@ -724,11 +744,9 @@ * exact details of this calculation which is based on a * setting of the SXFER register */ min_period = 1000*(4+min_xferp)/(4*hostdata->sync_clock); - if(min_period > NCR_700_MIN_PERIOD) { - NCR_700_SDTR_msg[3] = min_period; - } - if(hostdata->chip710) - NCR_700_SDTR_msg[4] = NCR_710_MAX_OFFSET; + hostdata->min_period = NCR_700_MIN_PERIOD; + if(min_period > NCR_700_MIN_PERIOD) + hostdata->min_period = min_period; } STATIC void @@ -777,20 +795,25 @@ if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { __u8 period = hostdata->msgin[3]; __u8 offset = hostdata->msgin[4]; - __u8 sxfer; - if(offset != 0 && period != 0) - sxfer = NCR_700_offset_period_to_sxfer(hostdata, offset, period); - else - sxfer = 0; + if(offset == 0 || period == 0) { + offset = 0; + period = 0; + } - if(sxfer != NCR_700_get_SXFER(SCp->device)) { - printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n", - host->host_no, pun, lun, - offset, period*4); - - NCR_700_set_SXFER(SCp->device, sxfer); + if(NCR_700_is_flag_set(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION)) { + if(spi_offset(SCp->device) != 0) + printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n", + host->host_no, pun, lun, + offset, period*4); + else + printk(KERN_INFO "scsi%d: (%d:%d) Asynchronous\n", + host->host_no, pun, lun); + NCR_700_clear_flag(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); } + + spi_offset(SCp->device) = offset; + spi_period(SCp->device) = period; NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); @@ -870,7 +893,7 @@ case A_REJECT_MSG: if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { /* Rejected our sync negotiation attempt */ - NCR_700_set_SXFER(SCp->device, 0); + spi_period(SCp->device) = spi_offset(SCp->device) = 0; NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } else if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { @@ -1396,6 +1419,8 @@ NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, sizeof(NCR_700_SDTR_msg)); + hostdata->msgout[count+3] = spi_period(SCp->device); + hostdata->msgout[count+4] = spi_offset(SCp->device); count += sizeof(NCR_700_SDTR_msg); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } @@ -1967,9 +1992,51 @@ return SUCCESS; } +STATIC void +NCR_700_set_period(struct scsi_device *SDp, int period) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + + if(!hostdata->fast || period < hostdata->min_period) + return; + + spi_period(SDp) = period; + NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); + NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); +} + +STATIC void +NCR_700_set_offset(struct scsi_device *SDp, int offset) +{ + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + + if(!hostdata->fast || + offset > (hostdata->chip710 + ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET)) + return; + + /* if we're currently async, make sure the period is reasonable */ + if(spi_offset(SDp) == 0 && (spi_period(SDp) < hostdata->min_period || + spi_period(SDp) > 0xff)) + spi_period(SDp) = hostdata->min_period; + + spi_offset(SDp) = offset; + NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); + NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); +} + + + STATIC int NCR_700_slave_configure(Scsi_Device *SDp) { + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + /* to do here: allocate memory; build a queue_full list */ if(SDp->tagged_supported) { /* do TCQ stuff here */ @@ -1977,6 +2044,11 @@ /* initialise to default depth */ scsi_adjust_queue_depth(SDp, 0, SDp->host->cmd_per_lun); } + if(hostdata->fast) { + NCR_700_set_period(SDp, hostdata->min_period); + NCR_700_set_offset(SDp, hostdata->chip710 + ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET); + } return 0; } @@ -2033,3 +2105,25 @@ EXPORT_SYMBOL(NCR_700_detect); EXPORT_SYMBOL(NCR_700_release); EXPORT_SYMBOL(NCR_700_intr); + +static struct spi_function_template NCR_700_transport_functions = { + .set_period = NCR_700_set_period, + .set_offset = NCR_700_set_offset, +}; + +static int __init NCR_700_init(void) +{ + NCR_700_transport_template = spi_attach_transport(&NCR_700_transport_functions); + if(!NCR_700_transport_template) + return -ENODEV; + return 0; +} + +static void __exit NCR_700_exit(void) +{ + spi_release_transport(NCR_700_transport_template); +} + +module_init(NCR_700_init); +module_exit(NCR_700_exit); + diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h --- a/drivers/scsi/53c700.h Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/53c700.h Wed Mar 10 21:09:42 2004 @@ -99,19 +99,9 @@ #define NCR_700_DEV_NEGOTIATED_SYNC (1<<16) #define NCR_700_DEV_BEGIN_SYNC_NEGOTIATION (1<<17) #define NCR_700_DEV_BEGIN_TAG_QUEUEING (1<<18) -#define NCR_700_DEV_TAG_STARVATION_WARNED (1<<19) +#define NCR_700_DEV_PRINT_SYNC_NEGOTIATION (1<<19) static inline void -NCR_700_set_SXFER(Scsi_Device *SDp, __u8 sxfer) -{ - SDp->hostdata = (void *)(((long)SDp->hostdata & 0xffffff00) | - (sxfer & 0xff)); -} -static inline __u8 NCR_700_get_SXFER(Scsi_Device *SDp) -{ - return (((unsigned long)SDp->hostdata) & 0xff); -} -static inline void NCR_700_set_depth(Scsi_Device *SDp, __u8 depth) { long l = (long)SDp->hostdata; @@ -215,6 +205,7 @@ __u8 tag_negotiated; __u8 rev; __u8 reselection_id; + __u8 min_period; /* Free list, singly linked by ITL_forw elements */ struct NCR_700_command_slot *free_list; @@ -438,6 +429,7 @@ #symbol, A_##symbol##_used[i], val)); \ } \ } + static inline __u8 NCR_700_mem_readb(struct Scsi_Host *host, __u32 reg) diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/BusLogic.c Wed Mar 10 21:09:43 2004 @@ -140,7 +140,7 @@ Name, Copyright Notice, and Electronic Mail Address. */ -static void __init BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter) +static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter) { BusLogic_Announce("***** BusLogic SCSI Driver Version " BusLogic_DriverVersion " of " diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/Kconfig Wed Mar 10 21:09:43 2004 @@ -196,6 +196,25 @@ there should be no noticeable performance impact as long as you have logging turned off. +menu "SCSI Transport Attributes" + depends on SCSI + +config SCSI_SPI_ATTRS + tristate "Parallel SCSI (SPI) Transport Attributes" + depends on SCSI + help + If you wish to export transport-specific information about + each attached SCSI device to sysfs, say Y. Otherwise, say N. + +config SCSI_FC_ATTRS + tristate "FiberChannel Transport Attributes" + depends on SCSI + help + If you wish to export transport-specific information about + each attached FiberChannel device to sysfs, say Y. + Otherwise, say N. + +endmenu menu "SCSI low-level drivers" depends on SCSI!=n @@ -845,6 +864,7 @@ config SCSI_NCR_D700 tristate "NCR Dual 700 MCA SCSI support" depends on MCA && SCSI + select SCSI_SPI_ATTRS help This is a driver for the MicroChannel Dual 700 card produced by NCR and commonly used in 345x/35xx/4100 class machines. It always @@ -861,6 +881,7 @@ config SCSI_LASI700 tristate "HP Lasi SCSI support for 53c700/710" depends on GSC && SCSI + select SCSI_SPI_ATTRS help This is a driver for the SCSI controller in the Lasi chip found in many PA-RISC workstations & servers. If you do not know whether you @@ -1212,6 +1233,7 @@ config SCSI_SIM710 tristate "Simple 53c710 SCSI support (Compaq, NCR machines)" depends on (EISA || MCA) && SCSI + select SCSI_SPI_ATTRS ---help--- This driver for NCR53c710 based SCSI host adapters. diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile --- a/drivers/scsi/Makefile Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/Makefile Wed Mar 10 21:09:43 2004 @@ -22,6 +22,14 @@ obj-$(CONFIG_SCSI) += scsi_mod.o +# --- NOTE ORDERING HERE --- +# For kernel non-modular link, transport attributes need to +# be initialised before drivers +# -------------------------- +obj-$(CONFIG_SCSI_SPI_ATTRS) += scsi_transport_spi.o +obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o + + obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o @@ -41,7 +49,7 @@ obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o sun3_scsi_vme.o obj-$(CONFIG_MVME16x_SCSI) += mvme16x.o 53c7xx.o obj-$(CONFIG_BVME6000_SCSI) += bvme6000.o 53c7xx.o -obj-$(CONFIG_SCSI_SIM710) += sim710.o 53c700.o +obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o obj-$(CONFIG_SCSI_PCI2000) += pci2000.o obj-$(CONFIG_SCSI_PCI2220I) += pci2220i.o @@ -64,7 +72,7 @@ obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o -obj-$(CONFIG_SCSI_NCR_D700) += NCR_D700.o 53c700.o +obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas.o @@ -107,7 +115,7 @@ obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o -obj-$(CONFIG_SCSI_LASI700) += lasi700.o 53c700.o +obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o @@ -130,7 +138,7 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o - + sd_mod-objs := sd.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o initio-objs := ini9100u.o i91uscsi.o diff -Nru a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx Wed Mar 10 21:09:42 2004 @@ -4,7 +4,7 @@ # config SCSI_AIC79XX tristate "Adaptec AIC79xx U320 support" - depends on PCI + depends on PCI && SCSI help This driver supports all of Adaptec's Ultra 320 PCI-X based SCSI controllers. diff -Nru a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx Wed Mar 10 21:09:42 2004 @@ -4,7 +4,7 @@ # config SCSI_AIC7XXX tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)" - depends on PCI || EISA + depends on (PCI || EISA) && SCSI ---help--- This driver supports all of Adaptec's Fast through Ultra 160 PCI based SCSI controllers as well as the aic7770 based EISA and VLB diff -Nru a/drivers/scsi/constants.c b/drivers/scsi/constants.c --- a/drivers/scsi/constants.c Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/constants.c Wed Mar 10 21:09:43 2004 @@ -1135,7 +1135,7 @@ static const char * hostbyte_table[]={ "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", -"DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL}; +"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", NULL}; void print_hostbyte(int scsiresult) { static int maxcode=0; diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c --- a/drivers/scsi/dc395x.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/dc395x.c Wed Mar 10 21:09:42 2004 @@ -62,6 +62,10 @@ #include #include +#define DC395X_NAME "dc395x" +#define DC395X_BANNER "Tekram DC395(U/UW/F), DC315(U) - ASIC TRM-S1040" +#define DC395X_VERSION "v2.05, 2004/03/08" + /*--------------------------------------------------------------------------- Features ---------------------------------------------------------------------------*/ @@ -82,22 +86,16 @@ #define DBG_KG 0x0001 #define DBG_0 0x0002 #define DBG_1 0x0004 -#define DBG_DCB 0x0008 -#define DBG_PARSE 0x0010 /* debug command line parsing */ -#define DBG_SGPARANOIA 0x0020 +#define DBG_SG 0x0020 #define DBG_FIFO 0x0040 #define DBG_PIO 0x0080 -#define DBG_RECURSION 0x0100 /* check for excessive recursion */ -#define DBG_MALLOC 0x0200 /* report on memory allocations */ -#define DBG_TRACE 0x0400 -#define DBG_TRACEALL 0x0800 /* * Set set of things to output debugging for. * Undefine to remove all debugging */ -/*#define DEBUG_MASK (DBG_0|DBG_1|DBG_DCB|DBG_PARSE|DBG_SGPARANOIA|DBG_FIFO|DBG_PIO|DBG_TRACE|DBG_TRACEALL)*/ +/*#define DEBUG_MASK (DBG_0|DBG_1|DBG_SG|DBG_FIFO|DBG_PIO)*/ /*#define DEBUG_MASK DBG_0*/ @@ -138,72 +136,6 @@ #endif -/* - * The recursion debugging just counts entries into the driver and - * prints out a messge if it exceeds a certain limit. This variable - * hold the count. - */ -#if debug_enabled(DBG_RECURSION) -static int dbg_in_driver = 0; -#endif - - -/* - * Memory allocation debugging - * Just reports when memory is allocated and/or released. - */ -#if debug_enabled(DBG_MALLOC) -inline void *dc395x_kmalloc(size_t sz, int fl) -{ - void *ptr = kmalloc(sz, fl); - dprintkl(KERN_DEBUG, "Alloc %i bytes @ %p w/ fl %08x\n", sz, ptr, fl); - return ptr; -} -inline void dc395x_kfree(const void *adr) -{ - dprintkl(KERN_DEBUG, "Free mem @ %p\n", adr); - kfree(adr); -} -#else -#define dc395x_kmalloc(sz, fl) kmalloc(sz, fl) -#define dc395x_kfree(adr) kfree(adr) -#endif - - -/* - * Debug/trace stuff - */ -#if debug_enabled(DBG_TRACEALL) -# define TRACEOUTALL(x...) printk ( x) -#else -# define TRACEOUTALL(x...) do {} while (0) -#endif - -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) -# define DEBUGTRACEBUFSZ 512 -static char tracebuf[64]; -static char traceoverflow[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -# define TRACEPRINTF(x...) \ - do { \ - int ln = sprintf(tracebuf, x); \ - if (srb->debugpos + ln >= DEBUGTRACEBUFSZ) { \ - srb->debugtrace[srb->debugpos] = 0; \ - srb->debugpos = DEBUGTRACEBUFSZ/5; \ - srb->debugtrace[srb->debugpos++] = '>'; \ - } \ - sprintf(srb->debugtrace + srb->debugpos, "%s", tracebuf); \ - srb->debugpos += ln - 1; \ - } while (0) -# define TRACEOUT(x...) printk (x) -#else -# define TRACEPRINTF(x...) do {} while (0) -# define TRACEOUT(x...) do {} while (0) -#endif - - -/*--------------------------------------------------------------------------- - ---------------------------------------------------------------------------*/ - #ifndef PCI_VENDOR_ID_TEKRAM #define PCI_VENDOR_ID_TEKRAM 0x1DE1 /* Vendor ID */ #endif @@ -212,32 +144,16 @@ #endif - #define DC395x_LOCK_IO(dev,flags) spin_lock_irqsave(((struct Scsi_Host *)dev)->host_lock, flags) #define DC395x_UNLOCK_IO(dev,flags) spin_unlock_irqrestore(((struct Scsi_Host *)dev)->host_lock, flags) -#define DC395x_ACB_INITLOCK(acb) spin_lock_init(&acb->smp_lock) -#define DC395x_ACB_LOCK(acb,acb_flags) if (!acb->lock_level_count[cpuid]) { spin_lock_irqsave(&acb->smp_lock,acb_flags); acb->lock_level_count[cpuid]++; } else { acb->lock_level_count[cpuid]++; } -#define DC395x_ACB_UNLOCK(acb,acb_flags) if (--acb->lock_level_count[cpuid] == 0) { spin_unlock_irqrestore(&acb->smp_lock,acb_flags); } - -#define DC395x_SMP_IO_LOCK(dev,irq_flags) spin_lock_irqsave(((struct Scsi_Host*)dev)->host_lock,irq_flags) -#define DC395x_SMP_IO_UNLOCK(dev,irq_flags) spin_unlock_irqrestore(((struct Scsi_Host*)dev)->host_lock,irq_flags) - - #define DC395x_read8(acb,address) (u8)(inb(acb->io_port_base + (address))) -#define DC395x_read8_(address, base) (u8)(inb((USHORT)(base) + (address))) #define DC395x_read16(acb,address) (u16)(inw(acb->io_port_base + (address))) #define DC395x_read32(acb,address) (u32)(inl(acb->io_port_base + (address))) #define DC395x_write8(acb,address,value) outb((value), acb->io_port_base + (address)) -#define DC395x_write8_(address,value,base) outb((value), (USHORT)(base) + (address)) #define DC395x_write16(acb,address,value) outw((value), acb->io_port_base + (address)) #define DC395x_write32(acb,address,value) outl((value), acb->io_port_base + (address)) - -#define BUS_ADDR(sg) sg_dma_address(&(sg)) -#define CPU_ADDR(sg) (page_address((sg).page)+(sg).offset) -#define PAGE_ADDRESS(sg) page_address((sg)->page) - /* cmd->result */ #define RES_TARGET 0x000000FF /* Target State */ #define RES_TARGET_LNX STATUS_MASK /* Only official ... */ @@ -254,20 +170,22 @@ #define SET_RES_DID(who,did) { who &= ~RES_DID; who |= (int)(did) << 16; } #define SET_RES_DRV(who,drv) { who &= ~RES_DRV; who |= (int)(drv) << 24; } -/* -************************************************************************** -*/ #define TAG_NONE 255 +/* + * srb->segement_x is the hw sg list. It is always allocated as a + * DC395x_MAX_SG_LISTENTRY entries in a linear block which does not + * cross a page boundy. + */ +#define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY) + + struct SGentry { u32 address; /* bus! address */ u32 length; }; - -/* - * The SEEPROM structure for TRM_S1040 - */ +/* The SEEPROM structure for TRM_S1040 */ struct NVRamTarget { u8 cfg0; /* Target configuration byte 0 */ u8 period; /* Target period */ @@ -275,7 +193,6 @@ u8 cfg3; /* Target configuration byte 3 */ }; - struct NvRamType { u8 sub_vendor_id[2]; /* 0,1 Sub Vendor ID */ u8 sub_sys_id[2]; /* 2,3 Sub System ID */ @@ -302,28 +219,31 @@ u16 cksum; /* 126,127 */ }; - -/*----------------------------------------------------------------------- - SCSI Request Block - -----------------------------------------------------------------------*/ struct ScsiReqBlk { struct list_head list; /* next/prev ptrs for srb lists */ struct DeviceCtlBlk *dcb; - - /* HW scatter list (up to 64 entries) */ - struct SGentry *segment_x; Scsi_Cmnd *cmd; - unsigned char *virt_addr; /* set by update_sg_list */ + struct SGentry *segment_x; /* Linear array of hw sg entries (up to 64 entries) */ + u32 sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */ - u32 total_xfer_length; - u32 xferred; /* Backup for the already xferred len */ + u8 sg_count; /* No of HW sg entries for this request */ + u8 sg_index; /* Index of HW sg entry for this request */ + u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ + unsigned char *virt_addr; /* Virtual address of current transfer position */ - u32 sg_bus_addr; /* bus address of DC395x scatterlist */ + /* + * The sense buffer handling function, request_sense, uses + * the first hw sg entry (segment_x[0]) and the transfer + * length (total_xfer_length). While doing this it stores the + * original values into the last sg hw list + * (srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1] and the + * total_xfer_length in xferred. These values are restored in + * pci_unmap_srb_sense. This is the only place xferred is used. + */ + u32 xferred; /* Saved copy of total_xfer_length */ u16 state; - u8 sg_count; - u8 sg_index; u8 msgin_buf[6]; u8 msgout_buf[6]; @@ -339,17 +259,8 @@ u8 flag; u8 scsi_phase; - -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - u16 debugpos; - char *debugtrace; -#endif }; - -/*----------------------------------------------------------------------- - Device Control Block - -----------------------------------------------------------------------*/ struct DeviceCtlBlk { struct list_head list; /* next/prev ptrs for the dcb list */ struct AdapterCtlBlk *acb; @@ -377,9 +288,6 @@ u8 init_tcq_flag; }; -/*----------------------------------------------------------------------- - Adapter Control Block - -----------------------------------------------------------------------*/ struct AdapterCtlBlk { struct Scsi_Host *scsi_host; @@ -423,80 +331,63 @@ }; - - /*--------------------------------------------------------------------------- Forward declarations ---------------------------------------------------------------------------*/ -static void data_out_phase0(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void data_in_phase0(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void command_phase0(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void status_phase0(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void msgout_phase0(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void msgin_phase0(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void data_out_phase1(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void data_in_phase1(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void command_phase1(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void status_phase1(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void msgout_phase1(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void msgin_phase1(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, - u16 * pscsi_status); +static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); +static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); static void nop0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status); -static void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status); + u16 *pscsi_status); +static void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status); static void set_basic_config(struct AdapterCtlBlk *acb); static void cleanup_after_transfer(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb); + struct ScsiReqBlk *srb); static void reset_scsi_bus(struct AdapterCtlBlk *acb); static void data_io_transfer(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb, u16 io_dir); + struct ScsiReqBlk *srb, u16 io_dir); static void disconnect(struct AdapterCtlBlk *acb); static void reselect(struct AdapterCtlBlk *acb); static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb); -static void build_srb(Scsi_Cmnd * cmd, struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb); + struct ScsiReqBlk *srb); +static void build_srb(Scsi_Cmnd *cmd, struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb); static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code, - Scsi_Cmnd * cmd, u8 force); + Scsi_Cmnd *cmd, u8 force); static void scsi_reset_detect(struct AdapterCtlBlk *acb); -static void pci_unmap_srb(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb); +static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb); + struct ScsiReqBlk *srb); static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb); -static void srb_done(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb); -static void request_sense(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb); + struct ScsiReqBlk *srb); +static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb); +static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb); static inline void set_xfer_rate(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk *dcb); + struct DeviceCtlBlk *dcb); static void waiting_timeout(unsigned long ptr); @@ -504,11 +395,7 @@ Static Data ---------------------------------------------------------------------------*/ static u16 current_sync_offset = 0; -static char monitor_next_irq = 0; -/* - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - */ static void *dc395x_scsi_phase0[] = { data_out_phase0,/* phase:0 */ data_in_phase0, /* phase:1 */ @@ -520,9 +407,6 @@ msgin_phase0, /* phase:7 */ }; -/* - * dc395x_statev = (void *)dc395x_scsi_phase1[phase] - */ static void *dc395x_scsi_phase1[] = { data_out_phase1,/* phase:0 */ data_in_phase1, /* phase:1 */ @@ -558,8 +442,6 @@ /* real period:48ns,76ns,100ns,124ns,148ns,176ns,200ns,248ns */ static u8 clock_period[] = { 12, 18, 25, 31, 37, 43, 50, 62 }; static u16 clock_speed[] = { 200, 133, 100, 80, 67, 58, 50, 40 }; -/* real period:48ns,72ns,100ns,124ns,148ns,172ns,200ns,248ns */ - /*--------------------------------------------------------------------------- @@ -655,8 +537,9 @@ /* - * Safe settings. If set to zero the the BIOS/default values with command line - * overrides will be used. If set to 1 then safe and slow settings will be used. + * Safe settings. If set to zero the the BIOS/default values with + * command line overrides will be used. If set to 1 then safe and + * slow settings will be used. */ static int use_safe_settings = 0; module_param_named(safe, use_safe_settings, bool, 0); @@ -686,8 +569,7 @@ * set_safe_settings - if the use_safe_settings option is set then * set all values to the safe and slow values. **/ -static -void __init set_safe_settings(void) +static void __init set_safe_settings(void) { if (use_safe_settings) { @@ -706,25 +588,24 @@ * fix_settings - reset any boot parameters which are out of range * back to the default values. **/ -static -void __init fix_settings(void) +static void __init fix_settings(void) { int i; - dprintkdbg(DBG_PARSE, "setup %08x %08x %08x %08x %08x %08x\n", - cfg_data[CFG_ADAPTER_ID].value, - cfg_data[CFG_MAX_SPEED].value, - cfg_data[CFG_DEV_MODE].value, - cfg_data[CFG_ADAPTER_MODE].value, - cfg_data[CFG_TAGS].value, - cfg_data[CFG_RESET_DELAY].value); + dprintkdbg(DBG_1, + "setup: AdapterId=%08x MaxSpeed=%08x DevMode=%08x " + "AdapterMode=%08x Tags=%08x ResetDelay=%08x\n", + cfg_data[CFG_ADAPTER_ID].value, + cfg_data[CFG_MAX_SPEED].value, + cfg_data[CFG_DEV_MODE].value, + cfg_data[CFG_ADAPTER_MODE].value, + cfg_data[CFG_TAGS].value, + cfg_data[CFG_RESET_DELAY].value); for (i = 0; i < CFG_NUM; i++) { - if (cfg_data[i].value < cfg_data[i].min || - cfg_data[i].value > cfg_data[i].max) - { + if (cfg_data[i].value < cfg_data[i].min + || cfg_data[i].value > cfg_data[i].max) cfg_data[i].value = cfg_data[i].def; - } } } @@ -734,8 +615,8 @@ * Mapping from the eeprom delay index value (index into this array) * to the the number of actual seconds that the delay should be for. */ -static -char __initdata eeprom_index_to_delay_map[] = { 1, 3, 5, 10, 16, 30, 60, 120 }; +static char __initdata eeprom_index_to_delay_map[] = + { 1, 3, 5, 10, 16, 30, 60, 120 }; /** @@ -744,25 +625,24 @@ * * @eeprom: The eeprom structure in which we find the delay index to map. **/ -static -void __init eeprom_index_to_delay(struct NvRamType *eeprom) +static void __init eeprom_index_to_delay(struct NvRamType *eeprom) { eeprom->delay_time = eeprom_index_to_delay_map[eeprom->delay_time]; } /** - * delay_to_eeprom_index - Take a delay in seconds and return the closest - * eeprom index which will delay for at least that amount of seconds. + * delay_to_eeprom_index - Take a delay in seconds and return the + * closest eeprom index which will delay for at least that amount of + * seconds. * * @delay: The delay, in seconds, to find the eeprom index for. **/ static int __init delay_to_eeprom_index(int delay) { u8 idx = 0; - while (idx < 7 && eeprom_index_to_delay_map[idx] < delay) { + while (idx < 7 && eeprom_index_to_delay_map[idx] < delay) idx++; - } return idx; } @@ -774,38 +654,34 @@ * * @eeprom: The eeprom data to override with command line options. **/ -static -void __init eeprom_override(struct NvRamType *eeprom) +static void __init eeprom_override(struct NvRamType *eeprom) { u8 id; /* Adapter Settings */ - if (cfg_data[CFG_ADAPTER_ID].value != CFG_PARAM_UNSET) { - eeprom->scsi_id = - (u8)cfg_data[CFG_ADAPTER_ID].value; - } - if (cfg_data[CFG_ADAPTER_MODE].value != CFG_PARAM_UNSET) { - eeprom->channel_cfg = - (u8)cfg_data[CFG_ADAPTER_MODE].value; - } - if (cfg_data[CFG_RESET_DELAY].value != CFG_PARAM_UNSET) { - eeprom->delay_time = - delay_to_eeprom_index(cfg_data[CFG_RESET_DELAY].value); - } - if (cfg_data[CFG_TAGS].value != CFG_PARAM_UNSET) { + if (cfg_data[CFG_ADAPTER_ID].value != CFG_PARAM_UNSET) + eeprom->scsi_id = (u8)cfg_data[CFG_ADAPTER_ID].value; + + if (cfg_data[CFG_ADAPTER_MODE].value != CFG_PARAM_UNSET) + eeprom->channel_cfg = (u8)cfg_data[CFG_ADAPTER_MODE].value; + + if (cfg_data[CFG_RESET_DELAY].value != CFG_PARAM_UNSET) + eeprom->delay_time = delay_to_eeprom_index( + cfg_data[CFG_RESET_DELAY].value); + + if (cfg_data[CFG_TAGS].value != CFG_PARAM_UNSET) eeprom->max_tag = (u8)cfg_data[CFG_TAGS].value; - } /* Device Settings */ for (id = 0; id < DC395x_MAX_SCSI_ID; id++) { - if (cfg_data[CFG_DEV_MODE].value != CFG_PARAM_UNSET) { + if (cfg_data[CFG_DEV_MODE].value != CFG_PARAM_UNSET) eeprom->target[id].cfg0 = - (u8)cfg_data[CFG_DEV_MODE].value; - } - if (cfg_data[CFG_MAX_SPEED].value != CFG_PARAM_UNSET) { + (u8)cfg_data[CFG_DEV_MODE].value; + + if (cfg_data[CFG_MAX_SPEED].value != CFG_PARAM_UNSET) eeprom->target[id].period = - (u8)cfg_data[CFG_MAX_SPEED].value; - } + (u8)cfg_data[CFG_MAX_SPEED].value; + } } @@ -813,39 +689,21 @@ /*--------------------------------------------------------------------------- ---------------------------------------------------------------------------*/ -/** - * list_size - Returns the size (in number of entries) of the - * supplied list. - * - * @head: The pointer to the head of the list to count the items in. - **/ -static -unsigned int list_size(struct list_head *head) +static unsigned int list_size(struct list_head *head) { unsigned int count = 0; struct list_head *pos; list_for_each(pos, head) count++; return count; -} +} -/** - * dcb_get_next - Given a dcb return the next dcb in the list of - * dcb's, wrapping back to the start of the dcb list if required. - * Returns the supplied dcb if there is only one dcb in the list. - * - * @head: The pointer to the head of the list to count the items in. - * @pos: The pointer the dcb for which we are searching for the - * following dcb. - **/ -static -struct DeviceCtlBlk *dcb_get_next( - struct list_head *head, +static struct DeviceCtlBlk *dcb_get_next(struct list_head *head, struct DeviceCtlBlk *pos) { int use_next = 0; - struct DeviceCtlBlk* next = NULL; + struct DeviceCtlBlk* next = NULL; struct DeviceCtlBlk* i; if (list_empty(head)) @@ -870,22 +728,7 @@ } -/* - * Queueing philosphy: - * There are a couple of lists: - * - Waiting: Contains a list of SRBs not yet sent (per DCB) - * - Free: List of free SRB slots - * - * If there are no waiting commands for the DCB, the new one is sent to the bus - * otherwise the oldest one is taken from the Waiting list and the new one is - * queued to the Waiting List - * - * Lists are managed using two pointers and eventually a counter - */ - -/* Nomen est omen ... */ -static inline -void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) +static void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { if (srb->tag_number < 255) { dcb->tag_mask &= ~(1 << srb->tag_number); /* free tag mask */ @@ -895,9 +738,8 @@ /* Find cmd in SRB list */ -inline static -struct ScsiReqBlk *find_cmd(Scsi_Cmnd *cmd, - struct list_head *head) +inline static struct ScsiReqBlk *find_cmd(Scsi_Cmnd *cmd, + struct list_head *head) { struct ScsiReqBlk *i; list_for_each_entry(i, head, list) @@ -907,88 +749,59 @@ } -/* - * srb_get_free - Return a free srb from the list of free SRBs that - * is stored with the acb. - */ -static -struct ScsiReqBlk *srb_get_free(struct AdapterCtlBlk *acb) +static struct ScsiReqBlk *srb_get_free(struct AdapterCtlBlk *acb) { struct list_head *head = &acb->srb_free_list; - struct ScsiReqBlk *srb; + struct ScsiReqBlk *srb = NULL; if (!list_empty(head)) { srb = list_entry(head->next, struct ScsiReqBlk, list); list_del(head->next); - dprintkdbg(DBG_0, "srb_get_free: got srb %p\n", srb); - } else { - srb = NULL; - dprintkl(KERN_ERR, "Out of Free SRBs :-(\n"); + dprintkdbg(DBG_0, "srb_get_free: srb=%p\n", srb); } return srb; } -/* - * srb_free_insert - Insert an srb to the head of the free list - * stored in the acb. - */ -static -void srb_free_insert(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +static void srb_free_insert(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { - dprintkdbg(DBG_0, "srb_free_insert: put srb %p\n", srb); - list_add_tail(&srb->list, &acb->srb_free_list); + dprintkdbg(DBG_0, "srb_free_insert: srb=%p\n", srb); + list_add_tail(&srb->list, &acb->srb_free_list); } -/* - * srb_waiting_insert - Insert an srb to the head of the wiating list - * stored in the dcb. - */ -static -void srb_waiting_insert(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) +static void srb_waiting_insert(struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) { - dprintkdbg(DBG_0, "srb_waiting_insert: srb %p cmd %li\n", srb, srb->cmd->pid); - list_add(&srb->list, &dcb->srb_waiting_list); + dprintkdbg(DBG_0, "srb_waiting_insert: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + list_add(&srb->list, &dcb->srb_waiting_list); } -/* - * srb_waiting_append - Append an srb to the tail of the waiting list - * stored in the dcb. - */ -static inline -void srb_waiting_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) +static void srb_waiting_append(struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) { - dprintkdbg(DBG_0, "srb_waiting_append: srb %p cmd %li\n", srb, srb->cmd->pid); - list_add_tail(&srb->list, &dcb->srb_waiting_list); + dprintkdbg(DBG_0, "srb_waiting_append: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + list_add_tail(&srb->list, &dcb->srb_waiting_list); } -/* - * srb_going_append - Append an srb to the tail of the going list - * stored in the dcb. - */ -static inline -void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) +static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { - dprintkdbg(DBG_0, "srb_going_append: srb %p\n", srb); - list_add_tail(&srb->list, &dcb->srb_going_list); + dprintkdbg(DBG_0, "srb_going_append: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + list_add_tail(&srb->list, &dcb->srb_going_list); } - -/* - * srb_going_remove - Remove an srb from the going list stored in the - * dcb. - */ -static -void srb_going_remove(struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) +static void srb_going_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; - dprintkdbg(DBG_0, "srb_going_remove: srb %p\n", srb); + dprintkdbg(DBG_0, "srb_going_remove: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list) if (i == srb) { @@ -998,17 +811,13 @@ } -/* - * srb_waiting_remove - Remove an srb from the waiting list stored in the - * dcb. - */ -static -void srb_waiting_remove(struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) +static void srb_waiting_remove(struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) { struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; - dprintkdbg(DBG_0, "srb_waiting_remove: srb %p\n", srb); + dprintkdbg(DBG_0, "srb_waiting_remove: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list) if (i == srb) { @@ -1018,37 +827,28 @@ } -/* - * srb_going_to_waiting_move - Remove an srb from the going list in - * the dcb and insert it at the head of the waiting list in the dcb. - */ -static -void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) +static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) { - dprintkdbg(DBG_0, "srb_going_waiting_move: srb %p, pid = %li\n", srb, srb->cmd->pid); + dprintkdbg(DBG_0, + "srb_going_to_waiting_move: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_waiting_list); } -/* - * srb_waiting_to_going_move - Remove an srb from the waiting list in - * the dcb and insert it at the head of the going list in the dcb. - */ -static -void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) -{ - /* Remove from waiting list */ - dprintkdbg(DBG_0, "srb_waiting_to_going: srb %p\n", srb); - TRACEPRINTF("WtG *"); +static void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) +{ + dprintkdbg(DBG_0, + "srb_waiting_to_going_move: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_going_list); } /* Sets the timer to wake us up */ -static -void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to) +static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to) { if (timer_pending(&acb->waiting_timer)) return; @@ -1065,8 +865,7 @@ /* Send the next command from the waiting list to the bus */ -static -void waiting_process_next(struct AdapterCtlBlk *acb) +static void waiting_process_next(struct AdapterCtlBlk *acb) { struct DeviceCtlBlk *start = NULL; struct DeviceCtlBlk *pos; @@ -1074,7 +873,7 @@ struct ScsiReqBlk *srb; struct list_head *dcb_list_head = &acb->dcb_list; - if ((acb->active_dcb) + if (acb->active_dcb || (acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV))) return; @@ -1135,8 +934,9 @@ static void waiting_timeout(unsigned long ptr) { unsigned long flags; - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *) ptr; - dprintkdbg(DBG_KG, "Debug: Waiting queue woken up by timer.\n"); + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)ptr; + dprintkdbg(DBG_1, + "waiting_timeout: Queue woken up by timer. acb=%p\n", acb); DC395x_LOCK_IO(acb->scsi_host, flags); waiting_process_next(acb); DC395x_UNLOCK_IO(acb->scsi_host, flags); @@ -1144,28 +944,17 @@ /* Get the DCB for a given ID/LUN combination */ -static inline -struct DeviceCtlBlk *find_dcb(struct AdapterCtlBlk *acb, u8 id, u8 lun) +static struct DeviceCtlBlk *find_dcb(struct AdapterCtlBlk *acb, u8 id, u8 lun) { return acb->children[id][lun]; } -/*********************************************************************** - * Function: static void send_srb (struct AdapterCtlBlk* acb, struct ScsiReqBlk* srb) - * - * Purpose: Send SCSI Request Block (srb) to adapter (acb) - * - * dc395x_queue_command - * waiting_process_next - * - ***********************************************************************/ -static -void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +/* Send SCSI Request Block (srb) to adapter (acb) */ +static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { - struct DeviceCtlBlk *dcb; + struct DeviceCtlBlk *dcb = srb->dcb; - dcb = srb->dcb; if (dcb->max_command <= list_size(&dcb->srb_going_list) || acb->active_dcb || (acb->acb_flag & (RESET_DETECT + RESET_DONE + RESET_DEV))) { @@ -1174,130 +963,29 @@ return; } - if (!start_scsi(acb, dcb, srb)) { + if (!start_scsi(acb, dcb, srb)) srb_going_append(dcb, srb); - } else { + else { srb_waiting_insert(dcb, srb); waiting_set_timer(acb, HZ / 50); } } -/* - ********************************************************************* - * - * Function: static void build_srb (Scsi_Cmd *cmd, struct DeviceCtlBlk* dcb, struct ScsiReqBlk* srb) - * - * Purpose: Prepare SRB for being sent to Device DCB w/ command *cmd - * - ********************************************************************* - */ -static -void build_srb(Scsi_Cmnd * cmd, struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) -{ - int i, max; - struct SGentry *sgp; - struct scatterlist *sl; - u32 request_size; - int dir; +/* Prepare SRB for being sent to Device DCB w/ command *cmd */ +static void build_srb(Scsi_Cmnd *cmd, struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) +{ + int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n", + cmd->pid, dcb->target_id, dcb->target_lun); - dprintkdbg(DBG_0, "build_srb..............\n"); - /*memset (srb, 0, sizeof (struct ScsiReqBlk)); */ srb->dcb = dcb; srb->cmd = cmd; - /* Find out about direction */ - dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - - if (cmd->use_sg && dir != PCI_DMA_NONE) { - unsigned int len = 0; - /* TODO: In case usg_sg and the no of segments differ, things - * will probably go wrong. */ - max = srb->sg_count = - pci_map_sg(dcb->acb->dev, - (struct scatterlist *) cmd->request_buffer, - cmd->use_sg, dir); - sgp = srb->segment_x; - request_size = cmd->request_bufflen; - dprintkdbg(DBG_SGPARANOIA, - "BuildSRB: Bufflen = %d, buffer = %p, use_sg = %d\n", - cmd->request_bufflen, cmd->request_buffer, - cmd->use_sg); - dprintkdbg(DBG_SGPARANOIA, - "Mapped %i Segments to %i\n", cmd->use_sg, - srb->sg_count); - sl = (struct scatterlist *) cmd->request_buffer; - - srb->virt_addr = page_address(sl->page); - for (i = 0; i < max; i++) { - u32 busaddr = (u32) sg_dma_address(&sl[i]); - u32 seglen = (u32) sl[i].length; - sgp[i].address = busaddr; - sgp[i].length = seglen; - len += seglen; - dprintkdbg(DBG_SGPARANOIA, - "Setting up sgp %d, address = 0x%08x, length = %d, tot len = %d\n", - i, busaddr, seglen, len); - } - sgp += max - 1; - /* Fixup for last buffer too big as it is allocated on even page boundaries */ - if (len > request_size) { -#if debug_enabled(DBG_KG) || debug_enabled(DBG_SGPARANOIA) - dprintkdbg(DBG_KG|DBG_SGPARANOIA, - "Fixup SG total length: %d->%d, last seg %d->%d\n", - len, request_size, sgp->length, - sgp->length - (len - request_size)); -#endif - sgp->length -= (len - request_size); - len = request_size; - } - /* WIDE padding */ - if (dcb->sync_period & WIDE_SYNC && len % 2) { - len++; - sgp->length++; - } - srb->total_xfer_length = len; /*? */ - /* Hopefully this does not cross a page boundary ... */ - srb->sg_bus_addr = - pci_map_single(dcb->acb->dev, srb->segment_x, - sizeof(struct SGentry) * - DC395x_MAX_SG_LISTENTRY, - PCI_DMA_TODEVICE); - dprintkdbg(DBG_SGPARANOIA, - "Map SG descriptor list %p (%05x) to %08x\n", - srb->segment_x, - sizeof(struct SGentry) * DC395x_MAX_SG_LISTENTRY, - srb->sg_bus_addr); - } else { - if (cmd->request_buffer && dir != PCI_DMA_NONE) { - u32 len = cmd->request_bufflen; /* Actual request size */ - srb->sg_count = 1; - srb->segment_x[0].address = - pci_map_single(dcb->acb->dev, - cmd->request_buffer, len, dir); - /* WIDE padding */ - if (dcb->sync_period & WIDE_SYNC && len % 2) - len++; - srb->segment_x[0].length = len; - srb->total_xfer_length = len; - srb->virt_addr = cmd->request_buffer; - srb->sg_bus_addr = 0; - dprintkdbg(DBG_SGPARANOIA, - "BuildSRB: len = %d, buffer = %p, use_sg = %d, map %08x\n", - len, cmd->request_buffer, cmd->use_sg, - srb->segment_x[0].address); - } else { - srb->sg_count = 0; - srb->total_xfer_length = 0; - srb->sg_bus_addr = 0; - srb->virt_addr = 0; - dprintkdbg(DBG_SGPARANOIA, - "BuildSRB: buflen = %d, buffer = %p, use_sg = %d, NOMAP %08x\n", - cmd->bufflen, cmd->request_buffer, - cmd->use_sg, srb->segment_x[0].address); - } - } - + srb->sg_count = 0; + srb->total_xfer_length = 0; + srb->sg_bus_addr = 0; + srb->virt_addr = 0; srb->sg_index = 0; srb->adapter_status = 0; srb->target_status = 0; @@ -1306,29 +994,80 @@ srb->flag = 0; srb->state = 0; srb->retry_count = 0; - -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) && debug_enabled(DBG_SGPARANOIA) - if ((unsigned long)srb->debugtrace & (DEBUGTRACEBUFSZ - 1)) { - dprintkdbg(DBG_SGPARANOIA, - "SRB %i (%p): debugtrace %p corrupt!\n", - (srb - dcb->acb->srb_array) / - sizeof(struct ScsiReqBlk), srb, srb->debugtrace); - } -#endif -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - srb->debugpos = 0; - srb->debugtrace = 0; -#endif - TRACEPRINTF("pid %li(%li):%02x %02x..(%i-%i) *", cmd->pid, - jiffies, cmd->cmnd[0], cmd->cmnd[1], - cmd->device->id, cmd->device->lun); srb->tag_number = TAG_NONE; - srb->scsi_phase = PH_BUS_FREE; /* initial phase */ srb->end_message = 0; - return; -} + if (dir == PCI_DMA_NONE || !cmd->request_buffer) { + dprintkdbg(DBG_0, + "build_srb: [0] len=%d buf=%p use_sg=%d !MAP=%08x\n", + cmd->bufflen, cmd->request_buffer, + cmd->use_sg, srb->segment_x[0].address); + } else if (cmd->use_sg) { + int i; + u32 reqlen = cmd->request_bufflen; + struct scatterlist *sl = (struct scatterlist *) + cmd->request_buffer; + struct SGentry *sgp = srb->segment_x; + srb->sg_count = pci_map_sg(dcb->acb->dev, sl, cmd->use_sg, + dir); + dprintkdbg(DBG_0, + "build_srb: [n] len=%d buf=%p use_sg=%d segs=%d\n", + reqlen, cmd->request_buffer, cmd->use_sg, + srb->sg_count); + + srb->virt_addr = page_address(sl->page); + for (i = 0; i < srb->sg_count; i++) { + u32 busaddr = (u32)sg_dma_address(&sl[i]); + u32 seglen = (u32)sl[i].length; + sgp[i].address = busaddr; + sgp[i].length = seglen; + srb->total_xfer_length += seglen; + } + sgp += srb->sg_count - 1; + + /* + * adjust last page if too big as it is allocated + * on even page boundaries + */ + if (srb->total_xfer_length > reqlen) { + sgp->length -= (srb->total_xfer_length - reqlen); + srb->total_xfer_length = reqlen; + } + + /* Fixup for WIDE padding - make sure length is even */ + if (dcb->sync_period & WIDE_SYNC && + srb->total_xfer_length % 2) { + srb->total_xfer_length++; + sgp->length++; + } + + srb->sg_bus_addr = pci_map_single(dcb->acb->dev, + srb->segment_x, + SEGMENTX_LEN, + PCI_DMA_TODEVICE); + + dprintkdbg(DBG_SG, "build_srb: [n] map sg %p->%08x(%05x)\n", + srb->segment_x, srb->sg_bus_addr, SEGMENTX_LEN); + } else { + srb->total_xfer_length = cmd->request_bufflen; + srb->sg_count = 1; + srb->segment_x[0].address = + pci_map_single(dcb->acb->dev, cmd->request_buffer, + srb->total_xfer_length, dir); + + /* Fixup for WIDE padding - make sure length is even */ + if (dcb->sync_period & WIDE_SYNC && srb->total_xfer_length % 2) + srb->total_xfer_length++; + + srb->segment_x[0].length = srb->total_xfer_length; + srb->virt_addr = cmd->request_buffer; + dprintkdbg(DBG_0, + "build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n", + srb->total_xfer_length, cmd->request_buffer, + cmd->use_sg, srb->segment_x[0].address); + } +} /** @@ -1350,27 +1089,14 @@ * and is expected to be held on return. * **/ -static int -dc395x_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +static int dc395x_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) { struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)cmd->device->host->hostdata; - - dprintkdbg(DBG_0, "Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li)\n", - cmd->cmnd[0], - cmd->device->id, - cmd->device->lun, - cmd->pid); - -#if debug_enabled(DBG_RECURSION) - if (dbg_in_driver++ > NORM_REC_LVL) { - dprintkl(KERN_DEBUG, - "%i queue_command () recursion? (pid=%li)\n", - dbg_in_driver, cmd->pid); - } -#endif + dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n", + cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); /* Assume BAD_TARGET; will be cleared later */ cmd->result = DID_BAD_TARGET << 16; @@ -1384,8 +1110,8 @@ /* does the specified lun on the specified device exist */ if (!(acb->dcb_map[cmd->device->id] & (1 << cmd->device->lun))) { - dprintkl(KERN_INFO, "Ignore target %02x lun %02x\n", cmd->device->id, - cmd->device->lun); + dprintkl(KERN_INFO, "queue_command: Ignore target <%02i-%i>\n", + cmd->device->id, cmd->device->lun); goto complete; } @@ -1393,9 +1119,8 @@ dcb = find_dcb(acb, cmd->device->id, cmd->device->lun); if (!dcb) { /* should never happen */ - dprintkl(KERN_ERR, "no DCB failed, target %02x lun %02x\n", - cmd->device->id, cmd->device->lun); - dprintkl(KERN_ERR, "No DCB in queuecommand (2)!\n"); + dprintkl(KERN_ERR, "queue_command: No such device <%02i-%i>", + cmd->device->id, cmd->device->lun); goto complete; } @@ -1403,7 +1128,6 @@ cmd->scsi_done = done; cmd->result = 0; - /* get a free SRB */ srb = srb_get_free(acb); if (!srb) { @@ -1411,11 +1135,10 @@ * Return 1 since we are unable to queue this command at this * point in time. */ - dprintkdbg(DBG_0, "No free SRB's in queuecommand\n"); + dprintkdbg(DBG_0, "queue_command: No free srb's\n"); return 1; } - /* build srb for the command */ build_srb(cmd, dcb, srb); if (!list_empty(&dcb->srb_waiting_list)) { @@ -1426,11 +1149,7 @@ /* process immediately */ send_srb(acb, srb); } - dprintkdbg(DBG_1, "... command (pid %li) queued successfully.\n", cmd->pid); - -#if debug_enabled(DBG_RECURSION) - dbg_in_driver-- -#endif + dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->pid); return 0; complete: @@ -1440,28 +1159,16 @@ * done when the commad is for things like non existent * devices. */ -#if debug_enabled(DBG_RECURSION) - dbg_in_driver-- -#endif done(cmd); return 0; } - - /* - ********************************************************************* - * - * Function : dc395x_bios_param - * Description: Return the disk geometry for the given SCSI device. - ********************************************************************* + * Return the disk geometry for the given SCSI device. */ -static -int dc395x_bios_param(struct scsi_device *sdev, - struct block_device *bdev, - sector_t capacity, - int *info) +static int dc395x_bios_param(struct scsi_device *sdev, + struct block_device *bdev, sector_t capacity, int *info) { #ifdef CONFIG_SCSI_DC395x_TRMS1040_TRADMAP int heads, sectors, cylinders; @@ -1469,7 +1176,7 @@ int size = capacity; dprintkdbg(DBG_0, "dc395x_bios_param..............\n"); - acb = (struct AdapterCtlBlk *) sdev->host->hostdata; + acb = (struct AdapterCtlBlk *)sdev->host->hostdata; heads = 64; sectors = 32; cylinders = size / (heads * sectors); @@ -1489,12 +1196,8 @@ } -/* - * DC395x register dump - */ -static -void dump_register_info(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) +static void dump_register_info(struct AdapterCtlBlk *acb, + struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { u16 pstat; struct pci_dev *dev = acb->dev; @@ -1504,64 +1207,58 @@ if (!srb && dcb) srb = dcb->active_srb; if (srb) { - if (!(srb->cmd)) - dprintkl(KERN_INFO, "dump: SRB %p: cmd %p OOOPS!\n", srb, - srb->cmd); + if (!srb->cmd) + dprintkl(KERN_INFO, "dump: srb=%p cmd=%p OOOPS!\n", + srb, srb->cmd); else - dprintkl(KERN_INFO, "dump: SRB %p: cmd %p pid %li: %02x (%02i-%i)\n", - srb, srb->cmd, srb->cmd->pid, - srb->cmd->cmnd[0], srb->cmd->device->id, - srb->cmd->device->lun); - printk(" SGList %p Cnt %i Idx %i Len %i\n", + dprintkl(KERN_INFO, "dump: srb=%p cmd=%p (pid#%li) " + "cmnd=0x%02x <%02i-%i>\n", + srb, srb->cmd, srb->cmd->pid, + srb->cmd->cmnd[0], srb->cmd->device->id, + srb->cmd->device->lun); + printk(" sglist=%p cnt=%i idx=%i len=%i\n", srb->segment_x, srb->sg_count, srb->sg_index, srb->total_xfer_length); - printk - (" State %04x Status %02x Phase %02x (%sconn.)\n", - srb->state, srb->status, srb->scsi_phase, - (acb->active_dcb) ? "" : "not"); - TRACEOUT(" %s\n", srb->debugtrace); - } - dprintkl(KERN_INFO, "dump: SCSI block\n"); - printk - (" Status %04x FIFOCnt %02x Signals %02x IRQStat %02x\n", - DC395x_read16(acb, TRM_S1040_SCSI_STATUS), - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), - DC395x_read8(acb, TRM_S1040_SCSI_SIGNAL), - DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS)); - printk - (" Sync %02x Target %02x RSelID %02x SCSICtr %08x\n", - DC395x_read8(acb, TRM_S1040_SCSI_SYNC), - DC395x_read8(acb, TRM_S1040_SCSI_TARGETID), - DC395x_read8(acb, TRM_S1040_SCSI_IDMSG), - DC395x_read32(acb, TRM_S1040_SCSI_COUNTER)); - printk - (" IRQEn %02x Config %04x Cfg2 %02x Cmd %02x SelTO %02x\n", - DC395x_read8(acb, TRM_S1040_SCSI_INTEN), - DC395x_read16(acb, TRM_S1040_SCSI_CONFIG0), - DC395x_read8(acb, TRM_S1040_SCSI_CONFIG2), - DC395x_read8(acb, TRM_S1040_SCSI_COMMAND), - DC395x_read8(acb, TRM_S1040_SCSI_TIMEOUT)); - dprintkl(KERN_INFO, "dump: DMA block\n"); - printk - (" Cmd %04x FIFOCnt %02x FStat %02x IRQStat %02x IRQEn %02x Cfg %04x\n", - DC395x_read16(acb, TRM_S1040_DMA_COMMAND), - DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), - DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), - DC395x_read8(acb, TRM_S1040_DMA_STATUS), - DC395x_read8(acb, TRM_S1040_DMA_INTEN), - DC395x_read16(acb, TRM_S1040_DMA_CONFIG)); - printk(" TCtr %08x CTCtr %08x Addr %08x%08x\n", - DC395x_read32(acb, TRM_S1040_DMA_XCNT), - DC395x_read32(acb, TRM_S1040_DMA_CXCNT), - DC395x_read32(acb, TRM_S1040_DMA_XHIGHADDR), - DC395x_read32(acb, TRM_S1040_DMA_XLOWADDR)); - dprintkl(KERN_INFO, "dump: Misc: GCtrl %02x GStat %02x GTmr %02x\n", - DC395x_read8(acb, TRM_S1040_GEN_CONTROL), - DC395x_read8(acb, TRM_S1040_GEN_STATUS), - DC395x_read8(acb, TRM_S1040_GEN_TIMER)); - dprintkl(KERN_INFO, "dump: PCI Status %04x\n", pstat); - - + printk(" state=0x%04x status=0x%02x phase=0x%02x (%sconn.)\n", + srb->state, srb->status, srb->scsi_phase, + (acb->active_dcb) ? "" : "not"); + } + dprintkl(KERN_INFO, "dump: SCSI{status=0x%04x fifocnt=0x%02x " + "signals=0x%02x irqstat=0x%02x sync=0x%02x target=0x%02x " + "rselid=0x%02x ctr=0x%08x irqen=0x%02x config=0x%04x " + "config2=0x%02x cmd=0x%02x selto=0x%02x}\n", + DC395x_read16(acb, TRM_S1040_SCSI_STATUS), + DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), + DC395x_read8(acb, TRM_S1040_SCSI_SIGNAL), + DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS), + DC395x_read8(acb, TRM_S1040_SCSI_SYNC), + DC395x_read8(acb, TRM_S1040_SCSI_TARGETID), + DC395x_read8(acb, TRM_S1040_SCSI_IDMSG), + DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), + DC395x_read8(acb, TRM_S1040_SCSI_INTEN), + DC395x_read16(acb, TRM_S1040_SCSI_CONFIG0), + DC395x_read8(acb, TRM_S1040_SCSI_CONFIG2), + DC395x_read8(acb, TRM_S1040_SCSI_COMMAND), + DC395x_read8(acb, TRM_S1040_SCSI_TIMEOUT)); + dprintkl(KERN_INFO, "dump: DMA{cmd=0x%04x fifocnt=0x%02x fstat=0x%02x " + "irqstat=0x%02x irqen=0x%02x cfg=0x%04x tctr=0x%08x " + "ctctr=0x%08x addr=0x%08x:0x%08x}\n", + DC395x_read16(acb, TRM_S1040_DMA_COMMAND), + DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), + DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), + DC395x_read8(acb, TRM_S1040_DMA_STATUS), + DC395x_read8(acb, TRM_S1040_DMA_INTEN), + DC395x_read16(acb, TRM_S1040_DMA_CONFIG), + DC395x_read32(acb, TRM_S1040_DMA_XCNT), + DC395x_read32(acb, TRM_S1040_DMA_CXCNT), + DC395x_read32(acb, TRM_S1040_DMA_XHIGHADDR), + DC395x_read32(acb, TRM_S1040_DMA_XLOWADDR)); + dprintkl(KERN_INFO, "dump: gen{gctrl=0x%02x gstat=0x%02x gtmr=0x%02x} " + "pci{status=0x%04x}\n", + DC395x_read8(acb, TRM_S1040_GEN_CONTROL), + DC395x_read8(acb, TRM_S1040_GEN_STATUS), + DC395x_read8(acb, TRM_S1040_GEN_TIMER), + pstat); } @@ -1572,32 +1269,19 @@ u8 fifocnt = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT); if (!(fifocnt & 0x40)) dprintkdbg(DBG_FIFO, - "Clr FIFO (%i bytes) on phase %02x in %s\n", + "clear_fifo: (%i bytes) on phase %02x in %s\n", fifocnt & 0x3f, lines, txt); #endif -#if debug_enabled(DBG_TRACE) - if (acb->active_dcb && acb->active_dcb->active_srb) { - struct ScsiReqBlk *srb = acb->active_dcb->active_srb; - TRACEPRINTF("#*"); - } -#endif DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); } -/* - ******************************************************************** - * - * DC395x_reset scsi_reset_detect - * - ******************************************************************** - */ static void reset_dev_param(struct AdapterCtlBlk *acb) { struct DeviceCtlBlk *dcb; struct NvRamType *eeprom = &acb->eeprom; + dprintkdbg(DBG_0, "reset_dev_param: acb=%p\n", acb); - dprintkdbg(DBG_0, "reset_dev_param..............\n"); list_for_each_entry(dcb, &acb->dcb_list, list) { u8 period_index; @@ -1616,22 +1300,17 @@ /* - ********************************************************************* - * Function : int dc395x_eh_bus_reset(Scsi_Cmnd *cmd) - * Purpose : perform a hard reset on the SCSI bus - * Inputs : cmd - some command for this host (for fetching hooks) - * Returns : SUCCESS (0x2002) on success, else FAILED (0x2003). - ********************************************************************* + * perform a hard reset on the SCSI bus + * @cmd - some command for this host (for fetching hooks) + * Returns: SUCCESS (0x2002) on success, else FAILED (0x2003). */ -static int dc395x_eh_bus_reset(Scsi_Cmnd * cmd) +static int dc395x_eh_bus_reset(Scsi_Cmnd *cmd) { - struct AdapterCtlBlk *acb; - /*u32 acb_flags=0; */ - - dprintkl(KERN_INFO, "reset requested!\n"); - acb = (struct AdapterCtlBlk *) cmd->device->host->hostdata; - /* mid level guarantees no recursion */ - /*DC395x_ACB_LOCK(acb,acb_flags); */ + struct AdapterCtlBlk *acb = + (struct AdapterCtlBlk *)cmd->device->host->hostdata; + dprintkl(KERN_INFO, + "eh_bus_reset: (pid#%li) target=<%02i-%i> cmd=%p\n", + cmd->pid, cmd->device->id, cmd->device->lun, cmd); if (timer_pending(&acb->waiting_timer)) del_timer(&acb->waiting_timer); @@ -1657,52 +1336,42 @@ */ /* Clear SCSI FIFO */ DC395x_write8(acb, TRM_S1040_DMA_CONTROL, CLRXFIFO); - clear_fifo(acb, "reset"); + clear_fifo(acb, "eh_bus_reset"); /* Delete pending IRQ */ DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS); set_basic_config(acb); reset_dev_param(acb); doing_srb_done(acb, DID_RESET, cmd, 0); - acb->active_dcb = NULL; - acb->acb_flag = 0; /* RESET_DETECT, RESET_DONE ,RESET_DEV */ waiting_process_next(acb); - /*DC395x_ACB_LOCK(acb,acb_flags); */ return SUCCESS; } /* - ********************************************************************* - * Function : int dc395x_eh_abort(Scsi_Cmnd *cmd) - * Purpose : abort an errant SCSI command - * Inputs : cmd - command to be aborted - * Returns : SUCCESS (0x2002) on success, else FAILED (0x2003). - ********************************************************************* + * abort an errant SCSI command + * @cmd - command to be aborted + * Returns: SUCCESS (0x2002) on success, else FAILED (0x2003). */ -static int dc395x_eh_abort(Scsi_Cmnd * cmd) +static int dc395x_eh_abort(Scsi_Cmnd *cmd) { /* * Look into our command queues: If it has not been sent already, * we remove it and return success. Otherwise fail. */ struct AdapterCtlBlk *acb = - (struct AdapterCtlBlk *) cmd->device->host->hostdata; + (struct AdapterCtlBlk *)cmd->device->host->hostdata; struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; - - dprintkl(KERN_INFO, "eh abort: cmd %p (pid %li, %02i-%i) ", - cmd, - cmd->pid, - cmd->device->id, - cmd->device->lun); + dprintkl(KERN_INFO, "eh_abort: (pid#%li) target=<%02i-%i> cmd=%p\n", + cmd->pid, cmd->device->id, cmd->device->lun, cmd); dcb = find_dcb(acb, cmd->device->id, cmd->device->lun); if (!dcb) { - dprintkl(KERN_DEBUG, "abort - no DCB found"); + dprintkl(KERN_DEBUG, "eh_abort: No such device\n"); return FAILED; } @@ -1713,32 +1382,31 @@ pci_unmap_srb(acb, srb); free_tag(dcb, srb); srb_free_insert(acb, srb); - dprintkl(KERN_DEBUG, "abort - command found in waiting commands queue"); + dprintkl(KERN_DEBUG, "eh_abort: Command was waiting\n"); cmd->result = DID_ABORT << 16; return SUCCESS; } srb = find_cmd(cmd, &dcb->srb_going_list); if (srb) { - dprintkl(KERN_DEBUG, "abort - command currently in progress"); + dprintkl(KERN_DEBUG, "eh_abort: Command in progress"); /* XXX: Should abort the command here */ } else { - dprintkl(KERN_DEBUG, "abort - command not found"); + dprintkl(KERN_DEBUG, "eh_abort: Command not found"); } return FAILED; } /* SDTR */ -static -void build_sdtr(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, +static void build_sdtr(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { u8 *ptr = srb->msgout_buf + srb->msg_count; if (srb->msg_count > 1) { dprintkl(KERN_INFO, - "Build_SDTR: msgout_buf BUSY (%i: %02x %02x)\n", - srb->msg_count, srb->msgout_buf[0], - srb->msgout_buf[1]); + "build_sdtr: msgout_buf BUSY (%i: %02x %02x)\n", + srb->msg_count, srb->msgout_buf[0], + srb->msgout_buf[1]); return; } if (!(dcb->dev_mode & NTC_DO_SYNC_NEGO)) { @@ -1754,25 +1422,21 @@ *ptr++ = dcb->sync_offset; /* Transfer period (max. REQ/ACK dist) */ srb->msg_count += 5; srb->state |= SRB_DO_SYNC_NEGO; - TRACEPRINTF("S *"); } -/* SDTR */ -static -void build_wdtr(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, +/* WDTR */ +static void build_wdtr(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { - u8 wide = - ((dcb->dev_mode & NTC_DO_WIDE_NEGO) & (acb-> - config & HCC_WIDE_CARD)) - ? 1 : 0; + u8 wide = ((dcb->dev_mode & NTC_DO_WIDE_NEGO) & + (acb->config & HCC_WIDE_CARD)) ? 1 : 0; u8 *ptr = srb->msgout_buf + srb->msg_count; if (srb->msg_count > 1) { dprintkl(KERN_INFO, - "Build_WDTR: msgout_buf BUSY (%i: %02x %02x)\n", - srb->msg_count, srb->msgout_buf[0], - srb->msgout_buf[1]); + "build_wdtr: msgout_buf BUSY (%i: %02x %02x)\n", + srb->msg_count, srb->msgout_buf[0], + srb->msgout_buf[1]); return; } *ptr++ = MSG_EXTENDED; /* (01h) */ @@ -1781,7 +1445,6 @@ *ptr++ = wide; srb->msg_count += 4; srb->state |= SRB_DO_WIDE_NEGO; - TRACEPRINTF("W *"); } @@ -1809,7 +1472,7 @@ void selection_timeout_missed(unsigned long ptr) { unsigned long flags; - struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *) ptr; + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)ptr; struct ScsiReqBlk *srb; dprintkl(KERN_DEBUG, "Chip forgot to produce SelTO IRQ!\n"); if (!acb->active_dcb || !acb->active_dcb->active_srb) { @@ -1818,39 +1481,30 @@ } DC395x_LOCK_IO(acb->scsi_host, flags); srb = acb->active_dcb->active_srb; - TRACEPRINTF("N/TO *"); disconnect(acb); DC395x_UNLOCK_IO(acb->scsi_host, flags); } #endif -/* - * scsiio - * DC395x_DoWaitingSRB srb_done - * send_srb request_sense - */ -static -u8 start_scsi(struct AdapterCtlBlk * acb, struct DeviceCtlBlk * dcb, - struct ScsiReqBlk * srb) +static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, + struct ScsiReqBlk* srb) { u16 s_stat2, return_code; u8 s_stat, scsicommand, i, identify_message; u8 *ptr; + dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> srb=%p\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); - dprintkdbg(DBG_0, "start_scsi..............\n"); srb->tag_number = TAG_NONE; /* acb->tag_max_num: had error read in eeprom */ s_stat = DC395x_read8(acb, TRM_S1040_SCSI_SIGNAL); s_stat2 = 0; s_stat2 = DC395x_read16(acb, TRM_S1040_SCSI_STATUS); - TRACEPRINTF("Start %02x *", s_stat); #if 1 if (s_stat & 0x20 /* s_stat2 & 0x02000 */ ) { - dprintkdbg(DBG_KG, - "StartSCSI: pid %li(%02i-%i): BUSY %02x %04x\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, - s_stat, s_stat2); + dprintkdbg(DBG_KG, "start_scsi: (pid#%li) BUSY %02x %04x\n", + srb->cmd->pid, s_stat, s_stat2); /* * Try anyway? * @@ -1861,41 +1515,32 @@ * Instead let this fail and have the timer make sure the command is * tried again after a short time */ - TRACEPRINTF("^*"); /*selto_timer (acb); */ - /*monitor_next_irq = 1; */ return 1; } #endif if (acb->active_dcb) { - dprintkl(KERN_DEBUG, "We try to start a SCSI command (%li)!\n", - srb->cmd->pid); - dprintkl(KERN_DEBUG, "While another one (%li) is active!!\n", - (acb->active_dcb->active_srb ? acb->active_dcb-> - active_srb->cmd->pid : 0)); - TRACEOUT(" %s\n", srb->debugtrace); - if (acb->active_dcb->active_srb) - TRACEOUT(" %s\n", - acb->active_dcb->active_srb->debugtrace); + dprintkl(KERN_DEBUG, "start_scsi: (pid#%li) Attempt to start a" + "command while another command (pid#%li) is active.", + srb->cmd->pid, + acb->active_dcb->active_srb ? + acb->active_dcb->active_srb->cmd->pid : 0); return 1; } if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) { - dprintkdbg(DBG_KG, - "StartSCSI failed (busy) for pid %li(%02i-%i)\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun); - TRACEPRINTF("°*"); + dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n", + srb->cmd->pid); return 1; } /* Allow starting of SCSI commands half a second before we allow the mid-level * to queue them again after a reset */ if (time_before(jiffies, acb->scsi_host->last_reset - HZ / 2)) { - dprintkdbg(DBG_KG, - "We were just reset and don't accept commands yet!\n"); + dprintkdbg(DBG_KG, "start_scsi: Refuse cmds (reset wait)\n"); return 1; } /* Flush FIFO */ - clear_fifo(acb, "Start"); + clear_fifo(acb, "start_scsi"); DC395x_write8(acb, TRM_S1040_SCSI_HOSTID, acb->scsi_host->this_id); DC395x_write8(acb, TRM_S1040_SCSI_TARGETID, dcb->target_id); DC395x_write8(acb, TRM_S1040_SCSI_SYNC, dcb->sync_period); @@ -1939,9 +1584,7 @@ } srb->msg_count = 0; } - /* - ** Send identify message - */ + /* Send identify message */ DC395x_write8(acb, TRM_S1040_SCSI_FIFO, identify_message); scsicommand = SCMD_SEL_ATN; @@ -1958,37 +1601,29 @@ tag_number++; } if (tag_number >= dcb->max_command) { - dprintkl(KERN_WARNING, - "Start_SCSI: Out of tags for pid %li (%i-%i)\n", - srb->cmd->pid, srb->cmd->device->id, - srb->cmd->device->lun); + dprintkl(KERN_WARNING, "start_scsi: (pid#%li) " + "Out of tags target=<%02i-%i>)\n", + srb->cmd->pid, srb->cmd->device->id, + srb->cmd->device->lun); srb->state = SRB_READY; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); return 1; } - /* - ** Send Tag id - */ + /* Send Tag id */ DC395x_write8(acb, TRM_S1040_SCSI_FIFO, MSG_SIMPLE_QTAG); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, tag_number); dcb->tag_mask |= tag_mask; srb->tag_number = tag_number; - TRACEPRINTF("Tag %i *", tag_number); - scsicommand = SCMD_SEL_ATN3; srb->state = SRB_START_; } #endif /*polling:*/ - /* - * Send CDB ..command block ......... - */ - dprintkdbg(DBG_KG, - "StartSCSI (pid %li) %02x (%i-%i): Tag %i\n", - srb->cmd->pid, srb->cmd->cmnd[0], - srb->cmd->device->id, srb->cmd->device->lun, - srb->tag_number); + /* Send CDB ..command block ......... */ + dprintkdbg(DBG_KG, "start_scsi: (pid#%li) <%02i-%i> cmnd=0x%02x tag=%i\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd->cmnd[0], srb->tag_number); if (srb->flag & AUTO_REQSENSE) { DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, (dcb->target_lun << 5)); @@ -1998,7 +1633,7 @@ sizeof(srb->cmd->sense_buffer)); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 0); } else { - ptr = (u8 *) srb->cmd->cmnd; + ptr = (u8 *)srb->cmd->cmnd; for (i = 0; i < srb->cmd->cmd_len; i++) DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *ptr++); } @@ -2011,10 +1646,8 @@ * we caught an interrupt (must be reset or reselection ... ) * : Let's process it first! */ - dprintkdbg(DBG_0, "Debug: StartSCSI failed (busy) for pid %li(%02i-%i)!\n", + dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> Failed - busy\n", srb->cmd->pid, dcb->target_id, dcb->target_lun); - /*clear_fifo (acb, "Start2"); */ - /*DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); */ srb->state = SRB_READY; free_tag(dcb, srb); srb->msg_count = 0; @@ -2032,23 +1665,13 @@ /* it's important for atn stop */ DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH | DO_HWRESELECT); - /* - ** SCSI command - */ - TRACEPRINTF("%02x *", scsicommand); + /* SCSI command */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, scsicommand); } return return_code; } -/* - ******************************************************************** - * scsiio - * init_adapter - ******************************************************************** - */ - /** * dc395x_handle_interrupt - Handle an interrupt that has been confirmed to * have been triggered for this card. @@ -2056,37 +1679,29 @@ * @acb: a pointer to the adpter control block * @scsi_status: the status return when we checked the card **/ -static void dc395x_handle_interrupt(struct AdapterCtlBlk *acb, u16 scsi_status) +static void dc395x_handle_interrupt(struct AdapterCtlBlk *acb, + u16 scsi_status) { struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; u16 phase; u8 scsi_intstatus; unsigned long flags; - void (*dc395x_statev) (struct AdapterCtlBlk *, struct ScsiReqBlk *, - u16 *); + void (*dc395x_statev)(struct AdapterCtlBlk *, struct ScsiReqBlk *, + u16 *); DC395x_LOCK_IO(acb->scsi_host, flags); /* This acknowledges the IRQ */ scsi_intstatus = DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS); if ((scsi_status & 0x2007) == 0x2002) - dprintkl(KERN_DEBUG, "COP after COP completed? %04x\n", - scsi_status); -#if 1 /*def DBG_0 */ - if (monitor_next_irq) { - dprintkl(KERN_INFO, - "status=%04x intstatus=%02x\n", scsi_status, - scsi_intstatus); - monitor_next_irq--; - } -#endif - /*DC395x_ACB_LOCK(acb,acb_flags); */ + dprintkl(KERN_DEBUG, + "COP after COP completed? %04x\n", scsi_status); if (debug_enabled(DBG_KG)) { if (scsi_intstatus & INT_SELTIMEOUT) - dprintkdbg(DBG_KG, "Sel Timeout IRQ\n"); + dprintkdbg(DBG_KG, "handle_interrupt: Selection timeout\n"); } - /*dprintkl(KERN_DEBUG, "DC395x_IRQ: intstatus = %02x ", scsi_intstatus); */ + /*dprintkl(KERN_DEBUG, "handle_interrupt: intstatus = 0x%02x ", scsi_intstatus); */ if (timer_pending(&acb->selto_timer)) del_timer(&acb->selto_timer); @@ -2111,8 +1726,8 @@ dcb = acb->active_dcb; if (!dcb) { dprintkl(KERN_DEBUG, - "Oops: BusService (%04x %02x) w/o ActiveDCB!\n", - scsi_status, scsi_intstatus); + "Oops: BusService (%04x %02x) w/o ActiveDCB!\n", + scsi_status, scsi_intstatus); goto out_unlock; } srb = dcb->active_srb; @@ -2120,12 +1735,10 @@ dprintkdbg(DBG_0, "MsgOut Abort Device.....\n"); enable_msgout_abort(acb, srb); } - /* - ************************************************************ - * software sequential machine - ************************************************************ - */ - phase = (u16) srb->scsi_phase; + + /* software sequential machine */ + phase = (u16)srb->scsi_phase; + /* * 62037 or 62137 * call dc395x_scsi_phase0[]... "phase entry" @@ -2139,22 +1752,20 @@ /* nop0, phase:5 PH_BUS_FREE .. initial phase */ /* msgout_phase0, phase:6 */ /* msgin_phase0, phase:7 */ - dc395x_statev = (void *) dc395x_scsi_phase0[phase]; + dc395x_statev = dc395x_scsi_phase0[phase]; dc395x_statev(acb, srb, &scsi_status); + /* - *$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ - * - * if there were any exception occured - * scsi_status will be modify to bus free phase - * new scsi_status transfer out from ... previous dc395x_statev - * - *$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + * if there were any exception occured scsi_status + * will be modify to bus free phase new scsi_status + * transfer out from ... previous dc395x_statev */ srb->scsi_phase = scsi_status & PHASEMASK; - phase = (u16) scsi_status & PHASEMASK; + phase = (u16)scsi_status & PHASEMASK; + /* - * call dc395x_scsi_phase1[]... "phase entry" - * handle every phase do transfer + * call dc395x_scsi_phase1[]... "phase entry" handle + * every phase to do transfer */ /* data_out_phase1, phase:0 */ /* data_in_phase1, phase:1 */ @@ -2164,30 +1775,22 @@ /* nop1, phase:5 PH_BUS_FREE .. initial phase */ /* msgout_phase1, phase:6 */ /* msgin_phase1, phase:7 */ - dc395x_statev = (void *) dc395x_scsi_phase1[phase]; + dc395x_statev = dc395x_scsi_phase1[phase]; dc395x_statev(acb, srb, &scsi_status); } out_unlock: DC395x_UNLOCK_IO(acb->scsi_host, flags); - return; } -static -irqreturn_t dc395x_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dc395x_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)dev_id; u16 scsi_status; u8 dma_status; irqreturn_t handled = IRQ_NONE; - dprintkdbg(DBG_0, "dc395x_interrupt..............\n"); -#if debug_enabled(DBG_RECURSION) - if (dbg_in_driver++ > NORM_REC_LVL) { - dprintkl(KERN_DEBUG, "%i interrupt recursion?\n", dbg_in_driver); - } -#endif - /* * Check for pending interupt */ @@ -2200,7 +1803,7 @@ } else if (dma_status & 0x20) { /* Error from the DMA engine */ - dprintkl(KERN_INFO, "Interrupt from DMA engine: %02x!\n", dma_status); + dprintkl(KERN_INFO, "Interrupt from DMA engine: 0x%02x!\n", dma_status); #if 0 dprintkl(KERN_INFO, "This means DMA error! Try to handle ...\n"); if (acb->active_dcb) { @@ -2216,135 +1819,75 @@ handled = IRQ_HANDLED; } -#if debug_enabled(DBG_RECURSION) - dbg_in_driver-- -#endif return handled; } -/* - ******************************************************************** - * scsiio - * msgout_phase0: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =6 - ******************************************************************** - */ -static -void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - dprintkdbg(DBG_0, "msgout_phase0.....\n"); - if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT)) { + dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->pid); + if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT)) *pscsi_status = PH_BUS_FREE; /*.. initial phase */ - } + DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ srb->state &= ~SRB_MSGOUT; - TRACEPRINTF("MOP0 *"); } -/* - ******************************************************************** - * scsiio - * msgout_phase1: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =6 - ******************************************************************** - */ -static -void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { u16 i; u8 *ptr; - struct DeviceCtlBlk *dcb; + dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->pid); - dprintkdbg(DBG_0, "msgout_phase1..............\n"); - TRACEPRINTF("MOP1*"); - dcb = acb->active_dcb; - clear_fifo(acb, "MOP1"); + clear_fifo(acb, "msgout_phase1"); if (!(srb->state & SRB_MSGOUT)) { srb->state |= SRB_MSGOUT; - dprintkl(KERN_DEBUG, "Debug: pid %li: MsgOut Phase unexpected.\n", srb->cmd->pid); /* So what ? */ + dprintkl(KERN_DEBUG, + "msgout_phase1: (pid#%li) Phase unexpected\n", + srb->cmd->pid); /* So what ? */ } if (!srb->msg_count) { - dprintkdbg(DBG_0, "Debug: pid %li: NOP Msg (no output message there).\n", + dprintkdbg(DBG_0, "msgout_phase1: (pid#%li) NOP msg\n", srb->cmd->pid); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, MSG_NOP); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT); - TRACEPRINTF("\\*"); - TRACEOUT(" %s\n", srb->debugtrace); return; } - ptr = (u8 *) srb->msgout_buf; - TRACEPRINTF("(*"); - /*dprintkl(KERN_DEBUG, "Send msg: "); print_msg (ptr, srb->msg_count); */ - /*dprintkl(KERN_DEBUG, "MsgOut: "); */ - for (i = 0; i < srb->msg_count; i++) { - TRACEPRINTF("%02x *", *ptr); + ptr = (u8 *)srb->msgout_buf; + for (i = 0; i < srb->msg_count; i++) DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *ptr++); - } - TRACEPRINTF(")*"); srb->msg_count = 0; - /*printk("\n"); */ - if (/*(dcb->flag & ABORT_DEV_) && */ - (srb->msgout_buf[0] == MSG_ABORT)) + if (srb->msgout_buf[0] == MSG_ABORT) srb->state = SRB_ABORT_SENT; - /*1.25 */ - /*DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH); *//* it's important for atn stop */ - /* - ** SCSI command - */ - /*TRACEPRINTF (".*"); */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT); } -/* - ******************************************************************** - * scsiio - * command_phase0: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =2 - ******************************************************************** - */ -static -void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - TRACEPRINTF("COP0 *"); - /*1.25 */ - /*clear_fifo (acb, COP0); */ + dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->pid); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); } -/* - ******************************************************************** - * scsiio - * command_phase1: one of dc395x_scsi_phase1[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase1[phase] - * if phase =2 - ******************************************************************** - */ -static -void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { struct DeviceCtlBlk *dcb; u8 *ptr; u16 i; + dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->pid); - dprintkdbg(DBG_0, "command_phase1..............\n"); - TRACEPRINTF("COP1*"); - clear_fifo(acb, "COP1"); + clear_fifo(acb, "command_phase1"); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN); if (!(srb->flag & AUTO_REQSENSE)) { - ptr = (u8 *) srb->cmd->cmnd; + ptr = (u8 *)srb->cmd->cmnd; for (i = 0; i < srb->cmd->cmd_len; i++) { DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *ptr); ptr++; @@ -2364,22 +1907,24 @@ /* it's important for atn stop */ DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* SCSI command */ - TRACEPRINTF(".*"); DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT); } -/* Do sanity checks for S/G list */ -static inline void check_sg_list(struct ScsiReqBlk *srb) +/* + * Verify that the remaining space in the hw sg lists is the same as + * the count of remaining bytes in srb->total_xfer_length + */ +static void sg_verify_length(struct ScsiReqBlk *srb) { - if (debug_enabled(DBG_SGPARANOIA)) { + if (debug_enabled(DBG_SG)) { unsigned len = 0; unsigned idx = srb->sg_index; struct SGentry *psge = srb->segment_x + idx; for (; idx < srb->sg_count; psge++, idx++) len += psge->length; if (len != srb->total_xfer_length) - dprintkdbg(DBG_SGPARANOIA, + dprintkdbg(DBG_SG, "Inconsistent SRB S/G lengths (Tot=%i, Count=%i) !!\n", srb->total_xfer_length, len); } @@ -2390,75 +1935,90 @@ * Compute the next Scatter Gather list index and adjust its length * and address if necessary; also compute virt_addr */ -static void update_sg_list(struct ScsiReqBlk *srb, u32 left) +static void sg_update_list(struct ScsiReqBlk *srb, u32 left) { - struct SGentry *psge; - u32 xferred = 0; u8 idx; - Scsi_Cmnd *cmd = srb->cmd; struct scatterlist *sg; + Scsi_Cmnd *cmd = srb->cmd; int segment = cmd->use_sg; + u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ + struct SGentry *psge = srb->segment_x + srb->sg_index; - dprintkdbg(DBG_KG, "Update SG: Total %i, Left %i\n", - srb->total_xfer_length, left); - check_sg_list(srb); - psge = srb->segment_x + srb->sg_index; - /* data that has already been transferred */ - xferred = srb->total_xfer_length - left; - if (srb->total_xfer_length != left) { - /*check_sg_list_TX (srb, xferred); */ - /* Remaining */ - srb->total_xfer_length = left; - /* parsing from last time disconnect SGIndex */ - for (idx = srb->sg_index; idx < srb->sg_count; idx++) { + dprintkdbg(DBG_0, + "sg_update_list: Transfered %i of %i bytes, %i remain\n", + xferred, srb->total_xfer_length, left); + if (xferred == 0) { + /* nothing to update since we did not transfer any data */ + return; + } + + sg_verify_length(srb); + srb->total_xfer_length = left; /* update remaining count */ + for (idx = srb->sg_index; idx < srb->sg_count; idx++) { + if (xferred >= psge->length) { /* Complete SG entries done */ - if (xferred >= psge->length) - xferred -= psge->length; - /* Partial SG entries done */ - else { - psge->length -= xferred; /* residue data length */ - psge->address += xferred; /* residue data pointer */ - srb->sg_index = idx; - pci_dma_sync_single(srb->dcb-> - acb->dev, - srb->sg_bus_addr, - sizeof(struct SGentry) - * - DC395x_MAX_SG_LISTENTRY, - PCI_DMA_TODEVICE); - break; - } - psge++; + xferred -= psge->length; + } else { + /* Partial SG entry done */ + psge->length -= xferred; + psge->address += xferred; + srb->sg_index = idx; + pci_dma_sync_single(srb->dcb-> + acb->dev, + srb->sg_bus_addr, + SEGMENTX_LEN, + PCI_DMA_TODEVICE); + break; } - check_sg_list(srb); + psge++; } - /* We need the corresponding virtual address sg_to_virt */ - /*dprintkl(KERN_DEBUG, "sg_to_virt: bus %08x -> virt ", psge->address); */ + sg_verify_length(srb); + + /* we need the corresponding virtual address */ if (!segment) { srb->virt_addr += xferred; - /*printk("%p\n", srb->virt_addr); */ return; } + /* We have to walk the scatterlist to find it */ - sg = (struct scatterlist *) cmd->request_buffer; + sg = (struct scatterlist *)cmd->request_buffer; while (segment--) { - /*printk("(%08x)%p ", BUS_ADDR(*sg), PAGE_ADDRESS(sg)); */ unsigned long mask = - ~((unsigned long) sg->length - 1) & PAGE_MASK; - if ((BUS_ADDR(*sg) & mask) == (psge->address & mask)) { - srb->virt_addr = (PAGE_ADDRESS(sg) + ~((unsigned long)sg->length - 1) & PAGE_MASK; + if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { + srb->virt_addr = (page_address(sg->page) + psge->address - (psge->address & PAGE_MASK)); - /*printk("%p\n", srb->virt_addr); */ return; } ++sg; } - dprintkl(KERN_ERR, "sg_to_virt failed!\n"); + + dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); srb->virt_addr = 0; } +/* + * We have transfered a single byte (PIO mode?) and need to update + * the count of bytes remaining (total_xfer_length) and update the sg + * entry to either point to next byte in the current sg entry, or of + * already at the end to point to the start of the next sg entry + */ +static void sg_subtract_one(struct ScsiReqBlk *srb) +{ + srb->total_xfer_length--; + srb->segment_x[srb->sg_index].length--; + if (srb->total_xfer_length && + !srb->segment_x[srb->sg_index].length) { + if (debug_enabled(DBG_PIO)) + printk(" (next segment)"); + srb->sg_index++; + sg_update_list(srb, srb->total_xfer_length); + } +} + + /* * cleanup_after_transfer * @@ -2467,27 +2027,21 @@ * Should probably also be called from other places * Best might be to call it in DataXXPhase0, if new phase will differ */ -static -void cleanup_after_transfer(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb) +static void cleanup_after_transfer(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb) { - TRACEPRINTF(" Cln*"); /*DC395x_write8 (TRM_S1040_DMA_STATUS, FORCEDMACOMP); */ if (DC395x_read16(acb, TRM_S1040_DMA_COMMAND) & 0x0001) { /* read */ if (!(DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x40)) - clear_fifo(acb, "ClnIn"); - + clear_fifo(acb, "cleanup/in"); if (!(DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT) & 0x80)) DC395x_write8(acb, TRM_S1040_DMA_CONTROL, CLRXFIFO); } else { /* write */ if (!(DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT) & 0x80)) DC395x_write8(acb, TRM_S1040_DMA_CONTROL, CLRXFIFO); - if (!(DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x40)) - clear_fifo(acb, "ClnOut"); - + clear_fifo(acb, "cleanup/out"); } - /*1.25 */ DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); } @@ -2497,26 +2051,16 @@ * Seems to be needed for unknown reasons; could be a hardware bug :-( */ #define DC395x_LASTPIO 4 -/* - ******************************************************************** - * scsiio - * data_out_phase0: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =0 - ******************************************************************** - */ -static -void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) + + +static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - u16 scsi_status; - u32 d_left_counter = 0; struct DeviceCtlBlk *dcb = srb->dcb; - - dprintkdbg(DBG_0, "data_out_phase0.....\n"); - TRACEPRINTF("DOP0*"); - dcb = srb->dcb; - scsi_status = *pscsi_status; + u16 scsi_status = *pscsi_status; + u32 d_left_counter = 0; + dprintkdbg(DBG_0, "data_out_phase0: (pid#%li) <%02i-%i>\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); /* * KG: We need to drain the buffers before we draw any conclusions! @@ -2530,12 +2074,14 @@ * KG: Stop DMA engine pushing more data into the SCSI FIFO * If we need more data, the DMA SG list will be freshly set up, anyway */ - dprintkdbg(DBG_PIO, "DOP0: DMA_FCNT: %02x, DMA_FSTAT: %02x, SCSI_FCNT: %02x, CTR %06x, stat %04x, Tot: %06x\n", - DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), - DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), - DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), scsi_status, - srb->total_xfer_length); + dprintkdbg(DBG_PIO, "data_out_phase0: " + "DMA{fifcnt=0x%02x fifostat=0x%02x} " + "SCSI{fifocnt=0x%02x cnt=0x%06x status=0x%04x} total=0x%06x\n", + DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), + DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), + DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), + DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), scsi_status, + srb->total_xfer_length); DC395x_write8(acb, TRM_S1040_DMA_CONTROL, STOPDMAXFER | CLRXFIFO); if (!(srb->state & SRB_XFERPAD)) { @@ -2554,31 +2100,21 @@ * if there was some data left in SCSI FIFO */ d_left_counter = - (u32) (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & - 0x1F); + (u32)(DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & + 0x1F); if (dcb->sync_period & WIDE_SYNC) d_left_counter <<= 1; - dprintkdbg(DBG_KG, - "Debug: SCSI FIFO contains %i %s in DOP0\n", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), - (dcb-> - sync_period & WIDE_SYNC) ? "words" : - "bytes"); - dprintkdbg(DBG_KG, - "SCSI FIFOCNT %02x, SCSI CTR %08x\n", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), - DC395x_read32(acb, TRM_S1040_SCSI_COUNTER)); - dprintkdbg(DBG_KG, - "DMA FIFOCNT %04x, FIFOSTAT %02x, DMA CTR %08x\n", - DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), - DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), - DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); - - /* - * if WIDE scsi SCSI FIFOCNT unit is word !!! - * so need to *= 2 - */ + dprintkdbg(DBG_KG, "data_out_phase0: FIFO contains %i %s\n" + "SCSI{fifocnt=0x%02x cnt=0x%08x} " + "DMA{fifocnt=0x%04x cnt=0x%02x ctr=0x%08x}\n", + DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), + (dcb->sync_period & WIDE_SYNC) ? "words" : "bytes", + DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), + DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), + DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), + DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), + DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); } /* * calculate all the residue data that not yet tranfered @@ -2592,16 +2128,16 @@ if (srb->total_xfer_length > DC395x_LASTPIO) d_left_counter += DC395x_read32(acb, TRM_S1040_SCSI_COUNTER); - TRACEPRINTF("%06x *", d_left_counter); /* Is this a good idea? */ - /*clear_fifo (acb, "DOP1"); */ + /*clear_fifo(acb, "DOP1"); */ /* KG: What is this supposed to be useful for? WIDE padding stuff? */ if (d_left_counter == 1 && dcb->sync_period & WIDE_SYNC && srb->cmd->request_bufflen % 2) { d_left_counter = 0; - dprintkl(KERN_INFO, "DOP0: Discard 1 byte. (%02x)\n", - scsi_status); + dprintkl(KERN_INFO, + "data_out_phase0: Discard 1 byte (0x%02x)\n", + scsi_status); } /* * KG: Oops again. Same thinko as above: The SCSI might have been @@ -2613,19 +2149,9 @@ * KG: This is nonsense: We have been WRITING data to the bus * If the SCSI engine has no bytes left, how should the DMA engine? */ - if ((d_left_counter == - 0) /*|| (scsi_status & SCSIXFERCNT_2_ZERO) ) */ ) { - /* - * int ctr = 6000000; u8 TempDMAstatus; - * do - * { - * TempDMAstatus = DC395x_read8(acb, TRM_S1040_DMA_STATUS); - * } while( !(TempDMAstatus & DMAXFERCOMP) && --ctr); - * if (ctr < 6000000-1) dprintkl(KERN_DEBUG, "DMA should be complete ... in DOP1\n"); - * if (!ctr) dprintkl(KERN_ERR, "Deadlock in DataOutPhase0 !!\n"); - */ + if (d_left_counter == 0) { srb->total_xfer_length = 0; - } else { /* Update SG list */ + } else { /* * if transfer not yet complete * there were some data residue in SCSI FIFO or @@ -2635,18 +2161,18 @@ srb->total_xfer_length - d_left_counter; const int diff = (dcb->sync_period & WIDE_SYNC) ? 2 : 1; - update_sg_list(srb, d_left_counter); + sg_update_list(srb, d_left_counter); /* KG: Most ugly hack! Apparently, this works around a chip bug */ if ((srb->segment_x[srb->sg_index].length == diff && srb->cmd->use_sg) || ((oldxferred & ~PAGE_MASK) == (PAGE_SIZE - diff)) ) { - dprintkl(KERN_INFO, - "Work around chip bug (%i)?\n", diff); + dprintkl(KERN_INFO, "data_out_phase0: " + "Work around chip bug (%i)?\n", diff); d_left_counter = srb->total_xfer_length - diff; - update_sg_list(srb, d_left_counter); + sg_update_list(srb, d_left_counter); /*srb->total_xfer_length -= diff; */ /*srb->virt_addr += diff; */ /*if (srb->cmd->use_sg) */ @@ -2654,71 +2180,30 @@ } } } -#if 0 - if (!(DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x40)) - dprintkl(KERN_DEBUG, - "DOP0(%li): %i bytes in SCSI FIFO! (Clear!)\n", - srb->cmd->pid, - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f); -#endif - /*clear_fifo (acb, "DOP0"); */ - /*DC395x_write8 (TRM_S1040_DMA_CONTROL, CLRXFIFO | ABORTXFER); */ -#if 1 if ((*pscsi_status & PHASEMASK) != PH_DATA_OUT) { - /*dprintkl(KERN_DEBUG, "Debug: Clean up after Data Out ...\n"); */ cleanup_after_transfer(acb, srb); } -#endif - TRACEPRINTF(".*"); } -/* - ******************************************************************** - * scsiio - * data_out_phase1: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =0 - * 62037 - ******************************************************************** - */ -static -void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - - dprintkdbg(DBG_0, "data_out_phase1.....\n"); - /*1.25 */ - TRACEPRINTF("DOP1*"); - clear_fifo(acb, "DOP1"); - /* - ** do prepare befor transfer when data out phase - */ + dprintkdbg(DBG_0, "data_out_phase1: (pid#%li) <%02i-%i>\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + clear_fifo(acb, "data_out_phase1"); + /* do prepare before transfer when data out phase */ data_io_transfer(acb, srb, XFERDATAOUT); - TRACEPRINTF(".*"); } -/* - ******************************************************************** - * scsiio - * data_in_phase0: one of dc395x_scsi_phase1[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase1[phase] - * if phase =1 - ******************************************************************** - */ -static -void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - u16 scsi_status; + u16 scsi_status = *pscsi_status; u32 d_left_counter = 0; - /*struct DeviceCtlBlk* dcb = srb->dcb; */ - /*u8 bval; */ - - dprintkdbg(DBG_0, "data_in_phase0..............\n"); - TRACEPRINTF("DIP0*"); - scsi_status = *pscsi_status; + dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); /* * KG: DataIn is much more tricky than DataOut. When the device is finished @@ -2735,10 +2220,8 @@ */ if (!(srb->state & SRB_XFERPAD)) { if (scsi_status & PARITYERROR) { - dprintkl(KERN_INFO, - "Parity Error (pid %li, target %02i-%i)\n", - srb->cmd->pid, srb->cmd->device->id, - srb->cmd->device->lun); + dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) " + "Parity Error\n", srb->cmd->pid); srb->status |= PARITY_ERROR; } /* @@ -2751,7 +2234,7 @@ #if 0 int ctr = 6000000; dprintkl(KERN_DEBUG, - "DIP0: Wait for DMA FIFO to flush ...\n"); + "DIP0: Wait for DMA FIFO to flush ...\n"); /*DC395x_write8 (TRM_S1040_DMA_CONTROL, STOPDMAXFER); */ /*DC395x_write32 (TRM_S1040_SCSI_COUNTER, 7); */ /*DC395x_write8 (TRM_S1040_SCSI_COMMAND, SCMD_DMA_IN); */ @@ -2766,73 +2249,56 @@ "Deadlock in DIP0 waiting for DMA FIFO empty!!\n"); /*DC395x_write32 (TRM_S1040_SCSI_COUNTER, 0); */ #endif - dprintkdbg(DBG_KG, "DIP0: DMA_FIFO: %02x %02x\n", - DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), - DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT)); + dprintkdbg(DBG_KG, "data_in_phase0: " + "DMA{fifocnt=0x%02x fifostat=0x%02x}\n", + DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), + DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT)); } /* Now: Check remainig data: The SCSI counters should tell us ... */ d_left_counter = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER) + ((DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f) << ((srb->dcb->sync_period & WIDE_SYNC) ? 1 : 0)); - - dprintkdbg(DBG_KG, "SCSI FIFO contains %i %s in DIP0\n", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f, - (srb->dcb-> - sync_period & WIDE_SYNC) ? "words" : "bytes"); - dprintkdbg(DBG_KG, "SCSI FIFOCNT %02x, SCSI CTR %08x\n", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), - DC395x_read32(acb, TRM_S1040_SCSI_COUNTER)); - dprintkdbg(DBG_KG, "DMA FIFOCNT %02x,%02x DMA CTR %08x\n", - DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), - DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), - DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); - dprintkdbg(DBG_KG, "Remaining: TotXfer: %i, SCSI FIFO+Ctr: %i\n", - srb->total_xfer_length, d_left_counter); + dprintkdbg(DBG_KG, "data_in_phase0: " + "SCSI{fifocnt=0x%02x%s ctr=0x%08x} " + "DMA{fifocnt=0x%02x fifostat=0x%02x ctr=0x%08x} " + "Remain{totxfer=%i scsi_fifo+ctr=%i}\n", + DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), + (srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes", + DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), + DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), + DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), + DC395x_read32(acb, TRM_S1040_DMA_CXCNT), + srb->total_xfer_length, d_left_counter); #if DC395x_LASTPIO /* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */ if (d_left_counter && srb->total_xfer_length <= DC395x_LASTPIO) { /*u32 addr = (srb->segment_x[srb->sg_index].address); */ - /*update_sg_list (srb, d_left_counter); */ - dprintkdbg(DBG_PIO, "DIP0: PIO (%i %s) to %p for remaining %i bytes:", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & - 0x1f, - (srb->dcb-> - sync_period & WIDE_SYNC) ? "words" : - "bytes", srb->virt_addr, - srb->total_xfer_length); - + /*sg_update_list (srb, d_left_counter); */ + dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) to " + "%p for remaining %i bytes:", + DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f, + (srb->dcb->sync_period & WIDE_SYNC) ? + "words" : "bytes", + srb->virt_addr, + srb->total_xfer_length); if (srb->dcb->sync_period & WIDE_SYNC) DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); - - while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != - 0x40) { - u8 byte = - DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) { + u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); *(srb->virt_addr)++ = byte; if (debug_enabled(DBG_PIO)) printk(" %02x", byte); - srb->total_xfer_length--; d_left_counter--; - srb->segment_x[srb->sg_index].length--; - if (srb->total_xfer_length - && !srb->segment_x[srb->sg_index]. - length) { - if (debug_enabled(DBG_PIO)) - printk(" (next segment)"); - srb->sg_index++; - update_sg_list(srb, - d_left_counter); - } + sg_subtract_one(srb); } if (srb->dcb->sync_period & WIDE_SYNC) { -#if 1 /* Read the last byte ... */ +#if 1 + /* Read the last byte ... */ if (srb->total_xfer_length > 0) { - u8 byte = - DC395x_read8 - (acb, TRM_S1040_SCSI_FIFO); + u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); *(srb->virt_addr)++ = byte; srb->total_xfer_length--; if (debug_enabled(DBG_PIO)) @@ -2859,8 +2325,8 @@ * if there was some data left in SCSI FIFO */ d_left_counter = - (u32) (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & - 0x1F); + (u32)(DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & + 0x1F); if (srb->dcb->sync_period & WIDE_SYNC) d_left_counter <<= 1; /* @@ -2870,19 +2336,8 @@ */ } #endif - /*d_left_counter += DC395x_read32(acb, TRM_S1040_SCSI_COUNTER); */ -#if 0 - dprintkl(KERN_DEBUG, - "DIP0: ctr=%08x, DMA_FIFO=%02x,%02x SCSI_FIFO=%02x\n", - d_left_counter, DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), - DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT)); - dprintkl(KERN_DEBUG, "DIP0: DMAStat %02x\n", - DC395x_read8(acb, TRM_S1040_DMA_STATUS)); -#endif - /* KG: This should not be needed any more! */ - if ((d_left_counter == 0) + if (d_left_counter == 0 || (scsi_status & SCSIXFERCNT_2_ZERO)) { #if 0 int ctr = 6000000; @@ -2896,12 +2351,6 @@ "Deadlock in DataInPhase0 waiting for DMA!!\n"); srb->total_xfer_length = 0; #endif -#if 0 /*def DBG_KG */ - dprintkl(KERN_DEBUG, - "DIP0: DMA not yet ready: %02x: %i -> %i bytes\n", - DC395x_read8(acb, TRM_S1040_DMA_STATUS), - srb->total_xfer_length, d_left_counter); -#endif srb->total_xfer_length = d_left_counter; } else { /* phase changed */ /* @@ -2912,333 +2361,209 @@ * there were some data residue in SCSI FIFO or * SCSI transfer counter not empty */ - update_sg_list(srb, d_left_counter); + sg_update_list(srb, d_left_counter); } } /* KG: The target may decide to disconnect: Empty FIFO before! */ if ((*pscsi_status & PHASEMASK) != PH_DATA_IN) { - /*dprintkl(KERN_DEBUG, "Debug: Clean up after Data In ...\n"); */ cleanup_after_transfer(acb, srb); } -#if 0 - /* KG: Make sure, no previous transfers are pending! */ - bval = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT); - if (!(bval & 0x40)) { - bval &= 0x1f; - dprintkl(KERN_DEBUG, - "DIP0(%li): %i bytes in SCSI FIFO (stat %04x) (left %08x)!!\n", - srb->cmd->pid, bval & 0x1f, scsi_status, - d_left_counter); - if ((d_left_counter == 0) - || (scsi_status & SCSIXFERCNT_2_ZERO)) { - dprintkl(KERN_DEBUG, "Clear FIFO!\n"); - clear_fifo(acb, "DIP0"); - } - } -#endif - /*DC395x_write8 (TRM_S1040_DMA_CONTROL, CLRXFIFO | ABORTXFER); */ - - /*clear_fifo (acb, "DIP0"); */ - /*DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH); */ - TRACEPRINTF(".*"); } -/* - ******************************************************************** - * scsiio - * data_in_phase1: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =1 - ******************************************************************** - */ -static -void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) -{ - dprintkdbg(DBG_0, "data_in_phase1.....\n"); - /* FIFO should be cleared, if previous phase was not DataPhase */ - /*clear_fifo (acb, "DIP1"); */ - /* Allow data in! */ - /*DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH); */ - TRACEPRINTF("DIP1:*"); - /* - ** do prepare before transfer when data in phase - */ +static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) +{ + dprintkdbg(DBG_0, "data_in_phase1: (pid#%li) <%02i-%i>\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); data_io_transfer(acb, srb, XFERDATAIN); - TRACEPRINTF(".*"); } -/* - ******************************************************************** - * scsiio - * data_out_phase1 - * data_in_phase1 - ******************************************************************** - */ -static -void data_io_transfer(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 io_dir) +static void data_io_transfer(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb, u16 io_dir) { + struct DeviceCtlBlk *dcb = srb->dcb; u8 bval; - struct DeviceCtlBlk *dcb; - - dprintkdbg(DBG_0, "DataIO_transfer %c (pid %li): len = %i, SG: %i/%i\n", - ((io_dir & DMACMD_DIR) ? 'r' : 'w'), srb->cmd->pid, - srb->total_xfer_length, srb->sg_index, - srb->sg_count); - TRACEPRINTF("%05x(%i/%i)*", srb->total_xfer_length, - srb->sg_index, srb->sg_count); - dcb = srb->dcb; - if (srb == acb->tmp_srb) { - dprintkl(KERN_ERR, "Using tmp_srb in DataPhase!\n"); - } - if (srb->sg_index < srb->sg_count) { - if (srb->total_xfer_length > DC395x_LASTPIO) { - u8 dma_status = DC395x_read8(acb, TRM_S1040_DMA_STATUS); - /* - * KG: What should we do: Use SCSI Cmd 0x90/0x92? - * Maybe, even ABORTXFER would be appropriate - */ - if (dma_status & XFERPENDING) { - dprintkl(KERN_DEBUG, "Xfer pending! Expect trouble!!\n"); - dump_register_info(acb, dcb, srb); - DC395x_write8(acb, TRM_S1040_DMA_CONTROL, - CLRXFIFO); - } - /*clear_fifo (acb, "IO"); */ - /* - * load what physical address of Scatter/Gather list table want to be - * transfer - */ - srb->state |= SRB_DATA_XFER; - DC395x_write32(acb, TRM_S1040_DMA_XHIGHADDR, 0); - if (srb->cmd->use_sg) { /* with S/G */ - io_dir |= DMACMD_SG; - DC395x_write32(acb, TRM_S1040_DMA_XLOWADDR, - srb->sg_bus_addr + - sizeof(struct SGentry) * - srb->sg_index); - /* load how many bytes in the Scatter/Gather list table */ - DC395x_write32(acb, TRM_S1040_DMA_XCNT, - ((u32) - (srb->sg_count - - srb->sg_index) << 3)); - } else { /* without S/G */ - io_dir &= ~DMACMD_SG; - DC395x_write32(acb, TRM_S1040_DMA_XLOWADDR, - srb->segment_x[0].address); - DC395x_write32(acb, TRM_S1040_DMA_XCNT, - srb->segment_x[0].length); - } - /* load total transfer length (24bits) max value 16Mbyte */ - DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, - srb->total_xfer_length); - DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ - if (io_dir & DMACMD_DIR) { /* read */ - DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, - SCMD_DMA_IN); - DC395x_write16(acb, TRM_S1040_DMA_COMMAND, - io_dir); - } else { - DC395x_write16(acb, TRM_S1040_DMA_COMMAND, - io_dir); - DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, - SCMD_DMA_OUT); - } + dprintkdbg(DBG_0, + "data_io_transfer: (pid#%li) <%02i-%i> %c len=%i, sg=(%i/%i)\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun, + ((io_dir & DMACMD_DIR) ? 'r' : 'w'), + srb->total_xfer_length, srb->sg_index, srb->sg_count); + if (srb == acb->tmp_srb) + dprintkl(KERN_ERR, "data_io_transfer: Using tmp_srb!\n"); + if (srb->sg_index >= srb->sg_count) { + /* can't happen? out of bounds error */ + return; + } + if (srb->total_xfer_length > DC395x_LASTPIO) { + u8 dma_status = DC395x_read8(acb, TRM_S1040_DMA_STATUS); + /* + * KG: What should we do: Use SCSI Cmd 0x90/0x92? + * Maybe, even ABORTXFER would be appropriate + */ + if (dma_status & XFERPENDING) { + dprintkl(KERN_DEBUG, "data_io_transfer: Xfer pending! " + "Expect trouble!\n"); + dump_register_info(acb, dcb, srb); + DC395x_write8(acb, TRM_S1040_DMA_CONTROL, CLRXFIFO); } + /* clear_fifo(acb, "IO"); */ + /* + * load what physical address of Scatter/Gather list table + * want to be transfer + */ + srb->state |= SRB_DATA_XFER; + DC395x_write32(acb, TRM_S1040_DMA_XHIGHADDR, 0); + if (srb->cmd->use_sg) { /* with S/G */ + io_dir |= DMACMD_SG; + DC395x_write32(acb, TRM_S1040_DMA_XLOWADDR, + srb->sg_bus_addr + + sizeof(struct SGentry) * + srb->sg_index); + /* load how many bytes in the sg list table */ + DC395x_write32(acb, TRM_S1040_DMA_XCNT, + ((u32)(srb->sg_count - + srb->sg_index) << 3)); + } else { /* without S/G */ + io_dir &= ~DMACMD_SG; + DC395x_write32(acb, TRM_S1040_DMA_XLOWADDR, + srb->segment_x[0].address); + DC395x_write32(acb, TRM_S1040_DMA_XCNT, + srb->segment_x[0].length); + } + /* load total transfer length (24bits) max value 16Mbyte */ + DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, + srb->total_xfer_length); + DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ + if (io_dir & DMACMD_DIR) { /* read */ + DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, + SCMD_DMA_IN); + DC395x_write16(acb, TRM_S1040_DMA_COMMAND, io_dir); + } else { + DC395x_write16(acb, TRM_S1040_DMA_COMMAND, io_dir); + DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, + SCMD_DMA_OUT); + } + + } #if DC395x_LASTPIO - else if (srb->total_xfer_length > 0) { /* The last four bytes: Do PIO */ - /*clear_fifo (acb, "IO"); */ - /* - * load what physical address of Scatter/Gather list table want to be - * transfer - */ - srb->state |= SRB_DATA_XFER; - /* load total transfer length (24bits) max value 16Mbyte */ - DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, - srb->total_xfer_length); - DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ - if (io_dir & DMACMD_DIR) { /* read */ - DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, - SCMD_FIFO_IN); - } else { /* write */ - int ln = srb->total_xfer_length; - if (srb->dcb->sync_period & WIDE_SYNC) - DC395x_write8 - (acb, TRM_S1040_SCSI_CONFIG2, - CFG2_WIDEFIFO); - dprintkdbg(DBG_PIO, "DOP1: PIO %i bytes from %p:", - srb->total_xfer_length, - srb->virt_addr); - while (srb->total_xfer_length) { - if (debug_enabled(DBG_PIO)) - printk(" %02x", (unsigned char) *(srb->virt_addr)); - DC395x_write8 - (acb, TRM_S1040_SCSI_FIFO, - *(srb->virt_addr)++); - srb->total_xfer_length--; - srb->segment_x[srb->sg_index]. - length--; - if (srb->total_xfer_length - && !srb->segment_x[srb-> - sg_index]. - length) { - if (debug_enabled(DBG_PIO)) - printk(" (next segment)"); - srb->sg_index++; - update_sg_list(srb, - srb->total_xfer_length); - } - } - if (srb->dcb->sync_period & WIDE_SYNC) { - if (ln % 2) { - DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 0); - if (debug_enabled(DBG_PIO)) - printk(" |00"); - } - DC395x_write8 - (acb, TRM_S1040_SCSI_CONFIG2, 0); - } - /*DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, ln); */ + else if (srb->total_xfer_length > 0) { /* The last four bytes: Do PIO */ + /* + * load what physical address of Scatter/Gather list table + * want to be transfer + */ + srb->state |= SRB_DATA_XFER; + /* load total transfer length (24bits) max value 16Mbyte */ + DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, + srb->total_xfer_length); + DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ + if (io_dir & DMACMD_DIR) { /* read */ + DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, + SCMD_FIFO_IN); + } else { /* write */ + int ln = srb->total_xfer_length; + if (srb->dcb->sync_period & WIDE_SYNC) + DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, + CFG2_WIDEFIFO); + dprintkdbg(DBG_PIO, + "data_io_transfer: PIO %i bytes from %p:", + srb->total_xfer_length, srb->virt_addr); + + while (srb->total_xfer_length) { if (debug_enabled(DBG_PIO)) - printk("\n"); - DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, - SCMD_FIFO_OUT); - } - } -#endif /* DC395x_LASTPIO */ - else { /* xfer pad */ + printk(" %02x", (unsigned char) *(srb->virt_addr)); - u8 data = 0, data2 = 0; - if (srb->sg_count) { - srb->adapter_status = H_OVER_UNDER_RUN; - srb->status |= OVER_RUN; + DC395x_write8(acb, TRM_S1040_SCSI_FIFO, + *(srb->virt_addr)++); + + sg_subtract_one(srb); } - /* - * KG: despite the fact that we are using 16 bits I/O ops - * the SCSI FIFO is only 8 bits according to the docs - * (we can set bit 1 in 0x8f to serialize FIFO access ...) - */ - if (dcb->sync_period & WIDE_SYNC) { - DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 2); - DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, - CFG2_WIDEFIFO); - if (io_dir & DMACMD_DIR) { /* read */ - data = - DC395x_read8 - (acb, TRM_S1040_SCSI_FIFO); - data2 = - DC395x_read8 - (acb, TRM_S1040_SCSI_FIFO); - /*dprintkl(KERN_DEBUG, "DataIO: Xfer pad: %02x %02x\n", data, data2); */ - } else { - /* Danger, Robinson: If you find KGs scattered over the wide - * disk, the driver or chip is to blame :-( */ - DC395x_write8(acb, TRM_S1040_SCSI_FIFO, - 'K'); - DC395x_write8(acb, TRM_S1040_SCSI_FIFO, - 'G'); + if (srb->dcb->sync_period & WIDE_SYNC) { + if (ln % 2) { + DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 0); + if (debug_enabled(DBG_PIO)) + printk(" |00"); } DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); + } + /*DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, ln); */ + if (debug_enabled(DBG_PIO)) + printk("\n"); + DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, + SCMD_FIFO_OUT); + } + } +#endif /* DC395x_LASTPIO */ + else { /* xfer pad */ + u8 data = 0, data2 = 0; + if (srb->sg_count) { + srb->adapter_status = H_OVER_UNDER_RUN; + srb->status |= OVER_RUN; + } + /* + * KG: despite the fact that we are using 16 bits I/O ops + * the SCSI FIFO is only 8 bits according to the docs + * (we can set bit 1 in 0x8f to serialize FIFO access ...) + */ + if (dcb->sync_period & WIDE_SYNC) { + DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 2); + DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, + CFG2_WIDEFIFO); + if (io_dir & DMACMD_DIR) { + data = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + data2 = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); } else { - DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1); - /* Danger, Robinson: If you find a collection of Ks on your disk - * something broke :-( */ - if (io_dir & DMACMD_DIR) { /* read */ - data = - DC395x_read8 - (acb, TRM_S1040_SCSI_FIFO); - /*dprintkl(KERN_DEBUG, "DataIO: Xfer pad: %02x\n", data); */ - } else { - DC395x_write8(acb, TRM_S1040_SCSI_FIFO, - 'K'); - } + /* Danger, Robinson: If you find KGs + * scattered over the wide disk, the driver + * or chip is to blame :-( */ + DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 'K'); + DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 'G'); } - srb->state |= SRB_XFERPAD; - DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ - /* - * SCSI command - */ - bval = - (io_dir & DMACMD_DIR) ? SCMD_FIFO_IN : - SCMD_FIFO_OUT; - DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, bval); + DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); + } else { + DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1); + /* Danger, Robinson: If you find a collection of Ks on your disk + * something broke :-( */ + if (io_dir & DMACMD_DIR) + data = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + else + DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 'K'); } + srb->state |= SRB_XFERPAD; + DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ + /* SCSI command */ + bval = (io_dir & DMACMD_DIR) ? SCMD_FIFO_IN : SCMD_FIFO_OUT; + DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, bval); } - /*monitor_next_irq = 2; */ - /*printk(" done\n"); */ } -/* - ******************************************************************** - * scsiio - * status_phase0: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =3 - ******************************************************************** - */ -static -void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - dprintkdbg(DBG_0, "StatusPhase0 (pid %li)\n", srb->cmd->pid); - TRACEPRINTF("STP0 *"); + dprintkdbg(DBG_0, "status_phase0: (pid#%li) <%02i-%i>\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */ srb->state = SRB_COMPLETED; *pscsi_status = PH_BUS_FREE; /*.. initial phase */ - /*1.25 */ - /*clear_fifo (acb, "STP0"); */ DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ - /* - ** SCSI command - */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_MSGACCEPT); } -/* - ******************************************************************** - * scsiio - * status_phase1: one of dc395x_scsi_phase1[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase1[phase] - * if phase =3 - ******************************************************************** - */ -static -void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) -{ - dprintkdbg(DBG_0, "StatusPhase1 (pid=%li)\n", srb->cmd->pid); - TRACEPRINTF("STP1 *"); - /* Cleanup is now done at the end of DataXXPhase0 */ - /*cleanup_after_transfer (acb, srb); */ - +static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) +{ + dprintkdbg(DBG_0, "status_phase1: (pid#%li) <%02i-%i>\n", + srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); srb->state = SRB_STATUS; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ - /* - * SCSI command - */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP); } -/* Message handling */ - -#if 0 -/* Print received message */ -static void print_msg(u8 * msg_buf, u32 len) -{ - int i; - printk(" %02x", msg_buf[0]); - for (i = 1; i < len; i++) - printk(" %02x", msg_buf[i]); - printk("\n"); -} -#endif /* Check if the message is complete */ static inline u8 msgin_completed(u8 * msgbuf, u32 len) @@ -3260,53 +2585,44 @@ /* reject_msg */ -static inline -void msgin_reject(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +static inline void msgin_reject(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb) { srb->msgout_buf[0] = MESSAGE_REJECT; srb->msg_count = 1; DC395x_ENABLE_MSGOUT; srb->state &= ~SRB_MSGIN; srb->state |= SRB_MSGOUT; - dprintkl(KERN_INFO, - "Reject message %02x from %02i-%i\n", srb->msgin_buf[0], - srb->dcb->target_id, srb->dcb->target_lun); - TRACEPRINTF("\\*"); + dprintkl(KERN_INFO, "msgin_reject: 0x%02x <%02i-%i>\n", + srb->msgin_buf[0], + srb->dcb->target_id, srb->dcb->target_lun); } /* abort command */ -static inline -void enable_msgout_abort(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb) +static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb) { srb->msgout_buf[0] = ABORT; srb->msg_count = 1; DC395x_ENABLE_MSGOUT; srb->state &= ~SRB_MSGIN; srb->state |= SRB_MSGOUT; - /* - if (srb->dcb) - srb->dcb->flag &= ~ABORT_DEV_; - */ - TRACEPRINTF("#*"); } -static -struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, - struct DeviceCtlBlk *dcb, - u8 tag) +static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, + struct DeviceCtlBlk *dcb, u8 tag) { struct ScsiReqBlk *srb = NULL; struct ScsiReqBlk *i; - + dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) tag=%i srb=%p\n", + srb->cmd->pid, tag, srb); - dprintkdbg(DBG_0, "QTag Msg (SRB %p): %i\n", srb, tag); if (!(dcb->tag_mask & (1 << tag))) dprintkl(KERN_DEBUG, - "MsgIn_QTag: tag_mask (%08x) does not reserve tag %i!\n", - dcb->tag_mask, tag); + "msgin_qtag: tag_mask=0x%08x does not reserve tag %i!\n", + dcb->tag_mask, tag); if (list_empty(&dcb->srb_going_list)) goto mingx0; @@ -3319,8 +2635,8 @@ if (!srb) goto mingx0; - dprintkdbg(DBG_0, "pid %li (%i-%i)\n", srb->cmd->pid, - srb->dcb->target_id, srb->dcb->target_lun); + dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) <%02i-%i>\n", + srb->cmd->pid, srb->dcb->target_id, srb->dcb->target_lun); if (dcb->flag & ABORT_DEV_) { /*srb->state = SRB_ABORT_SENT; */ enable_msgout_abort(acb, srb); @@ -3329,20 +2645,6 @@ if (!(srb->state & SRB_DISCONNECT)) goto mingx0; - /* Tag found */ - { - struct ScsiReqBlk *last_srb; - - TRACEPRINTF("[%s]*", dcb->active_srb->debugtrace); - TRACEPRINTF("RTag*"); - /* Just for debugging ... */ - - last_srb = srb; - srb = dcb->active_srb; - TRACEPRINTF("Found.*"); - srb = last_srb; - } - memcpy(srb->msgin_buf, dcb->active_srb->msgin_buf, acb->msg_len); srb->state |= dcb->active_srb->state; srb->state |= SRB_DATA_XFER; @@ -3357,15 +2659,13 @@ srb->msgout_buf[0] = MSG_ABORT_TAG; srb->msg_count = 1; DC395x_ENABLE_MSGOUT; - TRACEPRINTF("?*"); - dprintkl(KERN_DEBUG, "Unknown tag received: %i: abort !!\n", tag); + dprintkl(KERN_DEBUG, "msgin_qtag: Unknown tag %i - abort\n", tag); return srb; } -/* Reprogram registers */ -static inline void -reprogram_regs(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) +static inline void reprogram_regs(struct AdapterCtlBlk *acb, + struct DeviceCtlBlk *dcb) { DC395x_write8(acb, TRM_S1040_SCSI_TARGETID, dcb->target_id); DC395x_write8(acb, TRM_S1040_SCSI_SYNC, dcb->sync_period); @@ -3375,12 +2675,12 @@ /* set async transfer mode */ -static -void msgin_set_async(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +static void msgin_set_async(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { struct DeviceCtlBlk *dcb = srb->dcb; - dprintkl(KERN_DEBUG, "Target %02i: No sync transfers\n", dcb->target_id); - TRACEPRINTF("!S *"); + dprintkl(KERN_DEBUG, "msgin_set_async: No sync transfers <%02i-%i>\n", + dcb->target_id, dcb->target_lun); + dcb->sync_mode &= ~(SYNC_NEGO_ENABLE); dcb->sync_mode |= SYNC_NEGO_DONE; /*dcb->sync_period &= 0; */ @@ -3392,26 +2692,23 @@ && !(dcb->sync_mode & WIDE_NEGO_DONE)) { build_wdtr(acb, dcb, srb); DC395x_ENABLE_MSGOUT; - dprintkdbg(DBG_0, "SDTR(rej): Try WDTR anyway ...\n"); + dprintkdbg(DBG_0, "msgin_set_async(rej): Try WDTR anyway\n"); } } /* set sync transfer mode */ -static -void msgin_set_sync(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +static void msgin_set_sync(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { + struct DeviceCtlBlk *dcb = srb->dcb; u8 bval; int fact; - struct DeviceCtlBlk *dcb = srb->dcb; - /*u8 oldsyncperiod = dcb->sync_period; */ - /*u8 oldsyncoffset = dcb->sync_offset; */ - - dprintkdbg(DBG_1, "Target %02i: Sync: %ins (%02i.%01i MHz) Offset %i\n", - dcb->target_id, srb->msgin_buf[3] << 2, - (250 / srb->msgin_buf[3]), - ((250 % srb->msgin_buf[3]) * 10) / srb->msgin_buf[3], - srb->msgin_buf[4]); + dprintkdbg(DBG_1, "msgin_set_sync: <%02i> Sync: %ins " + "(%02i.%01i MHz) Offset %i\n", + dcb->target_id, srb->msgin_buf[3] << 2, + (250 / srb->msgin_buf[3]), + ((250 % srb->msgin_buf[3]) * 10) / srb->msgin_buf[3], + srb->msgin_buf[4]); if (srb->msgin_buf[4] > 15) srb->msgin_buf[4] = 15; @@ -3430,8 +2727,8 @@ bval++; if (srb->msgin_buf[3] < clock_period[bval]) dprintkl(KERN_INFO, - "Increase sync nego period to %ins\n", - clock_period[bval] << 2); + "msgin_set_sync: Increase sync nego period to %ins\n", + clock_period[bval] << 2); srb->msgin_buf[3] = clock_period[bval]; dcb->sync_period &= 0xf0; dcb->sync_period |= ALT_SYNC | bval; @@ -3443,18 +2740,17 @@ fact = 250; dprintkl(KERN_INFO, - "Target %02i: %s Sync: %ins Offset %i (%02i.%01i MB/s)\n", - dcb->target_id, (fact == 500) ? "Wide16" : "", - dcb->min_nego_period << 2, dcb->sync_offset, - (fact / dcb->min_nego_period), - ((fact % dcb->min_nego_period) * 10 + + "Target %02i: %s Sync: %ins Offset %i (%02i.%01i MB/s)\n", + dcb->target_id, (fact == 500) ? "Wide16" : "", + dcb->min_nego_period << 2, dcb->sync_offset, + (fact / dcb->min_nego_period), + ((fact % dcb->min_nego_period) * 10 + dcb->min_nego_period / 2) / dcb->min_nego_period); - TRACEPRINTF("S%i *", dcb->min_nego_period << 2); if (!(srb->state & SRB_DO_SYNC_NEGO)) { /* Reply with corrected SDTR Message */ - dprintkl(KERN_DEBUG, " .. answer w/ %ins %i\n", - srb->msgin_buf[3] << 2, srb->msgin_buf[4]); + dprintkl(KERN_DEBUG, "msgin_set_sync: answer w/%ins %i\n", + srb->msgin_buf[3] << 2, srb->msgin_buf[4]); memcpy(srb->msgout_buf, srb->msgin_buf, 5); srb->msg_count = 5; @@ -3465,7 +2761,7 @@ && !(dcb->sync_mode & WIDE_NEGO_DONE)) { build_wdtr(acb, dcb, srb); DC395x_ENABLE_MSGOUT; - dprintkdbg(DBG_0, "SDTR: Also try WDTR ...\n"); + dprintkdbg(DBG_0, "msgin_set_sync: Also try WDTR\n"); } } srb->state &= ~SRB_DO_SYNC_NEGO; @@ -3475,14 +2771,12 @@ } -static inline -void msgin_set_nowide(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb) +static inline void msgin_set_nowide(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb) { struct DeviceCtlBlk *dcb = srb->dcb; - dprintkdbg(DBG_KG, "WDTR got rejected from target %02i\n", - dcb->target_id); - TRACEPRINTF("!W *"); + dprintkdbg(DBG_1, "msgin_set_nowide: <%02i>\n", dcb->target_id); + dcb->sync_period &= ~WIDE_SYNC; dcb->sync_mode &= ~(WIDE_NEGO_ENABLE); dcb->sync_mode |= WIDE_NEGO_DONE; @@ -3492,23 +2786,24 @@ && !(dcb->sync_mode & SYNC_NEGO_DONE)) { build_sdtr(acb, dcb, srb); DC395x_ENABLE_MSGOUT; - dprintkdbg(DBG_0, "WDTR(rej): Try SDTR anyway ...\n"); + dprintkdbg(DBG_0, "msgin_set_nowide: Rejected. Try SDTR anyway\n"); } } -static -void msgin_set_wide(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +static void msgin_set_wide(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { struct DeviceCtlBlk *dcb = srb->dcb; u8 wide = (dcb->dev_mode & NTC_DO_WIDE_NEGO && acb->config & HCC_WIDE_CARD) ? 1 : 0; + dprintkdbg(DBG_1, "msgin_set_wide: <%02i>\n", dcb->target_id); + if (srb->msgin_buf[3] > wide) srb->msgin_buf[3] = wide; /* Completed */ if (!(srb->state & SRB_DO_WIDE_NEGO)) { dprintkl(KERN_DEBUG, - "Target %02i initiates Wide Nego ...\n", - dcb->target_id); + "msgin_set_wide: Wide nego initiated <%02i>\n", + dcb->target_id); memcpy(srb->msgout_buf, srb->msgin_buf, 4); srb->msg_count = 4; srb->state |= SRB_DO_WIDE_NEGO; @@ -3521,28 +2816,21 @@ else dcb->sync_period &= ~WIDE_SYNC; srb->state &= ~SRB_DO_WIDE_NEGO; - TRACEPRINTF("W%i *", (dcb->sync_period & WIDE_SYNC ? 1 : 0)); /*dcb->sync_mode &= ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE); */ - dprintkdbg(DBG_KG, - "Wide transfers (%i bit) negotiated with target %02i\n", - (8 << srb->msgin_buf[3]), dcb->target_id); + dprintkdbg(DBG_1, + "msgin_set_wide: Wide (%i bit) negotiated <%02i>\n", + (8 << srb->msgin_buf[3]), dcb->target_id); reprogram_regs(acb, dcb); if ((dcb->sync_mode & SYNC_NEGO_ENABLE) && !(dcb->sync_mode & SYNC_NEGO_DONE)) { build_sdtr(acb, dcb, srb); DC395x_ENABLE_MSGOUT; - dprintkdbg(DBG_0, "WDTR: Also try SDTR ...\n"); + dprintkdbg(DBG_0, "msgin_set_wide: Also try SDTR.\n"); } } /* - ******************************************************************** - * scsiio - * msgin_phase0: one of dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * if phase =7 - * * extended message codes: * * code description @@ -3553,25 +2841,15 @@ * 03h WIDE DATA TRANSFER REQUEST * 04h - 7Fh Reserved * 80h - FFh Vendor specific - * - ******************************************************************** */ -static -void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - struct DeviceCtlBlk *dcb; - - dprintkdbg(DBG_0, "msgin_phase0..............\n"); - TRACEPRINTF("MIP0*"); - dcb = acb->active_dcb; + struct DeviceCtlBlk *dcb = acb->active_dcb; + dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->pid); srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); if (msgin_completed(srb->msgin_buf, acb->msg_len)) { - TRACEPRINTF("(%02x)*", srb->msgin_buf[0]); - /*dprintkl(KERN_INFO, "MsgIn:"); */ - /*print_msg (srb->msgin_buf, acb->msg_len); */ - /* Now eval the msg */ switch (srb->msgin_buf[0]) { case DISCONNECT: @@ -3581,7 +2859,6 @@ case SIMPLE_QUEUE_TAG: case HEAD_OF_QUEUE_TAG: case ORDERED_QUEUE_TAG: - TRACEPRINTF("(%02x)*", srb->msgin_buf[1]); srb = msgin_qtag(acb, dcb, srb->msgin_buf[1]); @@ -3605,7 +2882,6 @@ break; case EXTENDED_MESSAGE: - TRACEPRINTF("(%02x)*", srb->msgin_buf[2]); /* SDTR */ if (srb->msgin_buf[1] == 3 && srb->msgin_buf[2] == EXTENDED_SDTR) { @@ -3613,52 +2889,51 @@ break; } /* WDTR */ - if (srb->msgin_buf[1] == 2 && srb->msgin_buf[2] == EXTENDED_WDTR && srb->msgin_buf[3] <= 2) { /* sanity check ... */ + if (srb->msgin_buf[1] == 2 + && srb->msgin_buf[2] == EXTENDED_WDTR + && srb->msgin_buf[3] <= 2) { /* sanity check ... */ msgin_set_wide(acb, srb); break; } msgin_reject(acb, srb); break; - /* Discard wide residual */ case MSG_IGNOREWIDE: - dprintkdbg(DBG_0, "Ignore Wide Residual!\n"); - /*DC395x_write32 (TRM_S1040_SCSI_COUNTER, 1); */ - /*DC395x_read8 (TRM_S1040_SCSI_FIFO); */ + /* Discard wide residual */ + dprintkdbg(DBG_0, "msgin_phase0: Ignore Wide Residual!\n"); break; - /* nothing has to be done */ case COMMAND_COMPLETE: + /* nothing has to be done */ break; + case SAVE_POINTERS: /* - * SAVE POINTER may be ignored as we have the struct ScsiReqBlk* associated with the - * scsi command. Thanks, Gérard, for pointing it out. + * SAVE POINTER may be ignored as we have the struct + * ScsiReqBlk* associated with the scsi command. */ - case SAVE_POINTERS: - dprintkdbg(DBG_0, "SAVE POINTER message received (pid %li: rem.%i) ... ignore :-(\n", - srb->cmd->pid, srb->total_xfer_length); - /*srb->Saved_Ptr = srb->TotalxferredLen; */ + dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) " + "SAVE POINTER rem=%i Ignore\n", + srb->cmd->pid, srb->total_xfer_length); break; - /* The device might want to restart transfer with a RESTORE */ + case RESTORE_POINTERS: - dprintkl(KERN_DEBUG, - "RESTORE POINTER message received ... ignore :-(\n"); - /*dc395x_restore_ptr (acb, srb); */ + dprintkdbg(DBG_0, "msgin_phase0: RESTORE POINTER. Ignore\n"); break; + case ABORT: - dprintkl(KERN_DEBUG, - "ABORT msg received (pid %li %02i-%i)\n", - srb->cmd->pid, dcb->target_id, - dcb->target_lun); + dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) " + "<%02i-%i> ABORT msg\n", + srb->cmd->pid, dcb->target_id, + dcb->target_lun); dcb->flag |= ABORT_DEV_; enable_msgout_abort(acb, srb); break; - /* reject unknown messages */ + default: + /* reject unknown messages */ if (srb->msgin_buf[0] & IDENTIFY_BASE) { - dprintkl(KERN_DEBUG, "Identify Message received?\n"); - /*TRACEOUT (" %s\n", srb->debugtrace); */ + dprintkdbg(DBG_0, "msgin_phase0: Identify msg\n"); srb->msg_count = 1; srb->msgout_buf[0] = dcb->identify_msg; DC395x_ENABLE_MSGOUT; @@ -3666,104 +2941,51 @@ /*break; */ } msgin_reject(acb, srb); - TRACEOUT(" %s\n", srb->debugtrace); } - TRACEPRINTF(".*"); /* Clear counter and MsgIn state */ srb->state &= ~SRB_MSGIN; acb->msg_len = 0; } - - /*1.25 */ - if ((*pscsi_status & PHASEMASK) != PH_MSG_IN) -#if 0 - clear_fifo(acb, "MIP0_"); -#else - TRACEPRINTF("N/Cln *"); -#endif *pscsi_status = PH_BUS_FREE; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important ... you know! */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_MSGACCEPT); } -/* - ******************************************************************** - * scsiio - * msgin_phase1: one of dc395x_scsi_phase1[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase1[phase] - * if phase =7 - ******************************************************************** - */ -static -void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) -{ - dprintkdbg(DBG_0, "msgin_phase1..............\n"); - TRACEPRINTF("MIP1 *"); - clear_fifo(acb, "MIP1"); +static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) +{ + dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->pid); + clear_fifo(acb, "msgin_phase1"); DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1); if (!(srb->state & SRB_MSGIN)) { srb->state &= ~SRB_DISCONNECT; srb->state |= SRB_MSGIN; } DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ - /* - * SCSI command - */ + /* SCSI command */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_IN); } -/* - ******************************************************************** - * scsiio - * nop0: one of dc395x_scsi_phase1[] ,dc395x_scsi_phase0[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * dc395x_statev = (void *)dc395x_scsi_phase1[phase] - * if phase =4 ..PH_BUS_FREE - ******************************************************************** - */ -static -void nop0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void nop0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - /*TRACEPRINTF("NOP0 *"); */ } -/* - ******************************************************************** - * scsiio - * nop1: one of dc395x_scsi_phase0[] ,dc395x_scsi_phase1[] vectors - * dc395x_statev = (void *)dc395x_scsi_phase0[phase] - * dc395x_statev = (void *)dc395x_scsi_phase1[phase] - * if phase =5 - ******************************************************************** - */ -static -void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, - u16 * pscsi_status) +static void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, + u16 *pscsi_status) { - /*TRACEPRINTF("NOP1 *"); */ } -/* - ******************************************************************** - * scsiio - * msgin_phase0 - ******************************************************************** - */ -static -void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) +static void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) { struct DeviceCtlBlk *i; - /* - * set all lun device's period , offset - */ + /* set all lun device's period, offset */ if (dcb->identify_msg & 0x07) return; @@ -3782,47 +3004,39 @@ } -/* - ******************************************************************** - * scsiio - * dc395x_interrupt - ******************************************************************** - */ static void disconnect(struct AdapterCtlBlk *acb) { - struct DeviceCtlBlk *dcb; + struct DeviceCtlBlk *dcb = acb->active_dcb; struct ScsiReqBlk *srb; - dprintkdbg(DBG_0, "Disconnect (pid=%li)\n", acb->active_dcb->active_srb->cmd->pid); - dcb = acb->active_dcb; if (!dcb) { - dprintkl(KERN_ERR, "Disc: Exception Disconnect dcb=NULL !!\n "); + dprintkl(KERN_ERR, "disconnect: No such device\n"); udelay(500); /* Suspend queue for a while */ acb->scsi_host->last_reset = jiffies + HZ / 2 + HZ * acb->eeprom.delay_time; - clear_fifo(acb, "DiscEx"); + clear_fifo(acb, "disconnectEx"); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); return; } srb = dcb->active_srb; acb->active_dcb = NULL; - TRACEPRINTF("DISC *"); + dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->pid); srb->scsi_phase = PH_BUS_FREE; /* initial phase */ - clear_fifo(acb, "Disc"); + clear_fifo(acb, "disconnect"); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); if (srb->state & SRB_UNEXPECT_RESEL) { - dprintkl(KERN_ERR, "Disc: Unexpected Reselection (%i-%i)\n", - dcb->target_id, dcb->target_lun); + dprintkl(KERN_ERR, + "disconnect: Unexpected reselection <%02i-%i>\n", + dcb->target_id, dcb->target_lun); srb->state = 0; waiting_process_next(acb); } else if (srb->state & SRB_ABORT_SENT) { - /*Scsi_Cmnd* cmd = srb->cmd; */ dcb->flag &= ~ABORT_DEV_; acb->scsi_host->last_reset = jiffies + HZ / 2 + 1; - dprintkl(KERN_ERR, "Disc: SRB_ABORT_SENT!\n"); + dprintkl(KERN_ERR, "disconnect: SRB_ABORT_SENT\n"); doing_srb_done(acb, DID_ABORT, srb->cmd, 1); waiting_process_next(acb); } else { @@ -3837,19 +3051,16 @@ if (srb->state != SRB_START_ && srb->state != SRB_MSGOUT) { srb->state = SRB_READY; - dprintkl(KERN_DEBUG, "Unexpected Disconnection (pid %li)!\n", - srb->cmd->pid); + dprintkl(KERN_DEBUG, + "disconnect: (pid#%li) Unexpected\n", + srb->cmd->pid); srb->target_status = SCSI_STAT_SEL_TIMEOUT; - TRACEPRINTF("UnExpD *"); - TRACEOUT("%s\n", srb->debugtrace); goto disc1; } else { /* Normal selection timeout */ - TRACEPRINTF("SlTO *"); - dprintkdbg(DBG_KG, - "Disc: SelTO (pid=%li) for dev %02i-%i\n", - srb->cmd->pid, dcb->target_id, - dcb->target_lun); + dprintkdbg(DBG_KG, "disconnect: (pid#%li) " + "<%02i-%i> SelTO\n", srb->cmd->pid, + dcb->target_id, dcb->target_lun); if (srb->retry_count++ > DC395x_MAX_RETRIES || acb->scan_devices) { srb->target_status = @@ -3858,8 +3069,9 @@ } free_tag(dcb, srb); srb_going_to_waiting_move(dcb, srb); - dprintkdbg(DBG_KG, "Retry pid %li ...\n", - srb->cmd->pid); + dprintkdbg(DBG_KG, + "disconnect: (pid#%li) Retry\n", + srb->cmd->pid); waiting_set_timer(acb, HZ / 20); } } else if (srb->state & SRB_DISCONNECT) { @@ -3867,18 +3079,11 @@ /* * SRB_DISCONNECT (This is what we expect!) */ - /* dprintkl(KERN_DEBUG, "DoWaitingSRB (pid=%li)\n", srb->cmd->pid); */ - TRACEPRINTF("+*"); if (bval & 0x40) { - dprintkdbg(DBG_0, "Debug: DISC: SCSI bus stat %02x: ACK set! Other controllers?\n", + dprintkdbg(DBG_0, "disconnect: SCSI bus stat " + " 0x%02x: ACK set! Other controllers?\n", bval); /* It could come from another initiator, therefore don't do much ! */ - TRACEPRINTF("ACK(%02x) *", bval); - /*dump_register_info (acb, dcb, srb); */ - /*TRACEOUT (" %s\n", srb->debugtrace); */ - /*dcb->flag |= ABORT_DEV_; */ - /*enable_msgout_abort (acb, srb); */ - /*DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO | DO_CLRATN | DO_HWRESELECT); */ } else waiting_process_next(acb); } else if (srb->state & SRB_COMPLETED) { @@ -3889,51 +3094,40 @@ free_tag(dcb, srb); dcb->active_srb = NULL; srb->state = SRB_FREE; - /*dprintkl(KERN_DEBUG, "done (pid=%li)\n", srb->cmd->pid); */ srb_done(acb, dcb, srb); } } - return; } -/* - ******************************************************************** - * scsiio - * reselect - ******************************************************************** - */ static void reselect(struct AdapterCtlBlk *acb) { - struct DeviceCtlBlk *dcb; + struct DeviceCtlBlk *dcb = acb->active_dcb; struct ScsiReqBlk *srb = NULL; u16 rsel_tar_lun_id; u8 id, lun; u8 arblostflag = 0; + dprintkdbg(DBG_0, "reselect: acb=%p\n", acb); - dprintkdbg(DBG_0, "reselect..............\n"); - - clear_fifo(acb, "Resel"); + clear_fifo(acb, "reselect"); /*DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); */ /* Read Reselected Target ID and LUN */ rsel_tar_lun_id = DC395x_read16(acb, TRM_S1040_SCSI_TARGETID); - dcb = acb->active_dcb; if (dcb) { /* Arbitration lost but Reselection win */ srb = dcb->active_srb; if (!srb) { - dprintkl(KERN_DEBUG, "Arb lost Resel won, but active_srb == NULL!\n"); + dprintkl(KERN_DEBUG, "reselect: Arb lost Resel won, " + "but active_srb == NULL\n"); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ return; } /* Why the if ? */ - if (!(acb->scan_devices)) { - dprintkdbg(DBG_KG, - "Arb lost but Resel win pid %li (%02i-%i) Rsel %04x Stat %04x\n", - srb->cmd->pid, dcb->target_id, - dcb->target_lun, rsel_tar_lun_id, - DC395x_read16(acb, TRM_S1040_SCSI_STATUS)); - TRACEPRINTF("ArbLResel!*"); - /*TRACEOUT (" %s\n", srb->debugtrace); */ + if (!acb->scan_devices) { + dprintkdbg(DBG_KG, "reselect: (pid#%li) <%02i-%i> " + "Arb lost but Resel win rsel=%i stat=0x%04x\n", + srb->cmd->pid, dcb->target_id, + dcb->target_lun, rsel_tar_lun_id, + DC395x_read16(acb, TRM_S1040_SCSI_STATUS)); arblostflag = 1; /*srb->state |= SRB_DISCONNECT; */ @@ -3947,47 +3141,37 @@ } /* Read Reselected Target Id and LUN */ if (!(rsel_tar_lun_id & (IDENTIFY_BASE << 8))) - dprintkl(KERN_DEBUG, "Resel expects identify msg! Got %04x!\n", - rsel_tar_lun_id); + dprintkl(KERN_DEBUG, "reselect: Expects identify msg. " + "Got %i!\n", rsel_tar_lun_id); id = rsel_tar_lun_id & 0xff; lun = (rsel_tar_lun_id >> 8) & 7; dcb = find_dcb(acb, id, lun); if (!dcb) { - dprintkl(KERN_ERR, "Reselect from non existing device (%02i-%i)\n", - id, lun); + dprintkl(KERN_ERR, "reselect: From non existent device " + "<%02i-%i>\n", id, lun); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ return; } - acb->active_dcb = dcb; if (!(dcb->dev_mode & NTC_DO_DISCONNECT)) - dprintkl(KERN_DEBUG, "Reselection in spite of forbidden disconnection? (%02i-%i)\n", - dcb->target_id, dcb->target_lun); + dprintkl(KERN_DEBUG, "reselect: in spite of forbidden " + "disconnection? <%02i-%i>\n", + dcb->target_id, dcb->target_lun); - if ((dcb->sync_mode & EN_TAG_QUEUEING) /*&& !arblostflag */ ) { - struct ScsiReqBlk *oldSRB = srb; + if (dcb->sync_mode & EN_TAG_QUEUEING /*&& !arblostflag */) { srb = acb->tmp_srb; -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - srb->debugpos = 0; - srb->debugtrace[0] = 0; -#endif dcb->active_srb = srb; - if (oldSRB) - TRACEPRINTF("ArbLResel(%li):*", oldSRB->cmd->pid); - /*if (arblostflag) dprintkl(KERN_DEBUG, "Reselect: Wait for Tag ... \n"); */ } else { /* There can be only one! */ srb = dcb->active_srb; - if (srb) - TRACEPRINTF("RSel *"); if (!srb || !(srb->state & SRB_DISCONNECT)) { /* * abort command */ dprintkl(KERN_DEBUG, - "Reselected w/o disconnected cmds from %02i-%i?\n", - dcb->target_id, dcb->target_lun); + "reselect: w/o disconnected cmds <%02i-%i>\n", + dcb->target_id, dcb->target_lun); srb = acb->tmp_srb; srb->state = SRB_UNEXPECT_RESEL; dcb->active_srb = srb; @@ -4000,14 +3184,11 @@ srb->state = SRB_DATA_XFER; } - /*if (arblostflag) TRACEOUT (" %s\n", srb->debugtrace); */ } srb->scsi_phase = PH_BUS_FREE; /* initial phase */ - /* - *********************************************** - ** Program HA ID, target ID, period and offset - *********************************************** - */ + + /* Program HA ID, target ID, period and offset */ + dprintkdbg(DBG_0, "reselect: select <%i>\n", dcb->target_id); DC395x_write8(acb, TRM_S1040_SCSI_HOSTID, acb->scsi_host->this_id); /* host ID */ DC395x_write8(acb, TRM_S1040_SCSI_TARGETID, dcb->target_id); /* target ID */ DC395x_write8(acb, TRM_S1040_SCSI_OFFSET, dcb->sync_offset); /* offset */ @@ -4018,10 +3199,6 @@ } - - - - static inline u8 tagq_blacklist(char *name) { #ifndef DC395x_NO_TAGQ @@ -4038,8 +3215,7 @@ } -static -void disc_tagq_set(struct DeviceCtlBlk *dcb, struct ScsiInqData *ptr) +static void disc_tagq_set(struct DeviceCtlBlk *dcb, struct ScsiInqData *ptr) { /* Check for SCSI format (ANSI and Response data format) */ if ((ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2) { @@ -4048,7 +3224,7 @@ /*(dcb->dev_mode & NTC_DO_DISCONNECT) */ /* ((dcb->dev_type == TYPE_DISK) || (dcb->dev_type == TYPE_MOD)) && */ - !tagq_blacklist(((char *) ptr) + 8)) { + !tagq_blacklist(((char *)ptr) + 8)) { if (dcb->max_command == 1) dcb->max_command = dcb->acb->tag_max_num; @@ -4060,9 +3236,8 @@ } -static -void add_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, - struct ScsiInqData *ptr) +static void add_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, + struct ScsiInqData *ptr) { u8 bval1 = ptr->DevType & SCSI_DEVTYPE; dcb->dev_type = bval1; @@ -4071,59 +3246,45 @@ } -/* - ******************************************************************** - * unmap mapped pci regions from SRB - ******************************************************************** - */ -static -void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +/* unmap mapped pci regions from SRB */ +static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { - int dir; Scsi_Cmnd *cmd = srb->cmd; - dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); if (cmd->use_sg && dir != PCI_DMA_NONE) { /* unmap DC395x SG list */ - dprintkdbg(DBG_SGPARANOIA, - "Unmap SG descriptor list %08x (%05x)\n", - srb->sg_bus_addr, - sizeof(struct SGentry) * DC395x_MAX_SG_LISTENTRY); + dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", + srb->sg_bus_addr, SEGMENTX_LEN); pci_unmap_single(acb->dev, srb->sg_bus_addr, - sizeof(struct SGentry) * - DC395x_MAX_SG_LISTENTRY, + SEGMENTX_LEN, PCI_DMA_TODEVICE); - dprintkdbg(DBG_SGPARANOIA, "Unmap %i SG segments from %p\n", - cmd->use_sg, cmd->request_buffer); + dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", + cmd->use_sg, cmd->request_buffer); /* unmap the sg segments */ pci_unmap_sg(acb->dev, - (struct scatterlist *) cmd->request_buffer, + (struct scatterlist *)cmd->request_buffer, cmd->use_sg, dir); } else if (cmd->request_buffer && dir != PCI_DMA_NONE) { - dprintkdbg(DBG_SGPARANOIA, "Unmap buffer at %08x (%05x)\n", - srb->segment_x[0].address, cmd->request_bufflen); + dprintkdbg(DBG_SG, "pci_unmap_srb: buffer=%08x(%05x)\n", + srb->segment_x[0].address, cmd->request_bufflen); pci_unmap_single(acb->dev, srb->segment_x[0].address, cmd->request_bufflen, dir); } } -/* - ******************************************************************** - * unmap mapped pci sense buffer from SRB - ******************************************************************** - */ -static -void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) +/* unmap mapped pci sense buffer from SRB */ +static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb) { if (!(srb->flag & AUTO_REQSENSE)) return; /* Unmap sense buffer */ - dprintkdbg(DBG_SGPARANOIA, "Unmap sense buffer from %08x\n", + dprintkdbg(DBG_SG, "pci_unmap_srb_sense: buffer=%08x\n", srb->segment_x[0].address); pci_unmap_single(acb->dev, srb->segment_x[0].address, srb->segment_x[0].length, PCI_DMA_FROMDEVICE); /* Restore SG stuff */ - /*printk ("Auto_ReqSense finished: Restore Counters ...\n"); */ srb->total_xfer_length = srb->xferred; srb->segment_x[0].address = srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address; @@ -4133,42 +3294,33 @@ /* - ******************************************************************** - * scsiio - * disconnect - * Complete execution of a SCSI command - * Signal completion to the generic SCSI driver - ******************************************************************** + * Complete execution of a SCSI command + * Signal completion to the generic SCSI driver */ -static -void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) +static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) { u8 tempcnt, status; - Scsi_Cmnd *cmd; + Scsi_Cmnd *cmd = srb->cmd; struct ScsiInqData *ptr; - /*u32 drv_flags=0; */ int dir; - cmd = srb->cmd; - TRACEPRINTF("DONE *"); - dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - ptr = (struct ScsiInqData *) (cmd->request_buffer); - if (cmd->use_sg) - ptr = - (struct ScsiInqData *) CPU_ADDR(*(struct scatterlist *) - ptr); - dprintkdbg(DBG_SGPARANOIA, - "SRBdone SG=%i (%i/%i), req_buf = %p, adr = %p\n", - cmd->use_sg, srb->sg_index, srb->sg_count, - cmd->request_buffer, ptr); - dprintkdbg(DBG_KG, - "SRBdone (pid %li, target %02i-%i): ", srb->cmd->pid, - srb->cmd->device->id, srb->cmd->device->lun); + if (cmd->use_sg) { + struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; + ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); + } else { + ptr = (struct ScsiInqData *)(cmd->request_buffer); + } + + dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, + srb->cmd->device->id, srb->cmd->device->lun); + dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p addr=%p\n", + srb, cmd->use_sg, srb->sg_index, srb->sg_count, + cmd->request_buffer, ptr); status = srb->target_status; if (srb->flag & AUTO_REQSENSE) { - dprintkdbg(DBG_0, "AUTO_REQSENSE1..............\n"); + dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n"); pci_unmap_srb_sense(acb, srb); /* ** target status.......................... @@ -4176,61 +3328,60 @@ srb->flag &= ~AUTO_REQSENSE; srb->adapter_status = 0; srb->target_status = CHECK_CONDITION << 1; - if (debug_enabled(DBG_KG)) { + if (debug_enabled(DBG_1)) { switch (cmd->sense_buffer[2] & 0x0f) { case NOT_READY: dprintkl(KERN_DEBUG, - "ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i) ", + "ReqSense: NOT_READY cmnd=0x%02x <%02i-%i> stat=%i scan=%i ", cmd->cmnd[0], dcb->target_id, dcb->target_lun, status, acb->scan_devices); break; case UNIT_ATTENTION: dprintkl(KERN_DEBUG, - "ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i) ", + "ReqSense: UNIT_ATTENTION cmnd=0x%02x <%02i-%i> stat=%i scan=%i ", cmd->cmnd[0], dcb->target_id, dcb->target_lun, status, acb->scan_devices); break; case ILLEGAL_REQUEST: dprintkl(KERN_DEBUG, - "ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i) ", + "ReqSense: ILLEGAL_REQUEST cmnd=0x%02x <%02i-%i> stat=%i scan=%i ", cmd->cmnd[0], dcb->target_id, dcb->target_lun, status, acb->scan_devices); break; case MEDIUM_ERROR: dprintkl(KERN_DEBUG, - "ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i) ", + "ReqSense: MEDIUM_ERROR cmnd=0x%02x <%02i-%i> stat=%i scan=%i ", cmd->cmnd[0], dcb->target_id, dcb->target_lun, status, acb->scan_devices); break; case HARDWARE_ERROR: dprintkl(KERN_DEBUG, - "ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i) ", + "ReqSense: HARDWARE_ERROR cmnd=0x%02x <%02i-%i> stat=%i scan=%i ", cmd->cmnd[0], dcb->target_id, dcb->target_lun, status, acb->scan_devices); break; } if (cmd->sense_buffer[7] >= 6) - dprintkl(KERN_DEBUG, - "Sense=%02x, ASC=%02x, ASCQ=%02x (%08x %08x) ", - cmd->sense_buffer[2], cmd->sense_buffer[12], - cmd->sense_buffer[13], - *((unsigned int *) (cmd->sense_buffer + 3)), - *((unsigned int *) (cmd->sense_buffer + 8))); + printk("sense=0x%02x ASC=0x%02x ASCQ=0x%02x " + "(0x%08x 0x%08x)\n", + cmd->sense_buffer[2], cmd->sense_buffer[12], + cmd->sense_buffer[13], + *((unsigned int *)(cmd->sense_buffer + 3)), + *((unsigned int *)(cmd->sense_buffer + 8))); else - dprintkl(KERN_DEBUG, - "Sense=%02x, No ASC/ASCQ (%08x) ", - cmd->sense_buffer[2], - *((unsigned int *) (cmd->sense_buffer + 3))); + printk("sense=0x%02x No ASC/ASCQ (0x%08x)\n", + cmd->sense_buffer[2], + *((unsigned int *)(cmd->sense_buffer + 3))); } if (status == (CHECK_CONDITION << 1)) { cmd->result = DID_BAD_TARGET << 16; goto ckc_e; } - dprintkdbg(DBG_0, "AUTO_REQSENSE2..............\n"); + dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE2\n"); - if ((srb->total_xfer_length) - && (srb->total_xfer_length >= cmd->underflow)) + if (srb->total_xfer_length + && srb->total_xfer_length >= cmd->underflow) cmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, srb->end_message, CHECK_CONDITION); @@ -4253,8 +3404,7 @@ return; } else if (status_byte(status) == QUEUE_FULL) { tempcnt = (u8)list_size(&dcb->srb_going_list); - printk - ("\nDC395x: QUEUE_FULL for dev %02i-%i with %i cmnds\n", + dprintkl(KERN_INFO, "QUEUE_FULL for dev <%02i-%i> with %i cmnds\n", dcb->target_id, dcb->target_lun, tempcnt); if (tempcnt > 1) tempcnt--; @@ -4299,7 +3449,7 @@ if (dir != PCI_DMA_NONE) { if (cmd->use_sg) pci_dma_sync_sg(acb->dev, - (struct scatterlist *) cmd-> + (struct scatterlist *)cmd-> request_buffer, cmd->use_sg, dir); else if (cmd->request_buffer) pci_dma_sync_single(acb->dev, @@ -4336,48 +3486,35 @@ cmd->SCp.buffers_residual = 0; if (debug_enabled(DBG_KG)) { if (srb->total_xfer_length) - dprintkdbg(DBG_KG, "pid %li: %02x (%02i-%i): Missed %i bytes\n", - cmd->pid, cmd->cmnd[0], cmd->device->id, - cmd->device->lun, srb->total_xfer_length); + dprintkdbg(DBG_KG, "srb_done: (pid#%li) <%02i-%i> " + "cmnd=0x%02x Missed %i bytes\n", + cmd->pid, cmd->device->id, cmd->device->lun, + cmd->cmnd[0], srb->total_xfer_length); } srb_going_remove(dcb, srb); /* Add to free list */ if (srb == acb->tmp_srb) - dprintkl(KERN_ERR, "ERROR! Completed Cmnd with tmp_srb!\n"); - else + dprintkl(KERN_ERR, "srb_done: ERROR! Completed cmd with tmp_srb\n"); + else { + dprintkdbg(DBG_0, "srb_done: (pid#%li) done result=0x%08x\n", + cmd->pid, cmd->result); srb_free_insert(acb, srb); - - dprintkdbg(DBG_0, "SRBdone: done pid %li\n", cmd->pid); - if (debug_enabled(DBG_KG)) { - printk(" 0x%08x\n", cmd->result); } - TRACEPRINTF("%08x(%li)*", cmd->result, jiffies); pci_unmap_srb(acb, srb); - /*DC395x_UNLOCK_ACB_NI; */ - cmd->scsi_done(cmd); - /*DC395x_LOCK_ACB_NI; */ - TRACEOUTALL(KERN_INFO " %s\n", srb->debugtrace); + cmd->scsi_done(cmd); waiting_process_next(acb); - return; } -/* - ******************************************************************** - * scsiio - * DC395x_reset - * abort all cmds in our queues - ******************************************************************** - */ -static -void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, - Scsi_Cmnd * cmd, u8 force) +/* abort all cmds in our queues */ +static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, + Scsi_Cmnd *cmd, u8 force) { struct DeviceCtlBlk *dcb; - dprintkl(KERN_INFO, "doing_srb_done: pids "); + list_for_each_entry(dcb, &acb->dcb_list, list) { struct ScsiReqBlk *srb; struct ScsiReqBlk *tmp; @@ -4390,16 +3527,8 @@ p = srb->cmd; dir = scsi_to_pci_dma_dir(p->sc_data_direction); result = MK_RES(0, did_flag, 0, 0); - - /*result = MK_RES(0,DID_RESET,0,0); */ - TRACEPRINTF("Reset(%li):%08x*", jiffies, result); - printk(" (G)"); -#if 1 /*ndef DC395x_DEBUGTRACE */ - printk("%li(%02i-%i) ", p->pid, + printk("G:%li(%02i-%i) ", p->pid, p->device->id, p->device->lun); -#endif - TRACEOUT("%s\n", srb->debugtrace); - srb_going_remove(dcb, srb); free_tag(dcb, srb); srb_free_insert(acb, srb); @@ -4414,11 +3543,11 @@ } if (!list_empty(&dcb->srb_going_list)) dprintkl(KERN_DEBUG, - "How could the ML send cmnds to the Going queue? (%02i-%i)!!\n", + "How could the ML send cmnds to the Going queue? <%02i-%i>\n", dcb->target_id, dcb->target_lun); if (dcb->tag_mask) dprintkl(KERN_DEBUG, - "tag_mask for %02i-%i should be empty, is %08x!\n", + "tag_mask for <%02i-%i> should be empty, is %08x!\n", dcb->target_id, dcb->target_lun, dcb->tag_mask); @@ -4428,16 +3557,10 @@ p = srb->cmd; result = MK_RES(0, did_flag, 0, 0); - TRACEPRINTF("Reset(%li):%08x*", jiffies, result); - printk(" (W)"); -#if 1 /*ndef DC395x_DEBUGTRACE */ - printk("%li(%i-%i)", p->pid, p->device->id, + printk("W:%li<%02i-%i>", p->pid, p->device->id, p->device->lun); -#endif - TRACEOUT("%s\n", srb->debugtrace); srb_waiting_remove(dcb, srb); srb_free_insert(acb, srb); - p->result = result; pci_unmap_srb_sense(acb, srb); pci_unmap_srb(acb, srb); @@ -4448,41 +3571,26 @@ } } if (!list_empty(&dcb->srb_waiting_list)) - printk - ("\nDC395x: Debug: ML queued %i cmnds again to %02i-%i\n", + dprintkl(KERN_DEBUG, "ML queued %i cmnds again to <%02i-%i>\n", list_size(&dcb->srb_waiting_list), dcb->target_id, dcb->target_lun); - dcb->flag &= ~ABORT_DEV_; } printk("\n"); } -/* - ******************************************************************** - * scsiio - * DC395x_shutdown DC395x_reset - ******************************************************************** - */ static void reset_scsi_bus(struct AdapterCtlBlk *acb) { - /*u32 drv_flags=0; */ - - dprintkdbg(DBG_0, "reset_scsi_bus..............\n"); - - /*DC395x_DRV_LOCK(drv_flags); */ + dprintkdbg(DBG_0, "reset_scsi_bus: acb=%p\n", acb); acb->acb_flag |= RESET_DEV; /* RESET_DETECT, RESET_DONE, RESET_DEV */ - DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI); - while (!(DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET)); - /*DC395x_DRV_UNLOCK(drv_flags); */ - return; + while (!(DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET)) + /* nothing */; } -/* Set basic config */ static void set_basic_config(struct AdapterCtlBlk *acb) { u8 bval; @@ -4508,7 +3616,6 @@ wval = DC395x_read16(acb, TRM_S1040_DMA_CONFIG) & ~DMA_FIFO_CTRL; wval |= DMA_FIFO_HALF_HALF | DMA_ENHANCE /*| DMA_MEM_MULTI_READ */ ; - /*dprintkl(KERN_INFO, "DMA_Config: %04x\n", wval); */ DC395x_write16(acb, TRM_S1040_DMA_CONFIG, wval); /* Clear pending interrupt status */ DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS); @@ -4520,15 +3627,9 @@ } -/* - ******************************************************************** - * scsiio - * dc395x_interrupt - ******************************************************************** - */ static void scsi_reset_detect(struct AdapterCtlBlk *acb) { - dprintkl(KERN_INFO, "scsi_reset_detect\n"); + dprintkl(KERN_INFO, "scsi_reset_detect: acb=%p\n", acb); /* delay half a second */ if (timer_pending(&acb->waiting_timer)) del_timer(&acb->waiting_timer); @@ -4542,7 +3643,7 @@ jiffies + 5 * HZ / 2 + HZ * acb->eeprom.delay_time; - clear_fifo(acb, "RstDet"); + clear_fifo(acb, "scsi_reset_detect"); set_basic_config(acb); /*1.25 */ /*DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); */ @@ -4558,28 +3659,16 @@ acb->acb_flag = 0; waiting_process_next(acb); } - - return; } -/* - ******************************************************************** - * scsiio - * srb_done - ******************************************************************** - */ -static -void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, - struct ScsiReqBlk *srb) +static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, + struct ScsiReqBlk *srb) { - Scsi_Cmnd *cmd; + Scsi_Cmnd *cmd = srb->cmd; + dprintkdbg(DBG_1, "request_sense: (pid#%li) <%02i-%i>\n", + cmd->pid, cmd->device->id, cmd->device->lun); - cmd = srb->cmd; - dprintkdbg(DBG_KG, - "request_sense for pid %li, target %02i-%i\n", - cmd->pid, cmd->device->id, cmd->device->lun); - TRACEPRINTF("RqSn*"); srb->flag |= AUTO_REQSENSE; srb->adapter_status = 0; srb->target_status = 0; @@ -4600,27 +3689,22 @@ srb->segment_x[0].address = pci_map_single(acb->dev, cmd->sense_buffer, sizeof(cmd->sense_buffer), PCI_DMA_FROMDEVICE); - dprintkdbg(DBG_SGPARANOIA, "Map sense buffer at %p (%05x) to %08x\n", - cmd->sense_buffer, sizeof(cmd->sense_buffer), - srb->segment_x[0].address); + dprintkdbg(DBG_SG, "request_sense: map buffer %p->%08x(%05x)\n", + cmd->sense_buffer, srb->segment_x[0].address, + sizeof(cmd->sense_buffer)); srb->sg_count = 1; srb->sg_index = 0; if (start_scsi(acb, dcb, srb)) { /* Should only happen, if sb. else grabs the bus */ dprintkl(KERN_DEBUG, - "Request Sense failed for pid %li (%02i-%i)!\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun); - TRACEPRINTF("?*"); + "request_sense: (pid#%li) failed <%02i-%i>\n", + srb->cmd->pid, dcb->target_id, dcb->target_lun); srb_going_to_waiting_move(dcb, srb); waiting_set_timer(acb, HZ / 100); } - TRACEPRINTF(".*"); } - - - /** * device_alloc - Allocate a new device instance. This create the * devices instance and sets up all the data items. The adapter @@ -4634,18 +3718,17 @@ * * Return the new device if succesfull or NULL on failure. **/ -static -struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, u8 target, u8 lun) +static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, + u8 target, u8 lun) { struct NvRamType *eeprom = &acb->eeprom; u8 period_index = eeprom->target[target].period & 0x07; struct DeviceCtlBlk *dcb; - dcb = dc395x_kmalloc(sizeof(struct DeviceCtlBlk), GFP_ATOMIC); - dprintkdbg(DBG_0, "device_alloc: device %p\n", dcb); - if (!dcb) { + dcb = kmalloc(sizeof(struct DeviceCtlBlk), GFP_ATOMIC); + dprintkdbg(DBG_0, "device_alloc: <%02i-%i>\n", target, lun); + if (!dcb) return NULL; - } dcb->acb = NULL; INIT_LIST_HEAD(&dcb->srb_going_list); INIT_LIST_HEAD(&dcb->srb_waiting_list); @@ -4684,10 +3767,10 @@ list_for_each_entry(p, &acb->dcb_list, list) if (p->target_id == dcb->target_id) break; - dprintkdbg(DBG_KG, - "Copy settings from %02i-%02i to %02i-%02i\n", - p->target_id, p->target_lun, - dcb->target_id, dcb->target_lun); + dprintkdbg(DBG_1, + "device_alloc: <%02i-%i> copy from <%02i-%i>\n", + dcb->target_id, dcb->target_lun, + p->target_id, p->target_lun); dcb->sync_mode = p->sync_mode; dcb->sync_period = p->sync_period; dcb->min_nego_period = p->min_nego_period; @@ -4704,8 +3787,8 @@ * @acb: The adapter device to be updated * @dcb: A newly created and intialised device instance to add. **/ -static -void adapter_add_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) +static void adapter_add_device(struct AdapterCtlBlk *acb, + struct DeviceCtlBlk *dcb) { /* backpointer to adapter */ dcb->acb = acb; @@ -4732,13 +3815,13 @@ * @acb: The adapter device to be updated * @dcb: A device that has previously been added to the adapter. **/ -static -void adapter_remove_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) +static void adapter_remove_device(struct AdapterCtlBlk *acb, + struct DeviceCtlBlk *dcb) { struct DeviceCtlBlk *i; struct DeviceCtlBlk *tmp; - dprintkdbg(DBG_0, "adapter_remove_device: Remove device (ID %i, LUN %i): %p\n", - dcb->target_id, dcb->target_lun, dcb); + dprintkdbg(DBG_0, "adapter_remove_device: <%02i-%i>\n", + dcb->target_id, dcb->target_lun); /* fix up any pointers to this device that we have in the adapter */ if (acb->active_dcb == dcb) @@ -4767,17 +3850,18 @@ * @acb: The adapter device to be updated * @dcb: A device that has previously been added to the adapter. */ -static -void adapter_remove_and_free_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb) +static void adapter_remove_and_free_device(struct AdapterCtlBlk *acb, + struct DeviceCtlBlk *dcb) { if (list_size(&dcb->srb_going_list) > 1) { - dprintkdbg(DBG_DCB, "adapter_remove_and_free_device: " - "Won't remove because of %i active requests\n", + dprintkdbg(DBG_1, "adapter_remove_and_free_device: <%02i-%i> " + "Won't remove because of %i active requests.\n", + dcb->target_id, dcb->target_lun, list_size(&dcb->srb_going_list)); return; } adapter_remove_device(acb, dcb); - dc395x_kfree(dcb); + kfree(dcb); } @@ -4787,12 +3871,11 @@ * * @acb: The adapter from which all devices should be removed. **/ -static -void adapter_remove_and_free_all_devices(struct AdapterCtlBlk* acb) +static void adapter_remove_and_free_all_devices(struct AdapterCtlBlk* acb) { struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *tmp; - dprintkdbg(DBG_DCB, "adapter_remove_and_free_all_devices: Free all devices (%i devices)\n", + dprintkdbg(DBG_1, "adapter_remove_and_free_all_devices: num=%i\n", list_size(&acb->dcb_list)); list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) @@ -4807,8 +3890,7 @@ * * @scsi_device: The new scsi device that we need to handle. **/ -static -int dc395x_slave_alloc(struct scsi_device *scsi_device) +static int dc395x_slave_alloc(struct scsi_device *scsi_device) { struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata; struct DeviceCtlBlk *dcb; @@ -4828,8 +3910,7 @@ * * @scsi_device: The new scsi device that we need to handle. **/ -static -void dc395x_slave_destroy(struct scsi_device *scsi_device) +static void dc395x_slave_destroy(struct scsi_device *scsi_device) { struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata; struct DeviceCtlBlk *dcb = find_dcb(acb, scsi_device->id, scsi_device->lun); @@ -4847,14 +3928,12 @@ * * @io_port: base I/O address **/ -static -void __init trms1040_wait_30us(u16 io_port) +static void __init trms1040_wait_30us(u16 io_port) { /* ScsiPortStallExecution(30); wait 30 us */ outb(5, io_port + TRM_S1040_GEN_TIMER); while (!(inb(io_port + TRM_S1040_GEN_STATUS) & GTIMEOUT)) /* nothing */ ; - return; } @@ -4866,8 +3945,7 @@ * @cmd: SB + op code (command) to send * @addr: address to send **/ -static -void __init trms1040_write_cmd(u16 io_port, u8 cmd, u8 addr) +static void __init trms1040_write_cmd(u16 io_port, u8 cmd, u8 addr) { int i; u8 send_data; @@ -4912,8 +3990,7 @@ * @addr: offset into EEPROM * @byte: bytes to write **/ -static -void __init trms1040_set_data(u16 io_port, u8 addr, u8 byte) +static void __init trms1040_set_data(u16 io_port, u8 addr, u8 byte) { int i; u8 send_data; @@ -4967,10 +4044,9 @@ * @eeprom: the data to write * @io_port: the base io port **/ -static -void __init trms1040_write_all(struct NvRamType *eeprom, u16 io_port) +static void __init trms1040_write_all(struct NvRamType *eeprom, u16 io_port) { - u8 *b_eeprom = (u8 *) eeprom; + u8 *b_eeprom = (u8 *)eeprom; u8 addr; /* Enable SEEPROM */ @@ -4983,9 +4059,8 @@ trms1040_wait_30us(io_port); /* write */ - for (addr = 0; addr < 128; addr++, b_eeprom++) { + for (addr = 0; addr < 128; addr++, b_eeprom++) trms1040_set_data(io_port, addr, *b_eeprom); - } /* write disable */ trms1040_write_cmd(io_port, 0x04, 0x00); @@ -5009,8 +4084,7 @@ * * Returns the the byte read. **/ -static -u8 __init trms1040_get_data(u16 io_port, u8 addr) +static u8 __init trms1040_get_data(u16 io_port, u8 addr) { int i; u8 read_byte; @@ -5048,10 +4122,9 @@ * @eeprom: where to store the data * @io_port: the base io port **/ -static -void __init trms1040_read_all(struct NvRamType *eeprom, u16 io_port) +static void __init trms1040_read_all(struct NvRamType *eeprom, u16 io_port) { - u8 *b_eeprom = (u8 *) eeprom; + u8 *b_eeprom = (u8 *)eeprom; u8 addr; /* Enable SEEPROM */ @@ -5059,9 +4132,8 @@ io_port + TRM_S1040_GEN_CONTROL); /* read details */ - for (addr = 0; addr < 128; addr++, b_eeprom++) { + for (addr = 0; addr < 128; addr++, b_eeprom++) *b_eeprom = trms1040_get_data(io_port, addr); - } /* Disable SEEPROM */ outb((inb(io_port + TRM_S1040_GEN_CONTROL) & ~EN_EEPROM), @@ -5080,10 +4152,9 @@ * @eeprom: caller allocated strcuture to read the eeprom data into * @io_port: io port to read from **/ -static -void __init check_eeprom(struct NvRamType *eeprom, u16 io_port) +static void __init check_eeprom(struct NvRamType *eeprom, u16 io_port) { - u16 *w_eeprom = (u16 *) eeprom; + u16 *w_eeprom = (u16 *)eeprom; u16 w_addr; u16 cksum; u32 d_addr; @@ -5092,7 +4163,7 @@ trms1040_read_all(eeprom, io_port); /* read eeprom */ cksum = 0; - for (w_addr = 0, w_eeprom = (u16 *) eeprom; w_addr < 64; + for (w_addr = 0, w_eeprom = (u16 *)eeprom; w_addr < 64; w_addr++, w_eeprom++) cksum += *w_eeprom; if (cksum != 0x1234) { @@ -5101,21 +4172,21 @@ * Load a set of defaults into the eeprom buffer */ dprintkl(KERN_WARNING, - "EEProm checksum error: using default values and options.\n"); - eeprom->sub_vendor_id[0] = (u8) PCI_VENDOR_ID_TEKRAM; - eeprom->sub_vendor_id[1] = (u8) (PCI_VENDOR_ID_TEKRAM >> 8); - eeprom->sub_sys_id[0] = (u8) PCI_DEVICE_ID_TEKRAM_TRMS1040; + "EEProm checksum error: using default values and options.\n"); + eeprom->sub_vendor_id[0] = (u8)PCI_VENDOR_ID_TEKRAM; + eeprom->sub_vendor_id[1] = (u8)(PCI_VENDOR_ID_TEKRAM >> 8); + eeprom->sub_sys_id[0] = (u8)PCI_DEVICE_ID_TEKRAM_TRMS1040; eeprom->sub_sys_id[1] = - (u8) (PCI_DEVICE_ID_TEKRAM_TRMS1040 >> 8); + (u8)(PCI_DEVICE_ID_TEKRAM_TRMS1040 >> 8); eeprom->sub_class = 0x00; - eeprom->vendor_id[0] = (u8) PCI_VENDOR_ID_TEKRAM; - eeprom->vendor_id[1] = (u8) (PCI_VENDOR_ID_TEKRAM >> 8); - eeprom->device_id[0] = (u8) PCI_DEVICE_ID_TEKRAM_TRMS1040; + eeprom->vendor_id[0] = (u8)PCI_VENDOR_ID_TEKRAM; + eeprom->vendor_id[1] = (u8)(PCI_VENDOR_ID_TEKRAM >> 8); + eeprom->device_id[0] = (u8)PCI_DEVICE_ID_TEKRAM_TRMS1040; eeprom->device_id[1] = - (u8) (PCI_DEVICE_ID_TEKRAM_TRMS1040 >> 8); + (u8)(PCI_DEVICE_ID_TEKRAM_TRMS1040 >> 8); eeprom->reserved = 0x00; - for (d_addr = 0, d_eeprom = (u32 *) eeprom->target; + for (d_addr = 0, d_eeprom = (u32 *)eeprom->target; d_addr < 16; d_addr++, d_eeprom++) *d_eeprom = 0x00000077; /* cfg3,cfg2,period,cfg0 */ @@ -5130,7 +4201,7 @@ eeprom_override(eeprom); eeprom->cksum = 0x00; - for (w_addr = 0, cksum = 0, w_eeprom = (u16 *) eeprom; + for (w_addr = 0, cksum = 0, w_eeprom = (u16 *)eeprom; w_addr < 63; w_addr++, w_eeprom++) cksum += *w_eeprom; @@ -5145,113 +4216,47 @@ } - - /** * print_eeprom_settings - output the eeprom settings * to the kernel log so people can see what they were. * * @eeprom: The eeprom data strucutre to show details for. **/ -static -void __init print_eeprom_settings(struct NvRamType *eeprom) +static void __init print_eeprom_settings(struct NvRamType *eeprom) { dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n", - eeprom->scsi_id, - eeprom->target[0].period, - clock_speed[eeprom->target[0].period] / 10, - clock_speed[eeprom->target[0].period] % 10, - eeprom->target[0].cfg0); + eeprom->scsi_id, + eeprom->target[0].period, + clock_speed[eeprom->target[0].period] / 10, + clock_speed[eeprom->target[0].period] % 10, + eeprom->target[0].cfg0); dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n", - eeprom->channel_cfg, - eeprom->max_tag, - 1 << eeprom->max_tag, - eeprom->delay_time); + eeprom->channel_cfg, eeprom->max_tag, + 1 << eeprom->max_tag, eeprom->delay_time); } - -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) -/* - * Memory for trace buffers - */ -static -void free_tracebufs(struct AdapterCtlBlk *acb) -{ - int i; - const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; - - for (i = 0; i < srb_idx; i += bufs_per_page) - if (acb->srb_array[i].debugtrace) - dc395x_kfree(acb->srb_array[i].debugtrace); -} - - -static -int alloc_tracebufs(struct AdapterCtlBlk *acb) -{ - const unsigned mem_needed = - (DC395x_MAX_SRB_CNT + 1) * DEBUGTRACEBUFSZ; - int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; - const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ; - int srb_idx = 0; - unsigned i = 0; - unsigned char *ptr; - - for (i = 0; i < DC395x_MAX_SRB_CNT; i++) - acb->srb_array[i].debugtrace = NULL; - - while (pages--) { - ptr = dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ptr) { - free_tracebufs(acb); - return 1; - } - /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for tracebuf %i\n", */ - /* PAGE_SIZE, ptr, srb_idx); */ - i = 0; - while (i < bufs_per_page && srb_idx < DC395x_MAX_SRB_CNT) - acb->srb_array[srb_idx++].debugtrace = - ptr + (i++ * DEBUGTRACEBUFSZ); - } - if (i < bufs_per_page) { - acb->srb.debugtrace = ptr + (i * DEBUGTRACEBUFSZ); - acb->srb.debugtrace[0] = 0; - } else - dprintkl(KERN_DEBUG, "No space for tmsrb tracebuf reserved?!\n"); - return 0; -} -#else -static void free_tracebufs(struct AdapterCtlBlk *acb) {} -static int alloc_tracebufs(struct AdapterCtlBlk *acb) { return 0; } -#endif - /* Free SG tables */ -static -void adapter_sg_tables_free(struct AdapterCtlBlk *acb) +static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) { int i; - const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY - *sizeof(struct SGentry)); + const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) if (acb->srb_array[i].segment_x) - dc395x_kfree(acb->srb_array[i].segment_x); + kfree(acb->srb_array[i].segment_x); } /* * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*) * should never cross a page boundary */ -static -int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) +static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) { const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1) - *DC395x_MAX_SG_LISTENTRY - *sizeof(struct SGentry); + *SEGMENTX_LEN; int pages = (mem_needed+(PAGE_SIZE-1))/PAGE_SIZE; - const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY - *sizeof(struct SGentry)); + const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; int srb_idx = 0; unsigned i = 0; struct SGentry *ptr; @@ -5261,13 +4266,13 @@ dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); while (pages--) { - ptr = (struct SGentry *)dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL); + ptr = (struct SGentry *)kmalloc(PAGE_SIZE, GFP_KERNEL); if (!ptr) { adapter_sg_tables_free(acb); return 1; } dprintkdbg(DBG_1, "Allocate %li bytes at %p for SG segments %i\n", - PAGE_SIZE, ptr, srb_idx); + PAGE_SIZE, ptr, srb_idx); i = 0; while (i < srbs_per_page && srb_idx < DC395x_MAX_SRB_CNT) acb->srb_array[srb_idx++].segment_x = @@ -5292,14 +4297,13 @@ * * @acb: The adapter to print the information for. **/ -static -void __init adapter_print_config(struct AdapterCtlBlk *acb) +static void __init adapter_print_config(struct AdapterCtlBlk *acb) { u8 bval; bval = DC395x_read8(acb, TRM_S1040_GEN_STATUS); - dprintkl(KERN_INFO, "%s Connectors: ", - ((bval & WIDESCSI) ? "(Wide)" : "")); + dprintkl(KERN_INFO, "%sConnectors: ", + ((bval & WIDESCSI) ? "(Wide) " : "")); if (!(bval & CON5068)) printk("ext%s ", !(bval & EXT68HIGH) ? "68" : "50"); if (!(bval & CON68)) @@ -5337,8 +4341,7 @@ * * @acb: The adapter to initialize. **/ -static -void __init adapter_init_params(struct AdapterCtlBlk *acb) +static void __init adapter_init_params(struct AdapterCtlBlk *acb) { struct NvRamType *eeprom = &acb->eeprom; int i; @@ -5400,8 +4403,7 @@ * * @host: The scsi host instance to fill in the values for. **/ -static -void __init adapter_init_scsi_host(struct Scsi_Host *host) +static void __init adapter_init_scsi_host(struct Scsi_Host *host) { struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; struct NvRamType *eeprom = &acb->eeprom; @@ -5495,8 +4497,8 @@ * Returns 0 if the initialization succeeds, any other value on * failure. **/ -static -int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port, u32 io_port_len, u8 irq) +static int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port, + u32 io_port_len, u8 irq) { if (!request_region(io_port, io_port_len, DC395X_NAME)) { dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port); @@ -5528,19 +4530,15 @@ dprintkl(KERN_DEBUG, "Memory allocation for SG tables failed\n"); goto failed; } - if (alloc_tracebufs(acb)) { - dprintkl(KERN_DEBUG, "Memory allocation for trace buffers failed\n"); - goto failed; - } adapter_init_scsi_host(acb->scsi_host); adapter_init_chip(acb); set_basic_config(acb); - dprintkdbg(DBG_0, "adapter_init: acb=%p, pdcb_map=%p " - "psrb_array=%p ACB size=%04x, DCB size=%04x " - "SRB size=%04x\n", - acb, acb->dcb_map, acb->srb_array, sizeof(struct AdapterCtlBlk), - sizeof(struct DeviceCtlBlk), sizeof(struct ScsiReqBlk)); + dprintkdbg(DBG_0, + "adapter_init: acb=%p, pdcb_map=%p psrb_array=%p " + "size{acb=0x%04x dcb=0x%04x srb=0x%04x}\n", + acb, acb->dcb_map, acb->srb_array, sizeof(struct AdapterCtlBlk), + sizeof(struct DeviceCtlBlk), sizeof(struct ScsiReqBlk)); return 0; failed: @@ -5549,7 +4547,6 @@ if (acb->io_port_base) release_region(acb->io_port_base, acb->io_port_len); adapter_sg_tables_free(acb); - free_tracebufs(acb); return 1; } @@ -5562,8 +4559,7 @@ * * @acb: The adapter which we are to shutdown. **/ -static -void adapter_uninit_chip(struct AdapterCtlBlk *acb) +static void adapter_uninit_chip(struct AdapterCtlBlk *acb) { /* disable interrupts */ DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0); @@ -5586,8 +4582,7 @@ * * @acb: The adapter which we are to un-initialize. **/ -static -void adapter_uninit(struct AdapterCtlBlk *acb) +static void adapter_uninit(struct AdapterCtlBlk *acb) { unsigned long flags; DC395x_LOCK_IO(acb->scsi_host, flags); @@ -5608,31 +4603,9 @@ release_region(acb->io_port_base, acb->io_port_len); adapter_sg_tables_free(acb); - free_tracebufs(acb); } -/* - ****************************************************************** - * Function: dc395x_proc_info(char* buffer, char **start, - * off_t offset, int length, int hostno, int inout) - * Purpose: return SCSI Adapter/Device Info - * Input: - * buffer: Pointer to a buffer where to write info - * start : - * offset: - * hostno: Host adapter index - * inout : Read (=0) or set(!=0) info - * Output: - * buffer: contains info length - * - * return value: length of info in buffer - * - ****************************************************************** - */ - -/* KG: dc395x_proc_info taken from driver aha152x.c */ - #undef SPRINTF #define SPRINTF(args...) pos += sprintf(pos, args) @@ -5641,9 +4614,8 @@ if (YN) SPRINTF(" Yes ");\ else SPRINTF(" No ") -static -int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, - int inout) +static int dc395x_proc_info(struct Scsi_Host *host, char *buffer, + char **start, off_t offset, int length, int inout) { struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; int spd, spd1; @@ -5741,16 +4713,12 @@ dcb->target_id, dcb->target_lun, list_size(&dcb->srb_going_list)); list_for_each_entry(srb, &dcb->srb_going_list, list) -#if debug_enabled(DBG_TRACE|DBG_TRACEALL) - SPRINTF("\n %s", srb->debugtrace); -#else SPRINTF(" %li", srb->cmd->pid); -#endif if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list)) SPRINTF("\n"); } - if (debug_enabled(DBG_DCB)) { + if (debug_enabled(DBG_1)) { SPRINTF("DCB list for ACB %p:\n", acb); list_for_each_entry(dcb, &acb->dcb_list, list) { SPRINTF("%p -> ", dcb); @@ -5770,11 +4738,6 @@ } - - -/* - * SCSI host template - */ static Scsi_Host_Template dc395x_driver_template = { .module = THIS_MODULE, .proc_name = DC395X_NAME, @@ -5799,8 +4762,7 @@ * banner_display - Display banner on first instance of driver * initialized. **/ -static -void banner_display(void) +static void banner_display(void) { static int banner_done = 0; if (!banner_done) @@ -5824,9 +4786,8 @@ * * Returns 0 on success, or an error code (-ve) on failure. **/ -static -int __devinit dc395x_init_one(struct pci_dev *dev, - const struct pci_device_id *id) +static int __devinit dc395x_init_one(struct pci_dev *dev, + const struct pci_device_id *id) { struct Scsi_Host *scsi_host; struct AdapterCtlBlk *acb; @@ -5859,7 +4820,7 @@ /* initialise the adapter and everything we need */ if (adapter_init(acb, io_port_base, io_port_len, irq)) { - dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n"); + dprintkl(KERN_INFO, "adapter init failed\n"); scsi_host_put(scsi_host); return -ENODEV; } @@ -5870,7 +4831,7 @@ if (scsi_add_host(scsi_host, &dev->dev)) { dprintkl(KERN_ERR, "scsi_add_host failed\n"); adapter_uninit(acb); - scsi_host_put(scsi_host); + scsi_host_put(scsi_host); return -ENODEV; } pci_set_drvdata(dev, scsi_host); @@ -5891,7 +4852,7 @@ struct Scsi_Host *scsi_host = pci_get_drvdata(dev); struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(scsi_host->hostdata); - dprintkdbg(DBG_0, "Removing instance\n"); + dprintkdbg(DBG_0, "dc395x_remove_one: acb=%p\n", acb); scsi_remove_host(scsi_host); adapter_uninit(acb); @@ -5900,10 +4861,6 @@ } -/* - * Table which identifies the PCI devices which - * are handled by this device driver. - */ static struct pci_device_id dc395x_pci_table[] = { { .vendor = PCI_VENDOR_ID_TEKRAM, @@ -5916,10 +4873,6 @@ MODULE_DEVICE_TABLE(pci, dc395x_pci_table); -/* - * PCI driver operations. - * Tells the PCI sub system what can be done with the card. - */ static struct pci_driver dc395x_driver = { .name = DC395X_NAME, .id_table = dc395x_pci_table, @@ -5933,8 +4886,7 @@ * * Used by both module and built-in driver to initialise this driver. **/ -static -int __init dc395x_module_init(void) +static int __init dc395x_module_init(void) { return pci_module_init(&dc395x_driver); } @@ -5943,8 +4895,7 @@ /** * dc395x_module_exit - Module cleanup function. **/ -static -void __exit dc395x_module_exit(void) +static void __exit dc395x_module_exit(void) { pci_unregister_driver(&dc395x_driver); } diff -Nru a/drivers/scsi/dc395x.h b/drivers/scsi/dc395x.h --- a/drivers/scsi/dc395x.h Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/dc395x.h Wed Mar 10 21:09:43 2004 @@ -7,18 +7,8 @@ /* (SCSI chip set used Tekram ASIC TRM-S1040) */ /* */ /************************************************************************/ - #ifndef DC395x_H #define DC395x_H - -/************************************************************************/ -/* */ -/* Name, Banner and Version */ -/* */ -/************************************************************************/ -#define DC395X_NAME "dc395x" -#define DC395X_BANNER "Tekram DC395(U/UW/F), DC315(U) - ASIC TRM-S1040" -#define DC395X_VERSION "v2.04, 2003/05/19" /************************************************************************/ /* */ diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c --- a/drivers/scsi/hosts.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/hosts.c Wed Mar 10 21:09:42 2004 @@ -32,6 +32,7 @@ #include #include +#include #include "scsi.h" #include "scsi_priv.h" @@ -221,6 +222,11 @@ shost->max_channel = 0; shost->max_id = 8; shost->max_lun = 8; + + /* Give each shost a default transportt if the driver + * doesn't yet support Transport Attributes */ + if (!shost->transportt) + shost->transportt = &blank_transport_template; /* * All drivers right now should be able to handle 12 byte diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/ini9100u.c Wed Mar 10 21:09:42 2004 @@ -180,15 +180,6 @@ static char *setup_str = (char *) NULL; -static irqreturn_t i91u_intr0(int irq, void *dev_id, struct pt_regs *); -static irqreturn_t i91u_intr1(int irq, void *dev_id, struct pt_regs *); -static irqreturn_t i91u_intr2(int irq, void *dev_id, struct pt_regs *); -static irqreturn_t i91u_intr3(int irq, void *dev_id, struct pt_regs *); -static irqreturn_t i91u_intr4(int irq, void *dev_id, struct pt_regs *); -static irqreturn_t i91u_intr5(int irq, void *dev_id, struct pt_regs *); -static irqreturn_t i91u_intr6(int irq, void *dev_id, struct pt_regs *); -static irqreturn_t i91u_intr7(int irq, void *dev_id, struct pt_regs *); - static void i91u_panic(char *msg); static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); @@ -278,7 +269,7 @@ unsigned long flags; spin_lock_irqsave(dev->host_lock, flags); - tul_isr((HCS *)hreg->base); + tul_isr((HCS *)dev->base); spin_unlock_irqrestore(dev->host_lock, flags); return IRQ_HANDLED; } diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/megaraid.c Wed Mar 10 21:09:42 2004 @@ -5118,10 +5118,6 @@ if (max_mbox_busy_wait > MBOX_BUSY_WAIT) max_mbox_busy_wait = MBOX_BUSY_WAIT; - error = pci_module_init(&megaraid_pci_driver); - if (error) - return error; - #ifdef CONFIG_PROC_FS mega_proc_dir_entry = proc_mkdir("megaraid", &proc_root); if (!mega_proc_dir_entry) { @@ -5129,6 +5125,13 @@ "megaraid: failed to create megaraid root\n"); } #endif + error = pci_module_init(&megaraid_pci_driver); + if (error) { +#ifdef CONFIG_PROC_FS + remove_proc_entry("megaraid", &proc_root); +#endif + return error; + } /* * Register the driver as a character device, for applications diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c --- a/drivers/scsi/pcmcia/qlogic_stub.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/pcmcia/qlogic_stub.c Wed Mar 10 21:09:42 2004 @@ -43,9 +43,11 @@ #include #include #include +#include #include "scsi.h" #include "hosts.h" +#include "../qlogicfas.h" #include #include @@ -57,8 +59,10 @@ extern Scsi_Host_Template qlogicfas_driver_template; extern void qlogicfas_preset(int port, int irq); -extern struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *); extern int qlogicfas_bus_reset(Scsi_Cmnd *); +extern irqreturn_t do_ql_ihandl(int irq, void *dev_id, struct pt_regs *regs); + +static char *qlogic_name = "qlogic_cs"; #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; @@ -100,6 +104,71 @@ static dev_info_t dev_info = "qlogic_cs"; +static struct Scsi_Host *qlogic_detect(Scsi_Host_Template *host, + dev_link_t *link, int qbase, int qlirq) +{ + int qltyp; /* type of chip */ + int qinitid; + struct Scsi_Host *shost; /* registered host structure */ + qlogicfas_priv_t priv; + + qltyp = inb(qbase + 0xe) & 0xf8; + qinitid = host->this_id; + if (qinitid < 0) + qinitid = 7; /* if no ID, use 7 */ + outb(1, qbase + 8); /* set for PIO pseudo DMA */ + REG0; + outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ + outb(qlcfg5, qbase + 5); /* select timer */ + outb(qlcfg9, qbase + 9); /* prescaler */ + +#if QL_RESET_AT_START + outb(3, qbase + 3); + REG1; + /* FIXME: timeout */ + while (inb(qbase + 0xf) & 4) + cpu_relax(); + REG0; +#endif + + host->name = qlogic_name; + shost = scsi_host_alloc(host, sizeof(struct qlogicfas_priv)); + if (!shost) + goto err; + shost->io_port = qbase; + shost->n_io_port = 16; + shost->dma_channel = -1; + if (qlirq != -1) + shost->irq = qlirq; + + priv = (qlogicfas_priv_t)&(shost->hostdata[0]); + priv->qlirq = qlirq; + priv->qbase = qbase; + priv->qinitid = qinitid; + + if (request_irq(qlirq, do_ql_ihandl, 0, qlogic_name, shost)) + goto free_scsi_host; + + sprintf(priv->qinfo, + "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d", + qltyp, qbase, qlirq, QL_TURBO_PDMA); + + if (scsi_add_host(shost, NULL)) + goto free_interrupt; + + scsi_scan_host(shost); + + return shost; + +free_interrupt: + free_irq(qlirq, shost); + +free_scsi_host: + scsi_host_put(shost); + +err: + return NULL; +} static dev_link_t *qlogic_attach(void) { scsi_info_t *info; @@ -238,18 +307,19 @@ outb(0x04, link->io.BasePort1 + 0xd); } - /* A bad hack... */ - release_region(link->io.BasePort1, link->io.NumPorts1); + qlogicfas_driver_template.name = qlogic_name; + qlogicfas_driver_template.proc_name = qlogic_name; /* The KXL-810AN has a bigger IO port window */ if (link->io.NumPorts1 == 32) - qlogicfas_preset(link->io.BasePort1 + 16, link->irq.AssignedIRQ); + host = qlogic_detect(&qlogicfas_driver_template, link, + link->io.BasePort1 + 16, link->irq.AssignedIRQ); else - qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ); - - host = __qlogicfas_detect(&qlogicfas_driver_template); + host = qlogic_detect(&qlogicfas_driver_template, link, + link->io.BasePort1, link->irq.AssignedIRQ); + if (!host) { - printk(KERN_INFO "qlogic_cs: no SCSI devices found\n"); + printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); goto out; } @@ -257,16 +327,17 @@ link->dev = &info->node; info->host = host; - scsi_add_host(host, NULL); /* XXX handle failure */ - scsi_scan_host(host); - out: link->state &= ~DEV_CONFIG_PENDING; return; cs_failed: cs_error(link->handle, last_fn, last_ret); - qlogic_release(link); + link->dev = NULL; + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + link->state &= ~DEV_CONFIG; return; } /* qlogic_config */ @@ -282,11 +353,13 @@ scsi_remove_host(info->host); link->dev = NULL; + free_irq(link->irq.AssignedIRQ, info->host); + pcmcia_release_configuration(link->handle); pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); - scsi_unregister(info->host); + scsi_host_put(info->host); link->state &= ~DEV_CONFIG; } @@ -340,7 +413,7 @@ static struct pcmcia_driver qlogic_cs_driver = { .owner = THIS_MODULE, .drv = { - .name = "qlogic_cs", + .name = "qlogic_cs", }, .attach = qlogic_attach, .detach = qlogic_detach, @@ -360,5 +433,8 @@ qlogic_detach(dev_list); } +MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); +MODULE_DESCRIPTION("Driver for the PCMCIA Qlogic FAS SCSI controllers"); +MODULE_LICENSE("GPL"); module_init(init_qlogic_cs); module_exit(exit_qlogic_cs); diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/qlogicfas.c Wed Mar 10 21:09:43 2004 @@ -27,7 +27,6 @@ SCSI driver cleanup and audit. This driver still needs work on the following - Non terminating hardware waits - - Support multiple cards at a time - Some layering violations with its pcmcia stub Redistributable under terms of the GNU General Public License @@ -39,92 +38,6 @@ are deemed to be part of the source code. */ -/*----------------------------------------------------------------*/ -/* Configuration */ - -/* Set the following to 2 to use normal interrupt (active high/totempole- - tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open - drain */ - -#define QL_INT_ACTIVE_HIGH 2 - -/* Set the following to 1 to enable the use of interrupts. Note that 0 tends - to be more stable, but slower (or ties up the system more) */ - -#define QL_USE_IRQ 1 - -/* Set the following to max out the speed of the PIO PseudoDMA transfers, - again, 0 tends to be slower, but more stable. */ - -#define QL_TURBO_PDMA 1 - -/* This should be 1 to enable parity detection */ - -#define QL_ENABLE_PARITY 1 - -/* This will reset all devices when the driver is initialized (during bootup). - The other linux drivers don't do this, but the DOS drivers do, and after - using DOS or some kind of crash or lockup this will bring things back - without requiring a cold boot. It does take some time to recover from a - reset, so it is slower, and I have seen timeouts so that devices weren't - recognized when this was set. */ - -#define QL_RESET_AT_START 0 - -/* crystal frequency in megahertz (for offset 5 and 9) - Please set this for your card. Most Qlogic cards are 40 Mhz. The - Control Concepts ISA (not VLB) is 24 Mhz */ - -#define XTALFREQ 40 - -/**********/ -/* DANGER! modify these at your own risk */ -/* SLOWCABLE can usually be reset to zero if you have a clean setup and - proper termination. The rest are for synchronous transfers and other - advanced features if your device can transfer faster than 5Mb/sec. - If you are really curious, email me for a quick howto until I have - something official */ -/**********/ - -/*****/ -/* config register 1 (offset 8) options */ -/* This needs to be set to 1 if your cabling is long or noisy */ -#define SLOWCABLE 1 - -/*****/ -/* offset 0xc */ -/* This will set fast (10Mhz) synchronous timing when set to 1 - For this to have an effect, FASTCLK must also be 1 */ -#define FASTSCSI 0 - -/* This when set to 1 will set a faster sync transfer rate */ -#define FASTCLK 0 /*(XTALFREQ>25?1:0)*/ - -/*****/ -/* offset 6 */ -/* This is the sync transfer divisor, XTALFREQ/X will be the maximum - achievable data rate (assuming the rest of the system is capable - and set properly) */ -#define SYNCXFRPD 5 /*(XTALFREQ/5)*/ - -/*****/ -/* offset 7 */ -/* This is the count of how many synchronous transfers can take place - i.e. how many reqs can occur before an ack is given. - The maximum value for this is 15, the upper bits can modify - REQ/ACK assertion and deassertion during synchronous transfers - If this is 0, the bus will only transfer asynchronously */ -#define SYNCOFFST 0 -/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles - of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will - cause the deassertion to be early by 1/2 clock. Bits 5&4 control - the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ - -/*----------------------------------------------------------------*/ -#ifdef PCMCIA -#undef QL_INT_ACTIVE_HIGH -#define QL_INT_ACTIVE_HIGH 0 -#endif #include #include /* to get disk capacity */ @@ -144,42 +57,21 @@ #include "scsi.h" #include "hosts.h" +#include "qlogicfas.h" /*----------------------------------------------------------------*/ -/* driver state info, local to driver */ -static int qbase; /* Port */ -static int qinitid; /* initiator ID */ -static int qabort; /* Flag to cause an abort */ -static int qlirq = -1; /* IRQ being used */ -static char qinfo[80]; /* description */ -static Scsi_Cmnd *qlcmd; /* current command being processed */ - -static int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */ -static int qlcfg6 = SYNCXFRPD; -static int qlcfg7 = SYNCOFFST; -static int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4); -static int qlcfg9 = ((XTALFREQ + 4) / 5); -static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); - -int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); +int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */ +int qlcfg6 = SYNCXFRPD; +int qlcfg7 = SYNCOFFST; +int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4); +int qlcfg9 = ((XTALFREQ + 4) / 5); +int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); -/*----------------------------------------------------------------*/ -/* The qlogic card uses two register maps - These macros select which one */ -#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) -#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) +static char qlogicfas_name[] = "qlogicfas"; -/* following is watchdog timeout in microseconds */ -#define WATCHDOG 5000000 +int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); /*----------------------------------------------------------------*/ -/* the following will set the monitor border color (useful to find - where something crashed or gets stuck at and as a simple profiler) */ - -#if 0 -#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} -#else -#define rtrc(i) {} -#endif /*----------------------------------------------------------------*/ /* local functions */ @@ -187,9 +79,10 @@ /* error recovery - reset everything */ -static void ql_zap(void) +static void ql_zap(qlogicfas_priv_t priv) { int x; + int qbase = priv->qbase; x = inb(qbase + 0xd); REG0; @@ -203,9 +96,10 @@ * Do a pseudo-dma tranfer */ -static int ql_pdma(int phase, char *request, int reqlen) +static int ql_pdma(qlogicfas_priv_t priv, int phase, char *request, int reqlen) { int j; + int qbase = priv->qbase; j = 0; if (phase & 1) { /* in */ #if QL_TURBO_PDMA @@ -287,23 +181,25 @@ * Wait for interrupt flag (polled - not real hardware interrupt) */ -static int ql_wai(void) +static int ql_wai(qlogicfas_priv_t priv) { int k; + int qbase = priv->qbase; unsigned long i; k = 0; i = jiffies + WATCHDOG; - while (time_before(jiffies, i) && !qabort && !((k = inb(qbase + 4)) & 0xe0)) { + while (time_before(jiffies, i) && !priv->qabort && + !((k = inb(qbase + 4)) & 0xe0)) { barrier(); cpu_relax(); } if (time_after_eq(jiffies, i)) return (DID_TIME_OUT); - if (qabort) - return (qabort == 1 ? DID_ABORT : DID_RESET); + if (priv->qabort) + return (priv->qabort == 1 ? DID_ABORT : DID_RESET); if (k & 0x60) - ql_zap(); + ql_zap(priv); if (k & 0x20) return (DID_PARITY); if (k & 0x40) @@ -318,9 +214,11 @@ static void ql_icmd(Scsi_Cmnd * cmd) { + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); + int qbase = priv->qbase; unsigned int i; - qabort = 0; + priv->qabort = 0; REG0; /* clearing of interrupts and the fifo is needed */ @@ -341,7 +239,7 @@ /* configurables */ outb(qlcfgc, qbase + 0xc); /* config: no reset interrupt, (initiator) bus id */ - outb(0x40 | qlcfg8 | qinitid, qbase + 8); + outb(0x40 | qlcfg8 | priv->qinitid, qbase + 8); outb(qlcfg7, qbase + 7); outb(qlcfg6, qbase + 6); /**/ outb(qlcfg5, qbase + 5); /* select timer */ @@ -352,7 +250,7 @@ for (i = 0; i < cmd->cmd_len; i++) outb(cmd->cmnd[i], qbase + 2); - qlcmd = cmd; + priv->qlcmd = cmd; outb(0x41, qbase + 3); /* select and send command */ } @@ -372,6 +270,8 @@ struct scatterlist *sglist; /* scatter-gather list pointer */ unsigned int sgcount; /* sg counter */ char *buf; + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); + int qbase = priv->qbase; rtrc(1) j = inb(qbase + 6); @@ -382,7 +282,7 @@ i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ if (i != 0x18) { printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i); - ql_zap(); + ql_zap(priv); return (DID_BAD_INTR << 16); } j &= 7; /* j = inb( qbase + 7 ) >> 5; */ @@ -395,7 +295,7 @@ if (j != 3 && j != 4) { printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb(qbase + 7) & 0x1f); - ql_zap(); + ql_zap(priv); return (DID_ERROR << 16); } result = DID_OK; @@ -413,18 +313,19 @@ /* PIO pseudo DMA to buffer or sglist */ REG1; if (!cmd->use_sg) - ql_pdma(phase, cmd->request_buffer, + ql_pdma(priv, phase, cmd->request_buffer, cmd->request_bufflen); else { sgcount = cmd->use_sg; sglist = cmd->request_buffer; while (sgcount--) { - if (qabort) { + if (priv->qabort) { REG0; - return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); + return ((priv->qabort == 1 ? + DID_ABORT : DID_RESET) << 16); } buf = page_address(sglist->page) + sglist->offset; - if (ql_pdma(phase, buf, sglist->length)) + if (ql_pdma(priv, phase, buf, sglist->length)) break; sglist++; } @@ -435,7 +336,7 @@ * Wait for irq (split into second state of irq handler * if this can take time) */ - if ((k = ql_wai())) + if ((k = ql_wai(priv))) return (k << 16); k = inb(qbase + 5); /* should be 0x10, bus service */ } @@ -446,11 +347,12 @@ k = jiffies + WATCHDOG; - while (time_before(jiffies, k) && !qabort && !(inb(qbase + 4) & 6)) + while (time_before(jiffies, k) && !priv->qabort && + !(inb(qbase + 4) & 6)) cpu_relax(); /* wait for status phase */ if (time_after_eq(jiffies, k)) { - ql_zap(); + ql_zap(priv); return (DID_TIME_OUT << 16); } @@ -458,11 +360,11 @@ while (inb(qbase + 5)) cpu_relax(); /* clear pending ints */ - if (qabort) - return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); + if (priv->qabort) + return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); outb(0x11, qbase + 3); /* get status and message */ - if ((k = ql_wai())) + if ((k = ql_wai(priv))) return (k << 16); i = inb(qbase + 5); /* get chip irq stat */ j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ @@ -479,7 +381,7 @@ } outb(0x12, qbase + 3); /* done, disconnect */ rtrc(1) - if ((k = ql_wai())) + if ((k = ql_wai(priv))) return (k << 16); /* @@ -487,21 +389,19 @@ */ i = inb(qbase + 5); /* should be bus service */ - while (!qabort && ((i & 0x20) != 0x20)) { + while (!priv->qabort && ((i & 0x20) != 0x20)) { barrier(); cpu_relax(); i |= inb(qbase + 5); } rtrc(0) - if (qabort) - return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); + if (priv->qabort) + return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); return (result << 16) | (message << 8) | (status & STATUS_MASK); } -#if QL_USE_IRQ - /* * Interrupt handler */ @@ -509,20 +409,23 @@ static void ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) { Scsi_Cmnd *icmd; + struct Scsi_Host *host = (struct Scsi_Host *)dev_id; + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(host->hostdata[0]); + int qbase = priv->qbase; REG0; if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ return; - if (qlcmd == NULL) { /* no command to process? */ + if (priv->qlcmd == NULL) { /* no command to process? */ int i; i = 16; while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ return; } - icmd = qlcmd; + icmd = priv->qlcmd; icmd->result = ql_pcmd(icmd); - qlcmd = NULL; + priv->qlcmd = NULL; /* * If result is CHECK CONDITION done calls qcommand to request * sense @@ -530,7 +433,7 @@ (icmd->scsi_done) (icmd); } -static irqreturn_t do_ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t do_ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; struct Scsi_Host *host = dev_id; @@ -541,17 +444,14 @@ return IRQ_HANDLED; } -#endif - -#if QL_USE_IRQ - /* * Queued command */ int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { - if (cmd->device->id == qinitid) { + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); + if (cmd->device->id == priv->qinitid) { cmd->result = DID_BAD_TARGET << 16; done(cmd); return 0; @@ -559,44 +459,27 @@ cmd->scsi_done = done; /* wait for the last command's interrupt to finish */ - while (qlcmd != NULL) { + while (priv->qlcmd != NULL) { barrier(); cpu_relax(); } ql_icmd(cmd); return 0; } -#else -int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) -{ - return 1; -} -#endif - -#ifdef PCMCIA - -/* - * Allow PCMCIA code to preset the port - * port should be 0 and irq to -1 respectively for autoprobing - */ - -void qlogicfas_preset(int port, int irq) -{ - qbase = port; - qlirq = irq; -} - -#endif +#ifndef PCMCIA /* * Look for qlogic card and init if found */ -struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host) +struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host, int qbase, + int qlirq) { int i, j; /* these are only used by IRQ detect */ int qltyp; /* type of chip */ + int qinitid; struct Scsi_Host *hreg; /* registered host structure */ + qlogicfas_priv_t priv; /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself * decodes the address - I check 230 first since MIDI cards are @@ -609,7 +492,7 @@ if (!qbase) { for (qbase = 0x230; qbase < 0x430; qbase += 0x100) { - if (!request_region(qbase, 0x10, "qlogicfas")) + if (!request_region(qbase, 0x10, qlogicfas_name)) continue; REG1; if (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) @@ -641,7 +524,6 @@ REG0; #endif -#if QL_USE_IRQ /* * IRQ probe - toggle pin and check request pending */ @@ -668,49 +550,98 @@ } else printk(KERN_INFO "Ql: Using preset IRQ %d\n", qlirq); - if (qlirq >= 0 && !request_irq(qlirq, do_ql_ihandl, 0, "qlogicfas", NULL)) - host->can_queue = 1; -#endif - hreg = scsi_register(host, 0); /* no host data */ + hreg = scsi_host_alloc(host, sizeof(struct qlogicfas_priv)); if (!hreg) goto err_release_mem; + priv = (qlogicfas_priv_t)&(hreg->hostdata[0]); hreg->io_port = qbase; hreg->n_io_port = 16; hreg->dma_channel = -1; if (qlirq != -1) hreg->irq = qlirq; + priv->qbase = qbase; + priv->qlirq = qlirq; + priv->qinitid = qinitid; + priv->shost = hreg; - sprintf(qinfo, + sprintf(priv->qinfo, "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d", qltyp, qbase, qlirq, QL_TURBO_PDMA); - host->name = qinfo; + host->name = qlogicfas_name; + + if (request_irq(qlirq, do_ql_ihandl, 0, qlogicfas_name, hreg)) + goto free_scsi_host; + + if (scsi_add_host(hreg, NULL)) + goto free_interrupt; + + scsi_scan_host(hreg); return hreg; +free_interrupt: + free_irq(qlirq, hreg); + +free_scsi_host: + scsi_host_put(hreg); + err_release_mem: release_region(qbase, 0x10); - if (host->can_queue) - free_irq(qlirq, do_ql_ihandl); - return NULL;; - + return NULL; } +#define MAX_QLOGICFAS 8 +static qlogicfas_priv_t cards; +static int iobase[MAX_QLOGICFAS]; +static int irq[MAX_QLOGICFAS] = { [0 ... MAX_QLOGICFAS-1] = -1 }; +MODULE_PARM(iobase, "1-" __MODULE_STRING(MAX_QLOGICFAS) "i"); +MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_QLOGICFAS) "i"); +MODULE_PARM_DESC(iobase, "I/O address"); +MODULE_PARM_DESC(irq, "IRQ"); + int __devinit qlogicfas_detect(Scsi_Host_Template *sht) { - return (__qlogicfas_detect(sht) != NULL); + struct Scsi_Host *shost; + qlogicfas_priv_t priv; + int i, + num = 0; + + for (i = 0; i < MAX_QLOGICFAS; i++) { + shost = __qlogicfas_detect(sht, iobase[num], irq[num]); + if (shost == NULL) { + /* no more devices */ + break; + } + priv = (qlogicfas_priv_t)&(shost->hostdata[0]); + priv->next = cards; + cards = priv; + num++; + } + + return num; } static int qlogicfas_release(struct Scsi_Host *shost) { - if (shost->irq) - free_irq(shost->irq, NULL); + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(shost->hostdata[0]); + int qbase = priv->qbase; + + if (shost->irq) { + REG1; + outb(0, qbase + 0xb); /* disable ints */ + + free_irq(shost->irq, shost); + } if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); + scsi_remove_host(shost); + scsi_host_put(shost); + return 0; } +#endif /* ifndef PCMCIA */ /* * Return bios parameters @@ -742,8 +673,9 @@ static int qlogicfas_abort(Scsi_Cmnd * cmd) { - qabort = 1; - ql_zap(); + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); + priv->qabort = 1; + ql_zap(priv); return SUCCESS; } @@ -755,8 +687,9 @@ int qlogicfas_bus_reset(Scsi_Cmnd * cmd) { - qabort = 2; - ql_zap(); + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(cmd->device->host->hostdata[0]); + priv->qabort = 2; + ql_zap(priv); return SUCCESS; } @@ -784,22 +717,17 @@ static const char *qlogicfas_info(struct Scsi_Host *host) { - return qinfo; + qlogicfas_priv_t priv = (qlogicfas_priv_t)&(host->hostdata[0]); + return priv->qinfo; } -MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); -MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers"); -MODULE_LICENSE("GPL"); - /* * The driver template is also needed for PCMCIA */ Scsi_Host_Template qlogicfas_driver_template = { .module = THIS_MODULE, - .name = "qlogicfas", - .proc_name = "qlogicfas", - .detect = qlogicfas_detect, - .release = qlogicfas_release, + .name = qlogicfas_name, + .proc_name = qlogicfas_name, .info = qlogicfas_info, .queuecommand = qlogicfas_queuecommand, .eh_abort_handler = qlogicfas_abort, @@ -807,7 +735,7 @@ .eh_device_reset_handler= qlogicfas_device_reset, .eh_host_reset_handler = qlogicfas_host_reset, .bios_param = qlogicfas_biosparam, - .can_queue = 0, + .can_queue = 1, .this_id = -1, .sg_tablesize = SG_ALL, .cmd_per_lun = 1, @@ -815,6 +743,28 @@ }; #ifndef PCMCIA -#define driver_template qlogicfas_driver_template -#include "scsi_module.c" -#endif +static __init int qlogicfas_init(void) +{ + if (!qlogicfas_detect(&qlogicfas_driver_template)) { + /* no cards found */ + return -ENODEV; + } + + return 0; +} + +static __exit void qlogicfas_exit(void) +{ + qlogicfas_priv_t priv; + + for (priv = cards; priv != NULL; priv = priv->next) + qlogicfas_release(priv->shost); +} + +MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); +MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers"); +MODULE_LICENSE("GPL"); +module_init(qlogicfas_init); +module_exit(qlogicfas_exit); +#endif /* ifndef PCMCIA */ + diff -Nru a/drivers/scsi/qlogicfas.h b/drivers/scsi/qlogicfas.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/qlogicfas.h Wed Mar 10 21:09:43 2004 @@ -0,0 +1,124 @@ +/* to be used by qlogicfas and qlogic_cs */ +#ifndef __QLOGICFAS_H +#define __QLOGICFAS_H + +/*----------------------------------------------------------------*/ +/* Configuration */ + +/* Set the following to 2 to use normal interrupt (active high/totempole- + tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open + drain */ + +#define QL_INT_ACTIVE_HIGH 2 + +/* Set the following to max out the speed of the PIO PseudoDMA transfers, + again, 0 tends to be slower, but more stable. */ + +#define QL_TURBO_PDMA 1 + +/* This should be 1 to enable parity detection */ + +#define QL_ENABLE_PARITY 1 + +/* This will reset all devices when the driver is initialized (during bootup). + The other linux drivers don't do this, but the DOS drivers do, and after + using DOS or some kind of crash or lockup this will bring things back + without requiring a cold boot. It does take some time to recover from a + reset, so it is slower, and I have seen timeouts so that devices weren't + recognized when this was set. */ + +#define QL_RESET_AT_START 0 + +/* crystal frequency in megahertz (for offset 5 and 9) + Please set this for your card. Most Qlogic cards are 40 Mhz. The + Control Concepts ISA (not VLB) is 24 Mhz */ + +#define XTALFREQ 40 + +/**********/ +/* DANGER! modify these at your own risk */ +/* SLOWCABLE can usually be reset to zero if you have a clean setup and + proper termination. The rest are for synchronous transfers and other + advanced features if your device can transfer faster than 5Mb/sec. + If you are really curious, email me for a quick howto until I have + something official */ +/**********/ + +/*****/ +/* config register 1 (offset 8) options */ +/* This needs to be set to 1 if your cabling is long or noisy */ +#define SLOWCABLE 1 + +/*****/ +/* offset 0xc */ +/* This will set fast (10Mhz) synchronous timing when set to 1 + For this to have an effect, FASTCLK must also be 1 */ +#define FASTSCSI 0 + +/* This when set to 1 will set a faster sync transfer rate */ +#define FASTCLK 0 /*(XTALFREQ>25?1:0)*/ + +/*****/ +/* offset 6 */ +/* This is the sync transfer divisor, XTALFREQ/X will be the maximum + achievable data rate (assuming the rest of the system is capable + and set properly) */ +#define SYNCXFRPD 5 /*(XTALFREQ/5)*/ + +/*****/ +/* offset 7 */ +/* This is the count of how many synchronous transfers can take place + i.e. how many reqs can occur before an ack is given. + The maximum value for this is 15, the upper bits can modify + REQ/ACK assertion and deassertion during synchronous transfers + If this is 0, the bus will only transfer asynchronously */ +#define SYNCOFFST 0 +/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles + of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will + cause the deassertion to be early by 1/2 clock. Bits 5&4 control + the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ + +/*----------------------------------------------------------------*/ +#ifdef PCMCIA +#undef QL_INT_ACTIVE_HIGH +#define QL_INT_ACTIVE_HIGH 0 +#endif + +struct qlogicfas_priv; +typedef struct qlogicfas_priv *qlogicfas_priv_t; +struct qlogicfas_priv { + int qbase; /* Port */ + int qinitid; /* initiator ID */ + int qabort; /* Flag to cause an abort */ + int qlirq; /* IRQ being used */ + char qinfo[80]; /* description */ + Scsi_Cmnd *qlcmd; /* current command being processed */ + struct Scsi_Host *shost; /* pointer back to host */ + qlogicfas_priv_t next; /* next private struct */ +}; + +extern int qlcfg5; +extern int qlcfg6; +extern int qlcfg7; +extern int qlcfg8; +extern int qlcfg9; +extern int qlcfgc; + +/* The qlogic card uses two register maps - These macros select which one */ +#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) +#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) + +/* following is watchdog timeout in microseconds */ +#define WATCHDOG 5000000 + +/*----------------------------------------------------------------*/ +/* the following will set the monitor border color (useful to find + where something crashed or gets stuck at and as a simple profiler) */ + +#if 0 +#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} +#else +#define rtrc(i) {} +#endif +#endif /* __QLOGICFAS_H */ + diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/scsi.c Wed Mar 10 21:09:42 2004 @@ -104,7 +104,7 @@ "Communications ", "Unknown ", "Unknown ", - "Unknown ", + "RAID ", "Enclosure ", }; diff -Nru a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c --- a/drivers/scsi/scsi_devinfo.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/scsi_devinfo.c Wed Mar 10 21:09:42 2004 @@ -94,95 +94,93 @@ * The following causes a failed REQUEST SENSE on lun 1 for * seagate controller, which causes SCSI code to reset bus. */ - {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, + {"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */ + {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ + {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ + {"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN}, /* locks up */ + {"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all lun */ + {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* locks up */ + {"NEC", "D3856", "0009", BLIST_NOLUN}, {"QUANTUM", "LPS525S", "3110", BLIST_NOLUN}, /* locks up */ {"QUANTUM", "PD1225S", "3110", BLIST_NOLUN}, /* locks up */ {"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN}, /* locks up */ - {"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN}, /* locks up */ + {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ - {"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */ - {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ - {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ + {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */ - {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* locks up */ - {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ - {"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all lun */ - {"NEC", "D3856", "0009", BLIST_NOLUN}, /* * Other types of devices that have special flags. */ - {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, - {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, - {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, - {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, - {"INSITE", "I325VM", NULL, BLIST_KEY}, - {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, - {"MICROP", "4110", NULL, BLIST_NOTQ}, - {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, - {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, + {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, + {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, {"CANON", "IPUBJD", NULL, BLIST_SPARSELUN}, - {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN}, - {"DEC", "HSG80", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, + {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ + {"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */ + {"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */ {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN}, {"COMPAQ", "CR3500", NULL, BLIST_FORCELUN}, - {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, - {"TOSHIBA", "CDROM", NULL, BLIST_ISROM}, - {"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM}, - {"MegaRAID", "LD", NULL, BLIST_FORCELUN}, - {"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, storage on LUN 0 */ - {"DGC", "DISK", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, no storage on LUN 0 */ + {"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, + {"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, + {"COMPAQ", "HSV110", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, + {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, + {"DEC", "HSG80", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, {"DELL", "PV660F", NULL, BLIST_SPARSELUN}, {"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN}, {"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */ {"DELL", "PV530F", NULL, BLIST_SPARSELUN}, + {"DELL", "PERCRAID", NULL, BLIST_FORCELUN}, + {"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, storage on LUN 0 */ + {"DGC", "DISK", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, no storage on LUN 0 */ {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, + {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, + {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN}, + {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ {"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */ - {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ - {"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */ - {"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */ - {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN}, - {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN}, - {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ - {"DELL", "PERCRAID", NULL, BLIST_FORCELUN}, {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, - {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, - {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, - {"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, - {"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, - {"COMPAQ", "HSV110", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, {"HP", "HSV100", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD}, {"HP", "C1557A", NULL, BLIST_FORCELUN}, {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, - {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SUN", "T300", "*", BLIST_SPARSELUN}, - {"SUN", "T4", "*", BLIST_SPARSELUN}, + {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, + {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, + {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, + {"INSITE", "I325VM", NULL, BLIST_KEY}, + {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, + {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"MegaRAID", "LD", NULL, BLIST_FORCELUN}, + {"MICROP", "4110", NULL, BLIST_NOTQ}, + {"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN}, + {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, {"SGI", "RAID3", "*", BLIST_SPARSELUN}, {"SGI", "RAID5", "*", BLIST_SPARSELUN}, {"SGI", "TP9100", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SGI", "TP9300", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SGI", "TP9400", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SGI", "TP9500", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, + {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ + {"SUN", "T300", "*", BLIST_SPARSELUN}, + {"SUN", "T4", "*", BLIST_SPARSELUN}, + {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, + {"TOSHIBA", "CDROM", NULL, BLIST_ISROM}, + {"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM}, {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN}, + {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN}, { NULL, NULL, NULL, 0 }, }; diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/scsi_error.c Wed Mar 10 21:09:42 2004 @@ -37,6 +37,8 @@ #define SENSE_TIMEOUT (10*HZ) #endif +#define START_UNIT_TIMEOUT (30*HZ) + /* * These should *probably* be handled by the host itself. * Since it is allowed to sleep, it probably should. @@ -282,6 +284,15 @@ (scmd->sense_buffer[13] == 0x01)) { return NEEDS_RETRY; } + /* + * if the device is not started, we need to wake + * the error handler to start the motor + */ + if (scmd->device->allow_restart && + (scmd->sense_buffer[12] == 0x04) && + (scmd->sense_buffer[13] == 0x02)) { + return FAILED; + } return SUCCESS; /* these three are not supported */ @@ -829,6 +840,105 @@ } /** + * scsi_eh_try_stu - Send START_UNIT to device. + * @scmd: Scsi cmd to send START_UNIT + * + * Return value: + * 0 - Device is ready. 1 - Device NOT ready. + **/ +static int scsi_eh_try_stu(struct scsi_cmnd *scmd) +{ + static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0}; + int rtn; + + if (!scmd->device->allow_restart) + return 1; + + memcpy(scmd->cmnd, stu_command, sizeof(stu_command)); + + /* + * zero the sense buffer. the scsi spec mandates that any + * untransferred sense data should be interpreted as being zero. + */ + memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); + + scmd->request_buffer = NULL; + scmd->request_bufflen = 0; + scmd->use_sg = 0; + scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); + scmd->underflow = 0; + scmd->sc_data_direction = DMA_NONE; + + rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT); + + /* + * when we eventually call scsi_finish, we really wish to complete + * the original request, so let's restore the original data. (db) + */ + scsi_setup_cmd_retry(scmd); + + /* + * hey, we are done. let's look to see what happened. + */ + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n", + __FUNCTION__, scmd, rtn)); + if (rtn == SUCCESS) + return 0; + return 1; +} + + /** + * scsi_eh_stu - send START_UNIT if needed + * @shost: scsi host being recovered. + * @eh_done_q: list_head for processed commands. + * + * Notes: + * If commands are failing due to not ready, initializing command required, + * try revalidating the device, which will end up sending a start unit. + **/ +static int scsi_eh_stu(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q) +{ + struct list_head *lh, *lh_sf; + struct scsi_cmnd *scmd, *stu_scmd; + struct scsi_device *sdev; + + shost_for_each_device(sdev, shost) { + stu_scmd = NULL; + list_for_each_entry(scmd, work_q, eh_entry) + if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) && + scsi_check_sense(scmd) == FAILED ) { + stu_scmd = scmd; + break; + } + + if (!stu_scmd) + continue; + + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending START_UNIT to sdev:" + " 0x%p\n", current->comm, sdev)); + + if (!scsi_eh_try_stu(stu_scmd)) { + if (!sdev->online || !scsi_eh_tur(stu_scmd)) { + list_for_each_safe(lh, lh_sf, work_q) { + scmd = list_entry(lh, struct scsi_cmnd, eh_entry); + if (scmd->device == sdev) + scsi_eh_finish_cmd(scmd, done_q); + } + } + } else { + SCSI_LOG_ERROR_RECOVERY(3, + printk("%s: START_UNIT failed to sdev:" + " 0x%p\n", current->comm, sdev)); + } + } + + return list_empty(work_q); +} + + +/** * scsi_eh_bus_device_reset - send bdr if needed * @shost: scsi host being recovered. * @eh_done_q: list_head for processed commands. @@ -1033,7 +1143,9 @@ if (rtn == SUCCESS) { list_for_each_safe(lh, lh_sf, work_q) { scmd = list_entry(lh, struct scsi_cmnd, eh_entry); - if (!scmd->device->online || !scsi_eh_tur(scmd)) + if (!scmd->device->online || + (!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) || + !scsi_eh_tur(scmd)) scsi_eh_finish_cmd(scmd, done_q); } } else { @@ -1181,6 +1293,8 @@ */ case DID_SOFT_ERROR: goto maybe_retry; + case DID_IMM_RETRY: + return NEEDS_RETRY; case DID_ERROR: if (msg_byte(scmd->result) == COMMAND_COMPLETE && @@ -1401,10 +1515,11 @@ struct list_head *work_q, struct list_head *done_q) { - if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) - if (!scsi_eh_bus_reset(shost, work_q, done_q)) - if (!scsi_eh_host_reset(work_q, done_q)) - scsi_eh_offline_sdevs(work_q, done_q); + if (!scsi_eh_stu(shost, work_q, done_q)) + if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) + if (!scsi_eh_bus_reset(shost, work_q, done_q)) + if (!scsi_eh_host_reset(work_q, done_q)) + scsi_eh_offline_sdevs(work_q, done_q); } /** diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/scsi_lib.c Wed Mar 10 21:09:42 2004 @@ -24,7 +24,7 @@ #include "scsi_logging.h" -#define SG_MEMPOOL_NR 5 +#define SG_MEMPOOL_NR (sizeof(scsi_sg_pools)/sizeof(struct scsi_host_sg_pool)) #define SG_MEMPOOL_SIZE 32 struct scsi_host_sg_pool { @@ -34,9 +34,27 @@ mempool_t *pool; }; +#if (SCSI_MAX_PHYS_SEGMENTS < 32) +#error SCSI_MAX_PHYS_SEGMENTS is too small +#endif + #define SP(x) { x, "sgpool-" #x } -struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR] = { - SP(8), SP(16), SP(32), SP(64), SP(MAX_PHYS_SEGMENTS) +struct scsi_host_sg_pool scsi_sg_pools[] = { + SP(8), + SP(16), + SP(32), +#if (SCSI_MAX_PHYS_SEGMENTS > 32) + SP(64), +#if (SCSI_MAX_PHYS_SEGMENTS > 64) + SP(128), +#if (SCSI_MAX_PHYS_SEGMENTS > 128) + SP(256), +#if (SCSI_MAX_PHYS_SEGMENTS > 256) +#error SCSI_MAX_PHYS_SEGMENTS is too large +#endif +#endif +#endif +#endif }; #undef SP @@ -558,12 +576,21 @@ case 17 ... 32: cmd->sglist_len = 2; break; +#if (SCSI_MAX_PHYS_SEGMENTS > 32) case 33 ... 64: cmd->sglist_len = 3; break; - case 65 ... MAX_PHYS_SEGMENTS: +#if (SCSI_MAX_PHYS_SEGMENTS > 64) + case 65 ... 128: cmd->sglist_len = 4; break; +#if (SCSI_MAX_PHYS_SEGMENTS > 128) + case 129 ... 256: + cmd->sglist_len = 5; + break; +#endif +#endif +#endif default: return NULL; } @@ -917,6 +944,7 @@ req->current_nr_sectors); /* release the command and kill it */ + scsi_release_buffers(cmd); scsi_put_command(cmd); return BLKPREP_KILL; } @@ -1285,7 +1313,7 @@ blk_queue_prep_rq(q, scsi_prep_fn); blk_queue_max_hw_segments(q, shost->sg_tablesize); - blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); + blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); blk_queue_max_sectors(q, shost->max_sectors); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); diff -Nru a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h --- a/drivers/scsi/scsi_priv.h Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/scsi_priv.h Wed Mar 10 21:09:43 2004 @@ -155,6 +155,7 @@ extern int scsi_sysfs_add_host(struct Scsi_Host *); extern int scsi_sysfs_register(void); extern void scsi_sysfs_unregister(void); +extern struct scsi_transport_template blank_transport_template; extern struct class sdev_class; extern struct bus_type scsi_bus_type; diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/scsi_scan.c Wed Mar 10 21:09:43 2004 @@ -35,6 +35,7 @@ #include #include #include +#include #include "scsi.h" #include "scsi_priv.h" @@ -192,7 +193,7 @@ struct scsi_device *sdev, *device; unsigned long flags; - sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC); + sdev = kmalloc(sizeof(*sdev) + shost->transportt->size, GFP_ATOMIC); if (!sdev) goto out; @@ -237,6 +238,11 @@ goto out_free_queue; } + if (shost->transportt->setup) { + if (shost->transportt->setup(sdev)) + goto out_cleanup_slave; + } + if (get_device(&sdev->host->shost_gendev)) { device_initialize(&sdev->sdev_gendev); @@ -253,8 +259,15 @@ snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); + + class_device_initialize(&sdev->transport_classdev); + sdev->transport_classdev.dev = &sdev->sdev_gendev; + sdev->transport_classdev.class = sdev->host->transportt->class; + snprintf(sdev->transport_classdev.class_id, BUS_ID_SIZE, + "%d:%d:%d:%d", sdev->host->host_no, + sdev->channel, sdev->id, sdev->lun); } else - goto out_cleanup_slave; + goto out_cleanup_transport; /* * If there are any same target siblings, add this to the @@ -283,6 +296,9 @@ spin_unlock_irqrestore(shost->host_lock, flags); return sdev; +out_cleanup_transport: + if (shost->transportt->cleanup) + shost->transportt->cleanup(sdev); out_cleanup_slave: if (shost->hostt->slave_destroy) shost->hostt->slave_destroy(sdev); @@ -744,6 +760,8 @@ } else { if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); + if (sdev->host->transportt->cleanup) + sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); } out: @@ -1300,5 +1318,7 @@ if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); + if (sdev->host->transportt->cleanup) + sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); } diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Wed Mar 10 21:09:42 2004 +++ b/drivers/scsi/scsi_sysfs.c Wed Mar 10 21:09:42 2004 @@ -13,6 +13,7 @@ #include #include +#include #include "scsi.h" #include "scsi_priv.h" @@ -58,21 +59,24 @@ * shost_show_function: macro to create an attr function that can be used to * show a non-bit field. */ -#define shost_show_function(field, format_string) \ +#define shost_show_function(name, field, format_string) \ static ssize_t \ -show_##field (struct class_device *class_dev, char *buf) \ +show_##name (struct class_device *class_dev, char *buf) \ { \ struct Scsi_Host *shost = class_to_shost(class_dev); \ - return snprintf (buf, 20, format_string, shost->field); \ + return snprintf (buf, 20, format_string, shost->field); \ } /* * shost_rd_attr: macro to create a function and attribute variable for a * read only field. */ -#define shost_rd_attr(field, format_string) \ - shost_show_function(field, format_string) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) +#define shost_rd_attr2(name, field, format_string) \ + shost_show_function(name, field, format_string) \ +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + +#define shost_rd_attr(field, format_string) \ +shost_rd_attr2(field, field, format_string) /* * Create the actual show/store functions and data structures. @@ -96,6 +100,7 @@ shost_rd_attr(cmd_per_lun, "%hd\n"); shost_rd_attr(sg_tablesize, "%hu\n"); shost_rd_attr(unchecked_isa_dma, "%d\n"); +shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { &class_device_attr_unique_id, @@ -103,6 +108,7 @@ &class_device_attr_cmd_per_lun, &class_device_attr_sg_tablesize, &class_device_attr_unchecked_isa_dma, + &class_device_attr_proc_name, &class_device_attr_scan, NULL }; @@ -344,6 +350,7 @@ **/ int scsi_sysfs_add_sdev(struct scsi_device *sdev) { + struct class_device_attribute **attrs; int error = -EINVAL, i; if (sdev->sdev_state != SDEV_CREATED) @@ -363,6 +370,12 @@ goto clean_device; } + if (sdev->transport_classdev.class) { + error = class_device_add(&sdev->transport_classdev); + if (error) + goto clean_device2; + } + get_device(&sdev->sdev_gendev); if (sdev->host->hostt->sdev_attrs) { @@ -388,10 +401,24 @@ } } + if (sdev->transport_classdev.class) { + attrs = sdev->host->transportt->attrs; + for (i = 0; attrs[i]; i++) { + error = class_device_create_file(&sdev->transport_classdev, + attrs[i]); + if (error) { + scsi_remove_device(sdev); + goto out; + } + } + } + out: return error; -clean_device: + clean_device2: + class_device_del(&sdev->sdev_classdev); + clean_device: sdev->sdev_state = SDEV_CANCEL; device_del(&sdev->sdev_gendev); @@ -409,9 +436,12 @@ if (sdev->sdev_state == SDEV_RUNNING || sdev->sdev_state == SDEV_CANCEL) { sdev->sdev_state = SDEV_DEL; class_device_unregister(&sdev->sdev_classdev); + class_device_unregister(&sdev->transport_classdev); device_del(&sdev->sdev_gendev); if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); + if (sdev->host->transportt->cleanup) + sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); } } @@ -498,3 +528,7 @@ return 0; } + +/* A blank transport template that is used in drivers that don't + * yet implement Transport Attributes */ +struct scsi_transport_template blank_transport_template = { 0, }; diff -Nru a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/scsi_transport_fc.c Wed Mar 10 21:09:43 2004 @@ -0,0 +1,104 @@ +/* + * FiberChannel transport specific attributes exported to sysfs. + * + * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + +static void transport_class_release(struct class_device *class_dev); + +struct class fc_transport_class = { + .name = "fc_transport", + .release = transport_class_release, +}; + +static __init int fc_transport_init(void) +{ + return class_register(&fc_transport_class); +} + +static void __exit fc_transport_exit(void) +{ + class_unregister(&fc_transport_class); +} + +static int fc_setup_transport_attrs(struct scsi_device *sdev) +{ + /* FIXME: Callback into the driver */ + fc_node_name(sdev) = -1; + fc_port_name(sdev) = -1; + fc_port_id(sdev) = -1; + + return 0; +} + +static void transport_class_release(struct class_device *class_dev) +{ + struct scsi_device *sdev = transport_class_to_sdev(class_dev); + put_device(&sdev->sdev_gendev); +} + +#define fc_transport_show_function(field, format_string, cast) \ +static ssize_t \ +show_fc_transport_##field (struct class_device *cdev, char *buf) \ +{ \ + struct scsi_device *sdev = transport_class_to_sdev(cdev); \ + struct fc_transport_attrs *tp; \ + tp = (struct fc_transport_attrs *)&sdev->transport_data; \ + return snprintf(buf, 20, format_string, cast tp->field); \ +} + +#define fc_transport_rd_attr(field, format_string) \ + fc_transport_show_function(field, format_string, ) \ +static CLASS_DEVICE_ATTR( field, S_IRUGO, show_fc_transport_##field, NULL) + +#define fc_transport_rd_attr_cast(field, format_string, cast) \ + fc_transport_show_function(field, format_string, (cast)) \ +static CLASS_DEVICE_ATTR( field, S_IRUGO, show_fc_transport_##field, NULL) + +/* the FiberChannel Tranport Attributes: */ +fc_transport_rd_attr_cast(node_name, "0x%llx\n", unsigned long long); +fc_transport_rd_attr_cast(port_name, "0x%llx\n", unsigned long long); +fc_transport_rd_attr(port_id, "0x%06x\n"); + +struct class_device_attribute *fc_transport_attrs[] = { + &class_device_attr_node_name, + &class_device_attr_port_name, + &class_device_attr_port_id, + NULL +}; + +struct scsi_transport_template fc_transport_template = { + .attrs = fc_transport_attrs, + .class = &fc_transport_class, + .setup = &fc_setup_transport_attrs, + .cleanup = NULL, + .size = sizeof(struct fc_transport_attrs) - sizeof(unsigned long), +}; +EXPORT_SYMBOL(fc_transport_template); + +MODULE_AUTHOR("Martin Hicks"); +MODULE_DESCRIPTION("FC Transport Attributes"); +MODULE_LICENSE("GPL"); + +module_init(fc_transport_init); +module_exit(fc_transport_exit); diff -Nru a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/scsi_transport_spi.c Wed Mar 10 21:09:43 2004 @@ -0,0 +1,302 @@ +/* + * Parallel SCSI (SPI) transport specific attributes exported to sysfs. + * + * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + +static void transport_class_release(struct class_device *class_dev); + +#define SPI_NUM_ATTRS 10 /* increase this if you add attributes */ + +struct spi_internal { + struct scsi_transport_template t; + struct spi_function_template *f; + /* The actual attributes */ + struct class_device_attribute private_attrs[SPI_NUM_ATTRS]; + /* The array of null terminated pointers to attributes + * needed by scsi_sysfs.c */ + struct class_device_attribute *attrs[SPI_NUM_ATTRS + 1]; +}; + +#define to_spi_internal(tmpl) container_of(tmpl, struct spi_internal, t) + +static const char *const ppr_to_ns[] = { + /* The PPR values 0-6 are reserved, fill them in when + * the committee defines them */ + NULL, /* 0x00 */ + NULL, /* 0x01 */ + NULL, /* 0x02 */ + NULL, /* 0x03 */ + NULL, /* 0x04 */ + NULL, /* 0x05 */ + NULL, /* 0x06 */ + "3.125", /* 0x07 */ + "6.25", /* 0x08 */ + "12.5", /* 0x09 */ + "25", /* 0x0a */ + "30.3", /* 0x0b */ + "50", /* 0x0c */ +}; +/* The PPR values at which you calculate the period in ns by multiplying + * by 4 */ +#define SPI_STATIC_PPR 0x0c + +struct class spi_transport_class = { + .name = "spi_transport", + .release = transport_class_release, +}; + +static __init int spi_transport_init(void) +{ + return class_register(&spi_transport_class); +} + +static void __exit spi_transport_exit(void) +{ + class_unregister(&spi_transport_class); +} + +static int spi_setup_transport_attrs(struct scsi_device *sdev) +{ + spi_period(sdev) = -1; /* illegal value */ + spi_offset(sdev) = 0; /* async */ + spi_width(sdev) = 0; /* narrow */ + spi_iu(sdev) = 0; /* no IU */ + spi_dt(sdev) = 0; /* ST */ + spi_qas(sdev) = 0; + spi_wr_flow(sdev) = 0; + spi_rd_strm(sdev) = 0; + spi_rti(sdev) = 0; + spi_pcomp_en(sdev) = 0; + + return 0; +} + +static void transport_class_release(struct class_device *class_dev) +{ + struct scsi_device *sdev = transport_class_to_sdev(class_dev); + put_device(&sdev->sdev_gendev); +} + +#define spi_transport_show_function(field, format_string) \ + \ +static ssize_t \ +show_spi_transport_##field(struct class_device *cdev, char *buf) \ +{ \ + struct scsi_device *sdev = transport_class_to_sdev(cdev); \ + struct spi_transport_attrs *tp; \ + struct spi_internal *i = to_spi_internal(sdev->host->transportt); \ + tp = (struct spi_transport_attrs *)&sdev->transport_data; \ + if(i->f->get_##field) \ + i->f->get_##field(sdev); \ + return snprintf(buf, 20, format_string, tp->field); \ +} + +#define spi_transport_store_function(field, format_string) \ +static ssize_t \ +store_spi_transport_##field(struct class_device *cdev, const char *buf, \ + size_t count) \ +{ \ + int val; \ + struct scsi_device *sdev = transport_class_to_sdev(cdev); \ + struct spi_internal *i = to_spi_internal(sdev->host->transportt); \ + \ + val = simple_strtoul(buf, NULL, 0); \ + i->f->set_##field(sdev, val); \ + return count; \ +} + +#define spi_transport_rd_attr(field, format_string) \ + spi_transport_show_function(field, format_string) \ + spi_transport_store_function(field, format_string) \ +static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ + show_spi_transport_##field, \ + store_spi_transport_##field) + +/* The Parallel SCSI Tranport Attributes: */ +spi_transport_rd_attr(offset, "%d\n"); +spi_transport_rd_attr(width, "%d\n"); +spi_transport_rd_attr(iu, "%d\n"); +spi_transport_rd_attr(dt, "%d\n"); +spi_transport_rd_attr(qas, "%d\n"); +spi_transport_rd_attr(wr_flow, "%d\n"); +spi_transport_rd_attr(rd_strm, "%d\n"); +spi_transport_rd_attr(rti, "%d\n"); +spi_transport_rd_attr(pcomp_en, "%d\n"); + +/* Translate the period into ns according to the current spec + * for SDTR/PPR messages */ +static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) + +{ + struct scsi_device *sdev = transport_class_to_sdev(cdev); + struct spi_transport_attrs *tp; + const char *str; + struct spi_internal *i = to_spi_internal(sdev->host->transportt); + + tp = (struct spi_transport_attrs *)&sdev->transport_data; + + if(i->f->get_period) + i->f->get_period(sdev); + + switch(tp->period) { + + case 0x07 ... SPI_STATIC_PPR: + str = ppr_to_ns[tp->period]; + if(!str) + str = "reserved"; + break; + + + case (SPI_STATIC_PPR+1) ... 0xff: + return sprintf(buf, "%d\n", tp->period * 4); + + default: + str = "unknown"; + } + return sprintf(buf, "%s\n", str); +} + +static ssize_t +store_spi_transport_period(struct class_device *cdev, const char *buf, + size_t count) +{ + struct scsi_device *sdev = transport_class_to_sdev(cdev); + struct spi_internal *i = to_spi_internal(sdev->host->transportt); + int j, period = -1; + + for(j = 0; j < SPI_STATIC_PPR; j++) { + int len; + + if(ppr_to_ns[j] == NULL) + continue; + + len = strlen(ppr_to_ns[j]); + + if(strncmp(ppr_to_ns[j], buf, len) != 0) + continue; + + if(buf[len] != '\n') + continue; + + period = j; + break; + } + + if(period == -1) { + int val = simple_strtoul(buf, NULL, 0); + + + if(val >= (SPI_STATIC_PPR + 1)*4) + period = val/4; + + } + + if(period == -1 || period > 0xff) + return -EINVAL; + + i->f->set_period(sdev, period); + + return count; +} + + + + + + +static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, + show_spi_transport_period, + store_spi_transport_period); + + +struct scsi_transport_template spi_transport_template = { + .class = &spi_transport_class, + .setup = &spi_setup_transport_attrs, + .cleanup = NULL, + .size = sizeof(struct spi_transport_attrs) - sizeof(unsigned long), +}; + +#define SETUP_ATTRIBUTE(field) \ + i->private_attrs[count] = class_device_attr_##field; \ + if(!i->f->set_##field) { \ + i->private_attrs[count].attr.mode = S_IRUGO; \ + i->private_attrs[count].store = NULL; \ + } \ + i->attrs[count] = &i->private_attrs[count]; \ + count++ + +struct scsi_transport_template * +spi_attach_transport(struct spi_function_template *ft) +{ + struct spi_internal *i = kmalloc(sizeof(struct spi_internal), + GFP_KERNEL); + int count = 0; + if(!i) + return NULL; + + memset(i, 0, sizeof(struct spi_internal)); + + + i->t.attrs = &i->attrs[0]; + i->t.class = &spi_transport_class; + i->t.setup = &spi_setup_transport_attrs; + i->t.size = sizeof(struct spi_transport_attrs) - sizeof(unsigned long); + i->f = ft; + + SETUP_ATTRIBUTE(period); + SETUP_ATTRIBUTE(offset); + SETUP_ATTRIBUTE(width); + SETUP_ATTRIBUTE(iu); + SETUP_ATTRIBUTE(dt); + SETUP_ATTRIBUTE(qas); + SETUP_ATTRIBUTE(wr_flow); + SETUP_ATTRIBUTE(rd_strm); + SETUP_ATTRIBUTE(rti); + SETUP_ATTRIBUTE(pcomp_en); + + /* if you add an attribute but forget to increase SPI_NUM_ATTRS + * this bug will trigger */ + BUG_ON(count != SPI_NUM_ATTRS); + + i->attrs[count] = NULL; + + return &i->t; +} +EXPORT_SYMBOL(spi_attach_transport); + +void spi_release_transport(struct scsi_transport_template *t) +{ + struct spi_internal *i = to_spi_internal(t); + + kfree(i); +} +EXPORT_SYMBOL(spi_release_transport); + + +MODULE_AUTHOR("Martin Hicks"); +MODULE_DESCRIPTION("SPI Transport Attributes"); +MODULE_LICENSE("GPL"); + +module_init(spi_transport_init); +module_exit(spi_transport_exit); diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/sd.c Wed Mar 10 21:09:43 2004 @@ -19,6 +19,9 @@ * not being read in sd_open. Fix problem where removable media * could be ejected after sd_open. * - Douglas Gilbert cleanup for lk 2.5.x + * - Badari Pulavarty , Matthew Wilcox + * , Kurt Garloff : + * Support 32k/1M disks. * * Logging policy (needs CONFIG_SCSI_LOGGING defined): * - setting up transfer: SCSI_LOG_HLQUEUE levels 1 and 2 @@ -61,7 +64,7 @@ * Remaining dev_t-handling stuff */ #define SD_MAJORS 16 -#define SD_DISKS (SD_MAJORS << 4) +#define SD_DISKS 32768 /* anything between 256 and 262144 */ /* * Time out in seconds for disks and Magneto-opticals (which are slower). @@ -121,6 +124,20 @@ .init_command = sd_init_command, }; +/* Device no to disk mapping: + * + * major disc2 disc p1 + * |............|.............|....|....| <- dev_t + * 31 20 19 8 7 4 3 0 + * + * Inside a major, we have 16k disks, however mapped non- + * contiguously. The first 16 disks are for major0, the next + * ones with major1, ... Disk 256 is for major0 again, disk 272 + * for major1, ... + * As we stay compatible with our numbering scheme, we can reuse + * the well-know SCSI majors 8, 65--71, 136--143. + */ + static int sd_major(int major_idx) { switch (major_idx) { @@ -136,6 +153,14 @@ } } +static unsigned int make_sd_dev(unsigned int sd_nr, unsigned int part) +{ + return (part & 0xf) | ((sd_nr & 0xf) << 4) | + (sd_major((sd_nr & 0xf0) >> 4) << 20) | (sd_nr & 0xfff00); +} + +/* reverse mapping dev -> (sd_nr, part) not currently needed */ + #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,kobj); static inline struct scsi_disk *scsi_disk(struct gendisk *disk) @@ -1301,7 +1326,7 @@ struct scsi_disk *sdkp; struct gendisk *gd; u32 index; - int error; + int error, devno; error = -ENODEV; if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)) @@ -1319,6 +1344,12 @@ kobject_init(&sdkp->kobj); sdkp->kobj.ktype = &scsi_disk_kobj_type; + /* Note: We can accomodate 64 partitions, but the genhd code + * assumes partitions allocate consecutive minors, which they don't. + * So for now stay with max 16 partitions and leave two spare bits. + * Later, we may change the genhd code and the alloc_disk() call + * and the ->minors assignment here. KG, 2004-02-10 + */ gd = alloc_disk(16); if (!gd) goto out_free; @@ -1339,16 +1370,23 @@ sdkp->index = index; sdkp->openers = 0; - gd->major = sd_major(index >> 4); - gd->first_minor = (index & 15) << 4; + devno = make_sd_dev(index, 0); + gd->major = MAJOR(devno); + gd->first_minor = MINOR(devno); gd->minors = 16; gd->fops = &sd_fops; - if (index >= 26) { + if (index < 26) { + sprintf(gd->disk_name, "sd%c", 'a' + index % 26); + } else if (index < (26*27)) { sprintf(gd->disk_name, "sd%c%c", - 'a' + index/26-1,'a' + index % 26); + 'a' + index / 26 - 1,'a' + index % 26); } else { - sprintf(gd->disk_name, "sd%c", 'a' + index % 26); + const unsigned int m1 = (index / 26 - 1) / 26 - 1; + const unsigned int m2 = (index / 26 - 1) % 26; + const unsigned int m3 = index % 26; + sprintf(gd->disk_name, "sd%c%c%c", + 'a' + m1, 'a' + m2, 'a' + m3); } strcpy(gd->devfs_name, sdp->devfs_name); diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/st.c Wed Mar 10 21:09:43 2004 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static char *verstr = "20040213"; +static char *verstr = "20040226"; #include @@ -121,7 +121,15 @@ }; #endif -static char *st_formats[ST_NBR_MODES] ={"", "l", "m", "a"}; +/* Restrict the number of modes so that names for all are assigned */ +#if ST_NBR_MODES > 16 +#error "Maximum number of modes is 16" +#endif +/* Bit reversed order to get same names for same minors with all + mode counts */ +static char *st_formats[] = { + "", "r", "k", "s", "l", "t", "o", "u", + "m", "v", "p", "x", "a", "y", "q", "z"}; /* The default definitions have been moved to st_options.h */ @@ -3888,8 +3896,11 @@ dev_num); goto out_free_tape; } - snprintf(cdev->kobj.name, KOBJ_NAME_LEN, "%sm%d%s", disk->disk_name, - mode, j ? "n" : ""); + /* Make sure that the minor numbers corresponding to the four + first modes always get the same names */ + i = mode << (4 - ST_NBR_MODE_BITS); + snprintf(cdev->kobj.name, KOBJ_NAME_LEN, "%s%s%s", j ? "n" : "", + disk->disk_name, st_formats[i]); cdev->owner = THIS_MODULE; cdev->ops = &st_fops; @@ -3909,22 +3920,26 @@ } for (mode = 0; mode < ST_NBR_MODES; ++mode) { + /* Make sure that the minor numbers corresponding to the four + first modes always get the same names */ + i = mode << (4 - ST_NBR_MODE_BITS); /* Rewind entry */ - devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)), + devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 0)), S_IFCHR | S_IRUGO | S_IWUGO, - "%s/mt%s", SDp->devfs_name, st_formats[mode]); + "%s/mt%s", SDp->devfs_name, st_formats[i]); /* No-rewind entry */ - devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128), + devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, 1)), S_IFCHR | S_IRUGO | S_IWUGO, - "%s/mt%sn", SDp->devfs_name, st_formats[mode]); + "%s/mt%sn", SDp->devfs_name, st_formats[i]); } disk->number = devfs_register_tape(SDp->devfs_name); printk(KERN_WARNING "Attached scsi tape %s at scsi%d, channel %d, id %d, lun %d\n", tape_name(tpnt), SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); - printk(KERN_WARNING "%s: try direct i/o: %s, max page reachable by HBA %lu\n", - tape_name(tpnt), tpnt->try_dio ? "yes" : "no", tpnt->max_pfn); + printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B), max page reachable by HBA %lu\n", + tape_name(tpnt), tpnt->try_dio ? "yes" : "no", + queue_dma_alignment(SDp->request_queue) + 1, tpnt->max_pfn); return 0; @@ -3977,8 +3992,9 @@ sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, "tape"); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[mode]); - devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[mode]); + j = mode << (4 - ST_NBR_MODE_BITS); + devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[j]); + devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[j]); for (j=0; j < 2; j++) { class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(i, mode, j))); diff -Nru a/drivers/scsi/st.h b/drivers/scsi/st.h --- a/drivers/scsi/st.h Wed Mar 10 21:09:43 2004 +++ b/drivers/scsi/st.h Wed Mar 10 21:09:43 2004 @@ -50,6 +50,8 @@ struct cdev *cdevs[2]; /* Auto-rewind and non-rewind devices */ } ST_mode; +/* Number of modes can be changed by changing ST_NBR_MODE_BITS. The maximum + number of modes is 16 (ST_NBR_MODE_BITS 4) */ #define ST_NBR_MODE_BITS 2 #define ST_NBR_MODES (1 << ST_NBR_MODE_BITS) #define ST_MODE_SHIFT (7 - ST_NBR_MODE_BITS) diff -Nru a/include/scsi/scsi.h b/include/scsi/scsi.h --- a/include/scsi/scsi.h Wed Mar 10 21:09:43 2004 +++ b/include/scsi/scsi.h Wed Mar 10 21:09:43 2004 @@ -10,6 +10,12 @@ #include +/* + * The maximum sg list length SCSI can cope with + * (currently must be a power of 2 between 32 and 256) + */ +#define SCSI_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS + /* * SCSI command lengths @@ -200,6 +206,7 @@ #define TYPE_MEDIUM_CHANGER 0x08 #define TYPE_COMM 0x09 /* Communications device */ #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ +#define TYPE_RAID 0x0c #define TYPE_NO_LUN 0x7f /* @@ -273,6 +280,7 @@ #define DID_BAD_INTR 0x09 /* Got an interrupt we weren't expecting. */ #define DID_PASSTHROUGH 0x0a /* Force command past mid-layer */ #define DID_SOFT_ERROR 0x0b /* The low level driver just wish a retry */ +#define DID_IMM_RETRY 0x0c /* Retry without decrementing retry count */ #define DRIVER_OK 0x00 /* Driver status */ /* diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h --- a/include/scsi/scsi_device.h Wed Mar 10 21:09:42 2004 +++ b/include/scsi/scsi_device.h Wed Mar 10 21:09:42 2004 @@ -94,6 +94,7 @@ unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ unsigned no_start_on_add:1; /* do not issue start on add */ + unsigned allow_restart:1; /* issue START_UNIT in error handler */ unsigned int device_blocked; /* Device returned QUEUE_FULL. */ @@ -103,12 +104,17 @@ struct device sdev_gendev; struct class_device sdev_classdev; + struct class_device transport_classdev; + enum scsi_device_state sdev_state; -}; + unsigned long transport_data[0]; +} __attribute__((aligned(sizeof(unsigned long)))); #define to_scsi_device(d) \ container_of(d, struct scsi_device, sdev_gendev) #define class_to_sdev(d) \ container_of(d, struct scsi_device, sdev_classdev) +#define transport_class_to_sdev(class_dev) \ + container_of(class_dev, struct scsi_device, transport_classdev) extern struct scsi_device *scsi_add_device(struct Scsi_Host *, uint, uint, uint); diff -Nru a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h --- a/include/scsi/scsi_host.h Wed Mar 10 21:09:42 2004 +++ b/include/scsi/scsi_host.h Wed Mar 10 21:09:42 2004 @@ -11,6 +11,7 @@ struct scsi_device; struct Scsi_Host; struct scsi_host_cmd_pool; +struct scsi_transport_template; /* @@ -395,6 +396,7 @@ unsigned int eh_kill:1; /* set when killing the eh thread */ wait_queue_head_t host_wait; struct scsi_host_template *hostt; + struct scsi_transport_template *transportt; volatile unsigned short host_busy; /* commands actually active on low-level */ volatile unsigned short host_failed; /* commands that failed. */ diff -Nru a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_transport.h Wed Mar 10 21:09:43 2004 @@ -0,0 +1,41 @@ +/* + * Transport specific attributes. + * + * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef SCSI_TRANSPORT_H +#define SCSI_TRANSPORT_H + +struct scsi_transport_template { + /* The NULL terminated list of transport attributes + * that should be exported. + */ + struct class_device_attribute **attrs; + + /* The transport class that the device is in */ + struct class *class; + + /* Constructor/Destructor functions */ + int (* setup)(struct scsi_device *); + void (* cleanup)(struct scsi_device *); + /* The size of the specific transport attribute structure (a + * space of this size will be left at the end of the + * scsi_device structure */ + int size; +}; + +#endif /* SCSI_TRANSPORT_H */ diff -Nru a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_transport_fc.h Wed Mar 10 21:09:43 2004 @@ -0,0 +1,38 @@ +/* + * FiberChannel transport specific attributes exported to sysfs. + * + * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef SCSI_TRANSPORT_FC_H +#define SCSI_TRANSPORT_FC_H + +struct scsi_transport_template; + +struct fc_transport_attrs { + int port_id; + uint64_t node_name; + uint64_t port_name; +}; + +/* accessor functions */ +#define fc_port_id(x) (((struct fc_transport_attrs *)&(x)->transport_data)->port_id) +#define fc_node_name(x) (((struct fc_transport_attrs *)&(x)->transport_data)->node_name) +#define fc_port_name(x) (((struct fc_transport_attrs *)&(x)->transport_data)->port_name) + +extern struct scsi_transport_template fc_transport_template; + +#endif /* SCSI_TRANSPORT_FC_H */ diff -Nru a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/scsi/scsi_transport_spi.h Wed Mar 10 21:09:43 2004 @@ -0,0 +1,79 @@ +/* + * Parallel SCSI (SPI) transport specific attributes exported to sysfs. + * + * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef SCSI_TRANSPORT_SPI_H +#define SCSI_TRANSPORT_SPI_H + +#include + +struct scsi_transport_template; + +struct spi_transport_attrs { + int period; /* value in the PPR/SDTR command */ + int offset; + int width:1; /* 0 - narrow, 1 - wide */ + int iu:1; /* Information Units enabled */ + int dt:1; /* DT clocking enabled */ + int qas:1; /* Quick Arbitration and Selection enabled */ + int wr_flow:1; /* Write Flow control enabled */ + int rd_strm:1; /* Read streaming enabled */ + int rti:1; /* Retain Training Information */ + int pcomp_en:1; /* Precompensation enabled */ +}; + +/* accessor functions */ +#define spi_period(x) (((struct spi_transport_attrs *)&(x)->transport_data)->period) +#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->transport_data)->offset) +#define spi_width(x) (((struct spi_transport_attrs *)&(x)->transport_data)->width) +#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->transport_data)->iu) +#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->transport_data)->dt) +#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->transport_data)->qas) +#define spi_wr_flow(x) (((struct spi_transport_attrs *)&(x)->transport_data)->wr_flow) +#define spi_rd_strm(x) (((struct spi_transport_attrs *)&(x)->transport_data)->rd_strm) +#define spi_rti(x) (((struct spi_transport_attrs *)&(x)->transport_data)->rti) +#define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->transport_data)->pcomp_en) + +/* The functions by which the transport class and the driver communicate */ +struct spi_function_template { + void (*get_period)(struct scsi_device *); + void (*set_period)(struct scsi_device *, int); + void (*get_offset)(struct scsi_device *); + void (*set_offset)(struct scsi_device *, int); + void (*get_width)(struct scsi_device *); + void (*set_width)(struct scsi_device *, int); + void (*get_iu)(struct scsi_device *); + void (*set_iu)(struct scsi_device *, int); + void (*get_dt)(struct scsi_device *); + void (*set_dt)(struct scsi_device *, int); + void (*get_qas)(struct scsi_device *); + void (*set_qas)(struct scsi_device *, int); + void (*get_wr_flow)(struct scsi_device *); + void (*set_wr_flow)(struct scsi_device *, int); + void (*get_rd_strm)(struct scsi_device *); + void (*set_rd_strm)(struct scsi_device *, int); + void (*get_rti)(struct scsi_device *); + void (*set_rti)(struct scsi_device *, int); + void (*get_pcomp_en)(struct scsi_device *); + void (*set_pcomp_en)(struct scsi_device *, int); +}; + +struct scsi_transport_template *spi_attach_transport(struct spi_function_template *); +void spi_release_transport(struct scsi_transport_template *); + +#endif /* SCSI_TRANSPORT_SPI_H */