diff options
author | Jeff Garzik <jgarzik@pretzel.yyz.us> | 2005-06-26 17:11:03 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-26 17:11:03 -0400 |
commit | 8b0ee07e108b2eefdab5bb73f33223f18926c3b2 (patch) | |
tree | f68ca04180c5488301a40ec212ef2eb2467cf56c /drivers/message | |
parent | 4638aef40ba9ebb9734caeed1f373c24015259fd (diff) | |
parent | 8678887e7fb43cd6c9be6c9807b05e77848e0920 (diff) | |
download | blackbird-op-linux-8b0ee07e108b2eefdab5bb73f33223f18926c3b2.tar.gz blackbird-op-linux-8b0ee07e108b2eefdab5bb73f33223f18926c3b2.zip |
Merge upstream (approx. 2.6.12-git8) into 'janitor' branch of netdev-2.6.
Diffstat (limited to 'drivers/message')
41 files changed, 5246 insertions, 2559 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 452418b24d7b..33f209a39cb6 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -2,34 +2,54 @@ menu "Fusion MPT device support" config FUSION - tristate "Fusion MPT (base + ScsiHost) drivers" + bool + default n + +config FUSION_SPI + tristate "Fusion MPT ScsiHost drivers for SPI" + depends on PCI && SCSI + select FUSION + ---help--- + SCSI HOST support for a parallel SCSI host adapters. + + List of supported controllers: + + LSI53C1020 + LSI53C1020A + LSI53C1030 + LSI53C1035 + +config FUSION_FC + tristate "Fusion MPT ScsiHost drivers for FC" depends on PCI && SCSI + select FUSION ---help--- - LSI Logic Fusion(TM) Message Passing Technology (MPT) device support - provides high performance SCSI host initiator, and LAN [1] interface - services to a host system. The Fusion architecture is capable of - duplexing these protocols on high-speed Fibre Channel - (up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320) - physical medium. + SCSI HOST support for a Fiber Channel host adapters. - [1] LAN is not supported on parallel SCSI medium. + List of supported controllers: + + LSIFC909 + LSIFC919 + LSIFC919X + LSIFC929 + LSIFC929X + LSIFC929XL config FUSION_MAX_SGE - int "Maximum number of scatter gather entries" + int "Maximum number of scatter gather entries (16 - 128)" depends on FUSION - default "40" + default "128" + range 16 128 help This option allows you to specify the maximum number of scatter- - gather entries per I/O. The driver defaults to 40, a reasonable number - for most systems. However, the user may increase this up to 128. - Increasing this parameter will require significantly more memory - on a per controller instance. Increasing the parameter is not - necessary (or recommended) unless the user will be running - large I/O's via the raw interface. + gather entries per I/O. The driver default is 128, which matches + SCSI_MAX_PHYS_SEGMENTS. However, it may decreased down to 16. + Decreasing this parameter will reduce memory requirements + on a per controller instance. config FUSION_CTL tristate "Fusion MPT misc device (ioctl) driver" - depends on FUSION + depends on FUSION_SPI || FUSION_FC ---help--- The Fusion MPT misc device driver provides specialized control of MPT adapters via system ioctl calls. Use of ioctl calls to @@ -48,7 +68,7 @@ config FUSION_CTL config FUSION_LAN tristate "Fusion MPT LAN driver" - depends on FUSION && NET_FC + depends on FUSION_FC && NET_FC ---help--- This module supports LAN IP traffic over Fibre Channel port(s) on Fusion MPT compatible hardware (LSIFC9xx chips). diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index f6fdcaaefc89..1d2f9db813c1 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -1,52 +1,38 @@ -# -# Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers. -# -# Note! If you want to turn on various debug defines for an extended period of -# time but don't want them lingering around in the Makefile when you pass it on -# to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer - -#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC - -# Architecture-specific... -# # intel -#EXTRA_CFLAGS += -g -# # sparc64 -#EXTRA_CFLAGS += -gstabs+ - -EXTRA_CFLAGS += ${MPT_CFLAGS} - # Fusion MPT drivers; recognized debug defines... # MPT general: -#EXTRA_CFLAGS += -DMPT_DEBUG_SCSI #EXTRA_CFLAGS += -DMPT_DEBUG #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME #EXTRA_CFLAGS += -DMPT_DEBUG_SG +#EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS +#EXTRA_CFLAGS += -DMPT_DEBUG_INIT +#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT +#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL + # # driver/module specifics... # # For mptbase: #CFLAGS_mptbase.o += -DMPT_DEBUG_HANDSHAKE +#CFLAGS_mptbase.o += -DMPT_DEBUG_CONFIG +#CFLAGS_mptbase.o += -DMPT_DEBUG_DL #CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ +#CFLAGS_mptbase.o += -DMPT_DEBUG_RESET # # For mptscsih: -#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCANDV -#CFLAGS_mptscsih.o += -DMPT_DEBUG_RESET -#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEH +#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV +#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO +#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM +#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI +#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY # # For mptctl: #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL # -# For mptlan: -#CFLAGS_mptlan.o += -DMPT_LAN_IO_DEBUG -# -# For isense: - -# EXP... -##mptscsih-objs := scsihost.o scsiherr.o #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC -obj-$(CONFIG_FUSION) += mptbase.o mptscsih.o +obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o +obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o obj-$(CONFIG_FUSION_CTL) += mptctl.o obj-$(CONFIG_FUSION_LAN) += mptlan.o diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h index 9dbb061265fe..9f98334e5076 100644 --- a/drivers/message/fusion/lsi/mpi.h +++ b/drivers/message/fusion/lsi/mpi.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2005 LSI Logic Corporation. * * * Name: mpi.h * Title: MPI Message independent structures and definitions * Creation Date: July 27, 2000 * - * mpi.h Version: 01.05.xx + * mpi.h Version: 01.05.07 * * Version History * --------------- @@ -52,6 +52,25 @@ * 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. + * 01-16-04 01.02.11 Added define for MPI_IOCLOGINFO_TYPE_SHIFT. + * 04-29-04 01.02.12 Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST + * and MPI_FUNCTION_DIAG_RELEASE. + * Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define. + * Bumped MPI_HEADER_VERSION_UNIT value. + * 05-11-04 01.03.01 Bumped MPI_VERSION_MINOR for MPI v1.3. + * Added codes for Inband. + * 08-19-04 01.05.01 Added defines for Host Buffer Access Control doorbell. + * Added define for offset of High Priority Request Queue. + * Added new function codes and new IOCStatus codes. + * Added a IOCLogInfo type of SAS. + * 12-07-04 01.05.02 Bumped MPI_HEADER_VERSION_UNIT. + * 12-09-04 01.05.03 Bumped MPI_HEADER_VERSION_UNIT. + * 01-15-05 01.05.04 Bumped MPI_HEADER_VERSION_UNIT. + * 02-09-05 01.05.05 Bumped MPI_HEADER_VERSION_UNIT. + * 02-22-05 01.05.06 Bumped MPI_HEADER_VERSION_UNIT. + * 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and + * TargetAssistExtended requests. + * Removed EEDP IOCStatus codes. * -------------------------------------------------------------------------- */ @@ -82,7 +101,7 @@ /* Note: The major versions of 0xe0 through 0xff are reserved */ /* versioning for this MPI header set */ -#define MPI_HEADER_VERSION_UNIT (0x00) +#define MPI_HEADER_VERSION_UNIT (0x09) #define MPI_HEADER_VERSION_DEV (0x00) #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI_HEADER_VERSION_UNIT_SHIFT (8) @@ -122,7 +141,11 @@ * *****************************************************************************/ -/* S y s t e m D o o r b e l l */ +/* + * Defines for working with the System Doorbell register. + * Values for doorbell function codes are included in the section that defines + * all the function codes (further on in this file). + */ #define MPI_DOORBELL_OFFSET (0x00000000) #define MPI_DOORBELL_ACTIVE (0x08000000) /* DoorbellUsed */ #define MPI_DOORBELL_USED (MPI_DOORBELL_ACTIVE) @@ -134,6 +157,13 @@ #define MPI_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) #define MPI_DOORBELL_ADD_DWORDS_SHIFT (16) #define MPI_DOORBELL_DATA_MASK (0x0000FFFF) +#define MPI_DOORBELL_FUNCTION_SPECIFIC_MASK (0x0000FFFF) + +/* values for Host Buffer Access Control doorbell function */ +#define MPI_DB_HPBAC_VALUE_MASK (0x0000F000) +#define MPI_DB_HPBAC_ENABLE_ACCESS (0x01) +#define MPI_DB_HPBAC_DISABLE_ACCESS (0x02) +#define MPI_DB_HPBAC_FREE_BUFFER (0x03) #define MPI_WRITE_SEQUENCE_OFFSET (0x00000004) @@ -257,16 +287,18 @@ #define MPI_FUNCTION_SMP_PASSTHROUGH (0x1A) #define MPI_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) +#define MPI_FUNCTION_SATA_PASSTHROUGH (0x1C) -#define MPI_DIAG_BUFFER_POST (0x1D) -#define MPI_DIAG_RELEASE (0x1E) - -#define MPI_FUNCTION_SCSI_IO_32 (0x1F) +#define MPI_FUNCTION_DIAG_BUFFER_POST (0x1D) +#define MPI_FUNCTION_DIAG_RELEASE (0x1E) #define MPI_FUNCTION_LAN_SEND (0x20) #define MPI_FUNCTION_LAN_RECEIVE (0x21) #define MPI_FUNCTION_LAN_RESET (0x22) +#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) +#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) + #define MPI_FUNCTION_INBAND_BUFFER_POST (0x28) #define MPI_FUNCTION_INBAND_SEND (0x29) #define MPI_FUNCTION_INBAND_RSP (0x2A) @@ -276,6 +308,7 @@ #define MPI_FUNCTION_IO_UNIT_RESET (0x41) #define MPI_FUNCTION_HANDSHAKE (0x42) #define MPI_FUNCTION_REPLY_FRAME_REMOVAL (0x43) +#define MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL (0x44) /* standard version format */ @@ -328,8 +361,8 @@ typedef struct _SGE_SIMPLE_UNION U32 Address32; U64 Address64; }u; -} SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t, - SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION; +} SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION, + SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t; /****************************************************************************/ /* Chain element structures */ @@ -648,27 +681,21 @@ typedef struct _MSG_DEFAULT_REPLY #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 */ +/* SCSI Target values */ /****************************************************************************/ #define MPI_IOCSTATUS_TARGET_PRIORITY_IO (0x0060) #define MPI_IOCSTATUS_TARGET_INVALID_PORT (0x0061) -#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete */ +#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete name */ #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) #define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) #define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT (0x006B) +#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) +#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) +#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) /****************************************************************************/ /* Additional FCP target values (obsolete) */ @@ -707,6 +734,7 @@ typedef struct _MSG_DEFAULT_REPLY /****************************************************************************/ #define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) +#define MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) /****************************************************************************/ /* Inband values */ diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index a5680d864bf0..15b12b06799d 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2005 LSI Logic Corporation. * * * Name: mpi_cnfg.h * Title: MPI Config message, structures, and Pages * Creation Date: July 27, 2000 * - * mpi_cnfg.h Version: 01.05.xx + * mpi_cnfg.h Version: 01.05.08 * * Version History * --------------- @@ -145,6 +145,93 @@ * In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field * with ADISCHardALPA. * Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define. + * 01-16-04 01.02.13 Added InitiatorDeviceTimeout and InitiatorIoPendTimeout + * fields and related defines to CONFIG_PAGE_FC_PORT_1. + * Added define for + * MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK. + * Added new fields to the substructures of + * CONFIG_PAGE_FC_PORT_10. + * 04-29-04 01.02.14 Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0, + * CONFIG_PAGE_SCSI_DEVICE_0, and + * CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for + * these pages. + * 05-11-04 01.03.01 Added structure for CONFIG_PAGE_INBAND_0. + * 08-19-04 01.05.01 Modified MSG_CONFIG request to support extended config + * pages. + * Added a new structure for extended config page header. + * Added new extended config pages types and structures for + * SAS IO Unit, SAS Expander, SAS Device, and SAS PHY. + * Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4 + * to add a Flags field. + * Two new Manufacturing config pages (5 and 6). + * Two new bits defined for IO Unit Page 1 Flags field. + * Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields + * to specify the BIOS boot device. + * Four new Flags bits defined for IO Unit Page 2. + * Added IO Unit Page 4. + * Added EEDP Flags settings to IOC Page 1. + * Added new BIOS Page 1 config page. + * 10-05-04 01.05.02 Added define for + * MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE. + * Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and + * associated defines. + * Added more defines for SAS IO Unit Page 0 + * DiscoveryStatus field. + * Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK + * and MPI_SAS_IOUNIT0_DS_TABLE_LINK. + * Added defines for Physical Mapping Modes to SAS IO Unit + * Page 2. + * Added define for + * MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH. + * 10-27-04 01.05.03 Added defines for new SAS PHY page addressing mode. + * Added defines for MaxTargetSpinUp to BIOS Page 1. + * Added 5 new ControlFlags defines for SAS IO Unit + * Page 1. + * Added MaxNumPhysicalMappedIDs field to SAS IO Unit + * Page 2. + * Added AccessStatus field to SAS Device Page 0 and added + * new Flags bits for supported SATA features. + * 12-07-04 01.05.04 Added config page structures for BIOS Page 2, RAID + * Volume Page 1, and RAID Physical Disk Page 1. + * Replaced IO Unit Page 1 BootTargetID,BootBus, and + * BootAdapterNum with reserved field. + * Added DataScrubRate and ResyncRate to RAID Volume + * Page 0. + * Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT + * define. + * 12-09-04 01.05.05 Added Target Mode Large CDB Enable to FC Port Page 1 + * Flags field. + * Added Auto Port Config flag define for SAS IOUNIT + * Page 1 ControlFlags. + * Added Disabled bad Phy define to Expander Page 1 + * Discovery Info field. + * Added SAS/SATA device support to SAS IOUnit Page 1 + * ControlFlags. + * Added Unsupported device to SAS Dev Page 0 Flags field + * Added disable use SATA Hash Address for SAS IOUNIT + * page 1 in ControlFields. + * 01-15-05 01.05.06 Added defaults for data scrub rate and resync rate to + * Manufacturing Page 4. + * Added new defines for BIOS Page 1 IOCSettings field. + * Added ExtDiskIdentifier field to RAID Physical Disk + * Page 0. + * Added new defines for SAS IO Unit Page 1 ControlFlags + * and to SAS Device Page 0 Flags to control SATA devices. + * Added defines and structures for the new Log Page 0, a + * new type of configuration page. + * 02-09-05 01.05.07 Added InactiveStatus field to RAID Volume Page 0. + * Added WWID field to RAID Volume Page 1. + * Added PhysicalPort field to SAS Expander pages 0 and 1. + * 03-11-05 01.05.08 Removed the EEDP flags from IOC Page 1. + * Added Enclosure/Slot boot device format to BIOS Page 2. + * New status value for RAID Volume Page 0 VolumeStatus + * (VolumeState subfield). + * New value for RAID Physical Page 0 InactiveStatus. + * Added Inactive Volume Member flag RAID Physical Disk + * Page 0 PhysDiskStatus field. + * New physical mapping mode in SAS IO Unit Page 2. + * Added CONFIG_PAGE_SAS_ENCLOSURE_0. + * Added Slot and Enclosure fields to SAS Device Page 0. * -------------------------------------------------------------------------- */ @@ -164,7 +251,7 @@ typedef struct _CONFIG_PAGE_HEADER U8 PageLength; /* 01h */ U8 PageNumber; /* 02h */ U8 PageType; /* 03h */ -} fCONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER, +} CONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER, ConfigPageHeader_t, MPI_POINTER pConfigPageHeader_t; typedef union _CONFIG_PAGE_HEADER_UNION @@ -174,7 +261,7 @@ typedef union _CONFIG_PAGE_HEADER_UNION U16 Word16[2]; U32 Word32; } ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion, - fCONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION; + CONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION; typedef struct _CONFIG_EXTENDED_PAGE_HEADER { @@ -185,7 +272,7 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER U16 ExtPageLength; /* 04h */ U8 ExtPageType; /* 06h */ U8 Reserved2; /* 07h */ -} fCONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER, +} CONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER, ConfigExtendedPageHeader_t, MPI_POINTER pConfigExtendedPageHeader_t; @@ -224,6 +311,8 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER #define MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) #define MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) #define MPI_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) +#define MPI_CONFIG_EXTPAGETYPE_LOG (0x14) +#define MPI_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15) /**************************************************************************** @@ -231,10 +320,19 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER ****************************************************************************/ #define MPI_SCSI_PORT_PGAD_PORT_MASK (0x000000FF) +#define MPI_SCSI_DEVICE_FORM_MASK (0xF0000000) +#define MPI_SCSI_DEVICE_FORM_BUS_TID (0x00000000) #define MPI_SCSI_DEVICE_TARGET_ID_MASK (0x000000FF) #define MPI_SCSI_DEVICE_TARGET_ID_SHIFT (0) #define MPI_SCSI_DEVICE_BUS_MASK (0x0000FF00) #define MPI_SCSI_DEVICE_BUS_SHIFT (8) +#define MPI_SCSI_DEVICE_FORM_TARGET_MODE (0x10000000) +#define MPI_SCSI_DEVICE_TM_RESPOND_ID_MASK (0x000000FF) +#define MPI_SCSI_DEVICE_TM_RESPOND_ID_SHIFT (0) +#define MPI_SCSI_DEVICE_TM_BUS_MASK (0x0000FF00) +#define MPI_SCSI_DEVICE_TM_BUS_SHIFT (8) +#define MPI_SCSI_DEVICE_TM_INIT_ID_MASK (0x00FF0000) +#define MPI_SCSI_DEVICE_TM_INIT_ID_SHIFT (16) #define MPI_FC_PORT_PGAD_PORT_MASK (0xF0000000) #define MPI_FC_PORT_PGAD_PORT_SHIFT (28) @@ -260,6 +358,20 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_SHIFT (0) +#define MPI_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_EXPAND_PGAD_FORM_SHIFT (28) +#define MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM (0x00000001) +#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE (0x00000002) +#define MPI_SAS_EXPAND_PGAD_GNH_MASK_HANDLE (0x0000FFFF) +#define MPI_SAS_EXPAND_PGAD_GNH_SHIFT_HANDLE (0) +#define MPI_SAS_EXPAND_PGAD_HPN_MASK_PHY (0x00FF0000) +#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_PHY (16) +#define MPI_SAS_EXPAND_PGAD_HPN_MASK_HANDLE (0x0000FFFF) +#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_HANDLE (0) +#define MPI_SAS_EXPAND_PGAD_H_MASK_HANDLE (0x0000FFFF) +#define MPI_SAS_EXPAND_PGAD_H_SHIFT_HANDLE (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) @@ -274,10 +386,24 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER #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) +#define MPI_SAS_PHY_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_PHY_PGAD_FORM_SHIFT (28) +#define MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x0) +#define MPI_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x1) +#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) +#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT (0) +#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF) +#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_SHIFT (0) + +#define MPI_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000) +#define MPI_SAS_ENCLOS_PGAD_FORM_SHIFT (28) +#define MPI_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) +#define MPI_SAS_ENCLOS_PGAD_FORM_HANDLE (0x00000001) +#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_SHIFT (0) +#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_MASK (0x0000FFFF) +#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_SHIFT (0) + /**************************************************************************** @@ -294,7 +420,7 @@ typedef struct _MSG_CONFIG U8 MsgFlags; /* 07h */ U32 MsgContext; /* 08h */ U8 Reserved2[8]; /* 0Ch */ - fCONFIG_PAGE_HEADER Header; /* 14h */ + CONFIG_PAGE_HEADER Header; /* 14h */ U32 PageAddress; /* 18h */ SGE_IO_UNION PageBufferSGE; /* 1Ch */ } MSG_CONFIG, MPI_POINTER PTR_MSG_CONFIG, @@ -327,7 +453,7 @@ typedef struct _MSG_CONFIG_REPLY U8 Reserved2[2]; /* 0Ch */ U16 IOCStatus; /* 0Eh */ U32 IOCLogInfo; /* 10h */ - fCONFIG_PAGE_HEADER Header; /* 14h */ + CONFIG_PAGE_HEADER Header; /* 14h */ } MSG_CONFIG_REPLY, MPI_POINTER PTR_MSG_CONFIG_REPLY, ConfigReply_t, MPI_POINTER pConfigReply_t; @@ -349,6 +475,8 @@ typedef struct _MSG_CONFIG_REPLY #define MPI_MANUFACTPAGE_DEVICEID_FC929 (0x0622) #define MPI_MANUFACTPAGE_DEVICEID_FC919X (0x0628) #define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) +#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642) +#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640) /* SCSI */ #define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) #define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) @@ -358,18 +486,25 @@ typedef struct _MSG_CONFIG_REPLY #define MPI_MANUFACTPAGE_DEVID_53C1035ZC (0x0041) /* SAS */ #define MPI_MANUFACTPAGE_DEVID_SAS1064 (0x0050) +#define MPI_MANUFACTPAGE_DEVID_SAS1064A (0x005C) +#define MPI_MANUFACTPAGE_DEVID_SAS1064E (0x0056) +#define MPI_MANUFACTPAGE_DEVID_SAS1066 (0x005E) +#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A) +#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054) +#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058) +#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060) typedef struct _CONFIG_PAGE_MANUFACTURING_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 ChipName[16]; /* 04h */ U8 ChipRevision[8]; /* 14h */ U8 BoardName[16]; /* 1Ch */ U8 BoardAssembly[16]; /* 2Ch */ U8 BoardTracerNumber[16]; /* 3Ch */ -} fCONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0, +} CONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0, ManufacturingPage0_t, MPI_POINTER pManufacturingPage0_t; #define MPI_MANUFACTURING0_PAGEVERSION (0x00) @@ -377,9 +512,9 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_0 typedef struct _CONFIG_PAGE_MANUFACTURING_1 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 VPD[256]; /* 04h */ -} fCONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1, +} CONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1, ManufacturingPage1_t, MPI_POINTER pManufacturingPage1_t; #define MPI_MANUFACTURING1_PAGEVERSION (0x00) @@ -404,10 +539,10 @@ typedef struct _MPI_CHIP_REVISION_ID typedef struct _CONFIG_PAGE_MANUFACTURING_2 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ MPI_CHIP_REVISION_ID ChipId; /* 04h */ U32 HwSettings[MPI_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 08h */ -} fCONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2, +} CONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2, ManufacturingPage2_t, MPI_POINTER pManufacturingPage2_t; #define MPI_MANUFACTURING2_PAGEVERSION (0x00) @@ -423,10 +558,10 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_2 typedef struct _CONFIG_PAGE_MANUFACTURING_3 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ MPI_CHIP_REVISION_ID ChipId; /* 04h */ U32 Info[MPI_MAN_PAGE_3_INFO_WORDS];/* 08h */ -} fCONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3, +} CONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3, ManufacturingPage3_t, MPI_POINTER pManufacturingPage3_t; #define MPI_MANUFACTURING3_PAGEVERSION (0x00) @@ -434,7 +569,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_3 typedef struct _CONFIG_PAGE_MANUFACTURING_4 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Reserved1; /* 04h */ U8 InfoOffset0; /* 08h */ U8 InfoSize0; /* 09h */ @@ -447,10 +582,23 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 U32 ISVolumeSettings; /* 48h */ U32 IMEVolumeSettings; /* 4Ch */ U32 IMVolumeSettings; /* 50h */ -} fCONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, + U32 Reserved3; /* 54h */ + U32 Reserved4; /* 58h */ + U8 ISDataScrubRate; /* 5Ch */ + U8 ISResyncRate; /* 5Dh */ + U16 Reserved5; /* 5Eh */ + U8 IMEDataScrubRate; /* 60h */ + U8 IMEResyncRate; /* 61h */ + U16 Reserved6; /* 62h */ + U8 IMDataScrubRate; /* 64h */ + U8 IMResyncRate; /* 65h */ + U16 Reserved7; /* 66h */ + U32 Reserved8; /* 68h */ + U32 Reserved9; /* 6Ch */ +} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; -#define MPI_MANUFACTURING4_PAGEVERSION (0x01) +#define MPI_MANUFACTURING4_PAGEVERSION (0x02) /* defines for the Flags field */ #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) @@ -458,19 +606,25 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 typedef struct _CONFIG_PAGE_MANUFACTURING_5 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U64 BaseWWID; /* 04h */ -} fCONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5, + U8 Flags; /* 0Ch */ + U8 Reserved1; /* 0Dh */ + U16 Reserved2; /* 0Eh */ +} CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5, ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t; -#define MPI_MANUFACTURING5_PAGEVERSION (0x00) +#define MPI_MANUFACTURING5_PAGEVERSION (0x01) + +/* defines for the Flags field */ +#define MPI_MANPAGE5_TWO_WWID_PER_PHY (0x01) typedef struct _CONFIG_PAGE_MANUFACTURING_6 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 ProductSpecificInfo;/* 04h */ -} fCONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6, +} CONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6, ManufacturingPage6_t, MPI_POINTER pManufacturingPage6_t; #define MPI_MANUFACTURING6_PAGEVERSION (0x00) @@ -482,9 +636,9 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_6 typedef struct _CONFIG_PAGE_IO_UNIT_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U64 UniqueValue; /* 04h */ -} fCONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0, +} CONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0, IOUnitPage0_t, MPI_POINTER pIOUnitPage0_t; #define MPI_IOUNITPAGE0_PAGEVERSION (0x00) @@ -492,9 +646,9 @@ typedef struct _CONFIG_PAGE_IO_UNIT_0 typedef struct _CONFIG_PAGE_IO_UNIT_1 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Flags; /* 04h */ -} fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, +} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; #define MPI_IOUNITPAGE1_PAGEVERSION (0x01) @@ -524,14 +678,15 @@ typedef struct _MPI_ADAPTER_INFO typedef struct _CONFIG_PAGE_IO_UNIT_2 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Flags; /* 04h */ U32 BiosVersion; /* 08h */ MPI_ADAPTER_INFO AdapterOrder[4]; /* 0Ch */ -} fCONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2, + U32 Reserved1; /* 1Ch */ +} CONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2, IOUnitPage2_t, MPI_POINTER pIOUnitPage2_t; -#define MPI_IOUNITPAGE2_PAGEVERSION (0x00) +#define MPI_IOUNITPAGE2_PAGEVERSION (0x02) #define MPI_IOUNITPAGE2_FLAGS_PAUSE_ON_ERROR (0x00000002) #define MPI_IOUNITPAGE2_FLAGS_VERBOSE_ENABLE (0x00000004) @@ -554,12 +709,12 @@ typedef struct _CONFIG_PAGE_IO_UNIT_2 typedef struct _CONFIG_PAGE_IO_UNIT_3 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 GPIOCount; /* 04h */ U8 Reserved1; /* 05h */ U16 Reserved2; /* 06h */ U16 GPIOVal[MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX]; /* 08h */ -} fCONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3, +} CONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3, IOUnitPage3_t, MPI_POINTER pIOUnitPage3_t; #define MPI_IOUNITPAGE3_PAGEVERSION (0x01) @@ -570,13 +725,24 @@ typedef struct _CONFIG_PAGE_IO_UNIT_3 #define MPI_IOUNITPAGE3_GPIO_SETTING_ON (0x01) +typedef struct _CONFIG_PAGE_IO_UNIT_4 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 04h */ + SGE_SIMPLE_UNION FWImageSGE; /* 08h */ +} CONFIG_PAGE_IO_UNIT_4, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_4, + IOUnitPage4_t, MPI_POINTER pIOUnitPage4_t; + +#define MPI_IOUNITPAGE4_PAGEVERSION (0x00) + + /**************************************************************************** * IOC Config Pages ****************************************************************************/ typedef struct _CONFIG_PAGE_IOC_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 TotalNVStore; /* 04h */ U32 FreeNVStore; /* 08h */ U16 VendorID; /* 0Ch */ @@ -586,7 +752,7 @@ typedef struct _CONFIG_PAGE_IOC_0 U32 ClassCode; /* 14h */ U16 SubsystemVendorID; /* 18h */ U16 SubsystemID; /* 1Ah */ -} fCONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0, +} CONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0, IOCPage0_t, MPI_POINTER pIOCPage0_t; #define MPI_IOCPAGE0_PAGEVERSION (0x01) @@ -594,23 +760,19 @@ typedef struct _CONFIG_PAGE_IOC_0 typedef struct _CONFIG_PAGE_IOC_1 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Flags; /* 04h */ U32 CoalescingTimeout; /* 08h */ U8 CoalescingDepth; /* 0Ch */ U8 PCISlotNum; /* 0Dh */ U8 Reserved[2]; /* 0Eh */ -} fCONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1, +} CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1, IOCPage1_t, MPI_POINTER pIOCPage1_t; -#define MPI_IOCPAGE1_PAGEVERSION (0x01) +#define MPI_IOCPAGE1_PAGEVERSION (0x02) /* 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_INITIATOR_CONTEXT_REPLY_DISABLE (0x00000010) #define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001) #define MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) @@ -625,7 +787,7 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL U8 VolumeType; /* 04h */ U8 Flags; /* 05h */ U16 Reserved3; /* 06h */ -} fCONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL, +} CONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL, ConfigPageIoc2RaidVol_t, MPI_POINTER pConfigPageIoc2RaidVol_t; /* IOC Page 2 Volume RAID Type values, also used in RAID Volume pages */ @@ -648,14 +810,14 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL typedef struct _CONFIG_PAGE_IOC_2 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 CapabilitiesFlags; /* 04h */ U8 NumActiveVolumes; /* 08h */ U8 MaxVolumes; /* 09h */ U8 NumActivePhysDisks; /* 0Ah */ U8 MaxPhysDisks; /* 0Bh */ - fCONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */ -} fCONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2, + CONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */ +} CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2, IOCPage2_t, MPI_POINTER pIOCPage2_t; #define MPI_IOCPAGE2_PAGEVERSION (0x02) @@ -689,12 +851,12 @@ typedef struct _IOC_3_PHYS_DISK typedef struct _CONFIG_PAGE_IOC_3 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 NumPhysDisks; /* 04h */ U8 Reserved1; /* 05h */ U16 Reserved2; /* 06h */ IOC_3_PHYS_DISK PhysDisk[MPI_IOC_PAGE_3_PHYSDISK_MAX]; /* 08h */ -} fCONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3, +} CONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3, IOCPage3_t, MPI_POINTER pIOCPage3_t; #define MPI_IOCPAGE3_PAGEVERSION (0x00) @@ -718,12 +880,12 @@ typedef struct _IOC_4_SEP typedef struct _CONFIG_PAGE_IOC_4 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 ActiveSEP; /* 04h */ U8 MaxSEP; /* 05h */ U16 Reserved1; /* 06h */ IOC_4_SEP SEP[MPI_IOC_PAGE_4_SEP_MAX]; /* 08h */ -} fCONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4, +} CONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4, IOCPage4_t, MPI_POINTER pIOCPage4_t; #define MPI_IOCPAGE4_PAGEVERSION (0x00) @@ -751,25 +913,25 @@ typedef struct _IOC_5_HOT_SPARE typedef struct _CONFIG_PAGE_IOC_5 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Reserved1; /* 04h */ U8 NumHotSpares; /* 08h */ U8 Reserved2; /* 09h */ U16 Reserved3; /* 0Ah */ IOC_5_HOT_SPARE HotSpare[MPI_IOC_PAGE_5_HOT_SPARE_MAX]; /* 0Ch */ -} fCONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5, +} CONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5, IOCPage5_t, MPI_POINTER pIOCPage5_t; #define MPI_IOCPAGE5_PAGEVERSION (0x00) /**************************************************************************** -* BIOS Port Config Pages +* BIOS Config Pages ****************************************************************************/ typedef struct _CONFIG_PAGE_BIOS_1 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 BiosOptions; /* 04h */ U32 IOCSettings; /* 08h */ U32 Reserved1; /* 0Ch */ @@ -780,10 +942,10 @@ typedef struct _CONFIG_PAGE_BIOS_1 U16 IOTimeoutSequential; /* 1Ah */ U16 IOTimeoutOther; /* 1Ch */ U16 IOTimeoutBlockDevicesRM; /* 1Eh */ -} fCONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, +} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, BIOSPage1_t, MPI_POINTER pBIOSPage1_t; -#define MPI_BIOSPAGE1_PAGEVERSION (0x00) +#define MPI_BIOSPAGE1_PAGEVERSION (0x01) /* values for the BiosOptions field */ #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) @@ -792,6 +954,13 @@ typedef struct _CONFIG_PAGE_BIOS_1 #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) /* values for the IOCSettings field */ +#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) +#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) +#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) + +#define MPI_BIOSPAGE1_IOCSET_MASK_MAX_TARGET_SPIN_UP (0x0000F000) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_MAX_TARGET_SPIN_UP (12) + #define MPI_BIOSPAGE1_IOCSET_MASK_SPINUP_DELAY (0x00000F00) #define MPI_BIOSPAGE1_IOCSET_SHIFT_SPINUP_DELAY (8) @@ -814,6 +983,191 @@ typedef struct _CONFIG_PAGE_BIOS_1 #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) #define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) +typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER +{ + U32 Reserved1; /* 00h */ + U32 Reserved2; /* 04h */ + U32 Reserved3; /* 08h */ + U32 Reserved4; /* 0Ch */ + U32 Reserved5; /* 10h */ + U32 Reserved6; /* 14h */ + U32 Reserved7; /* 18h */ + U32 Reserved8; /* 1Ch */ + U32 Reserved9; /* 20h */ + U32 Reserved10; /* 24h */ + U32 Reserved11; /* 28h */ + U32 Reserved12; /* 2Ch */ + U32 Reserved13; /* 30h */ + U32 Reserved14; /* 34h */ + U32 Reserved15; /* 38h */ + U32 Reserved16; /* 3Ch */ + U32 Reserved17; /* 40h */ +} MPI_BOOT_DEVICE_ADAPTER_ORDER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_ORDER; + +typedef struct _MPI_BOOT_DEVICE_ADAPTER_NUMBER +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 AdapterNumber; /* 02h */ + U8 Reserved1; /* 03h */ + U32 Reserved2; /* 04h */ + U32 Reserved3; /* 08h */ + U32 Reserved4; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved5; /* 18h */ + U32 Reserved6; /* 1Ch */ + U32 Reserved7; /* 20h */ + U32 Reserved8; /* 24h */ + U32 Reserved9; /* 28h */ + U32 Reserved10; /* 2Ch */ + U32 Reserved11; /* 30h */ + U32 Reserved12; /* 34h */ + U32 Reserved13; /* 38h */ + U32 Reserved14; /* 3Ch */ + U32 Reserved15; /* 40h */ +} MPI_BOOT_DEVICE_ADAPTER_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_NUMBER; + +typedef struct _MPI_BOOT_DEVICE_PCI_ADDRESS +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U16 PCIAddress; /* 02h */ + U32 Reserved1; /* 04h */ + U32 Reserved2; /* 08h */ + U32 Reserved3; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved4; /* 18h */ + U32 Reserved5; /* 1Ch */ + U32 Reserved6; /* 20h */ + U32 Reserved7; /* 24h */ + U32 Reserved8; /* 28h */ + U32 Reserved9; /* 2Ch */ + U32 Reserved10; /* 30h */ + U32 Reserved11; /* 34h */ + U32 Reserved12; /* 38h */ + U32 Reserved13; /* 3Ch */ + U32 Reserved14; /* 40h */ +} MPI_BOOT_DEVICE_PCI_ADDRESS, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_ADDRESS; + +typedef struct _MPI_BOOT_DEVICE_SLOT_NUMBER +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 PCISlotNumber; /* 02h */ + U8 Reserved1; /* 03h */ + U32 Reserved2; /* 04h */ + U32 Reserved3; /* 08h */ + U32 Reserved4; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved5; /* 18h */ + U32 Reserved6; /* 1Ch */ + U32 Reserved7; /* 20h */ + U32 Reserved8; /* 24h */ + U32 Reserved9; /* 28h */ + U32 Reserved10; /* 2Ch */ + U32 Reserved11; /* 30h */ + U32 Reserved12; /* 34h */ + U32 Reserved13; /* 38h */ + U32 Reserved14; /* 3Ch */ + U32 Reserved15; /* 40h */ +} MPI_BOOT_DEVICE_PCI_SLOT_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_SLOT_NUMBER; + +typedef struct _MPI_BOOT_DEVICE_FC_WWN +{ + U64 WWPN; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved3; /* 18h */ + U32 Reserved4; /* 1Ch */ + U32 Reserved5; /* 20h */ + U32 Reserved6; /* 24h */ + U32 Reserved7; /* 28h */ + U32 Reserved8; /* 2Ch */ + U32 Reserved9; /* 30h */ + U32 Reserved10; /* 34h */ + U32 Reserved11; /* 38h */ + U32 Reserved12; /* 3Ch */ + U32 Reserved13; /* 40h */ +} MPI_BOOT_DEVICE_FC_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_FC_WWN; + +typedef struct _MPI_BOOT_DEVICE_SAS_WWN +{ + U64 SASAddress; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U32 Reserved3; /* 18h */ + U32 Reserved4; /* 1Ch */ + U32 Reserved5; /* 20h */ + U32 Reserved6; /* 24h */ + U32 Reserved7; /* 28h */ + U32 Reserved8; /* 2Ch */ + U32 Reserved9; /* 30h */ + U32 Reserved10; /* 34h */ + U32 Reserved11; /* 38h */ + U32 Reserved12; /* 3Ch */ + U32 Reserved13; /* 40h */ +} MPI_BOOT_DEVICE_SAS_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_SAS_WWN; + +typedef struct _MPI_BOOT_DEVICE_ENCLOSURE_SLOT +{ + U64 EnclosureLogicalID; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U8 LUN[8]; /* 10h */ + U16 SlotNumber; /* 18h */ + U16 Reserved3; /* 1Ah */ + U32 Reserved4; /* 1Ch */ + U32 Reserved5; /* 20h */ + U32 Reserved6; /* 24h */ + U32 Reserved7; /* 28h */ + U32 Reserved8; /* 2Ch */ + U32 Reserved9; /* 30h */ + U32 Reserved10; /* 34h */ + U32 Reserved11; /* 38h */ + U32 Reserved12; /* 3Ch */ + U32 Reserved13; /* 40h */ +} MPI_BOOT_DEVICE_ENCLOSURE_SLOT, + MPI_POINTER PTR_MPI_BOOT_DEVICE_ENCLOSURE_SLOT; + +typedef union _MPI_BIOSPAGE2_BOOT_DEVICE +{ + MPI_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder; + MPI_BOOT_DEVICE_ADAPTER_NUMBER AdapterNumber; + MPI_BOOT_DEVICE_PCI_ADDRESS PCIAddress; + MPI_BOOT_DEVICE_PCI_SLOT_NUMBER PCISlotNumber; + MPI_BOOT_DEVICE_FC_WWN FcWwn; + MPI_BOOT_DEVICE_SAS_WWN SasWwn; + MPI_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot; +} MPI_BIOSPAGE2_BOOT_DEVICE, MPI_POINTER PTR_MPI_BIOSPAGE2_BOOT_DEVICE; + +typedef struct _CONFIG_PAGE_BIOS_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 04h */ + U32 Reserved2; /* 08h */ + U32 Reserved3; /* 0Ch */ + U32 Reserved4; /* 10h */ + U32 Reserved5; /* 14h */ + U32 Reserved6; /* 18h */ + U8 BootDeviceForm; /* 1Ch */ + U8 Reserved7; /* 1Dh */ + U16 Reserved8; /* 1Eh */ + MPI_BIOSPAGE2_BOOT_DEVICE BootDevice; /* 20h */ +} CONFIG_PAGE_BIOS_2, MPI_POINTER PTR_CONFIG_PAGE_BIOS_2, + BIOSPage2_t, MPI_POINTER pBIOSPage2_t; + +#define MPI_BIOSPAGE2_PAGEVERSION (0x01) + +#define MPI_BIOSPAGE2_FORM_MASK (0x0F) +#define MPI_BIOSPAGE2_FORM_ADAPTER_ORDER (0x00) +#define MPI_BIOSPAGE2_FORM_ADAPTER_NUMBER (0x01) +#define MPI_BIOSPAGE2_FORM_PCI_ADDRESS (0x02) +#define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER (0x03) +#define MPI_BIOSPAGE2_FORM_FC_WWN (0x04) +#define MPI_BIOSPAGE2_FORM_SAS_WWN (0x05) + /**************************************************************************** * SCSI Port Config Pages @@ -821,13 +1175,13 @@ typedef struct _CONFIG_PAGE_BIOS_1 typedef struct _CONFIG_PAGE_SCSI_PORT_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Capabilities; /* 04h */ U32 PhysicalInterface; /* 08h */ -} fCONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0, +} CONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0, SCSIPortPage0_t, MPI_POINTER pSCSIPortPage0_t; -#define MPI_SCSIPORTPAGE0_PAGEVERSION (0x01) +#define MPI_SCSIPORTPAGE0_PAGEVERSION (0x02) #define MPI_SCSIPORTPAGE0_CAP_IU (0x00000001) #define MPI_SCSIPORTPAGE0_CAP_DT (0x00000002) @@ -854,6 +1208,7 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0 ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \ >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \ ) +#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000) #define MPI_SCSIPORTPAGE0_CAP_WIDE (0x20000000) #define MPI_SCSIPORTPAGE0_CAP_AIP (0x80000000) @@ -869,13 +1224,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0 typedef struct _CONFIG_PAGE_SCSI_PORT_1 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_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, +} CONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1, SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t; #define MPI_SCSIPORTPAGE1_PAGEVERSION (0x03) @@ -900,11 +1255,11 @@ typedef struct _MPI_DEVICE_INFO typedef struct _CONFIG_PAGE_SCSI_PORT_2 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 PortFlags; /* 04h */ U32 PortSettings; /* 08h */ MPI_DEVICE_INFO DeviceSettings[16]; /* 0Ch */ -} fCONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2, +} CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2, SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t; #define MPI_SCSIPORTPAGE2_PAGEVERSION (0x02) @@ -953,13 +1308,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_2 typedef struct _CONFIG_PAGE_SCSI_DEVICE_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 NegotiatedParameters; /* 04h */ U32 Information; /* 08h */ -} fCONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0, +} CONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0, SCSIDevicePage0_t, MPI_POINTER pSCSIDevicePage0_t; -#define MPI_SCSIDEVPAGE0_PAGEVERSION (0x03) +#define MPI_SCSIDEVPAGE0_PAGEVERSION (0x04) #define MPI_SCSIDEVPAGE0_NP_IU (0x00000001) #define MPI_SCSIDEVPAGE0_NP_DT (0x00000002) @@ -973,6 +1328,7 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_0 #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_IDP (0x08000000) #define MPI_SCSIDEVPAGE0_NP_WIDE (0x20000000) #define MPI_SCSIDEVPAGE0_NP_AIP (0x80000000) @@ -984,14 +1340,14 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_0 typedef struct _CONFIG_PAGE_SCSI_DEVICE_1 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 RequestedParameters; /* 04h */ U32 Reserved; /* 08h */ U32 Configuration; /* 0Ch */ -} fCONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1, +} CONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1, SCSIDevicePage1_t, MPI_POINTER pSCSIDevicePage1_t; -#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x04) +#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x05) #define MPI_SCSIDEVPAGE1_RP_IU (0x00000001) #define MPI_SCSIDEVPAGE1_RP_DT (0x00000002) @@ -1005,6 +1361,7 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_1 #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_IDP (0x08000000) #define MPI_SCSIDEVPAGE1_RP_WIDE (0x20000000) #define MPI_SCSIDEVPAGE1_RP_AIP (0x80000000) @@ -1016,11 +1373,11 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_1 typedef struct _CONFIG_PAGE_SCSI_DEVICE_2 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 DomainValidation; /* 04h */ U32 ParityPipeSelect; /* 08h */ U32 DataPipeSelect; /* 0Ch */ -} fCONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2, +} CONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2, SCSIDevicePage2_t, MPI_POINTER pSCSIDevicePage2_t; #define MPI_SCSIDEVPAGE2_PAGEVERSION (0x01) @@ -1057,12 +1414,12 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_2 typedef struct _CONFIG_PAGE_SCSI_DEVICE_3 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U16 MsgRejectCount; /* 04h */ U16 PhaseErrorCount; /* 06h */ U16 ParityErrorCount; /* 08h */ U16 Reserved; /* 0Ah */ -} fCONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3, +} CONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3, SCSIDevicePage3_t, MPI_POINTER pSCSIDevicePage3_t; #define MPI_SCSIDEVPAGE3_PAGEVERSION (0x00) @@ -1077,7 +1434,7 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_3 typedef struct _CONFIG_PAGE_FC_PORT_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Flags; /* 04h */ U8 MPIPortNumber; /* 08h */ U8 LinkType; /* 09h */ @@ -1098,7 +1455,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_0 U8 MaxHardAliasesSupported; /* 49h */ U8 NumCurrentAliases; /* 4Ah */ U8 Reserved1; /* 4Bh */ -} fCONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0, +} CONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0, FCPortPage0_t, MPI_POINTER pFCPortPage0_t; #define MPI_FCPORTPAGE0_PAGEVERSION (0x02) @@ -1164,10 +1521,9 @@ typedef struct _CONFIG_PAGE_FC_PORT_0 #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 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Flags; /* 04h */ U64 NoSEEPROMWWNN; /* 08h */ U64 NoSEEPROMWWPN; /* 10h */ @@ -1179,7 +1535,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_1 U8 RR_TOV; /* 1Dh */ U8 InitiatorDeviceTimeout; /* 1Eh */ U8 InitiatorIoPendTimeout; /* 1Fh */ -} fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1, +} CONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1, FCPortPage1_t, MPI_POINTER pFCPortPage1_t; #define MPI_FCPORTPAGE1_PAGEVERSION (0x06) @@ -1191,6 +1547,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_1 #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_TARGET_LARGE_CDB_ENABLE (0x00000080) #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) @@ -1227,14 +1584,15 @@ typedef struct _CONFIG_PAGE_FC_PORT_1 #define MPI_FCPORTPAGE1_ALT_CONN_UNKNOWN (0x00) #define MPI_FCPORTPAGE1_INITIATOR_DEV_TIMEOUT_MASK (0x7F) +#define MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16 (0x80) typedef struct _CONFIG_PAGE_FC_PORT_2 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 NumberActive; /* 04h */ U8 ALPA[127]; /* 05h */ -} fCONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2, +} CONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2, FCPortPage2_t, MPI_POINTER pFCPortPage2_t; #define MPI_FCPORTPAGE2_PAGEVERSION (0x01) @@ -1280,9 +1638,9 @@ typedef struct _FC_PORT_PERSISTENT typedef struct _CONFIG_PAGE_FC_PORT_3 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ FC_PORT_PERSISTENT Entry[MPI_FC_PORT_PAGE_3_ENTRY_MAX]; /* 04h */ -} fCONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3, +} CONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3, FCPortPage3_t, MPI_POINTER pFCPortPage3_t; #define MPI_FCPORTPAGE3_PAGEVERSION (0x01) @@ -1290,10 +1648,10 @@ typedef struct _CONFIG_PAGE_FC_PORT_3 typedef struct _CONFIG_PAGE_FC_PORT_4 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 PortFlags; /* 04h */ U32 PortSettings; /* 08h */ -} fCONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4, +} CONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4, FCPortPage4_t, MPI_POINTER pFCPortPage4_t; #define MPI_FCPORTPAGE4_PAGEVERSION (0x00) @@ -1316,15 +1674,15 @@ typedef struct _CONFIG_PAGE_FC_PORT_5_ALIAS_INFO U16 Reserved; /* 02h */ U64 AliasWWNN; /* 04h */ U64 AliasWWPN; /* 0Ch */ -} fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO, +} CONFIG_PAGE_FC_PORT_5_ALIAS_INFO, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5_ALIAS_INFO, FcPortPage5AliasInfo_t, MPI_POINTER pFcPortPage5AliasInfo_t; typedef struct _CONFIG_PAGE_FC_PORT_5 { - fCONFIG_PAGE_HEADER Header; /* 00h */ - fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo; /* 04h */ -} fCONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5, + CONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo; /* 04h */ +} CONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5, FCPortPage5_t, MPI_POINTER pFCPortPage5_t; #define MPI_FCPORTPAGE5_PAGEVERSION (0x02) @@ -1337,7 +1695,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_5 typedef struct _CONFIG_PAGE_FC_PORT_6 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Reserved; /* 04h */ U64 TimeSinceReset; /* 08h */ U64 TxFrames; /* 10h */ @@ -1355,7 +1713,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_6 U64 InvalidTxWordCount; /* 70h */ U64 InvalidCrcCount; /* 78h */ U64 FcpInitiatorIoCount; /* 80h */ -} fCONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6, +} CONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6, FCPortPage6_t, MPI_POINTER pFCPortPage6_t; #define MPI_FCPORTPAGE6_PAGEVERSION (0x00) @@ -1363,10 +1721,10 @@ typedef struct _CONFIG_PAGE_FC_PORT_6 typedef struct _CONFIG_PAGE_FC_PORT_7 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Reserved; /* 04h */ U8 PortSymbolicName[256]; /* 08h */ -} fCONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7, +} CONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7, FCPortPage7_t, MPI_POINTER pFCPortPage7_t; #define MPI_FCPORTPAGE7_PAGEVERSION (0x00) @@ -1374,9 +1732,9 @@ typedef struct _CONFIG_PAGE_FC_PORT_7 typedef struct _CONFIG_PAGE_FC_PORT_8 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 BitVector[8]; /* 04h */ -} fCONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8, +} CONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8, FCPortPage8_t, MPI_POINTER pFCPortPage8_t; #define MPI_FCPORTPAGE8_PAGEVERSION (0x00) @@ -1384,7 +1742,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_8 typedef struct _CONFIG_PAGE_FC_PORT_9 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U32 Reserved; /* 04h */ U64 GlobalWWPN; /* 08h */ U64 GlobalWWNN; /* 10h */ @@ -1396,7 +1754,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_9 U8 IPAddress[16]; /* 28h */ U16 Reserved1; /* 38h */ U16 TopologyDiscoveryFlags; /* 3Ah */ -} fCONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9, +} CONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9, FCPortPage9_t, MPI_POINTER pFCPortPage9_t; #define MPI_FCPORTPAGE9_PAGEVERSION (0x00) @@ -1422,10 +1780,10 @@ typedef struct _CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA U8 VendorOUI[3]; /* 35h */ U8 VendorPN[16]; /* 38h */ U8 VendorRev[4]; /* 48h */ - U16 Reserved4; /* 4Ch */ - U8 Reserved5; /* 4Eh */ + U16 Wavelength; /* 4Ch */ + U8 Reserved4; /* 4Eh */ U8 CC_BASE; /* 4Fh */ -} fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA, +} CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA, FCPortPage10BaseSfpData_t, MPI_POINTER pFCPortPage10BaseSfpData_t; @@ -1481,9 +1839,11 @@ typedef struct _CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA U8 BitRateMin; /* 53h */ U8 VendorSN[16]; /* 54h */ U8 DateCode[8]; /* 64h */ - U8 Reserved5[3]; /* 6Ch */ + U8 DiagMonitoringType; /* 6Ch */ + U8 EnhancedOptions; /* 6Dh */ + U8 SFF8472Compliance; /* 6Eh */ U8 CC_EXT; /* 6Fh */ -} fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA, +} CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA, FCPortPage10ExtendedSfpData_t, MPI_POINTER pFCPortPage10ExtendedSfpData_t; @@ -1496,19 +1856,19 @@ typedef struct _CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA typedef struct _CONFIG_PAGE_FC_PORT_10 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 Flags; /* 04h */ U8 Reserved1; /* 05h */ U16 Reserved2; /* 06h */ U32 HwConfig1; /* 08h */ U32 HwConfig2; /* 0Ch */ - fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA Base; /* 10h */ - fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA Extended; /* 50h */ + CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA Base; /* 10h */ + CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA Extended; /* 50h */ U8 VendorSpecific[32]; /* 70h */ -} fCONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10, +} CONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10, FCPortPage10_t, MPI_POINTER pFCPortPage10_t; -#define MPI_FCPORTPAGE10_PAGEVERSION (0x00) +#define MPI_FCPORTPAGE10_PAGEVERSION (0x01) /* standard MODDEF pin definitions (from GBIC spec.) */ #define MPI_FCPORTPAGE10_FLAGS_MODDEF_MASK (0x00000007) @@ -1534,7 +1894,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_10 typedef struct _CONFIG_PAGE_FC_DEVICE_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U64 WWNN; /* 04h */ U64 WWPN; /* 0Ch */ U32 PortIdentifier; /* 14h */ @@ -1548,7 +1908,7 @@ typedef struct _CONFIG_PAGE_FC_DEVICE_0 U8 FcPhHighestVersion; /* 21h */ U8 CurrentTargetID; /* 22h */ U8 CurrentBus; /* 23h */ -} fCONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0, +} CONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0, FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t; #define MPI_FC_DEVICE_PAGE0_PAGEVERSION (0x03) @@ -1606,6 +1966,7 @@ typedef struct _RAID_VOL0_STATUS #define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL (0x00) #define MPI_RAIDVOL0_STATUS_STATE_DEGRADED (0x01) #define MPI_RAIDVOL0_STATUS_STATE_FAILED (0x02) +#define MPI_RAIDVOL0_STATUS_STATE_MISSING (0x03) typedef struct _RAID_VOL0_SETTINGS { @@ -1616,11 +1977,11 @@ typedef struct _RAID_VOL0_SETTINGS RaidVol0Settings, MPI_POINTER pRaidVol0Settings; /* RAID Volume Page 0 VolumeSettings defines */ - #define MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE (0x0001) #define MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART (0x0002) #define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE (0x0004) #define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC (0x0008) +#define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102 (0x0020) /* obsolete */ #define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0010) #define MPI_RAIDVOL0_SETTING_USE_DEFAULTS (0x8000) @@ -1644,7 +2005,7 @@ typedef struct _RAID_VOL0_SETTINGS typedef struct _CONFIG_PAGE_RAID_VOL_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 VolumeID; /* 04h */ U8 VolumeBus; /* 05h */ U8 VolumeIOC; /* 06h */ @@ -1657,13 +2018,41 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0 U32 Reserved2; /* 1Ch */ U32 Reserved3; /* 20h */ U8 NumPhysDisks; /* 24h */ - U8 Reserved4; /* 25h */ - U16 Reserved5; /* 26h */ + U8 DataScrubRate; /* 25h */ + U8 ResyncRate; /* 26h */ + U8 InactiveStatus; /* 27h */ RAID_VOL0_PHYS_DISK PhysDisk[MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX];/* 28h */ -} fCONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0, +} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0, RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t; -#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x01) +#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x04) + +/* values for RAID Volume Page 0 InactiveStatus field */ +#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) +#define MPI_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01) +#define MPI_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02) +#define MPI_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03) +#define MPI_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04) +#define MPI_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05) +#define MPI_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06) + + +typedef struct _CONFIG_PAGE_RAID_VOL_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 VolumeID; /* 01h */ + U8 VolumeBus; /* 02h */ + U8 VolumeIOC; /* 03h */ + U8 Reserved0; /* 04h */ + U8 GUID[24]; /* 05h */ + U8 Name[32]; /* 20h */ + U64 WWID; /* 40h */ + U32 Reserved1; /* 48h */ + U32 Reserved2; /* 4Ch */ +} CONFIG_PAGE_RAID_VOL_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_1, + RaidVolumePage1_t, MPI_POINTER pRaidVolumePage1_t; + +#define MPI_RAIDVOLPAGE1_PAGEVERSION (0x01) /**************************************************************************** @@ -1714,6 +2103,7 @@ typedef struct _RAID_PHYS_DISK0_STATUS #define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x01) #define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED (0x02) +#define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x04) #define MPI_PHYSDISK0_STATUS_ONLINE (0x00) #define MPI_PHYSDISK0_STATUS_MISSING (0x01) @@ -1726,24 +2116,54 @@ typedef struct _RAID_PHYS_DISK0_STATUS typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_PAGE_HEADER Header; /* 00h */ U8 PhysDiskID; /* 04h */ U8 PhysDiskBus; /* 05h */ U8 PhysDiskIOC; /* 06h */ U8 PhysDiskNum; /* 07h */ RAID_PHYS_DISK0_SETTINGS PhysDiskSettings; /* 08h */ U32 Reserved1; /* 0Ch */ - U32 Reserved2; /* 10h */ - U32 Reserved3; /* 14h */ + U8 ExtDiskIdentifier[8]; /* 10h */ U8 DiskIdentifier[16]; /* 18h */ RAID_PHYS_DISK0_INQUIRY_DATA InquiryData; /* 28h */ RAID_PHYS_DISK0_STATUS PhysDiskStatus; /* 64h */ U32 MaxLBA; /* 68h */ RAID_PHYS_DISK0_ERROR_DATA ErrorData; /* 6Ch */ -} fCONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0, +} CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0, RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t; -#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x00) +#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x01) + + +typedef struct _RAID_PHYS_DISK1_PATH +{ + U8 PhysDiskID; /* 00h */ + U8 PhysDiskBus; /* 01h */ + U16 Reserved1; /* 02h */ + U64 WWID; /* 04h */ + U64 OwnerWWID; /* 0Ch */ + U8 OwnerIdentifier; /* 14h */ + U8 Reserved2; /* 15h */ + U16 Flags; /* 16h */ +} RAID_PHYS_DISK1_PATH, MPI_POINTER PTR_RAID_PHYS_DISK1_PATH, + RaidPhysDisk1Path_t, MPI_POINTER pRaidPhysDisk1Path_t; + +/* RAID Physical Disk Page 1 Flags field defines */ +#define MPI_RAID_PHYSDISK1_FLAG_BROKEN (0x0002) +#define MPI_RAID_PHYSDISK1_FLAG_INVALID (0x0001) + +typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U8 NumPhysDiskPaths; /* 04h */ + U8 PhysDiskNum; /* 05h */ + U16 Reserved2; /* 06h */ + U32 Reserved1; /* 08h */ + RAID_PHYS_DISK1_PATH Path[1]; /* 0Ch */ +} CONFIG_PAGE_RAID_PHYS_DISK_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_1, + RaidPhysDiskPage1_t, MPI_POINTER pRaidPhysDiskPage1_t; + +#define MPI_RAIDPHYSDISKPAGE1_PAGEVERSION (0x00) /**************************************************************************** @@ -1756,7 +2176,7 @@ typedef struct _CONFIG_PAGE_LAN_0 U16 TxRxModes; /* 04h */ U16 Reserved; /* 06h */ U32 PacketPrePad; /* 08h */ -} fCONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0, +} CONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0, LANPage0_t, MPI_POINTER pLANPage0_t; #define MPI_LAN_PAGE0_PAGEVERSION (0x01) @@ -1781,7 +2201,7 @@ typedef struct _CONFIG_PAGE_LAN_1 U32 MaxReplySize; /* 24h */ U32 NegWireSpeedLow; /* 28h */ U32 NegWireSpeedHigh; /* 2Ch */ -} fCONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1, +} CONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1, LANPage1_t, MPI_POINTER pLANPage1_t; #define MPI_LAN_PAGE1_PAGEVERSION (0x03) @@ -1796,11 +2216,11 @@ typedef struct _CONFIG_PAGE_LAN_1 typedef struct _CONFIG_PAGE_INBAND_0 { - fCONFIG_PAGE_HEADER Header; /* 00h */ + CONFIG_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, +} CONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0, InbandPage0_t, MPI_POINTER pInbandPage0_t; #define MPI_INBAND_PAGEVERSION (0x00) @@ -1820,7 +2240,7 @@ typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA U32 ControllerPhyDeviceInfo;/* 04h */ U16 AttachedDeviceHandle; /* 08h */ U16 ControllerDevHandle; /* 0Ah */ - U32 Reserved2; /* 0Ch */ + U32 DiscoveryStatus; /* 0Ch */ } MPI_SAS_IO_UNIT0_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT0_PHY_DATA, SasIOUnit0PhyData, MPI_POINTER pSasIOUnit0PhyData; @@ -1834,22 +2254,21 @@ typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 { - fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + CONFIG_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, +} CONFIG_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) +#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x02) /* 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 */ @@ -1867,6 +2286,20 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0 /* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ +/* values for SAS IO Unit Page 0 DiscoveryStatus */ +#define MPI_SAS_IOUNIT0_DS_LOOP_DETECTED (0x00000001) +#define MPI_SAS_IOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_SAS_IOUNIT0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_SAS_IOUNIT0_DS_EXPANDER_ERR (0x00000008) +#define MPI_SAS_IOUNIT0_DS_SMP_TIMEOUT (0x00000010) +#define MPI_SAS_IOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_SAS_IOUNIT0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_SAS_IOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_SAS_IOUNIT0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI_SAS_IOUNIT0_DS_TABLE_LINK (0x00000400) +#define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) + typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA { @@ -1889,52 +2322,75 @@ typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA 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, + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U16 ControlFlags; /* 08h */ + U16 MaxNumSATATargets; /* 0Ah */ + U32 Reserved1; /* 0Ch */ + U8 NumPhys; /* 10h */ + U8 SATAMaxQDepth; /* 11h */ + U16 Reserved2; /* 12h */ + MPI_SAS_IO_UNIT1_PHY_DATA PhyData[MPI_SAS_IOUNIT1_PHY_MAX]; /* 14h */ +} CONFIG_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) +#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04) + +/* values for SAS IO Unit Page 1 ControlFlags */ +#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) +#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800) + +#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) +#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x10) + +#define MPI_SAS_IOUNIT1_CONTROL_AUTO_PORT_SAME_SAS_ADDR (0x0100) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) +#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008) +#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) +#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) +#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) + +/* values for SAS IO Unit Page 1 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_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) +#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) +#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 */ + CONFIG_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, + U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */ +} CONFIG_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) +#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x03) /* values for SAS IO Unit Page 2 Status field */ #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) @@ -1942,11 +2398,19 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 /* values for SAS IO Unit Page 2 Flags field */ #define MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS (0x01) +/* Physical Mapping Modes */ +#define MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE (0x0E) +#define MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE (1) +#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00) +#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01) +#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02) + +#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10) typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3 { - fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ U32 Reserved1; /* 08h */ U32 MaxInvalidDwordCount; /* 0Ch */ U32 InvalidDwordCountTime; /* 10h */ @@ -1956,18 +2420,24 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3 U32 LossDwordSynchCountTime; /* 20h */ U32 MaxPhyResetProblemCount; /* 24h */ U32 PhyResetProblemTime; /* 28h */ -} fCONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3, +} CONFIG_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) +/**************************************************************************** +* SAS Expander Config Pages +****************************************************************************/ + typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 { - fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ - U32 Reserved1; /* 08h */ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U8 PhysicalPort; /* 08h */ + U8 Reserved1; /* 09h */ + U16 Reserved2; /* 0Ah */ U64 SASAddress; /* 0Ch */ - U32 Reserved2; /* 14h */ + U32 DiscoveryStatus; /* 14h */ U16 DevHandle; /* 18h */ U16 ParentDevHandle; /* 1Ah */ U16 ExpanderChangeCount; /* 1Ch */ @@ -1976,45 +2446,127 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 U8 SASLevel; /* 21h */ U8 Flags; /* 22h */ U8 Reserved3; /* 23h */ -} fCONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, +} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t; -#define MPI_SASEXPANDER0_PAGEVERSION (0x00) +#define MPI_SASEXPANDER0_PAGEVERSION (0x02) + +/* values for SAS Expander Page 0 DiscoveryStatus field */ +#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) +#define MPI_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_SAS_EXPANDER0_DS_EXPANDER_ERR (0x00000008) +#define MPI_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010) +#define MPI_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400) +#define MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800) /* 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_EXPANDER_1 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U8 PhysicalPort; /* 08h */ + U8 Reserved1; /* 09h */ + U16 Reserved2; /* 0Ah */ + U8 NumPhys; /* 0Ch */ + U8 Phy; /* 0Dh */ + U16 NumTableEntriesProgrammed; /* 0Eh */ + U8 ProgrammedLinkRate; /* 10h */ + U8 HwLinkRate; /* 11h */ + U16 AttachedDevHandle; /* 12h */ + U32 PhyInfo; /* 14h */ + U32 AttachedDeviceInfo; /* 18h */ + U16 OwnerDevHandle; /* 1Ch */ + U8 ChangeCount; /* 1Eh */ + U8 NegotiatedLinkRate; /* 1Fh */ + U8 PhyIdentifier; /* 20h */ + U8 AttachedPhyIdentifier; /* 21h */ + U8 NumTableEntriesProg; /* 22h */ + U8 DiscoveryInfo; /* 23h */ + U32 Reserved3; /* 24h */ +} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1, + SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t; + +#define MPI_SASEXPANDER1_PAGEVERSION (0x01) + +/* use MPI_SAS_PHY0_PRATE_ defines for ProgrammedLinkRate */ + +/* use MPI_SAS_PHY0_HWRATE_ defines for HwLinkRate */ + +/* use MPI_SAS_PHY0_PHYINFO_ defines for PhyInfo */ + +/* see mpi_sas.h for values for SAS Expander Page 1 AttachedDeviceInfo values */ + +/* values for SAS Expander Page 1 DiscoveryInfo field */ +#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY DISABLED (0x04) +#define MPI_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) +#define MPI_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) + +/* values for SAS Expander Page 1 NegotiatedLinkRate field */ +#define MPI_SAS_EXPANDER1_NEG_RATE_UNKNOWN (0x00) +#define MPI_SAS_EXPANDER1_NEG_RATE_PHY_DISABLED (0x01) +#define MPI_SAS_EXPANDER1_NEG_RATE_FAILED_NEGOTIATION (0x02) +#define MPI_SAS_EXPANDER1_NEG_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI_SAS_EXPANDER1_NEG_RATE_1_5 (0x08) +#define MPI_SAS_EXPANDER1_NEG_RATE_3_0 (0x09) + + +/**************************************************************************** +* SAS Device Config Pages +****************************************************************************/ + typedef struct _CONFIG_PAGE_SAS_DEVICE_0 { - fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ - U32 Reserved1; /* 08h */ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U16 Slot; /* 08h */ + U16 EnclosureHandle; /* 0Ah */ U64 SASAddress; /* 0Ch */ - U32 Reserved2; /* 14h */ + U16 ParentDevHandle; /* 14h */ + U8 PhyNum; /* 16h */ + U8 AccessStatus; /* 17h */ 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, + U8 Reserved2; /* 23h */ +} CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0, SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t; -#define MPI_SASDEVICE0_PAGEVERSION (0x00) +#define MPI_SASDEVICE0_PAGEVERSION (0x04) + +/* values for SAS Device Page 0 AccessStatus field */ +#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) /* 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) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) +#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) +#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) +#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) +#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) +#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) +#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) /* 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 */ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ U32 Reserved1; /* 08h */ U64 SASAddress; /* 0Ch */ U32 Reserved2; /* 14h */ @@ -2022,15 +2574,30 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_1 U8 TargetID; /* 1Ah */ U8 Bus; /* 1Bh */ U8 InitialRegDeviceFIS[20];/* 1Ch */ -} fCONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1, +} CONFIG_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_DEVICE_2 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U64 PhysicalIdentifier; /* 08h */ + U32 Reserved1; /* 10h */ +} CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2, + SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t; + +#define MPI_SASDEVICE2_PAGEVERSION (0x00) + + +/**************************************************************************** +* SAS PHY Config Pages +****************************************************************************/ + typedef struct _CONFIG_PAGE_SAS_PHY_0 { - fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ U32 Reserved1; /* 08h */ U64 SASAddress; /* 0Ch */ U16 AttachedDevHandle; /* 14h */ @@ -2042,7 +2609,7 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0 U8 ChangeCount; /* 22h */ U8 Reserved3; /* 23h */ U32 PhyInfo; /* 24h */ -} fCONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0, +} CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0, SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t; #define MPI_SASPHY0_PAGEVERSION (0x00) @@ -2089,17 +2656,95 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0 typedef struct _CONFIG_PAGE_SAS_PHY_1 { - fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + CONFIG_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, +} CONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1, SasPhyPage1_t, MPI_POINTER pSasPhyPage1_t; #define MPI_SASPHY1_PAGEVERSION (0x00) +/**************************************************************************** +* SAS Enclosure Config Pages +****************************************************************************/ + +typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U64 EnclosureLogicalID; /* 0Ch */ + U16 Flags; /* 14h */ + U16 EnclosureHandle; /* 16h */ + U16 NumSlots; /* 18h */ + U16 StartSlot; /* 1Ah */ + U8 StartTargetID; /* 1Ch */ + U8 StartBus; /* 1Dh */ + U8 SEPTargetID; /* 1Eh */ + U8 SEPBus; /* 1Fh */ + U32 Reserved2; /* 20h */ + U32 Reserved3; /* 24h */ +} CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0, + SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t; + +#define MPI_SASENCLOSURE0_PAGEVERSION (0x00) + +/* values for SAS Enclosure Page 0 Flags field */ +#define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID (0x0020) +#define MPI_SAS_ENCLS0_FLAGS_START_BUS_ID_VALID (0x0010) + +#define MPI_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) +#define MPI_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) +#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) +#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) +#define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) +#define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) + + +/**************************************************************************** +* Log Config Pages +****************************************************************************/ +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check NumLogEntries at runtime. + */ +#ifndef MPI_LOG_0_NUM_LOG_ENTRIES +#define MPI_LOG_0_NUM_LOG_ENTRIES (1) +#endif + +#define MPI_LOG_0_LOG_DATA_LENGTH (20) + +typedef struct _MPI_LOG_0_ENTRY +{ + U64 WWID; /* 00h */ + U32 TimeStamp; /* 08h */ + U32 Reserved1; /* 0Ch */ + U16 LogSequence; /* 10h */ + U16 LogEntryQualifier; /* 12h */ + U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */ +} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY, + MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t; + +/* values for Log Page 0 LogEntry LogEntryQualifier field */ +#define MPI_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000) +#define MPI_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001) + +typedef struct _CONFIG_PAGE_LOG_0 +{ + CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ + U32 Reserved1; /* 08h */ + U32 Reserved2; /* 0Ch */ + U16 NumLogEntries; /* 10h */ + U16 Reserved3; /* 12h */ + MPI_LOG_0_ENTRY LogEntry[MPI_LOG_0_NUM_LOG_ENTRIES]; /* 14h */ +} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0, + LogPage0_t, MPI_POINTER pLogPage0_t; + +#define MPI_LOG_0_PAGEVERSION (0x00) + + #endif diff --git a/drivers/message/fusion/lsi/mpi_fc.h b/drivers/message/fusion/lsi/mpi_fc.h index ea266b236c1f..51a6aeb990ba 100644 --- a/drivers/message/fusion/lsi/mpi_fc.h +++ b/drivers/message/fusion/lsi/mpi_fc.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_fc.h * Title: MPI Fibre Channel messages and structures * Creation Date: June 12, 2000 * - * mpi_fc.h Version: 01.05.xx + * mpi_fc.h Version: 01.05.01 * * Version History * --------------- @@ -36,6 +36,9 @@ * 09-28-01 01.02.02 Change name of reserved field in * MSG_LINK_SERVICE_RSP_REPLY. * 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests. + * 01-16-04 01.02.04 Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. * -------------------------------------------------------------------------- */ diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index 0deb7721e936..c9edbee41edf 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt @@ -3,25 +3,28 @@ MPI Header File Change History ============================== - Copyright (c) 2000-2001 LSI Logic Corporation. + Copyright (c) 2000-2005 LSI Logic Corporation. --------------------------------------- - Header Set Release Version: 01.01.10 - Header Set Release Date: 04-09-01 + Header Set Release Version: 01.05.09 + Header Set Release Date: 03-11-05 --------------------------------------- Filename Current version Prior version ---------- --------------- ------------- - mpi.h 01.01.07 01.01.06 - mpi_ioc.h 01.01.07 01.01.06 - mpi_cnfg.h 01.01.11 01.01.10 - mpi_init.h 01.01.05 01.01.04 - mpi_targ.h 01.01.04 01.01.04 - mpi_fc.h 01.01.07 01.01.06 - mpi_lan.h 01.01.03 01.01.03 - mpi_raid.h 01.01.02 01.01.02 - mpi_type.h 01.01.02 01.01.02 - mpi_history.txt 01.01.09 01.01.09 + mpi.h 01.05.07 01.05.06 + mpi_ioc.h 01.05.08 01.05.07 + mpi_cnfg.h 01.05.08 01.05.07 + mpi_init.h 01.05.04 01.05.03 + mpi_targ.h 01.05.04 01.05.03 + mpi_fc.h 01.05.01 01.05.01 + mpi_lan.h 01.05.01 01.05.01 + mpi_raid.h 01.05.02 01.05.02 + mpi_tool.h 01.05.03 01.05.03 + mpi_inb.h 01.05.01 01.05.01 + mpi_sas.h 01.05.01 01.05.01 + mpi_type.h 01.05.01 01.05.01 + mpi_history.txt 01.05.09 01.05.08 * Date Version Description @@ -53,6 +56,38 @@ mpi.h * Added function codes for RAID. * 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE, * MPI_DOORBELL_USED, to better match the spec. + * 08-08-01 01.02.01 Original release for v1.2 work. + * Changed MPI_VERSION_MINOR from 0x01 to 0x02. + * Added define MPI_FUNCTION_TOOLBOX. + * 09-28-01 01.02.02 New function code MPI_SCSI_ENCLOSURE_PROCESSOR. + * 11-01-01 01.02.03 Changed name to MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR. + * 03-14-02 01.02.04 Added MPI_HEADER_VERSION_ defines. + * 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. + * 01-16-04 01.02.11 Added define for MPI_IOCLOGINFO_TYPE_SHIFT. + * 04-29-04 01.02.12 Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST + * and MPI_FUNCTION_DIAG_RELEASE. + * Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define. + * Bumped MPI_HEADER_VERSION_UNIT value. + * 05-11-04 01.03.01 Bumped MPI_VERSION_MINOR for MPI v1.3. + * Added codes for Inband. + * 08-19-04 01.05.01 Added defines for Host Buffer Access Control doorbell. + * Added define for offset of High Priority Request Queue. + * Added new function codes and new IOCStatus codes. + * Added a IOCLogInfo type of SAS. + * 12-07-04 01.05.02 Bumped MPI_HEADER_VERSION_UNIT. + * 12-09-04 01.05.03 Bumped MPI_HEADER_VERSION_UNIT. + * 01-15-05 01.05.04 Bumped MPI_HEADER_VERSION_UNIT. + * 02-09-05 01.05.05 Bumped MPI_HEADER_VERSION_UNIT. + * 02-22-05 01.05.06 Bumped MPI_HEADER_VERSION_UNIT. + * 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and + * TargetAssistExtended requests. + * Removed EEDP IOCStatus codes. * -------------------------------------------------------------------------- mpi_ioc.h @@ -81,6 +116,49 @@ mpi_ioc.h * 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER. * Added structure offset comments. * 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE. + * 08-08-01 01.02.01 Original release for v1.2 work. + * New format for FWVersion and ProductId in + * MSG_IOC_FACTS_REPLY and MPI_FW_HEADER. + * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and + * related structure and defines. + * Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED. + * Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE. + * Replaced a reserved field in MSG_IOC_FACTS_REPLY with + * IOCExceptions and changed DataImageSize to reserved. + * Added MPI_FW_DOWNLOAD_ITYPE_NVSTORE_DATA and + * MPI_FW_UPLOAD_ITYPE_NVDATA. + * 09-28-01 01.02.03 Modified Event Data for Integrated RAID. + * 11-01-01 01.02.04 Added defines for MPI_EXT_IMAGE_HEADER ImageType field. + * 03-14-02 01.02.05 Added HeaderVersion field to MSG_IOC_FACTS_REPLY. + * 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. + * 04-29-04 01.02.09 Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and + * added related defines. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added four new fields to MSG_IOC_INIT. + * Added three new fields to MSG_IOC_FACTS_REPLY. + * Defined four new bits for the IOCCapabilities field of + * the IOCFacts reply. + * Added two new PortTypes for the PortFacts reply. + * Added six new events along with their EventData + * structures. + * Added a new MsgFlag to the FwDownload request to + * indicate last segment. + * Defined a new image type of boot loader. + * Added FW family codes for SAS product families. + * 10-05-04 01.05.02 Added ReplyFifoHostSignalingAddr field to + * MSG_IOC_FACTS_REPLY. + * 12-07-04 01.05.03 Added more defines for SAS Discovery Error event. + * 12-09-04 01.05.04 Added Unsupported device to SAS Device event. + * 01-15-05 01.05.05 Added event data for SAS SES Event. + * 02-09-05 01.05.06 Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define. + * 02-22-05 01.05.07 Added Host Page Buffer Persistent flag to IOC Facts + * Reply and IOC Init Request. + * 03-11-05 01.05.08 Added family code for 1068E family. + * Removed IOCFacts Reply EEDP Capability bit. * -------------------------------------------------------------------------- mpi_cnfg.h @@ -142,6 +220,166 @@ mpi_cnfg.h * Added IO Unit Page 3. * Modified defines for Scsi Port Page 2. * Modified RAID Volume Pages. + * 08-08-01 01.02.01 Original release for v1.2 work. + * Added SepID and SepBus to RVP2 IMPhysicalDisk struct. + * Added defines for the SEP bits in RVP2 VolumeSettings. + * Modified the DeviceSettings field in RVP2 to use the + * proper structure. + * Added defines for SES, SAF-TE, and cross channel for + * IOCPage2 CapabilitiesFlags. + * Removed define for MPI_IOUNITPAGE2_FLAGS_RAID_DISABLE. + * Removed define for + * MPI_SCSIPORTPAGE2_PORT_FLAGS_PARITY_ENABLE. + * Added define for MPI_CONFIG_PAGEATTR_RO_PERSISTENT. + * 08-29-01 01.02.02 Fixed value for MPI_MANUFACTPAGE_DEVID_53C1035. + * Added defines for MPI_FCPORTPAGE1_FLAGS_HARD_ALPA_ONLY + * and MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY. + * Removed MPI_SCSIPORTPAGE0_CAP_PACING_TRANSFERS, + * MPI_SCSIDEVPAGE0_NP_PACING_TRANSFERS, and + * MPI_SCSIDEVPAGE1_RP_PACING_TRANSFERS, and + * MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED. + * Added defines for MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED + * and MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED. + * Added OnBusTimerValue to CONFIG_PAGE_SCSI_PORT_1. + * Added rejected bits to SCSI Device Page 0 Information. + * Increased size of ALPA array in FC Port Page 2 by one + * and removed a one byte reserved field. + * 09-28-01 01.02.03 Swapped NegWireSpeedLow and NegWireSpeedLow in + * CONFIG_PAGE_LAN_1 to match preferred 64-bit ordering. + * Added structures for Manufacturing Page 4, IO Unit + * Page 3, IOC Page 3, IOC Page 4, RAID Volume Page 0, and + * RAID PhysDisk Page 0. + * 10-04-01 01.02.04 Added define for MPI_CONFIG_PAGETYPE_RAID_PHYSDISK. + * Modified some of the new defines to make them 32 + * character unique. + * Modified how variable length pages (arrays) are defined. + * Added generic defines for hot spare pools and RAID + * volume types. + * 11-01-01 01.02.05 Added define for MPI_IOUNITPAGE1_DISABLE_IR. + * 03-14-02 01.02.06 Added PCISlotNum field to CONFIG_PAGE_IOC_1 along with + * related define, and bumped the page version define. + * 05-31-02 01.02.07 Added a Flags field to CONFIG_PAGE_IOC_2_RAID_VOL in a + * reserved byte and added a define. + * Added define for + * MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE. + * Added new config page: CONFIG_PAGE_IOC_5. + * Added MaxAliases, MaxHardAliases, and NumCurrentAliases + * fields to CONFIG_PAGE_FC_PORT_0. + * Added AltConnector and NumRequestedAliases fields to + * CONFIG_PAGE_FC_PORT_1. + * Added new config page: CONFIG_PAGE_FC_PORT_10. + * 07-12-02 01.02.08 Added more MPI_MANUFACTPAGE_DEVID_ defines. + * Added additional MPI_SCSIDEVPAGE0_NP_ defines. + * Added more MPI_SCSIDEVPAGE1_RP_ defines. + * Added define for + * 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 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. + * 01-16-04 01.02.13 Added InitiatorDeviceTimeout and InitiatorIoPendTimeout + * fields and related defines to CONFIG_PAGE_FC_PORT_1. + * Added define for + * MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK. + * Added new fields to the substructures of + * CONFIG_PAGE_FC_PORT_10. + * 04-29-04 01.02.14 Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0, + * CONFIG_PAGE_SCSI_DEVICE_0, and + * CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for + * these pages. + * 05-11-04 01.03.01 Added structure for CONFIG_PAGE_INBAND_0. + * 08-19-04 01.05.01 Modified MSG_CONFIG request to support extended config + * pages. + * Added a new structure for extended config page header. + * Added new extended config pages types and structures for + * SAS IO Unit, SAS Expander, SAS Device, and SAS PHY. + * Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4 + * to add a Flags field. + * Two new Manufacturing config pages (5 and 6). + * Two new bits defined for IO Unit Page 1 Flags field. + * Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields + * to specify the BIOS boot device. + * Four new Flags bits defined for IO Unit Page 2. + * Added IO Unit Page 4. + * Added EEDP Flags settings to IOC Page 1. + * Added new BIOS Page 1 config page. + * 10-05-04 01.05.02 Added define for + * MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE. + * Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and + * associated defines. + * Added more defines for SAS IO Unit Page 0 + * DiscoveryStatus field. + * Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK + * and MPI_SAS_IOUNIT0_DS_TABLE_LINK. + * Added defines for Physical Mapping Modes to SAS IO Unit + * Page 2. + * Added define for + * MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH. + * 10-27-04 01.05.03 Added defines for new SAS PHY page addressing mode. + * Added defines for MaxTargetSpinUp to BIOS Page 1. + * Added 5 new ControlFlags defines for SAS IO Unit + * Page 1. + * Added MaxNumPhysicalMappedIDs field to SAS IO Unit + * Page 2. + * Added AccessStatus field to SAS Device Page 0 and added + * new Flags bits for supported SATA features. + * 12-07-04 01.05.04 Added config page structures for BIOS Page 2, RAID + * Volume Page 1, and RAID Physical Disk Page 1. + * Replaced IO Unit Page 1 BootTargetID,BootBus, and + * BootAdapterNum with reserved field. + * Added DataScrubRate and ResyncRate to RAID Volume + * Page 0. + * Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT + * define. + * 12-09-04 01.05.05 Added Target Mode Large CDB Enable to FC Port Page 1 + * Flags field. + * Added Auto Port Config flag define for SAS IOUNIT + * Page 1 ControlFlags. + * Added Disabled bad Phy define to Expander Page 1 + * Discovery Info field. + * Added SAS/SATA device support to SAS IOUnit Page 1 + * ControlFlags. + * Added Unsupported device to SAS Dev Page 0 Flags field + * Added disable use SATA Hash Address for SAS IOUNIT + * page 1 in ControlFields. + * 01-15-05 01.05.06 Added defaults for data scrub rate and resync rate to + * Manufacturing Page 4. + * Added new defines for BIOS Page 1 IOCSettings field. + * Added ExtDiskIdentifier field to RAID Physical Disk + * Page 0. + * Added new defines for SAS IO Unit Page 1 ControlFlags + * and to SAS Device Page 0 Flags to control SATA devices. + * Added defines and structures for the new Log Page 0, a + * new type of configuration page. + * 02-09-05 01.05.07 Added InactiveStatus field to RAID Volume Page 0. + * Added WWID field to RAID Volume Page 1. + * Added PhysicalPort field to SAS Expander pages 0 and 1. + * 03-11-05 01.05.08 Removed the EEDP flags from IOC Page 1. + * Added Enclosure/Slot boot device format to BIOS Page 2. + * New status value for RAID Volume Page 0 VolumeStatus + * (VolumeState subfield). + * New value for RAID Physical Page 0 InactiveStatus. + * Added Inactive Volume Member flag RAID Physical Disk + * Page 0 PhysDiskStatus field. + * New physical mapping mode in SAS IO Unit Page 2. + * Added CONFIG_PAGE_SAS_ENCLOSURE_0. + * Added Slot and Enclosure fields to SAS Device Page 0. * -------------------------------------------------------------------------- mpi_init.h @@ -154,6 +392,32 @@ mpi_init.h * 02-20-01 01.01.03 Started using MPI_POINTER. * 03-27-01 01.01.04 Added structure offset comments. * 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 08-29-01 01.02.02 Added MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET. + * Added MPI_SCSI_STATE_QUEUE_TAG_REJECTED for + * MSG_SCSI_IO_REPLY. + * 09-28-01 01.02.03 Added structures and defines for SCSI Enclosure + * Processor messages. + * 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. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added MsgFlags defines for EEDP to SCSI IO request. + * Added new word to MSG_SCSI_IO_REPLY to add TaskTag field + * and a reserved U16. + * Added new MSG_SCSI_IO32_REQUEST structure. + * Added a TaskType of Clear Task Set to SCSI + * Task Management request. + * 12-07-04 01.05.02 Added support for Task Management Query Task. + * 01-15-05 01.05.03 Modified SCSI Enclosure Processor Request to support + * WWID addressing. + * 03-11-05 01.05.04 Removed EEDP flags from SCSI IO Request. + * Removed SCSI IO 32 Request. + * Modified SCSI Enclosure Processor Request and Reply to + * support Enclosure/Slot addressing rather than WWID + * addressing. * -------------------------------------------------------------------------- mpi_targ.h @@ -170,6 +434,33 @@ mpi_targ.h * Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and * MPI_TARGET_FCP_CMD_BUFFER. * 03-27-01 01.01.04 Added structure offset comments. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 09-28-01 01.02.02 Added structure for MPI_TARGET_SCSI_SPI_STATUS_IU. + * Added PriorityReason field to some replies and + * defined more PriorityReason codes. + * Added some defines for to support previous version + * of MPI. + * 10-04-01 01.02.03 Added PriorityReason to MSG_TARGET_ERROR_REPLY. + * 11-01-01 01.02.04 Added define for TARGET_STATUS_SEND_FLAGS_HIGH_PRIORITY. + * 03-14-02 01.02.05 Modified MPI_TARGET_FCP_RSP_BUFFER to get the proper + * byte ordering. + * 05-31-02 01.02.06 Modified TARGET_MODE_REPLY_ALIAS_MASK to only include + * one bit. + * 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. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added new request message structures for + * MSG_TARGET_CMD_BUF_POST_BASE_REQUEST, + * MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and + * MSG_TARGET_ASSIST_EXT_REQUEST. + * Added new structures for SAS SSP Command buffer, SSP + * Task buffer, and SSP Status IU. + * 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added. + * 02-22-05 01.05.03 Changed a comment. + * 03-11-05 01.05.04 Removed TargetAssistExtended Request. * -------------------------------------------------------------------------- mpi_fc.h @@ -192,6 +483,13 @@ mpi_fc.h * Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define. * Added structure offset comments. * 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 09-28-01 01.02.02 Change name of reserved field in + * MSG_LINK_SERVICE_RSP_REPLY. + * 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests. + * 01-16-04 01.02.04 Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. * -------------------------------------------------------------------------- mpi_lan.h @@ -209,11 +507,56 @@ mpi_lan.h * 11-02-00 01.01.01 Original release for post 1.0 work * 02-20-01 01.01.02 Started using MPI_POINTER. * 03-27-01 01.01.03 Added structure offset comments. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. * -------------------------------------------------------------------------- mpi_raid.h * 02-27-01 01.01.01 Original release for this file. * 03-27-01 01.01.02 Added structure offset comments. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines. + * 09-28-01 01.02.02 Major rework for MPI v1.2 Integrated RAID changes. + * 10-04-01 01.02.03 Added ActionData defines for + * MPI_RAID_ACTION_DELETE_VOLUME action. + * 11-01-01 01.02.04 Added define for MPI_RAID_ACTION_ADATA_DO_NOT_SYNC. + * 03-14-02 01.02.05 Added define for MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT. + * 05-07-02 01.02.06 Added define for MPI_RAID_ACTION_ACTIVATE_VOLUME, + * 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. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * 01-15-05 01.05.02 Added defines for the two new RAID Actions for + * _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE. + * -------------------------------------------------------------------------- + +mpi_tool.h + * 08-08-01 01.02.01 Original release. + * 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines. + * 01-16-04 01.02.03 Added defines and structures for new tools + *. MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and + * MPI_TOOLBOX_FC_MANAGEMENT_TOOL. + * 04-29-04 01.02.04 Added message structures for Diagnostic Buffer Post and + * Diagnostic Release requests and replies. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * 10-06-04 01.05.02 Added define for MPI_DIAG_BUF_TYPE_COUNT. + * 02-09-05 01.05.03 Added frame size option to FC management tool. + * Added Beacon tool to the Toolbox. + * -------------------------------------------------------------------------- + +mpi_inb.h + * 05-11-04 01.03.01 Original release. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * -------------------------------------------------------------------------- + +mpi_sas.h + * 08-19-04 01.05.01 Original release. * -------------------------------------------------------------------------- mpi_type.h @@ -221,21 +564,83 @@ mpi_type.h * 06-06-00 01.00.01 Update version number for 1.0 release. * 11-02-00 01.01.01 Original release for post 1.0 work * 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER. + * 08-08-01 01.02.01 Original release for v1.2 work. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. * -------------------------------------------------------------------------- mpi_history.txt Parts list history -Filename 01.01.10 +Filename 01.05.09 ---------- -------- -mpi.h 01.01.07 -mpi_ioc.h 01.01.07 -mpi_cnfg.h 01.01.11 -mpi_init.h 01.01.05 -mpi_targ.h 01.01.04 -mpi_fc.h 01.01.07 -mpi_lan.h 01.01.03 -mpi_raid.h 01.01.02 -mpi_type.h 01.01.02 +mpi.h 01.05.07 +mpi_ioc.h 01.05.08 +mpi_cnfg.h 01.05.08 +mpi_init.h 01.05.04 +mpi_targ.h 01.05.04 +mpi_fc.h 01.05.01 +mpi_lan.h 01.05.01 +mpi_raid.h 01.05.02 +mpi_tool.h 01.05.03 +mpi_inb.h 01.05.01 +mpi_sas.h 01.05.01 +mpi_type.h 01.05.01 + +Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 +---------- -------- -------- -------- -------- -------- -------- +mpi.h 01.05.06 01.05.05 01.05.04 01.05.03 01.05.02 01.05.01 +mpi_ioc.h 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 01.05.02 +mpi_cnfg.h 01.05.07 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 +mpi_init.h 01.05.03 01.05.03 01.05.03 01.05.02 01.05.02 01.05.01 +mpi_targ.h 01.05.03 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 +mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01 +mpi_tool.h 01.05.03 01.05.03 01.05.02 01.05.02 01.05.02 01.05.02 +mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_sas.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_type.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 + +Filename 01.05.02 01.05.01 01.03.01 01.02.14 01.02.13 01.02.12 +---------- -------- -------- -------- -------- -------- -------- +mpi.h 01.05.01 01.05.01 01.03.01 01.02.12 01.02.11 01.02.10 +mpi_ioc.h 01.05.02 01.05.01 01.03.01 01.02.09 01.02.08 01.02.08 +mpi_cnfg.h 01.05.02 01.05.01 01.03.01 01.02.14 01.02.13 01.02.12 +mpi_init.h 01.05.01 01.05.01 01.03.01 01.02.07 01.02.07 01.02.07 +mpi_targ.h 01.05.02 01.05.01 01.03.01 01.02.09 01.02.09 01.02.09 +mpi_fc.h 01.05.01 01.05.01 01.03.01 01.02.04 01.02.04 01.02.03 +mpi_lan.h 01.05.01 01.05.01 01.03.01 01.02.01 01.02.01 01.02.01 +mpi_raid.h 01.05.01 01.05.01 01.03.01 01.02.09 01.02.09 01.02.09 +mpi_tool.h 01.05.02 01.05.01 01.03.01 01.02.01 01.02.01 01.02.01 +mpi_inb.h 01.05.01 01.05.01 01.03.01 +mpi_sas.h 01.05.01 01.05.01 +mpi_type.h 01.05.01 01.05.01 01.03.01 01.02.04 01.02.03 01.02.02 + +Filename 01.02.11 01.02.10 01.02.09 01.02.08 01.02.07 01.02.06 +---------- -------- -------- -------- -------- -------- -------- +mpi.h 01.02.09 01.02.08 01.02.07 01.02.06 01.02.05 01.02.04 +mpi_ioc.h 01.02.07 01.02.06 01.02.06 01.02.06 01.02.06 01.02.05 +mpi_cnfg.h 01.02.11 01.02.10 01.02.09 01.02.08 01.02.07 01.02.06 +mpi_init.h 01.02.06 01.02.06 01.02.05 01.02.05 01.02.05 01.02.04 +mpi_targ.h 01.02.09 01.02.08 01.02.07 01.02.06 01.02.06 01.02.05 +mpi_fc.h 01.02.03 01.02.03 01.02.03 01.02.03 01.02.03 01.02.02 +mpi_lan.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 +mpi_raid.h 01.02.09 01.02.08 01.02.07 01.02.07 01.02.06 01.02.05 +mpi_tool.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 +mpi_type.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.02 01.02.02 + +Filename 01.02.05 01.02.04 01.02.03 01.02.02 01.02.01 01.01.10 +---------- -------- -------- -------- -------- -------- -------- +mpi.h 01.02.03 01.02.02 01.02.02 01.02.01 01.02.01 01.01.07 +mpi_ioc.h 01.02.04 01.02.03 01.02.03 01.02.02 01.02.01 01.01.07 +mpi_cnfg.h 01.02.05 01.02.04 01.02.03 01.02.02 01.02.01 01.01.11 +mpi_init.h 01.02.04 01.02.04 01.02.03 01.02.02 01.02.01 01.01.05 +mpi_targ.h 01.02.04 01.02.03 01.02.02 01.02.01 01.02.01 01.01.04 +mpi_fc.h 01.02.02 01.02.02 01.02.02 01.02.01 01.02.01 01.01.07 +mpi_lan.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.01.03 +mpi_raid.h 01.02.04 01.02.03 01.02.02 01.02.01 01.02.01 01.01.02 +mpi_tool.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.01 +mpi_type.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.01 01.01.02 Filename 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 01.01.04 ---------- -------- -------- -------- -------- -------- -------- diff --git a/drivers/message/fusion/lsi/mpi_inb.h b/drivers/message/fusion/lsi/mpi_inb.h index dae29fbed56f..ff167309ba27 100644 --- a/drivers/message/fusion/lsi/mpi_inb.h +++ b/drivers/message/fusion/lsi/mpi_inb.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2003 LSI Logic Corporation. + * Copyright (c) 2003-2004 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 + * mpi_inb.h Version: 01.05.01 * * Version History * --------------- * * Date Version Description * -------- -------- ------------------------------------------------------ - * ??-??-?? 01.03.01 Original release. + * 05-11-04 01.03.01 Original release. + * 08-19-04 01.05.01 Original release for MPI v1.5. * -------------------------------------------------------------------------- */ diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h index b3c95fd7256f..aca035801a86 100644 --- a/drivers/message/fusion/lsi/mpi_init.h +++ b/drivers/message/fusion/lsi/mpi_init.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2005 LSI Logic Corporation. * * * Name: mpi_init.h * Title: MPI initiator mode messages and structures * Creation Date: June 8, 2000 * - * mpi_init.h Version: 01.05.xx + * mpi_init.h Version: 01.05.04 * * Version History * --------------- @@ -33,6 +33,21 @@ * 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. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added MsgFlags defines for EEDP to SCSI IO request. + * Added new word to MSG_SCSI_IO_REPLY to add TaskTag field + * and a reserved U16. + * Added new MSG_SCSI_IO32_REQUEST structure. + * Added a TaskType of Clear Task Set to SCSI + * Task Management request. + * 12-07-04 01.05.02 Added support for Task Management Query Task. + * 01-15-05 01.05.03 Modified SCSI Enclosure Processor Request to support + * WWID addressing. + * 03-11-05 01.05.04 Removed EEDP flags from SCSI IO Request. + * Removed SCSI IO 32 Request. + * Modified SCSI Enclosure Processor Request and Reply to + * support Enclosure/Slot addressing rather than WWID + * addressing. * -------------------------------------------------------------------------- */ @@ -76,20 +91,12 @@ typedef struct _MSG_SCSI_IO_REQUEST #define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH (0x01) #define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32 (0x00) #define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 (0x01) + #define MPI_SCSIIO_MSGFLGS_SENSE_LOCATION (0x02) #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) +#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04) /* SCSI IO LUN fields */ @@ -148,6 +155,8 @@ typedef struct _MSG_SCSI_IO_REPLY U32 TransferCount; /* 14h */ U32 SenseCount; /* 18h */ U32 ResponseInfo; /* 1Ch */ + U16 TaskTag; /* 20h */ + U16 Reserved1; /* 22h */ } MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY, SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t; @@ -190,32 +199,7 @@ typedef struct _MSG_SCSI_IO_REPLY #define MPI_SCSI_RSP_INFO_TASK_MGMT_FAILED (0x05000000) #define MPI_SCSI_RSP_INFO_SPI_LQ_INVALID_TYPE (0x06000000) - -/****************************************************************************/ -/* 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 */ +#define MPI_SCSI_TASKTAG_UNKNOWN (0xFFFF) /****************************************************************************/ @@ -247,6 +231,7 @@ typedef struct _MSG_SCSI_TASK_MGMT #define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x04) #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) #define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) +#define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) /* MsgFlags bits */ #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00) @@ -260,7 +245,7 @@ typedef struct _MSG_SCSI_TASK_MGMT_REPLY U8 Bus; /* 01h */ U8 MsgLength; /* 02h */ U8 Function; /* 03h */ - U8 Reserved; /* 04h */ + U8 ResponseCode; /* 04h */ U8 TaskType; /* 05h */ U8 Reserved1; /* 06h */ U8 MsgFlags; /* 07h */ @@ -272,6 +257,15 @@ typedef struct _MSG_SCSI_TASK_MGMT_REPLY } MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY, SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t; +/* ResponseCode values */ +#define MPI_SCSITASKMGMT_RSP_TM_COMPLETE (0x00) +#define MPI_SCSITASKMGMT_RSP_INVALID_FRAME (0x02) +#define MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04) +#define MPI_SCSITASKMGMT_RSP_TM_FAILED (0x05) +#define MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08) +#define MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09) +#define MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80) + /****************************************************************************/ /* SCSI Enclosure Processor messages */ @@ -284,11 +278,16 @@ typedef struct _MSG_SEP_REQUEST U8 ChainOffset; /* 02h */ U8 Function; /* 03h */ U8 Action; /* 04h */ - U8 Reserved1; /* 05h */ - U8 Reserved2; /* 06h */ + U8 Flags; /* 05h */ + U8 Reserved1; /* 06h */ U8 MsgFlags; /* 07h */ U32 MsgContext; /* 08h */ U32 SlotStatus; /* 0Ch */ + U32 Reserved2; /* 10h */ + U32 Reserved3; /* 14h */ + U32 Reserved4; /* 18h */ + U16 Slot; /* 1Ch */ + U16 EnclosureHandle; /* 1Eh */ } MSG_SEP_REQUEST, MPI_POINTER PTR_MSG_SEP_REQUEST, SEPRequest_t, MPI_POINTER pSEPRequest_t; @@ -296,6 +295,10 @@ typedef struct _MSG_SEP_REQUEST #define MPI_SEP_REQ_ACTION_WRITE_STATUS (0x00) #define MPI_SEP_REQ_ACTION_READ_STATUS (0x01) +/* Flags defines */ +#define MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) +#define MPI_SEP_REQ_FLAGS_BUS_TARGETID_ADDRESS (0x00) + /* SlotStatus bits for MSG_SEP_REQUEST */ #define MPI_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) #define MPI_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) @@ -332,6 +335,9 @@ typedef struct _MSG_SEP_REPLY U16 IOCStatus; /* 0Eh */ U32 IOCLogInfo; /* 10h */ U32 SlotStatus; /* 14h */ + U32 Reserved4; /* 18h */ + U16 Slot; /* 1Ch */ + U16 EnclosureHandle; /* 1Eh */ } MSG_SEP_REPLY, MPI_POINTER PTR_MSG_SEP_REPLY, SEPReply_t, MPI_POINTER pSEPReply_t; diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index 82445d18b4d5..f91eb4efe8cc 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2005 LSI Logic Corporation. * * * 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.05.xx + * mpi_ioc.h Version: 01.05.08 * * Version History * --------------- @@ -57,6 +57,30 @@ * 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. + * 04-29-04 01.02.09 Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and + * added related defines. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added four new fields to MSG_IOC_INIT. + * Added three new fields to MSG_IOC_FACTS_REPLY. + * Defined four new bits for the IOCCapabilities field of + * the IOCFacts reply. + * Added two new PortTypes for the PortFacts reply. + * Added six new events along with their EventData + * structures. + * Added a new MsgFlag to the FwDownload request to + * indicate last segment. + * Defined a new image type of boot loader. + * Added FW family codes for SAS product families. + * 10-05-04 01.05.02 Added ReplyFifoHostSignalingAddr field to + * MSG_IOC_FACTS_REPLY. + * 12-07-04 01.05.03 Added more defines for SAS Discovery Error event. + * 12-09-04 01.05.04 Added Unsupported device to SAS Device event. + * 01-15-05 01.05.05 Added event data for SAS SES Event. + * 02-09-05 01.05.06 Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define. + * 02-22-05 01.05.07 Added Host Page Buffer Persistent flag to IOC Facts + * Reply and IOC Init Request. + * 03-11-05 01.05.08 Added family code for 1068E family. + * Removed IOCFacts Reply EEDP Capability bit. * -------------------------------------------------------------------------- */ @@ -90,20 +114,37 @@ typedef struct _MSG_IOC_INIT U32 HostMfaHighAddr; /* 10h */ U32 SenseBufferHighAddr; /* 14h */ U32 ReplyFifoHostSignalingAddr; /* 18h */ + SGE_SIMPLE_UNION HostPageBufferSGE; /* 1Ch */ + U16 MsgVersion; /* 28h */ + U16 HeaderVersion; /* 2Ah */ } 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_REPLY_FIFO_HOST_SIGNAL (0x02) +#define MPI_IOCINIT_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04) +#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02) +#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01) + +/* MsgVersion */ +#define MPI_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) +#define MPI_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI_IOCINIT_MSGVERSION_MINOR_SHIFT (0) + +/* HeaderVersion */ +#define MPI_IOCINIT_HEADERVERSION_UNIT_MASK (0xFF00) +#define MPI_IOCINIT_HEADERVERSION_UNIT_SHIFT (8) +#define MPI_IOCINIT_HEADERVERSION_DEV_MASK (0x00FF) +#define MPI_IOCINIT_HEADERVERSION_DEV_SHIFT (0) + typedef struct _MSG_IOC_INIT_REPLY { @@ -187,32 +228,39 @@ typedef struct _MSG_IOC_FACTS_REPLY MPI_FW_VERSION FWVersion; /* 38h */ U16 HighPriorityQueueDepth; /* 3Ch */ U16 Reserved2; /* 3Eh */ + SGE_SIMPLE_UNION HostPageBufferSGE; /* 40h */ + U32 ReplyFifoHostSignalingAddr; /* 4Ch */ } MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY, IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t; -#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) -#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) +#define MPI_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) +#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) +#define MPI_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) -#define MPI_IOCFACTS_HEADERVERSION_UNIT_MASK (0xFF00) -#define MPI_IOCFACTS_HEADERVERSION_DEV_MASK (0x00FF) +#define MPI_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) +#define MPI_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) +#define MPI_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) +#define MPI_IOCFACTS_HDRVERSION_DEV_SHIFT (0) -#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_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_FLAGS_FW_DOWNLOAD_BOOT (0x01) +#define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02) +#define MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04) -#define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00) -#define MPI_IOCFACTS_EVENTSTATE_ENABLED (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) +#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) @@ -408,6 +456,8 @@ typedef struct _MSG_EVENT_ACK_REPLY #define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F) #define MPI_EVENT_SAS_SES (0x00000010) #define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011) +#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012) +#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013) /* AckRequired field values */ @@ -467,6 +517,10 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE U8 ASCQ; /* 05h */ U16 DevHandle; /* 06h */ U32 DeviceInfo; /* 08h */ + U16 ParentDevHandle; /* 0Ch */ + U8 PhyNum; /* 0Eh */ + U8 Reserved1; /* 0Fh */ + U64 SASAddress; /* 10h */ } EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, MpiEventDataSasDeviceStatusChange_t, @@ -477,6 +531,8 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE #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) +#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) + /* SCSI Event data for Queue Full event */ @@ -488,6 +544,35 @@ typedef struct _EVENT_DATA_QUEUE_FULL } EVENT_DATA_QUEUE_FULL, MPI_POINTER PTR_EVENT_DATA_QUEUE_FULL, EventDataQueueFull_t, MPI_POINTER pEventDataQueueFull_t; +/* MPI Integrated RAID Event data */ + +typedef struct _EVENT_DATA_RAID +{ + U8 VolumeID; /* 00h */ + U8 VolumeBus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 PhysDiskNum; /* 03h */ + U8 ASC; /* 04h */ + U8 ASCQ; /* 05h */ + U16 Reserved; /* 06h */ + U32 SettingsStatus; /* 08h */ +} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID, + MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t; + +/* MPI Integrated RAID Event data ReasonCode values */ +#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00) +#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01) +#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02) +#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03) +#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04) +#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05) +#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06) +#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07) +#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08) +#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09) +#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) +#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) + /* MPI Link Status Change Event data */ typedef struct _EVENT_DATA_LINK_STATUS @@ -535,35 +620,63 @@ typedef struct _EVENT_DATA_LOGOUT #define MPI_EVENT_LOGOUT_ALL_ALIASES (0xFF) +/* SAS SES Event data */ -/* MPI Integrated RAID Event data */ - -typedef struct _EVENT_DATA_RAID +typedef struct _EVENT_DATA_SAS_SES { - U8 VolumeID; /* 00h */ - U8 VolumeBus; /* 01h */ - U8 ReasonCode; /* 02h */ - U8 PhysDiskNum; /* 03h */ - U8 ASC; /* 04h */ - U8 ASCQ; /* 05h */ - U16 Reserved; /* 06h */ - U32 SettingsStatus; /* 08h */ -} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID, - MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t; + U8 PhyNum; /* 00h */ + U8 Port; /* 01h */ + U8 PortWidth; /* 02h */ + U8 Reserved1; /* 04h */ +} EVENT_DATA_SAS_SES, MPI_POINTER PTR_EVENT_DATA_SAS_SES, + MpiEventDataSasSes_t, MPI_POINTER pMpiEventDataSasSes_t; -/* MPI Integrated RAID Event data ReasonCode values */ -#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00) -#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01) -#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02) -#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03) -#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04) -#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05) -#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06) -#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07) -#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08) -#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09) -#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) -#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) +/* SAS Phy Link Status Event data */ + +typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS +{ + U8 PhyNum; /* 00h */ + U8 LinkRates; /* 01h */ + U16 DevHandle; /* 02h */ + U64 SASAddress; /* 04h */ +} EVENT_DATA_SAS_PHY_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_SAS_PHY_LINK_STATUS, + MpiEventDataSasPhyLinkStatus_t, MPI_POINTER pMpiEventDataSasPhyLinkStatus_t; + +/* defines for the LinkRates field of the SAS PHY Link Status event */ +#define MPI_EVENT_SAS_PLS_LR_CURRENT_MASK (0xF0) +#define MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT (4) +#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_MASK (0x0F) +#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_SHIFT (0) +#define MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN (0x00) +#define MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED (0x01) +#define MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION (0x02) +#define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE (0x03) +#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08) +#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09) + +/* SAS Discovery Errror Event data */ + +typedef struct _EVENT_DATA_DISCOVERY_ERROR +{ + U32 DiscoveryStatus; /* 00h */ + U8 Port; /* 04h */ + U8 Reserved1; /* 05h */ + U16 Reserved2; /* 06h */ +} EVENT_DATA_DISCOVERY_ERROR, MPI_POINTER PTR_EVENT_DATA_DISCOVERY_ERROR, + EventDataDiscoveryError_t, MPI_POINTER pEventDataDiscoveryError_t; + +#define MPI_EVENT_DSCVRY_ERR_DS_LOOP_DETECTED (0x00000001) +#define MPI_EVENT_DSCVRY_ERR_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_EVENT_DSCVRY_ERR_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_EVENT_DSCVRY_ERR_DS_EXPANDER_ERR (0x00000008) +#define MPI_EVENT_DSCVRY_ERR_DS_SMP_TIMEOUT (0x00000010) +#define MPI_EVENT_DSCVRY_ERR_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_EVENT_DSCVRY_ERR_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_EVENT_DSCVRY_ERR_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE (0x00000200) +#define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE (0x00000400) +#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS (0x00000800) /***************************************************************************** @@ -589,11 +702,13 @@ typedef struct _MSG_FW_DOWNLOAD } MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD, FWDownload_t, MPI_POINTER pFWDownload_t; -#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00) -#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) +#define MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) + +#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00) +#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 @@ -647,6 +762,7 @@ typedef struct _MSG_FW_UPLOAD #define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) #define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03) #define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04) +#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) typedef struct _FWUploadTCSGE { @@ -723,6 +839,7 @@ typedef struct _MPI_FW_HEADER #define MPI_FW_HEADER_PID_PROD_IM_SCSI (0x0400) #define MPI_FW_HEADER_PID_PROD_IS_SCSI (0x0500) #define MPI_FW_HEADER_PID_PROD_CTX_SCSI (0x0600) +#define MPI_FW_HEADER_PID_PROD_IR_SCSI (0x0700) #define MPI_FW_HEADER_PID_FAMILY_MASK (0x00FF) /* SCSI */ @@ -740,13 +857,16 @@ typedef struct _MPI_FW_HEADER #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_919_FC (0x0001) /* 919 and 929 */ +#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002) /* 919X and 929X */ +#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */ +#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */ #define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005) /* SAS */ #define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001) +#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002) +#define MPI_FW_HEADER_PID_FAMILY_1078_SAS (0x0003) +#define MPI_FW_HEADER_PID_FAMILY_106xE_SAS (0x0004) /* 1068E, 1066E, and 1064E */ typedef struct _MPI_EXT_IMAGE_HEADER { diff --git a/drivers/message/fusion/lsi/mpi_lan.h b/drivers/message/fusion/lsi/mpi_lan.h index 3ced12784ee8..dc0b52ae83dd 100644 --- a/drivers/message/fusion/lsi/mpi_lan.h +++ b/drivers/message/fusion/lsi/mpi_lan.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_lan.h * Title: MPI LAN messages and structures * Creation Date: June 30, 2000 * - * mpi_lan.h Version: 01.05.xx + * mpi_lan.h Version: 01.05.01 * * Version History * --------------- @@ -28,6 +28,8 @@ * 02-20-01 01.01.02 Started using MPI_POINTER. * 03-27-01 01.01.03 Added structure offset comments. * 08-08-01 01.02.01 Original release for v1.2 work. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. * -------------------------------------------------------------------------- */ diff --git a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h index 9580a9de7fd2..802255d2747c 100644 --- a/drivers/message/fusion/lsi/mpi_raid.h +++ b/drivers/message/fusion/lsi/mpi_raid.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2001-2003 LSI Logic Corporation. + * Copyright (c) 2001-2005 LSI Logic Corporation. * * * Name: mpi_raid.h * Title: MPI RAID message and structures * Creation Date: February 27, 2001 * - * mpi_raid.h Version: 01.05.xx + * mpi_raid.h Version: 01.05.02 * * Version History * --------------- @@ -28,6 +28,10 @@ * 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. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * 01-15-05 01.05.02 Added defines for the two new RAID Actions for + * _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE. * -------------------------------------------------------------------------- */ @@ -84,6 +88,8 @@ typedef struct _MSG_RAID_ACTION #define MPI_RAID_ACTION_REPLACE_PHYSDISK (0x10) #define MPI_RAID_ACTION_ACTIVATE_VOLUME (0x11) #define MPI_RAID_ACTION_INACTIVATE_VOLUME (0x12) +#define MPI_RAID_ACTION_SET_RESYNC_RATE (0x13) +#define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE (0x14) /* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */ #define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC (0x00000001) @@ -99,6 +105,13 @@ typedef struct _MSG_RAID_ACTION /* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */ #define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL (0x00000001) +/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_RESYNC_RATE action */ +#define MPI_RAID_ACTION_ADATA_RESYNC_RATE_MASK (0x000000FF) + +/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */ +#define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK (0x000000FF) + + /* RAID Action reply message */ diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h index cb878f9c65de..230fa69b5353 100644 --- a/drivers/message/fusion/lsi/mpi_sas.h +++ b/drivers/message/fusion/lsi/mpi_sas.h @@ -1,25 +1,76 @@ /* - * Copyright (c) 2003 LSI Logic Corporation. + * Copyright (c) 2004 LSI Logic Corporation. * * * Name: mpi_sas.h * Title: MPI Serial Attached SCSI structures and definitions - * Creation Date: April 23, 2003 + * Creation Date: August 19, 2004 * - * mpi_sas.h Version: 01.05.xx + * mpi_sas.h Version: 01.05.01 * * Version History * --------------- * * Date Version Description * -------- -------- ------------------------------------------------------ - * xx-yy-zz 01.05.01 Original release. + * 08-19-04 01.05.01 Original release. * -------------------------------------------------------------------------- */ #ifndef MPI_SAS_H #define MPI_SAS_H + +/* + * Values for SASStatus. + */ +#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) + + + /***************************************************************************** * * 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 @@ -48,8 +99,10 @@ typedef struct _MSG_SMP_PASSTHROUGH_REQUEST } MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST, SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t; +/* values for PassthroughFlags field */ #define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) +/* values for ConnectionRate field */ #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) @@ -77,51 +130,69 @@ typedef struct _MSG_SMP_PASSTHROUGH_REPLY #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) +/****************************************************************************/ +/* SATA Passthrough Request */ +/****************************************************************************/ + +typedef struct _MSG_SATA_PASSTHROUGH_REQUEST +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 PassthroughFlags; /* 04h */ + U8 ConnectionRate; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved1; /* 0Ch */ + U32 Reserved2; /* 10h */ + U32 Reserved3; /* 14h */ + U32 DataLength; /* 18h */ + U8 CommandFIS[20]; /* 1Ch */ + SGE_SIMPLE_UNION SGL; /* 30h */ +} MSG_SATA_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REQUEST, + SataPassthroughRequest_t, MPI_POINTER pSataPassthroughRequest_t; + +/* values for PassthroughFlags field */ +#define MPI_SATA_PT_REQ_PT_FLAGS_RESET_DEVICE (0x0200) +#define MPI_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) +#define MPI_SATA_PT_REQ_PT_FLAGS_DMA_QUEUED (0x0080) +#define MPI_SATA_PT_REQ_PT_FLAGS_PACKET_COMMAND (0x0040) +#define MPI_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) +#define MPI_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) +#define MPI_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) +#define MPI_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) +#define MPI_SATA_PT_REQ_PT_FLAGS_READ (0x0001) + +/* values for ConnectionRate field */ +#define MPI_SATA_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00) +#define MPI_SATA_PT_REQ_CONNECT_RATE_1_5 (0x08) +#define MPI_SATA_PT_REQ_CONNECT_RATE_3_0 (0x09) + + +/* SATA Passthrough Reply */ +typedef struct _MSG_SATA_PASSTHROUGH_REPLY +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 PassthroughFlags; /* 04h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 Reserved2; /* 0Ch */ + U8 SASStatus; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U8 StatusFIS[20]; /* 14h */ + U32 StatusControlRegisters; /* 28h */ + U32 TransferCount; /* 2Ch */ +} MSG_SATA_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REPLY, + SataPassthroughReply_t, MPI_POINTER pSataPassthroughReply_t; -/* - * 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) /****************************************************************************/ @@ -148,15 +219,13 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST, SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t; -/* values for the ... field */ +/* values for the Operation 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_CLEAR_ALL_PERSISTENT (0x02) #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) +#define MPI_SAS_OP_MAP_CURRENT (0x09) /* SAS IO Unit Control Reply */ diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h index 804dc85426c1..623901fd82be 100644 --- a/drivers/message/fusion/lsi/mpi_targ.h +++ b/drivers/message/fusion/lsi/mpi_targ.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_targ.h * Title: MPI Target mode messages and structures * Creation Date: June 22, 2000 * - * mpi_targ.h Version: 01.05.xx + * mpi_targ.h Version: 01.05.04 * * Version History * --------------- @@ -43,6 +43,16 @@ * 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. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Added new request message structures for + * MSG_TARGET_CMD_BUF_POST_BASE_REQUEST, + * MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and + * MSG_TARGET_ASSIST_EXT_REQUEST. + * Added new structures for SAS SSP Command buffer, SSP + * Task buffer, and SSP Status IU. + * 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added. + * 02-22-05 01.05.03 Changed a comment. + * 03-11-05 01.05.04 Removed TargetAssistExtended Request. * -------------------------------------------------------------------------- */ @@ -133,6 +143,25 @@ typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY } MSG_PRIORITY_CMD_RECEIVED_REPLY, MPI_POINTER PTR_MSG_PRIORITY_CMD_RECEIVED_REPLY, PriorityCommandReceivedReply_t, MPI_POINTER pPriorityCommandReceivedReply_t; + +typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY +{ + U16 Reserved; /* 00h */ + U8 MsgLength; /* 02h */ + U8 Function; /* 03h */ + U16 Reserved1; /* 04h */ + U8 Reserved2; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U8 PriorityReason; /* 0Ch */ + U8 Reserved3; /* 0Dh */ + U16 IOCStatus; /* 0Eh */ + U32 IOCLogInfo; /* 10h */ + U32 ReplyWord; /* 14h */ +} MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, + MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, + TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t; + #define PRIORITY_REASON_NO_DISCONNECT (0x00) #define PRIORITY_REASON_SCSI_TASK_MANAGEMENT (0x01) #define PRIORITY_REASON_CMD_PARITY_ERR (0x02) @@ -146,7 +175,34 @@ typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY #define PRIORITY_REASON_UNKNOWN (0xFF) -typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY +/****************************************************************************/ +/* Target Command Buffer Post Base Request */ +/****************************************************************************/ + +typedef struct _MSG_TARGET_CMD_BUF_POST_BASE_REQUEST +{ + U8 BufferPostFlags; /* 00h */ + U8 PortNumber; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 TotalCmdBuffers; /* 04h */ + U8 Reserved; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved1; /* 0Ch */ + U16 CmdBufferLength; /* 10h */ + U16 NextCmdBufferOffset; /* 12h */ + U32 BaseAddressLow; /* 14h */ + U32 BaseAddressHigh; /* 18h */ +} MSG_TARGET_CMD_BUF_POST_BASE_REQUEST, + MPI_POINTER PTR__MSG_TARGET_CMD_BUF_POST_BASE_REQUEST, + TargetCmdBufferPostBaseRequest_t, + MPI_POINTER pTargetCmdBufferPostBaseRequest_t; + +#define CMD_BUFFER_POST_BASE_FLAGS_AUTO_POST_ALL (0x01) + + +typedef struct _MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY { U16 Reserved; /* 00h */ U8 MsgLength; /* 02h */ @@ -155,16 +211,41 @@ typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY U8 Reserved2; /* 06h */ U8 MsgFlags; /* 07h */ U32 MsgContext; /* 08h */ - U8 PriorityReason; /* 0Ch */ - U8 Reserved3; /* 0Dh */ + U16 Reserved3; /* 0Ch */ U16 IOCStatus; /* 0Eh */ U32 IOCLogInfo; /* 10h */ - U32 ReplyWord; /* 14h */ -} MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, - MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY, - TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t; +} MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY, + MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY, + TargetCmdBufferPostBaseListReply_t, + MPI_POINTER pTargetCmdBufferPostBaseListReply_t; + + +/****************************************************************************/ +/* Target Command Buffer Post List Request */ +/****************************************************************************/ + +typedef struct _MSG_TARGET_CMD_BUF_POST_LIST_REQUEST +{ + U8 Reserved; /* 00h */ + U8 PortNumber; /* 01h */ + U8 ChainOffset; /* 02h */ + U8 Function; /* 03h */ + U16 CmdBufferCount; /* 04h */ + U8 Reserved1; /* 06h */ + U8 MsgFlags; /* 07h */ + U32 MsgContext; /* 08h */ + U32 Reserved2; /* 0Ch */ + U16 IoIndex[2]; /* 10h */ +} MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, + MPI_POINTER PTR_MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, + TargetCmdBufferPostListRequest_t, + MPI_POINTER pTargetCmdBufferPostListRequest_t; +/****************************************************************************/ +/* Command Buffer Formats (with 16 byte CDB) */ +/****************************************************************************/ + typedef struct _MPI_TARGET_FCP_CMD_BUFFER { U8 FcpLun[8]; /* 00h */ @@ -201,6 +282,46 @@ typedef struct _MPI_TARGET_SCSI_SPI_CMD_BUFFER MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer; +typedef struct _MPI_TARGET_SSP_CMD_BUFFER +{ + U8 FrameType; /* 00h */ + U8 Reserved1; /* 01h */ + U16 Reserved2; /* 02h */ + U16 InitiatorTag; /* 04h */ + U16 DevHandle; /* 06h */ + /* COMMAND information unit starts here */ + U8 LogicalUnitNumber[8]; /* 08h */ + U8 Reserved3; /* 10h */ + U8 TaskAttribute; /* lower 3 bits */ /* 11h */ + U8 Reserved4; /* 12h */ + U8 AdditionalCDBLength; /* upper 5 bits */ /* 13h */ + U8 CDB[16]; /* 14h */ + /* Additional CDB bytes extend past the CDB field */ +} MPI_TARGET_SSP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_CMD_BUFFER, + MpiTargetSspCmdBuffer, MPI_POINTER pMpiTargetSspCmdBuffer; + +typedef struct _MPI_TARGET_SSP_TASK_BUFFER +{ + U8 FrameType; /* 00h */ + U8 Reserved1; /* 01h */ + U16 Reserved2; /* 02h */ + U16 InitiatorTag; /* 04h */ + U16 DevHandle; /* 06h */ + /* TASK information unit starts here */ + U8 LogicalUnitNumber[8]; /* 08h */ + U8 Reserved3; /* 10h */ + U8 Reserved4; /* 11h */ + U8 TaskManagementFunction; /* 12h */ + U8 Reserved5; /* 13h */ + U16 ManagedTaskTag; /* 14h */ + U16 Reserved6; /* 16h */ + U32 Reserved7; /* 18h */ + U32 Reserved8; /* 1Ch */ + U32 Reserved9; /* 20h */ +} MPI_TARGET_SSP_TASK_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_TASK_BUFFER, + MpiTargetSspTaskBuffer, MPI_POINTER pMpiTargetSspTaskBuffer; + + /****************************************************************************/ /* Target Assist Request */ /****************************************************************************/ @@ -308,6 +429,27 @@ typedef struct _MPI_TARGET_SCSI_SPI_STATUS_IU } MPI_TARGET_SCSI_SPI_STATUS_IU, MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_STATUS_IU, TargetScsiSpiStatusIU_t, MPI_POINTER pTargetScsiSpiStatusIU_t; +/* + * NOTE: The SSP status IU is big-endian. When used on a little-endian system, + * this structure properly orders the bytes. + */ +typedef struct _MPI_TARGET_SSP_RSP_IU +{ + U32 Reserved0[6]; /* reserved for SSP header */ /* 00h */ + /* start of RESPONSE information unit */ + U32 Reserved1; /* 18h */ + U32 Reserved2; /* 1Ch */ + U16 Reserved3; /* 20h */ + U8 DataPres; /* lower 2 bits */ /* 22h */ + U8 Status; /* 23h */ + U32 Reserved4; /* 24h */ + U32 SenseDataLength; /* 28h */ + U32 ResponseDataLength; /* 2Ch */ + U8 ResponseSenseData[4]; /* 30h */ +} MPI_TARGET_SSP_RSP_IU, MPI_POINTER PTR_MPI_TARGET_SSP_RSP_IU, + MpiTargetSspRspIu_t, MPI_POINTER pMpiTargetSspRspIu_t; + + /****************************************************************************/ /* Target Mode Abort Request */ /****************************************************************************/ diff --git a/drivers/message/fusion/lsi/mpi_tool.h b/drivers/message/fusion/lsi/mpi_tool.h index 536d197c4142..aa9053da1f58 100644 --- a/drivers/message/fusion/lsi/mpi_tool.h +++ b/drivers/message/fusion/lsi/mpi_tool.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2001-2003 LSI Logic Corporation. + * Copyright (c) 2001-2005 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 + * mpi_tool.h Version: 01.05.03 * * Version History * --------------- @@ -15,6 +15,16 @@ * -------- -------- ------------------------------------------------------ * 08-08-01 01.02.01 Original release. * 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines. + * 01-16-04 01.02.03 Added defines and structures for new tools + *. MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and + * MPI_TOOLBOX_FC_MANAGEMENT_TOOL. + * 04-29-04 01.02.04 Added message structures for Diagnostic Buffer Post and + * Diagnostic Release requests and replies. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. + * 10-06-04 01.05.02 Added define for MPI_DIAG_BUF_TYPE_COUNT. + * 02-09-05 01.05.03 Added frame size option to FC management tool. + * Added Beacon tool to the Toolbox. * -------------------------------------------------------------------------- */ @@ -26,6 +36,7 @@ #define MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) #define MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) #define MPI_TOOLBOX_FC_MANAGEMENT_TOOL (0x04) +#define MPI_TOOLBOX_BEACON_TOOL (0x05) /****************************************************************************/ @@ -185,11 +196,21 @@ typedef struct _MPI_TB_FC_MANAGE_PID_AI } MPI_TB_FC_MANAGE_PID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_PID_AI, MpiTbFcManagePidAi_t, MPI_POINTER pMpiTbFcManagePidAi_t; +/* ActionInfo for set max frame size */ +typedef struct _MPI_TB_FC_MANAGE_FRAME_SIZE_AI +{ + U16 FrameSize; /* 00h */ + U8 PortNum; /* 02h */ + U8 Reserved1; /* 03h */ +} MPI_TB_FC_MANAGE_FRAME_SIZE_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_FRAME_SIZE_AI, + MpiTbFcManageFrameSizeAi_t, MPI_POINTER pMpiTbFcManageFrameSizeAi_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_FRAME_SIZE_AI FrameSize; } MPI_TB_FC_MANAGE_AI_UNION, MPI_POINTER PTR_MPI_TB_FC_MANAGE_AI_UNION, MpiTbFcManageAiUnion_t, MPI_POINTER pMpiTbFcManageAiUnion_t; @@ -214,6 +235,32 @@ typedef struct _MSG_TOOLBOX_FC_MANAGE_REQUEST #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) +#define MPI_TB_FC_MANAGE_ACTION_SET_MAX_FRAME_SIZE (0x03) + + +/****************************************************************************/ +/* Toolbox Beacon Tool request */ +/****************************************************************************/ + +typedef struct _MSG_TOOLBOX_BEACON_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 ConnectNum; /* 0Ch */ + U8 PortNum; /* 0Dh */ + U8 Reserved3; /* 0Eh */ + U8 Flags; /* 0Fh */ +} MSG_TOOLBOX_BEACON_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_BEACON_REQUEST, + ToolboxBeaconRequest_t, MPI_POINTER pToolboxBeaconRequest_t; + +#define MPI_TOOLBOX_FLAGS_BEACON_MODE_OFF (0x00) +#define MPI_TOOLBOX_FLAGS_BEACON_MODE_ON (0x01) /****************************************************************************/ @@ -233,14 +280,16 @@ typedef struct _MSG_DIAG_BUFFER_POST_REQUEST U32 ExtendedType; /* 0Ch */ U32 BufferLength; /* 10h */ U32 ProductSpecific[4]; /* 14h */ - U32 Reserved3; /* 18h */ - SGE_SIMPLE_UNION SGL; /* 28h */ + U32 Reserved3; /* 24h */ + U64 BufferAddress; /* 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) +/* count of the number of buffer types */ +#define MPI_DIAG_BUF_TYPE_COUNT (0x03) #define MPI_DIAG_EXTENDED_QTAG (0x00000001) diff --git a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h index 239328a7689c..32cc9b1151b8 100644 --- a/drivers/message/fusion/lsi/mpi_type.h +++ b/drivers/message/fusion/lsi/mpi_type.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2003 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_type.h * Title: MPI Basic type definitions * Creation Date: June 6, 2000 * - * mpi_type.h Version: 01.05.xx + * mpi_type.h Version: 01.05.01 * * Version History * --------------- @@ -18,6 +18,8 @@ * 11-02-00 01.01.01 Original release for post 1.0 work * 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER. * 08-08-01 01.02.01 Original release for v1.2 work. + * 05-11-04 01.03.01 Original release for MPI v1.3. + * 08-19-04 01.05.01 Original release for MPI v1.5. * -------------------------------------------------------------------------- */ @@ -50,11 +52,6 @@ typedef unsigned short U16; typedef int32_t S32; typedef u_int32_t U32; -/* - * The only way crap below could work on big-endian boxen would be if it - * wasn't used at all. - */ - typedef struct _S64 { U32 Low; diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 8b22630f1aef..8b623278ccd2 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1,55 +1,13 @@ /* * linux/drivers/message/fusion/mptbase.c - * High performance SCSI + LAN / Fibre Channel device drivers. * This is the Fusion MPT base driver which supports multiple * (SCSI + LAN) specialized protocol drivers. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel + * For use with LSI Logic PCI chip/adapter(s) * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * There are lots of people not mentioned below that deserve credit - * and thanks but won't get it here - sorry in advance that you - * got overlooked. - * - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A special thanks to Noah Romer (LSI Logic) for tons of work - * and tough debugging on the LAN driver, especially early on;-) - * And to Roger Hickerson (LSI Logic) for tirelessly supporting - * this driver project. - * - * A special thanks to Pamela Delaney (LSI Logic) for tons of work - * and countless enhancements while adding support for the 1030 - * chip family. Pam has been instrumental in the development of - * of the 2.xx.xx series fusion drivers, and her contributions are - * far too numerous to hope to list in one place. - * - * All manner of help from Stephen Shirron (LSI Logic): - * low-level FC analysis, debug + various fixes in FCxx firmware, - * initial port to alpha platform, various driver code optimizations, - * being a faithful sounding board on all sorts of issues & ideas, - * etc. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * Special thanks goes to the I2O LAN driver people at the - * University of Helsinki, who, unbeknownst to them, provided - * the inspiration and initial structure for this driver. - * - * A really huge debt of gratitude is owed to Eddie C. Dost - * for gobs of hard work fixing and optimizing LAN code. - * THANK YOU! - * - * Copyright (c) 1999-2004 LSI Logic Corporation - * Originally By: Steven J. Ralston - * (mailto:sjralston1@netscape.net) + * Copyright (c) 1999-2005 LSI Logic Corporation * (mailto:mpt_linux_developer@lsil.com) * - * $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -101,6 +59,7 @@ #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> /* needed for in_interrupt() proto */ +#include <linux/dma-mapping.h> #include <asm/io.h> #ifdef CONFIG_MTRR #include <asm/mtrr.h> @@ -218,41 +177,35 @@ static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); /* module entry point */ -static int __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *); -static void __devexit mptbase_remove(struct pci_dev *); -static void mptbase_shutdown(struct device * ); static int __init fusion_init (void); static void __exit fusion_exit (void); -/**************************************************************************** - * Supported hardware - */ - -static struct pci_device_id mptbase_pci_table[] = { - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909, - PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929, - PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919, - PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X, - PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X, - PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030, - PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035, - PCI_ANY_ID, PCI_ANY_ID }, - {0} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, mptbase_pci_table); - #define CHIPREG_READ32(addr) readl_relaxed(addr) #define CHIPREG_READ32_dmasync(addr) readl(addr) #define CHIPREG_WRITE32(addr,val) writel(val, addr) #define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr) #define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr) +static void +pci_disable_io_access(struct pci_dev *pdev) +{ + u16 command_reg; + + pci_read_config_word(pdev, PCI_COMMAND, &command_reg); + command_reg &= ~1; + pci_write_config_word(pdev, PCI_COMMAND, command_reg); +} + +static void +pci_enable_io_access(struct pci_dev *pdev) +{ + u16 command_reg; + + pci_read_config_word(pdev, PCI_COMMAND, &command_reg); + command_reg |= 1; + pci_write_config_word(pdev, PCI_COMMAND, command_reg); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. @@ -330,8 +283,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) ioc->name, mr, req_idx)); DBG_DUMP_REPLY_FRAME(mr) - /* NEW! 20010301 -sralston - * Check/log IOC log info + /* Check/log IOC log info */ ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { @@ -357,9 +309,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) { cb_idx = mpt_lan_index; - /* - * BUG FIX! 20001218 -sralston - * Blind set of mf to NULL here was fatal + /* Blind set of mf to NULL here was fatal * after lan_reply says "freeme" * Fix sort of combined with an optimization here; * added explicit check for case where lan_reply @@ -430,15 +380,8 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) } if (freeme) { - unsigned long flags; - /* Put Request back on FreeQ! */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); -#ifdef MFCNT - ioc->mfcnt--; -#endif - spin_unlock_irqrestore(&ioc->FreeQlock, flags); + mpt_free_msg_frame(ioc, mf); } mb(); @@ -725,11 +668,9 @@ int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) { MPT_ADAPTER *ioc; - int error=0; if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) { - error= -EINVAL; - return error; + return -EINVAL; } MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; @@ -737,14 +678,12 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) /* call per pci device probe entry point */ list_for_each_entry(ioc, &ioc_list, list) { if(dd_cbfunc->probe) { - error = dd_cbfunc->probe(ioc->pcidev, + dd_cbfunc->probe(ioc->pcidev, ioc->pcidev->driver->id_table); - if(error != 0) - return error; } } - return error; + return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -809,8 +748,8 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ - req_idx = cpu_to_le16(req_offset / ioc->req_sz); - mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx; + req_idx = req_offset / ioc->req_sz; + mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */ #ifdef MFCNT @@ -856,8 +795,8 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ - req_idx = cpu_to_le16(req_offset / ioc->req_sz); - mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx; + req_idx = req_offset / ioc->req_sz; + mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; #ifdef MPT_DEBUG_MSG_FRAME @@ -1058,7 +997,7 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptbase_probe - Install a PCI intelligent MPT adapter. + * mpt_attach - Install a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure * * This routine performs all the steps necessary to bring the IOC of @@ -1073,8 +1012,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) * * TODO: Add support for polled controllers */ -static int __devinit -mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) +int +mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) { MPT_ADAPTER *ioc; u8 __iomem *mem; @@ -1084,7 +1023,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) u32 psize; int ii; int r = -ENODEV; - u64 mask = 0xffffffffffffffffULL; u8 revision; u8 pcixcmd; static int mpt_ids = 0; @@ -1097,15 +1035,15 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n")); - if (!pci_set_dma_mask(pdev, mask)) { + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { dprintk((KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); - } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) { + } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); return r; } - if (!pci_set_consistent_dma_mask(pdev, mask)) + if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) dprintk((KERN_INFO MYNAM ": Using 64 bit consistent mask\n")); else @@ -1243,6 +1181,16 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); } + else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) { + ioc->prod_name = "LSIFC939X"; + ioc->bus_type = FC; + ioc->errata_flag_1064 = 1; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) { + ioc->prod_name = "LSIFC949X"; + ioc->bus_type = FC; + ioc->errata_flag_1064 = 1; + } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { ioc->prod_name = "LSI53C1030"; ioc->bus_type = SCSI; @@ -1261,6 +1209,9 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->bus_type = SCSI; } + if (ioc->errata_flag_1064) + pci_disable_io_access(pdev); + sprintf(ioc->name, "ioc%d", ioc->id); spin_lock_init(&ioc->FreeQlock); @@ -1303,8 +1254,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) #endif } - /* NEW! 20010220 -sralston - * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. + /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ mpt_detect_bound_ports(ioc, pdev); @@ -1354,13 +1304,13 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptbase_remove - Remove a PCI intelligent MPT adapter. + * mpt_detach - Remove a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure * */ -static void __devexit -mptbase_remove(struct pci_dev *pdev) +void +mpt_detach(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); char pname[32]; @@ -1397,43 +1347,21 @@ mptbase_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptbase_shutdown - - * - */ -static void -mptbase_shutdown(struct device * dev) -{ - int ii; - - /* call per device driver shutdown entry point */ - for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { - if(MptDeviceDriverHandlers[ii] && - MptDeviceDriverHandlers[ii]->shutdown) { - MptDeviceDriverHandlers[ii]->shutdown(dev); - } - } - -} - - /************************************************************************** * Power Management */ #ifdef CONFIG_PM /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptbase_suspend - Fusion MPT base driver suspend routine. + * mpt_suspend - Fusion MPT base driver suspend routine. * * */ -static int -mptbase_suspend(struct pci_dev *pdev, pm_message_t state) +int +mpt_suspend(struct pci_dev *pdev, pm_message_t state) { u32 device_state; MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - int ii; switch(state) { @@ -1453,14 +1381,6 @@ mptbase_suspend(struct pci_dev *pdev, pm_message_t state) "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), device_state); - /* call per device driver suspend entry point */ - for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { - if(MptDeviceDriverHandlers[ii] && - MptDeviceDriverHandlers[ii]->suspend) { - MptDeviceDriverHandlers[ii]->suspend(pdev, state); - } - } - pci_save_state(pdev); /* put ioc into READY_STATE */ @@ -1484,18 +1404,18 @@ mptbase_suspend(struct pci_dev *pdev, pm_message_t state) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptbase_resume - Fusion MPT base driver resume routine. + * mpt_resume - Fusion MPT base driver resume routine. * * */ -static int -mptbase_resume(struct pci_dev *pdev) +int +mpt_resume(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); u32 device_state = pdev->current_state; int recovery_state; int ii; - + printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), device_state); @@ -1533,14 +1453,6 @@ mptbase_resume(struct pci_dev *pdev) "pci-resume: success\n", ioc->name); } - /* call per device driver resume entry point */ - for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { - if(MptDeviceDriverHandlers[ii] && - MptDeviceDriverHandlers[ii]->resume) { - MptDeviceDriverHandlers[ii]->resume(pdev); - } - } - return 0; } #endif @@ -1719,8 +1631,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ioc->alt_ioc->active = 1; } - /* NEW! 20010120 -sralston - * Enable MPT base driver management of EventNotification + /* Enable MPT base driver management of EventNotification * and EventAck handling. */ if ((ret == 0) && (!ioc->facts.EventState)) @@ -1729,9 +1640,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */ - /* (Bugzilla:fibrebugs, #513) - * Bug fix (part 2)! 20010905 -sralston - * Add additional "reason" check before call to GetLanConfigPages + /* Add additional "reason" check before call to GetLanConfigPages * (combined with GetIoUnitPage2 call). This prevents a somewhat * recursive scenario; GetLanConfigPages times out, timer expired * routine calls HardResetHandler, which calls into here again, @@ -1829,37 +1738,43 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) { - unsigned int match_lo, match_hi; + struct pci_dev *peer=NULL; + unsigned int slot = PCI_SLOT(pdev->devfn); + unsigned int func = PCI_FUNC(pdev->devfn); MPT_ADAPTER *ioc_srch; - match_lo = pdev->devfn-1; - match_hi = pdev->devfn+1; - dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n", - ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi)); + dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x," + " searching for devfn match on %x or %x\n", + ioc->name, pci_name(pdev), pdev->devfn, + func-1, func+1)); + + peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1)); + if (!peer) { + peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1)); + if (!peer) + return; + } list_for_each_entry(ioc_srch, &ioc_list, list) { struct pci_dev *_pcidev = ioc_srch->pcidev; - - if ((_pcidev->device == pdev->device) && - (_pcidev->bus->number == pdev->bus->number) && - (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) { + if (_pcidev == peer) { /* Paranoia checks */ if (ioc->alt_ioc != NULL) { printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", - ioc->name, ioc->alt_ioc->name); + ioc->name, ioc->alt_ioc->name); break; } else if (ioc_srch->alt_ioc != NULL) { printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", - ioc_srch->name, ioc_srch->alt_ioc->name); + ioc_srch->name, ioc_srch->alt_ioc->name); break; } dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", - ioc->name, ioc_srch->name)); + ioc->name, ioc_srch->name)); ioc_srch->alt_ioc = ioc; ioc->alt_ioc = ioc_srch; - break; } } + pci_dev_put(peer); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1922,15 +1837,10 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) ioc->alloc_total -= sz; } - if (ioc->spi_data.nvram != NULL) { - kfree(ioc->spi_data.nvram); - ioc->spi_data.nvram = NULL; - } - - if (ioc->spi_data.pIocPg3 != NULL) { - kfree(ioc->spi_data.pIocPg3); - ioc->spi_data.pIocPg3 = NULL; - } + kfree(ioc->spi_data.nvram); + kfree(ioc->spi_data.pIocPg3); + ioc->spi_data.nvram = NULL; + ioc->spi_data.pIocPg3 = NULL; if (ioc->spi_data.pIocPg4 != NULL) { sz = ioc->spi_data.IocPg4Sz; @@ -1947,10 +1857,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) ioc->ReqToChain = NULL; } - if (ioc->ChainToChain != NULL) { - kfree(ioc->ChainToChain); - ioc->ChainToChain = NULL; - } + kfree(ioc->ChainToChain); + ioc->ChainToChain = NULL; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2333,7 +2241,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) return -55; } - r = sz = le32_to_cpu(facts->BlockSize); + r = sz = facts->BlockSize; vv = ((63 / (sz * 4)) + 1) & 0x03; ioc->NB_for_64_byte_frame = vv; while ( sz ) @@ -2785,7 +2693,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* prevent a second downloadboot and memory free with alt_ioc */ if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) ioc->alt_ioc->cached_fw = NULL; - + CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); @@ -2843,6 +2751,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Write the LoadStartAddress to the DiagRw Address Register * using Programmed IO */ + if (ioc->errata_flag_1064) + pci_enable_io_access(ioc->pcidev); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress); ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n", ioc->name, pFwHeader->LoadStartAddress)); @@ -2889,6 +2800,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); + if (ioc->errata_flag_1064) + pci_disable_io_access(ioc->pcidev); + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n", ioc->name, diag0val)); @@ -4250,7 +4164,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) || (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) { - if (ioc->spi_data.minSyncFactor < MPT_ULTRA) + if (ioc->spi_data.minSyncFactor < MPT_ULTRA) ioc->spi_data.minSyncFactor = MPT_ULTRA; } } @@ -4482,10 +4396,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) /* Free the old page */ - if (ioc->spi_data.pIocPg3) { - kfree(ioc->spi_data.pIocPg3); - ioc->spi_data.pIocPg3 = NULL; - } + kfree(ioc->spi_data.pIocPg3); + ioc->spi_data.pIocPg3 = NULL; /* There is at least one physical disk. * Read and save IOC Page 3 @@ -4753,9 +4665,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) u32 flagsLength; int in_isr; - /* (Bugzilla:fibrebugs, #513) - * Bug fix (part 1)! 20010905 -sralston - * Prevent calling wait_event() (below), if caller happens + /* Prevent calling wait_event() (below), if caller happens * to be in ISR context, because that is fatal! */ in_isr = in_interrupt(); @@ -4861,9 +4771,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) u32 flagsLength; int in_isr; - /* (Bugzilla:fibrebugs, #513) - * Bug fix (part 1)! 20010905 -sralston - * Prevent calling wait_event() (below), if caller happens + /* Prevent calling wait_event() (below), if caller happens * to be in ISR context, because that is fatal! */ in_isr = in_interrupt(); @@ -5130,20 +5038,26 @@ static int procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) { int ii; - int scsi, lan, ctl, targ, dmp; + int scsi, fc, sas, lan, ctl, targ, dmp; char *drvname; int len; len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON); len += sprintf(buf+len, " Fusion MPT base driver\n"); - scsi = lan = ctl = targ = dmp = 0; + scsi = fc = sas = lan = ctl = targ = dmp = 0; for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { drvname = NULL; if (MptCallbacks[ii]) { switch (MptDriverClass[ii]) { - case MPTSCSIH_DRIVER: - if (!scsi++) drvname = "SCSI host"; + case MPTSPI_DRIVER: + if (!scsi++) drvname = "SPI host"; + break; + case MPTFC_DRIVER: + if (!fc++) drvname = "FC host"; + break; + case MPTSAS_DRIVER: + if (!sas++) drvname = "SAS host"; break; case MPTLAN_DRIVER: if (!lan++) drvname = "LAN"; @@ -5832,6 +5746,12 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +EXPORT_SYMBOL(mpt_attach); +EXPORT_SYMBOL(mpt_detach); +#ifdef CONFIG_PM +EXPORT_SYMBOL(mpt_resume); +EXPORT_SYMBOL(mpt_suspend); +#endif EXPORT_SYMBOL(ioc_list); EXPORT_SYMBOL(mpt_proc_root_dir); EXPORT_SYMBOL(mpt_register); @@ -5860,19 +5780,6 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); -static struct pci_driver mptbase_driver = { - .name = "mptbase", - .id_table = mptbase_pci_table, - .probe = mptbase_probe, - .remove = __devexit_p(mptbase_remove), - .driver = { - .shutdown = mptbase_shutdown, - }, -#ifdef CONFIG_PM - .suspend = mptbase_suspend, - .resume = mptbase_resume, -#endif -}; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -5884,7 +5791,6 @@ static int __init fusion_init(void) { int i; - int r; show_mptmod_ver(my_NAME, my_VERSION); printk(KERN_INFO COPYRIGHT "\n"); @@ -5896,8 +5802,7 @@ fusion_init(void) MptResetHandlers[i] = NULL; } - /* NEW! 20010120 -sralston - * Register ourselves (mptbase) in order to facilitate + /* Register ourselves (mptbase) in order to facilitate * EventNotification handling. */ mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER); @@ -5913,11 +5818,7 @@ fusion_init(void) #ifdef CONFIG_PROC_FS (void) procmpt_create(); #endif - r = pci_register_driver(&mptbase_driver); - if(r) - return(r); - - return r; + return 0; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -5933,7 +5834,6 @@ fusion_exit(void) dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n")); - pci_unregister_driver(&mptbase_driver); mpt_reset_deregister(mpt_base_index); #ifdef CONFIG_PROC_FS @@ -5941,6 +5841,5 @@ fusion_exit(void) #endif } - module_init(fusion_init); module_exit(fusion_exit); diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 6d16acc7a179..848fb236b175 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -5,15 +5,9 @@ * LSIFC9xx/LSI409xx Fibre Channel * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * (see mptbase.c) - * - * Copyright (c) 1999-2004 LSI Logic Corporation - * Originally By: Steven J. Ralston - * (mailto:sjralston1@netscape.net) + * Copyright (c) 1999-2005 LSI Logic Corporation * (mailto:mpt_linux_developer@lsil.com) * - * $Id: mptbase.h,v 1.144 2003/01/28 21:31:56 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -71,7 +65,6 @@ #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" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -80,11 +73,11 @@ #endif #ifndef COPYRIGHT -#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR +#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.01.20" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.20" +#define MPT_LINUX_VERSION_COMMON "3.03.02" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.02" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -203,7 +196,9 @@ typedef enum { MPTBASE_DRIVER, /* MPT base class */ MPTCTL_DRIVER, /* MPT ioctl class */ - MPTSCSIH_DRIVER, /* MPT SCSI host (initiator) class */ + MPTSPI_DRIVER, /* MPT SPI host class */ + MPTFC_DRIVER, /* MPT FC host class */ + MPTSAS_DRIVER, /* MPT SAS host class */ MPTLAN_DRIVER, /* MPT LAN class */ MPTSTM_DRIVER, /* MPT SCSI target mode class */ MPTUNKNOWN_DRIVER @@ -212,11 +207,6 @@ typedef enum { struct mpt_pci_driver{ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); void (*remove) (struct pci_dev *dev); - void (*shutdown) (struct device * dev); -#ifdef CONFIG_PM - int (*resume) (struct pci_dev *dev); - int (*suspend) (struct pci_dev *dev, pm_message_t state); -#endif }; /* @@ -483,6 +473,7 @@ typedef struct _ScsiCfgData { u8 forceDv; /* 1 to force DV scheduling */ u8 noQas; /* Disable QAS for this adapter */ u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */ + u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ u8 rsvd[1]; } ScsiCfgData; @@ -571,11 +562,21 @@ typedef struct _MPT_ADAPTER FCPortPage0_t fc_port_page0[2]; LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; + /* + * Description: errata_flag_1064 + * If a PCIX read occurs within 1 or 2 cycles after the chip receives + * a split completion for a read data, an internal address pointer incorrectly + * increments by 32 bytes + */ + int errata_flag_1064; u8 FirstWhoInit; u8 upload_fw; /* If set, do a fw upload */ u8 reload_fw; /* Force a FW Reload on next reset */ u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ u8 pad1[4]; + int DoneCtx; + int TaskCtx; + int InternalCtx; struct list_head list; struct net_device *netdev; } MPT_ADAPTER; @@ -773,12 +774,6 @@ typedef struct _mpt_sge { #define DBG_DUMP_TM_REPLY_FRAME(mfp) #endif -#ifdef MPT_DEBUG_NEH -#define nehprintk(x) printk x -#else -#define nehprintk(x) -#endif - #if defined(MPT_DEBUG_CONFIG) || defined(MPT_DEBUG) #define dcprintk(x) printk x #else @@ -898,6 +893,11 @@ typedef struct _MPT_SCSI_HOST { unsigned long soft_resets; /* fw/external bus resets count */ unsigned long timeouts; /* cmd timeouts */ ushort sel_timeout[MPT_MAX_FC_DEVICES]; + char *info_kbuf; + wait_queue_head_t scandv_waitq; + int scandv_wait_done; + long last_queue_full; + u8 mpt_pq_filter; } MPT_SCSI_HOST; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -931,6 +931,12 @@ typedef struct _x_config_parms { /* * Public entry points... */ +extern int mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id); +extern void mpt_detach(struct pci_dev *pdev); +#ifdef CONFIG_PM +extern int mpt_suspend(struct pci_dev *pdev, pm_message_t state); +extern int mpt_resume(struct pci_dev *pdev); +#endif extern int mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass); extern void mpt_deregister(int cb_idx); extern int mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 70b0cfb5ac5c..05ea5944c487 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1,40 +1,12 @@ /* * linux/drivers/message/fusion/mptctl.c - * Fusion MPT misc device (ioctl) driver. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel + * mpt Ioctl driver. + * For use with LSI Logic PCI chip/adapters * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A special thanks to Pamela Delaney (LSI Logic) for tons of work - * and countless enhancements while adding support for the 1030 - * chip family. Pam has been instrumental in the development of - * of the 2.xx.xx series fusion drivers, and her contributions are - * far too numerous to hope to list in one place. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * A big THANKS to Eddie C. Dost for fixing the ioctl path - * and most importantly f/w download on sparc64 platform! - * (plus Eddie's other helpful hints and insights) - * - * Thanks to Arnaldo Carvalho de Melo for finding and patching - * a potential memory leak in mptctl_do_fw_download(), - * and for some kmalloc insight:-) - * - * (see also mptbase.c) - * - * Copyright (c) 1999-2004 LSI Logic Corporation - * Originally By: Steven J. Ralston, Noah Romer - * (mailto:sjralston1@netscape.net) + * Copyright (c) 1999-2005 LSI Logic Corporation * (mailto:mpt_linux_developer@lsil.com) * - * $Id: mptctl.c,v 1.63 2002/12/03 21:26:33 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -95,8 +67,8 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> -#define COPYRIGHT "Copyright (c) 1999-2004 LSI Logic Corporation" -#define MODULEAUTHOR "Steven J. Ralston, Noah Romer, Pamela Delaney" +#define COPYRIGHT "Copyright (c) 1999-2005 LSI Logic Corporation" +#define MODULEAUTHOR "LSI Logic Corporation" #include "mptbase.h" #include "mptctl.h" @@ -127,14 +99,14 @@ struct buflist { * arg contents specific to function. */ static int mptctl_fw_download(unsigned long arg); -static int mptctl_getiocinfo (unsigned long arg, unsigned int cmd); -static int mptctl_gettargetinfo (unsigned long arg); -static int mptctl_readtest (unsigned long arg); -static int mptctl_mpt_command (unsigned long arg); -static int mptctl_eventquery (unsigned long arg); -static int mptctl_eventenable (unsigned long arg); -static int mptctl_eventreport (unsigned long arg); -static int mptctl_replace_fw (unsigned long arg); +static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd); +static int mptctl_gettargetinfo(unsigned long arg); +static int mptctl_readtest(unsigned long arg); +static int mptctl_mpt_command(unsigned long arg); +static int mptctl_eventquery(unsigned long arg); +static int mptctl_eventenable(unsigned long arg); +static int mptctl_eventreport(unsigned long arg); +static int mptctl_replace_fw(unsigned long arg); static int mptctl_do_reset(unsigned long arg); static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd); @@ -149,11 +121,11 @@ static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg); /* * Private function calls. */ -static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr); +static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr); static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen); -static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags, +static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags, struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); -static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma, +static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc); static void mptctl_timeout_expired (MPT_IOCTL *ioctl); static int mptctl_bus_reset(MPT_IOCTL *ioctl); @@ -1119,7 +1091,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) int numDevices = 0; unsigned int max_id; int ii; - int port; + unsigned int port; int cim_rev; u8 revision; @@ -1162,9 +1134,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) return -ENODEV; } - /* Verify the data transfer size is correct. - * Ignore the port setting. - */ + /* Verify the data transfer size is correct. */ if (karg->hdr.maxDataSize != data_size) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Structure size mismatch. Command not completed.\n", @@ -1181,6 +1151,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) else karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; + if (karg->hdr.port > 1) + return -EINVAL; port = karg->hdr.port; karg->port = port; diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index cc4ecf0382df..28754a9cb803 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -5,22 +5,9 @@ * LSIFC9xx/LSI409xx Fibre Channel * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * (see also mptbase.c) - * - * Copyright (c) 1999-2004 LSI Logic Corporation - * Originally By: Steven J. Ralston - * (mailto:sjralston1@netscape.net) + * Copyright (c) 1999-2005 LSI Logic Corporation * (mailto:mpt_linux_developer@lsil.com) * - * $Id: mptctl.h,v 1.13 2002/12/03 21:26:33 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c new file mode 100644 index 000000000000..d8d65397e06e --- /dev/null +++ b/drivers/message/fusion/mptfc.c @@ -0,0 +1,431 @@ +/* + * linux/drivers/message/fusion/mptfc.c + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * + * Copyright (c) 1999-2005 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsil.com) + * + */ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + 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; version 2 of the License. + + 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. + + NO WARRANTY + THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + solely responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, damage to or loss of data, + programs or equipment, and unavailability or interruption of operations. + + DISCLAIMER OF LIABILITY + NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + 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 "linux_compat.h" /* linux-2.6 tweaks */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/kdev_t.h> +#include <linux/blkdev.h> +#include <linux/delay.h> /* for mdelay */ +#include <linux/interrupt.h> /* needed for in_interrupt() proto */ +#include <linux/reboot.h> /* notifier code */ +#include <linux/sched.h> +#include <linux/workqueue.h> + +#include <scsi/scsi.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_tcq.h> + +#include "mptbase.h" +#include "mptscsih.h" + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +#define my_NAME "Fusion MPT FC Host driver" +#define my_VERSION MPT_LINUX_VERSION_COMMON +#define MYNAM "mptfc" + +MODULE_AUTHOR(MODULEAUTHOR); +MODULE_DESCRIPTION(my_NAME); +MODULE_LICENSE("GPL"); + +/* Command line args */ +static int mpt_pq_filter = 0; +module_param(mpt_pq_filter, int, 0); +MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); + +static int mptfcDoneCtx = -1; +static int mptfcTaskCtx = -1; +static int mptfcInternalCtx = -1; /* Used only for internal commands */ + +static struct device_attribute mptfc_queue_depth_attr = { + .attr = { + .name = "queue_depth", + .mode = S_IWUSR, + }, + .store = mptscsih_store_queue_depth, +}; + +static struct device_attribute *mptfc_dev_attrs[] = { + &mptfc_queue_depth_attr, + NULL, +}; + +static struct scsi_host_template mptfc_driver_template = { + .proc_name = "mptfc", + .proc_info = mptscsih_proc_info, + .name = "MPT FC Host", + .info = mptscsih_info, + .queuecommand = mptscsih_qcmd, + .slave_alloc = mptscsih_slave_alloc, + .slave_configure = mptscsih_slave_configure, + .slave_destroy = mptscsih_slave_destroy, + .eh_abort_handler = mptscsih_abort, + .eh_device_reset_handler = mptscsih_dev_reset, + .eh_bus_reset_handler = mptscsih_bus_reset, + .eh_host_reset_handler = mptscsih_host_reset, + .bios_param = mptscsih_bios_param, + .can_queue = MPT_FC_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, + .sdev_attrs = mptfc_dev_attrs, +}; + +/**************************************************************************** + * Supported hardware + */ + +static struct pci_device_id mptfc_pci_table[] = { + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X, + PCI_ANY_ID, PCI_ANY_ID }, + {0} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, mptfc_pci_table); + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mptfc_probe - Installs scsi devices per bus. + * @pdev: Pointer to pci_dev structure + * + * Returns 0 for success, non-zero for failure. + * + */ +static int +mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct Scsi_Host *sh; + MPT_SCSI_HOST *hd; + MPT_ADAPTER *ioc; + unsigned long flags; + int sz, ii; + int numSGE = 0; + int scale; + int ioc_cap; + u8 *mem; + int error=0; + int r; + + if ((r = mpt_attach(pdev,id)) != 0) + return r; + + ioc = pci_get_drvdata(pdev); + ioc->DoneCtx = mptfcDoneCtx; + ioc->TaskCtx = mptfcTaskCtx; + ioc->InternalCtx = mptfcInternalCtx; + + /* 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 (!ioc->active) { + printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", + ioc->name); + return -ENODEV; + } + + /* 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 ++; + } + + if (!ioc_cap) { + printk(MYIOC_s_WARN_FMT + "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", + ioc->name, ioc); + return -ENODEV; + } + + sh = scsi_host_alloc(&mptfc_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); + + /* 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; + + sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; + + sh->max_lun = MPT_LAST_LUN + 1; + 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; + } + + /* 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; + + /* SCSI needs scsi_cmnd lookup table! + * (with size equal to req_depth*PtrSz!) + */ + sz = ioc->req_depth * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptfc_probe_failed; + } + + memset(mem, 0, sz); + hd->ScsiLookup = (struct scsi_cmnd **) mem; + + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", + ioc->name, hd->ScsiLookup, sz)); + + /* 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 mptfc_probe_failed; + } + + memset(mem, 0, sz); + hd->Targets = (VirtDevice **) mem; + + dprintk((KERN_INFO + " Targets @ %p, sz=%d\n", hd->Targets, sz)); + + /* Clear the TM flags + */ + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + hd->resetPending = 0; + hd->abortSCpnt = NULL; + + /* Clear the pointer used to store + * single-threaded commands, i.e., those + * issued during a bus scan, dv and + * configuration pages. + */ + hd->cmdPtr = NULL; + + /* 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; + + hd->mpt_pq_filter = mpt_pq_filter; + + ddvprintk((MYIOC_s_INFO_FMT + "mpt_pq_filter %x\n", + ioc->name, + mpt_pq_filter)); + + init_waitqueue_head(&hd->scandv_waitq); + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; + + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { + dprintk((KERN_ERR MYNAM + "scsi_add_host failed\n")); + goto mptfc_probe_failed; + } + + scsi_scan_host(sh); + return 0; + +mptfc_probe_failed: + + mptscsih_remove(pdev); + return error; +} + +static struct pci_driver mptfc_driver = { + .name = "mptfc", + .id_table = mptfc_pci_table, + .probe = mptfc_probe, + .remove = __devexit_p(mptscsih_remove), + .driver = { + .shutdown = mptscsih_shutdown, + }, +#ifdef CONFIG_PM + .suspend = mptscsih_suspend, + .resume = mptscsih_resume, +#endif +}; + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mptfc_init - Register MPT adapter(s) as SCSI host(s) with + * linux scsi mid-layer. + * + * Returns 0 for success, non-zero for failure. + */ +static int __init +mptfc_init(void) +{ + + show_mptmod_ver(my_NAME, my_VERSION); + + mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); + mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); + mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); + + if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { + devtprintk((KERN_INFO MYNAM + ": Registered for IOC event notifications\n")); + } + + if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { + dprintk((KERN_INFO MYNAM + ": Registered for IOC reset notifications\n")); + } + + return pci_register_driver(&mptfc_driver); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mptfc_exit - Unregisters MPT adapter(s) + * + */ +static void __exit +mptfc_exit(void) +{ + pci_unregister_driver(&mptfc_driver); + + mpt_reset_deregister(mptfcDoneCtx); + dprintk((KERN_INFO MYNAM + ": Deregistered for IOC reset notifications\n")); + + mpt_event_deregister(mptfcDoneCtx); + dprintk((KERN_INFO MYNAM + ": Deregistered for IOC event notifications\n")); + + mpt_deregister(mptfcInternalCtx); + mpt_deregister(mptfcTaskCtx); + mpt_deregister(mptfcDoneCtx); +} + +module_init(mptfc_init); +module_exit(mptfc_exit); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index ef2713b93fab..52794be5a95c 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -1,33 +1,11 @@ /* * linux/drivers/message/fusion/mptlan.c * IP Over Fibre Channel device driver. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel + * For use with LSI Logic Fibre Channel PCI chip/adapters * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. + * Copyright (c) 2000-2005 LSI Logic Corporation * - * Special thanks goes to the I2O LAN driver people at the - * University of Helsinki, who, unbeknownst to them, provided - * the inspiration and initial structure for this driver. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * A really huge debt of gratitude is owed to Eddie C. Dost - * for gobs of hard work fixing and optimizing LAN code. - * THANK YOU! - * - * (see also mptbase.c) - * - * Copyright (c) 2000-2004 LSI Logic Corporation - * Originally By: Noah Romer - * (mailto:mpt_linux_developer@lsil.com) - * - * $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -221,7 +199,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) // NOTE! (Optimization) First case here is now caught in // mptbase.c::mpt_interrupt() routine and callcack here - // is now skipped for this case! 20001218 -sralston + // is now skipped for this case! #if 0 case LAN_REPLY_FORM_MESSAGE_CONTEXT: // dioprintk((KERN_INFO MYNAM "/lan_reply: " @@ -234,7 +212,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) // dioprintk((MYNAM "/lan_reply: " // "calling mpt_lan_send_reply (turbo)\n")); - // Potential BUG here? -sralston + // Potential BUG here? // FreeReqFrame = mpt_lan_send_turbo(dev, tmsg); // If/when mpt_lan_send_turbo would return 1 here, // calling routine (mptbase.c|mpt_interrupt) @@ -310,8 +288,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) case MPI_FUNCTION_EVENT_NOTIFICATION: case MPI_FUNCTION_EVENT_ACK: - /* UPDATE! 20010120 -sralston - * _EVENT_NOTIFICATION should NOT come down this path any more. + /* _EVENT_NOTIFICATION should NOT come down this path any more. * Should be routed to mpt_lan_event_process(), but just in case... */ FreeReqFrame = 1; @@ -561,8 +538,8 @@ mpt_lan_close(struct net_device *dev) } } - kfree (priv->RcvCtl); - kfree (priv->mpt_rxfidx); + kfree(priv->RcvCtl); + kfree(priv->mpt_rxfidx); for (i = 0; i < priv->tx_max_out; i++) { if (priv->SendCtl[i].skb != NULL) { diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 057904260ab1..750e343eb981 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -1,3 +1,49 @@ +/* + * linux/drivers/message/fusion/mptlan.h + * IP Over Fibre Channel device driver. + * For use with LSI Logic Fibre Channel PCI chip/adapters + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * + * Copyright (c) 2000-2005 LSI Logic Corporation + * + */ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + 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; version 2 of the License. + + 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. + + NO WARRANTY + THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + solely responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, damage to or loss of data, + programs or equipment, and unavailability or interruption of operations. + + DISCLAIMER OF LIABILITY + NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + 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 +*/ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* mptlan.h */ #ifndef LINUX_MPTLAN_H_INCLUDED @@ -29,7 +75,7 @@ #include <asm/io.h> /* Override mptbase.h by pre-defining these! */ - #define MODULEAUTHOR "Noah Romer, Eddie C. Dost" +#define MODULEAUTHOR "LSI Logic Corporation" #include "mptbase.h" diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 3a3ef127df04..a0078ae5b9b8 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1,32 +1,11 @@ /* * linux/drivers/message/fusion/mptscsih.c - * High performance SCSI / Fibre Channel SCSI Host device driver. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel + * For use with LSI Logic PCI chip/adapter(s) * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A special thanks to Pamela Delaney (LSI Logic) for tons of work - * and countless enhancements while adding support for the 1030 - * chip family. Pam has been instrumental in the development of - * of the 2.xx.xx series fusion drivers, and her contributions are - * far too numerous to hope to list in one place. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * (see mptbase.c) - * - * Copyright (c) 1999-2004 LSI Logic Corporation - * Original author: Steven J. Ralston - * (mailto:sjralston1@netscape.net) + * Copyright (c) 1999-2005 LSI Logic Corporation * (mailto:mpt_linux_developer@lsil.com) * - * $Id: mptscsih.c,v 1.104 2002/12/03 21:26:34 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -96,27 +75,6 @@ MODULE_AUTHOR(MODULEAUTHOR); MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); -/* Command line args */ -static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION; -MODULE_PARM(mpt_dv, "i"); -MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); - -static int mpt_width = MPTSCSIH_MAX_WIDTH; -MODULE_PARM(mpt_width, "i"); -MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)"); - -static int mpt_factor = MPTSCSIH_MIN_SYNC; -MODULE_PARM(mpt_factor, "h"); -MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)"); - -static int mpt_saf_te = MPTSCSIH_SAF_TE; -MODULE_PARM(mpt_saf_te, "i"); -MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); - -static int mpt_pq_filter = 0; -MODULE_PARM(mpt_pq_filter, "i"); -MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ typedef struct _BIG_SENSE_BUF { @@ -169,18 +127,17 @@ typedef struct _dv_parameters { u16 pad1; } DVPARAMETERS; - /* * Other private/forward protos... */ -static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); +int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq); -static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); +int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, SCSIIORequest_t *pReq, int req_idx); static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); -static void copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); +static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); @@ -188,8 +145,8 @@ static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); -static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); -static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); +int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); +int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen); static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56); @@ -198,8 +155,7 @@ static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *r 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); +int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); @@ -212,29 +168,14 @@ 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 -/* module entry point */ -static int __init mptscsih_init (void); -static void __exit mptscsih_exit (void); -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 *); +void mptscsih_remove(struct pci_dev *); +void mptscsih_shutdown(struct device *); #ifdef CONFIG_PM -static int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state); -static int mptscsih_resume(struct pci_dev *pdev); +int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state); +int mptscsih_resume(struct pci_dev *pdev); #endif - -/* - * Private data... - */ - -static int mpt_scsi_hosts = 0; - -static int ScsiDoneCtx = -1; -static int ScsiTaskCtx = -1; -static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */ - #define SNS_LEN(scp) sizeof((scp)->sense_buffer) #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION @@ -244,20 +185,9 @@ static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */ static DEFINE_SPINLOCK(dvtaskQ_lock); static int dvtaskQ_active = 0; static int dvtaskQ_release = 0; -static struct work_struct mptscsih_dvTask; +static struct work_struct dvTaskQ_task; #endif -/* - * Wait Queue setup - */ -static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq); -static int scandv_wait_done = 1; - - -/* Driver command line structure - */ -static struct scsi_host_template driver_template; - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_add_sge - Place a simple SGE at address pAddr. @@ -619,7 +549,7 @@ nextSGEset: * * Returns 1 indicating alloc'd request frame ptr should be freed. */ -static int +int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) { struct scsi_cmnd *sc; @@ -677,8 +607,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) sc->request_bufflen, xfer_cnt)); if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) - copy_sense_data(sc, hd, mf, pScsiReply); - + mptscsih_copy_sense_data(sc, hd, mf, pScsiReply); + /* * Look for + dump FCP ResponseInfo[]! */ @@ -740,7 +670,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target)); break; - + case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ /* * Do upfront check for valid SenseData and give it @@ -773,7 +703,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); - + break; case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ @@ -905,18 +835,16 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) * Do OS callback * Free driver resources (chain, msg buffers) */ - if (scsi_device_online(SCpnt->device)) { - if (SCpnt->use_sg) { - pci_unmap_sg(ioc->pcidev, - (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, - SCpnt->sc_data_direction); - } else if (SCpnt->request_bufflen) { - pci_unmap_single(ioc->pcidev, - SCpnt->SCp.dma_handle, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - } + if (SCpnt->use_sg) { + pci_unmap_sg(ioc->pcidev, + (struct scatterlist *) SCpnt->request_buffer, + SCpnt->use_sg, + SCpnt->sc_data_direction); + } else if (SCpnt->request_bufflen) { + pci_unmap_single(ioc->pcidev, + SCpnt->SCp.dma_handle, + SCpnt->request_bufflen, + SCpnt->sc_data_direction); } SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; @@ -981,11 +909,6 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Hack! It might be nice to report if a device is returning QUEUE_FULL - * but maybe not each and every time... - */ -static long last_queue_full = 0; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -1003,280 +926,20 @@ static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq) { long time = jiffies; - - if (time - last_queue_full > 10 * HZ) { - char *ioc_str = "ioc?"; - - if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL) - ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name; - dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", - ioc_str, 0, sc->device->id, sc->device->lun)); - last_queue_full = time; - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static char *info_kbuf = NULL; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_probe - Installs scsi devices per bus. - * @pdev: Pointer to pci_dev structure - * - * Returns 0 for success, non-zero for failure. - * - */ - -static int -mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct Scsi_Host *sh; MPT_SCSI_HOST *hd; - MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - unsigned long flags; - int sz, ii; - int numSGE = 0; - int scale; - int ioc_cap; - u8 *mem; - int error=0; - - - /* 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 (!ioc->active) { - printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", - ioc->name); - return -ENODEV; - } - - /* 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 ++; - } - - if (!ioc_cap) { - printk(MYIOC_s_WARN_FMT - "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", - ioc->name, ioc); - return -ENODEV; - } - - 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); - - /* 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 (ioc->bus_type == SCSI) { - 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_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; - } - - /* 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; - - /* SCSI needs scsi_cmnd lookup table! - * (with size equal to req_depth*PtrSz!) - */ - sz = ioc->req_depth * 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; - - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", - ioc->name, hd->ScsiLookup, sz)); - - /* 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->Targets = (VirtDevice **) mem; - - dprintk((KERN_INFO - " Targets @ %p, sz=%d\n", hd->Targets, sz)); - - /* Clear the TM flags - */ - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - hd->resetPending = 0; - hd->abortSCpnt = NULL; - - /* Clear the pointer used to store - * single-threaded commands, i.e., those - * issued during a bus scan, dv and - * configuration pages. - */ - hd->cmdPtr = NULL; - /* 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; - - if (ioc->bus_type == SCSI) { - /* Update with the driver setup - * values. - */ - if (ioc->spi_data.maxBusWidth > mpt_width) - ioc->spi_data.maxBusWidth = mpt_width; - if (ioc->spi_data.minSyncFactor < mpt_factor) - ioc->spi_data.minSyncFactor = mpt_factor; - - if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { - ioc->spi_data.maxSyncOffset = 0; - } - - ioc->spi_data.Saf_Te = mpt_saf_te; - - hd->negoNvram = 0; -#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - hd->negoNvram = MPT_SCSICFG_USE_NVRAM; -#endif - ioc->spi_data.forceDv = 0; - ioc->spi_data.noQas = 0; - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - ioc->spi_data.dvStatus[ii] = - MPT_SCSICFG_NEGOTIATE; - } - - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) - ioc->spi_data.dvStatus[ii] |= - MPT_SCSICFG_DV_NOT_DONE; - - dinitprintk((MYIOC_s_INFO_FMT - "dv %x width %x factor %x saf_te %x\n", - ioc->name, mpt_dv, - mpt_width, - mpt_factor, - mpt_saf_te)); - } - - mpt_scsi_hosts++; + if (sc->device == NULL) + return; + if (sc->device->host == NULL) + return; + if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL) + return; - error = scsi_add_host (sh, &ioc->pcidev->dev); - if(error) { - dprintk((KERN_ERR MYNAM - "scsi_add_host failed\n")); - goto mptscsih_probe_failed; + if (time - hd->last_queue_full > 10 * HZ) { + dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", + hd->ioc->name, 0, sc->device->id, sc->device->lun)); + hd->last_queue_full = time; } - - scsi_scan_host(sh); - return 0; - -mptscsih_probe_failed: - - mptscsih_remove(pdev); - return error; - } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1286,7 +949,7 @@ mptscsih_probe_failed: * * */ -static void +void mptscsih_remove(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); @@ -1294,12 +957,16 @@ mptscsih_remove(struct pci_dev *pdev) MPT_SCSI_HOST *hd; int count; unsigned long flags; + int sz1; if(!host) return; scsi_remove_host(host); + if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) + return; + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION /* Check DV thread active */ count = 10 * HZ; @@ -1321,40 +988,36 @@ mptscsih_remove(struct pci_dev *pdev) #endif #endif - hd = (MPT_SCSI_HOST *)host->hostdata; - if (hd != NULL) { - int sz1; + mptscsih_shutdown(&pdev->dev); - mptscsih_shutdown(&pdev->dev); + sz1=0; - sz1=0; + if (hd->ScsiLookup != NULL) { + sz1 = hd->ioc->req_depth * sizeof(void *); + kfree(hd->ScsiLookup); + hd->ScsiLookup = NULL; + } - if (hd->ScsiLookup != NULL) { - sz1 = hd->ioc->req_depth * sizeof(void *); - kfree(hd->ScsiLookup); - hd->ScsiLookup = NULL; - } + /* + * Free pointer array. + */ + kfree(hd->Targets); + hd->Targets = NULL; - if (hd->Targets != NULL) { - /* - * Free pointer array. - */ - kfree(hd->Targets); - hd->Targets = NULL; - } + dprintk((MYIOC_s_INFO_FMT + "Free'd ScsiLookup (%d) memory\n", + hd->ioc->name, sz1)); - dprintk((MYIOC_s_INFO_FMT - "Free'd ScsiLookup (%d) memory\n", - hd->ioc->name, sz1)); + kfree(hd->info_kbuf); - /* NULL the Scsi_Host pointer - */ - hd->ioc->sh = NULL; - } + /* NULL the Scsi_Host pointer + */ + hd->ioc->sh = NULL; scsi_host_put(host); - mpt_scsi_hosts--; + mpt_detach(pdev); + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1362,7 +1025,7 @@ mptscsih_remove(struct pci_dev *pdev) * mptscsih_shutdown - reboot notifier * */ -static void +void mptscsih_shutdown(struct device * dev) { MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev)); @@ -1384,15 +1047,15 @@ mptscsih_shutdown(struct device * dev) #ifdef CONFIG_PM /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptscsih_suspend - Fusion MPT scsie driver suspend routine. + * mptscsih_suspend - Fusion MPT scsi driver suspend routine. * * */ -static int +int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) { mptscsih_shutdown(&pdev->dev); - return 0; + return mpt_suspend(pdev,state); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1401,13 +1064,15 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) * * */ -static int +int mptscsih_resume(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct Scsi_Host *host = ioc->sh; MPT_SCSI_HOST *hd; + mpt_resume(pdev); + if(!host) return 0; @@ -1422,9 +1087,9 @@ mptscsih_resume(struct pci_dev *pdev) if (!dvtaskQ_active) { dvtaskQ_active = 1; spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - INIT_WORK(&mptscsih_dvTask, + INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd); - schedule_work(&mptscsih_dvTask); + schedule_work(&dvTaskQ_task); } else { spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } @@ -1435,82 +1100,6 @@ mptscsih_resume(struct pci_dev *pdev) #endif -static struct mpt_pci_driver mptscsih_driver = { - .probe = mptscsih_probe, - .remove = mptscsih_remove, - .shutdown = mptscsih_shutdown, -#ifdef CONFIG_PM - .suspend = mptscsih_suspend, - .resume = mptscsih_resume, -#endif -}; - -/* SCSI host fops start here... */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with - * linux scsi mid-layer. - * - * Returns 0 for success, non-zero for failure. - */ -static int __init -mptscsih_init(void) -{ - - show_mptmod_ver(my_NAME, my_VERSION); - - ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER); - ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER); - ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER); - - if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) { - devtprintk((KERN_INFO MYNAM - ": Registered for IOC event notifications\n")); - } - - if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM - ": Registered for IOC reset notifications\n")); - } - - if(mpt_device_driver_register(&mptscsih_driver, - MPTSCSIH_DRIVER) != 0 ) { - dprintk((KERN_INFO MYNAM - ": failed to register dd callbacks\n")); - } - - return 0; - -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mptscsih_exit - Unregisters MPT adapter(s) - * - */ -static void __exit -mptscsih_exit(void) -{ - mpt_device_driver_deregister(MPTSCSIH_DRIVER); - - mpt_reset_deregister(ScsiDoneCtx); - dprintk((KERN_INFO MYNAM - ": Deregistered for IOC reset notifications\n")); - - mpt_event_deregister(ScsiDoneCtx); - dprintk((KERN_INFO MYNAM - ": Deregistered for IOC event notifications\n")); - - mpt_deregister(ScsiScanDvCtx); - mpt_deregister(ScsiTaskCtx); - mpt_deregister(ScsiDoneCtx); - - if (info_kbuf != NULL) - kfree(info_kbuf); - -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_info - Return information about MPT adapter @@ -1520,24 +1109,25 @@ mptscsih_exit(void) * * Returns pointer to buffer where information was written. */ -static const char * +const char * mptscsih_info(struct Scsi_Host *SChost) { MPT_SCSI_HOST *h; int size = 0; - if (info_kbuf == NULL) - if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) - return info_kbuf; - h = (MPT_SCSI_HOST *)SChost->hostdata; - info_kbuf[0] = '\0'; + if (h) { - mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0); - info_kbuf[size-1] = '\0'; + if (h->info_kbuf == NULL) + if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) + return h->info_kbuf; + h->info_kbuf[0] = '\0'; + + mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); + h->info_kbuf[size-1] = '\0'; } - return info_kbuf; + return h->info_kbuf; } struct info_str { @@ -1547,7 +1137,8 @@ struct info_str { int pos; }; -static void copy_mem_info(struct info_str *info, char *data, int len) +static void +mptscsih_copy_mem_info(struct info_str *info, char *data, int len) { if (info->pos + len > info->length) len = info->length - info->pos; @@ -1568,7 +1159,8 @@ static void copy_mem_info(struct info_str *info, char *data, int len) } } -static int copy_info(struct info_str *info, char *fmt, ...) +static int +mptscsih_copy_info(struct info_str *info, char *fmt, ...) { va_list args; char buf[81]; @@ -1578,11 +1170,12 @@ static int copy_info(struct info_str *info, char *fmt, ...) len = vsprintf(buf, fmt, args); va_end(args); - copy_mem_info(info, buf, len); + mptscsih_copy_mem_info(info, buf, len); return len; } -static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len) +static int +mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len) { struct info_str info; @@ -1591,10 +1184,10 @@ static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int le info.offset = offset; info.pos = 0; - copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name); - copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); - copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts); - copy_info(&info, "MaxQ=%d\n", ioc->req_depth); + mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name); + mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); + mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts); + mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth); return ((info.pos > info.offset) ? info.pos - info.offset : 0); } @@ -1612,7 +1205,7 @@ static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int le * hostno: scsi host number * func: if write = 1; if read = 0 */ -static int +int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func) { @@ -1649,7 +1242,7 @@ mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t off * * Returns 0. (rtn value discarded by linux scsi mid-layer) */ -static int +int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { MPT_SCSI_HOST *hd; @@ -1684,7 +1277,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* * Put together a MPT SCSI request... */ - if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) { dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", hd->ioc->name)); return SCSI_MLQUEUE_HOST_BUSY; @@ -1696,8 +1289,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) ADD_INDEX_LOG(my_idx); - /* BUG FIX! 19991030 -sralston - * TUR's being issued with scsictl=0x02000000 (DATA_IN)! + /* TUR's being issued with scsictl=0x02000000 (DATA_IN)! * Seems we may receive a buffer (datalen>0) even when there * will be no data transfer! GRRRRR... */ @@ -1791,9 +1383,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) if (!dvtaskQ_active) { dvtaskQ_active = 1; spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); + INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd); - schedule_work(&mptscsih_dvTask); + schedule_work(&dvTaskQ_task); } else { spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } @@ -1819,7 +1411,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) } #endif - mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf); + mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", hd->ioc->name, SCpnt, mf, my_idx)); DBG_DUMP_REQUEST_FRAME(mf) @@ -2036,7 +1628,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun /* Return Fail to calling function if no message frames available. */ - if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) { dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", hd->ioc->name)); //return FAILED; @@ -2075,7 +1667,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); - if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc, + if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" @@ -2107,7 +1699,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun * * Returns SUCCESS or FAILED. */ -static int +int mptscsih_abort(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; @@ -2115,7 +1707,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) MPT_FRAME_HDR *mf; u32 ctx2abort; int scpnt_idx; - spinlock_t *host_lock = SCpnt->device->host->host_lock; /* If we can't locate our host adapter structure, return FAILED status. */ @@ -2163,7 +1754,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) hd->abortSCpnt = SCpnt; - spin_unlock_irq(host_lock); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, ctx2abort, 2 /* 2 second timeout */) @@ -2180,8 +1770,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - spin_lock_irq(host_lock); - /* Unmap the DMA buffers, if any. */ if (SCpnt->use_sg) { pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, @@ -2197,7 +1785,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) mpt_free_msg_frame(ioc, mf); return FAILED; } - spin_lock_irq(host_lock); return SUCCESS; } @@ -2210,11 +1797,10 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) * * Returns SUCCESS or FAILED. */ -static int +int mptscsih_dev_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; - spinlock_t *host_lock = SCpnt->device->host->host_lock; /* If we can't locate our host adapter structure, return FAILED status. */ @@ -2231,7 +1817,6 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", hd->ioc->name, SCpnt); - spin_unlock_irq(host_lock); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, SCpnt->device->channel, SCpnt->device->id, 0, 0, 5 /* 5 second timeout */) @@ -2243,12 +1828,10 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) hd->ioc->name, SCpnt); hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - spin_lock_irq(host_lock); return FAILED; } - spin_lock_irq(host_lock); - return SUCCESS; + return SUCCESS; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2260,7 +1843,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) * * Returns SUCCESS or FAILED. */ -static int +int mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; @@ -2282,7 +1865,6 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) hd->timeouts++; /* We are now ready to execute the task management request. */ - spin_unlock_irq(host_lock); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */) < 0){ @@ -2298,7 +1880,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) spin_lock_irq(host_lock); return FAILED; } - spin_lock_irq(host_lock); + return SUCCESS; } @@ -2312,12 +1894,11 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) * * Returns SUCCESS or FAILED. */ -static int +int mptscsih_host_reset(struct scsi_cmnd *SCpnt) { MPT_SCSI_HOST * hd; int status = SUCCESS; - spinlock_t *host_lock = SCpnt->device->host->host_lock; /* If we can't locate the host to reset, then we failed. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ @@ -2333,7 +1914,6 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) /* 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. */ - spin_unlock_irq(host_lock); if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){ status = FAILED; } else { @@ -2343,8 +1923,6 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) hd->tmPending = 0; hd->tmState = TM_STATE_NONE; } - spin_lock_irq(host_lock); - dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: " "Status = %s\n", @@ -2426,7 +2004,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) * * Returns 1 indicating alloc'd request frame ptr should be freed. */ -static int +int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) { SCSITaskMgmtReply_t *pScsiTmReply; @@ -2509,7 +2087,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m /* * This is anyones guess quite frankly. */ -static int +int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]) { @@ -2556,7 +2134,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, * Return non-zero if allocation fails. * Init memory once per id (not LUN). */ -static int +int mptscsih_slave_alloc(struct scsi_device *device) { struct Scsi_Host *host = device->host; @@ -2599,7 +2177,8 @@ mptscsih_slave_alloc(struct scsi_device *device) return 0; } -static int mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) +static int +mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) { int i; @@ -2618,7 +2197,7 @@ static int mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) * OS entry point to allow for host driver to free allocated memory * Called if no device present or device being unloaded */ -static void +void mptscsih_slave_destroy(struct scsi_device *device) { struct Scsi_Host *host = device->host; @@ -2639,7 +2218,7 @@ mptscsih_slave_destroy(struct scsi_device *device) kfree(hd->Targets[target]); hd->Targets[target] = NULL; - + if (hd->ioc->bus_type == SCSI) { if (mptscsih_is_raid_volume(hd, target)) { hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; @@ -2695,7 +2274,7 @@ mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd, * member to 1 if a device does not support Q tags. * Return non-zero if fails. */ -static int +int mptscsih_slave_configure(struct scsi_device *device) { struct Scsi_Host *sh = device->host; @@ -2758,8 +2337,8 @@ slave_configure_exit: return 0; } -static ssize_t -mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count) +ssize_t +mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int depth; struct scsi_device *sdev = to_scsi_device(dev); @@ -2788,7 +2367,7 @@ mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count) * */ static void -copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) +mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) { VirtDevice *target; SCSIIORequest_t *pReq; @@ -2854,7 +2433,7 @@ SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int +int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { MPT_SCSI_HOST *hd; @@ -2949,8 +2528,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) */ hd->pLocal = &hd->localReply; hd->pLocal->completion = MPT_SCANDV_DID_RESET; - scandv_wait_done = 1; - wake_up(&scandv_waitq); + hd->scandv_wait_done = 1; + wake_up(&hd->scandv_waitq); hd->cmdPtr = NULL; } @@ -2969,7 +2548,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int +int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { MPT_SCSI_HOST *hd; @@ -3085,42 +2664,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) return 1; /* currently means nothing really */ } -static struct device_attribute mptscsih_queue_depth_attr = { - .attr = { - .name = "queue_depth", - .mode = S_IWUSR, - }, - .store = mptscsih_store_queue_depth, -}; - -static struct device_attribute *mptscsih_dev_attrs[] = { - &mptscsih_queue_depth_attr, - NULL, -}; - -static struct scsi_host_template driver_template = { - .proc_name = "mptscsih", - .proc_info = mptscsih_proc_info, - .name = "MPT SCSI Host", - .info = mptscsih_info, - .queuecommand = mptscsih_qcmd, - .slave_alloc = mptscsih_slave_alloc, - .slave_configure = mptscsih_slave_configure, - .slave_destroy = mptscsih_slave_destroy, - .eh_abort_handler = mptscsih_abort, - .eh_device_reset_handler = mptscsih_dev_reset, - .eh_bus_reset_handler = mptscsih_bus_reset, - .eh_host_reset_handler = mptscsih_host_reset, - .bios_param = mptscsih_bios_param, - .can_queue = MPT_SCSI_CAN_QUEUE, - .this_id = -1, - .sg_tablesize = MPT_SCSI_SG_DEPTH, - .max_sectors = 8192, - .cmd_per_lun = 7, - .use_clustering = ENABLE_CLUSTERING, - .sdev_attrs = mptscsih_dev_attrs, -}; - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptscsih_initTarget - Target, LUN alloc/free functionality. @@ -3158,9 +2701,9 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * * around a bug in th emid-layer in some distributions in which the mid-layer will * continue to try to communicate to the LUN and evntually create a dummy LUN. */ - if (mpt_pq_filter && dlen && (data[0] & 0xE0)) + if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0)) data[0] |= 0x40; - + /* Is LUN supported? If so, upper 2 bits will be 0 * in first byte of inquiry data. */ @@ -3307,7 +2850,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); noQas = 0; } - + offset = pspi_data->maxSyncOffset; /* If RAID, never disable QAS @@ -3401,7 +2944,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) if ( (vdev = hd->Targets[ii]) ) { vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS; mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags); - } + } } } } @@ -3426,14 +2969,15 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) * Tapes, initTarget will set this flag on completion of Inquiry command. * Called only if DV_NOT_DONE flag is set */ -static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) +static void +mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) { u8 cmd; ScsiCfgData *pSpi; ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); - + if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) return; @@ -3464,7 +3008,8 @@ static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) * 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) +static void +mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id) { if ((hd->Targets) && (hd->Targets[target_id] == NULL)) @@ -3631,7 +3176,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) offset = pTarget->maxOffset; negoFlags = pTarget->negoFlags; } - + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION /* Force to async and narrow if DV has not been executed * for this ID @@ -3653,7 +3198,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) /* Get a MF for this command. */ - if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n", ioc->name)); return -EAGAIN; @@ -3717,7 +3262,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) ioc->name, id, (id | (bus<<8)), requested, configuration)); - mpt_put_msg_frame(ScsiDoneCtx, ioc, mf); + mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); } return 0; @@ -3748,7 +3293,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) /* Get a MF for this command. */ - if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", ioc->name)); return -EAGAIN; @@ -3794,7 +3339,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus)); - mpt_put_msg_frame(ScsiDoneCtx, ioc, mf); + mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); return 0; } @@ -3824,7 +3369,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) * in the IOC member localReply structure. * Used ONLY for DV and other internal commands. */ -static int +int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) { MPT_SCSI_HOST *hd; @@ -3832,6 +3377,8 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) int completionCode; u16 req_idx; + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + if ((mf == NULL) || (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { printk(MYIOC_s_ERR_FMT @@ -3840,7 +3387,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) goto wakeup; } - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; del_timer(&hd->timer); req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); hd->ScsiLookup[req_idx] = NULL; @@ -3972,8 +3518,8 @@ wakeup: /* * Wake up the original calling thread */ - scandv_wait_done = 1; - wake_up(&scandv_waitq); + hd->scandv_wait_done = 1; + wake_up(&hd->scandv_waitq); return 1; } @@ -3984,7 +3530,8 @@ wakeup: * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long * */ -static void mptscsih_timer_expired(unsigned long data) +void +mptscsih_timer_expired(unsigned long data) { MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; @@ -4051,7 +3598,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) /* Get and Populate a free Frame */ - if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", hd->ioc->name)); return -EAGAIN; @@ -4077,7 +3624,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) hd->pLocal = NULL; hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ - scandv_wait_done = 0; + hd->scandv_wait_done = 0; /* Save cmd pointer, for resource free if timeout or * FW reload occurs @@ -4085,8 +3632,8 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) hd->cmdPtr = mf; add_timer(&hd->timer); - mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf); - wait_event(scandv_waitq, scandv_wait_done); + mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); + wait_event(hd->scandv_waitq, hd->scandv_wait_done); if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD)) return -1; @@ -4232,7 +3779,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) /* Get and Populate a free Frame */ - if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n", hd->ioc->name)); return -EBUSY; @@ -4314,7 +3861,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) */ hd->pLocal = NULL; hd->timer.expires = jiffies + HZ*cmdTimeout; - scandv_wait_done = 0; + hd->scandv_wait_done = 0; /* Save cmd pointer, for resource free if timeout or * FW reload occurs @@ -4322,8 +3869,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) hd->cmdPtr = mf; add_timer(&hd->timer); - mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf); - wait_event(scandv_waitq, scandv_wait_done); + mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); + wait_event(hd->scandv_waitq, hd->scandv_wait_done); if (hd->pLocal) { rc = hd->pLocal->completion; @@ -4640,7 +4187,8 @@ mptscsih_domainValidation(void *arg) /* Search IOC page 3 to determine if this is hidden physical disk */ -static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) +static int +mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) { if (ioc->spi_data.pIocPg3) { Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; @@ -4659,7 +4207,8 @@ static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) /* Write SDP1 if no QAS has been enabled */ -static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) +static void +mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) { VirtDevice *pTarget; int ii; @@ -5157,7 +4706,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); - if (mpt_dv == 0) + if (ioc->spi_data.mpt_dv == 0) goto target_done; inq0 = (*pbuf1) & 0x1F; @@ -6015,7 +5564,29 @@ mptscsih_fillbuf(char *buffer, int size, int index, int width) } #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +EXPORT_SYMBOL(mptscsih_remove); +EXPORT_SYMBOL(mptscsih_shutdown); +#ifdef CONFIG_PM +EXPORT_SYMBOL(mptscsih_suspend); +EXPORT_SYMBOL(mptscsih_resume); +#endif +EXPORT_SYMBOL(mptscsih_proc_info); +EXPORT_SYMBOL(mptscsih_info); +EXPORT_SYMBOL(mptscsih_qcmd); +EXPORT_SYMBOL(mptscsih_slave_alloc); +EXPORT_SYMBOL(mptscsih_slave_destroy); +EXPORT_SYMBOL(mptscsih_slave_configure); +EXPORT_SYMBOL(mptscsih_abort); +EXPORT_SYMBOL(mptscsih_dev_reset); +EXPORT_SYMBOL(mptscsih_bus_reset); +EXPORT_SYMBOL(mptscsih_host_reset); +EXPORT_SYMBOL(mptscsih_bios_param); +EXPORT_SYMBOL(mptscsih_io_done); +EXPORT_SYMBOL(mptscsih_taskmgmt_complete); +EXPORT_SYMBOL(mptscsih_scandv_complete); +EXPORT_SYMBOL(mptscsih_event_process); +EXPORT_SYMBOL(mptscsih_ioc_reset); +EXPORT_SYMBOL(mptscsih_store_queue_depth); +EXPORT_SYMBOL(mptscsih_timer_expired); -module_init(mptscsih_init); -module_exit(mptscsih_exit); +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 5cb2fd45c38f..d73aec33e16a 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -1,26 +1,13 @@ /* - * linux/drivers/message/fusion/mptscsih.h + * linux/drivers/message/fusion/mptscsi.h * High performance SCSI / Fibre Channel SCSI Host device driver. * For use with PCI chip/adapter(s): * LSIFC9xx/LSI409xx Fibre Channel * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * (see also mptbase.c) - * - * Copyright (c) 1999-2004 LSI Logic Corporation - * Originally By: Steven J. Ralston - * (mailto:netscape.net) + * Copyright (c) 1999-2005 LSI Logic Corporation * (mailto:mpt_linux_developer@lsil.com) * - * $Id: mptscsih.h,v 1.21 2002/12/03 21:26:35 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -91,4 +78,30 @@ #define MPTSCSIH_MIN_SYNC 0x08 #define MPTSCSIH_SAF_TE 0 + +#endif + +extern void mptscsih_remove(struct pci_dev *); +extern void mptscsih_shutdown(struct device *); +#ifdef CONFIG_PM +extern int mptscsih_suspend(struct pci_dev *pdev, u32 state); +extern int mptscsih_resume(struct pci_dev *pdev); #endif +extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); +extern const char * mptscsih_info(struct Scsi_Host *SChost); +extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); +extern int mptscsih_slave_alloc(struct scsi_device *device); +extern void mptscsih_slave_destroy(struct scsi_device *device); +extern int mptscsih_slave_configure(struct scsi_device *device); +extern int mptscsih_abort(struct scsi_cmnd * SCpnt); +extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt); +extern int mptscsih_bus_reset(struct scsi_cmnd * SCpnt); +extern int mptscsih_host_reset(struct scsi_cmnd *SCpnt); +extern int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]); +extern int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); +extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); +extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); +extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); +extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); +extern ssize_t mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +extern void mptscsih_timer_expired(unsigned long data); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c new file mode 100644 index 000000000000..5f9a61b85b3b --- /dev/null +++ b/drivers/message/fusion/mptspi.c @@ -0,0 +1,486 @@ +/* + * linux/drivers/message/fusion/mptspi.c + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * + * Copyright (c) 1999-2005 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsil.com) + * + */ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + 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; version 2 of the License. + + 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. + + NO WARRANTY + THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + solely responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, damage to or loss of data, + programs or equipment, and unavailability or interruption of operations. + + DISCLAIMER OF LIABILITY + NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + 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 "linux_compat.h" /* linux-2.6 tweaks */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/kdev_t.h> +#include <linux/blkdev.h> +#include <linux/delay.h> /* for mdelay */ +#include <linux/interrupt.h> /* needed for in_interrupt() proto */ +#include <linux/reboot.h> /* notifier code */ +#include <linux/sched.h> +#include <linux/workqueue.h> + +#include <scsi/scsi.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_tcq.h> + +#include "mptbase.h" +#include "mptscsih.h" + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +#define my_NAME "Fusion MPT SPI Host driver" +#define my_VERSION MPT_LINUX_VERSION_COMMON +#define MYNAM "mptspi" + +MODULE_AUTHOR(MODULEAUTHOR); +MODULE_DESCRIPTION(my_NAME); +MODULE_LICENSE("GPL"); + +/* Command line args */ +#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION +static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION; +module_param(mpt_dv, int, 0); +MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); + +static int mpt_width = MPTSCSIH_MAX_WIDTH; +module_param(mpt_width, int, 0); +MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)"); + +static ushort mpt_factor = MPTSCSIH_MIN_SYNC; +module_param(mpt_factor, ushort, 0); +MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)"); +#endif + +static int mpt_saf_te = MPTSCSIH_SAF_TE; +module_param(mpt_saf_te, int, 0); +MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); + +static int mpt_pq_filter = 0; +module_param(mpt_pq_filter, int, 0); +MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); + +static int mptspiDoneCtx = -1; +static int mptspiTaskCtx = -1; +static int mptspiInternalCtx = -1; /* Used only for internal commands */ + +static struct device_attribute mptspi_queue_depth_attr = { + .attr = { + .name = "queue_depth", + .mode = S_IWUSR, + }, + .store = mptscsih_store_queue_depth, +}; + +static struct device_attribute *mptspi_dev_attrs[] = { + &mptspi_queue_depth_attr, + NULL, +}; + +static struct scsi_host_template mptspi_driver_template = { + .proc_name = "mptspi", + .proc_info = mptscsih_proc_info, + .name = "MPT SPI Host", + .info = mptscsih_info, + .queuecommand = mptscsih_qcmd, + .slave_alloc = mptscsih_slave_alloc, + .slave_configure = mptscsih_slave_configure, + .slave_destroy = mptscsih_slave_destroy, + .eh_abort_handler = mptscsih_abort, + .eh_device_reset_handler = mptscsih_dev_reset, + .eh_bus_reset_handler = mptscsih_bus_reset, + .eh_host_reset_handler = mptscsih_host_reset, + .bios_param = mptscsih_bios_param, + .can_queue = MPT_SCSI_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, + .sdev_attrs = mptspi_dev_attrs, +}; + + +/**************************************************************************** + * Supported hardware + */ + +static struct pci_device_id mptspi_pci_table[] = { + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035, + PCI_ANY_ID, PCI_ANY_ID }, + {0} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, mptspi_pci_table); + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mptspi_probe - Installs scsi devices per bus. + * @pdev: Pointer to pci_dev structure + * + * Returns 0 for success, non-zero for failure. + * + */ +static int +mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct Scsi_Host *sh; + MPT_SCSI_HOST *hd; + MPT_ADAPTER *ioc; + unsigned long flags; + int sz, ii; + int numSGE = 0; + int scale; + int ioc_cap; + u8 *mem; + int error=0; + int r; + + if ((r = mpt_attach(pdev,id)) != 0) + return r; + + ioc = pci_get_drvdata(pdev); + ioc->DoneCtx = mptspiDoneCtx; + ioc->TaskCtx = mptspiTaskCtx; + ioc->InternalCtx = mptspiInternalCtx; + + /* 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 (!ioc->active) { + printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", + ioc->name); + return -ENODEV; + } + + /* 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 ++; + } + + if (!ioc_cap) { + printk(MYIOC_s_WARN_FMT + "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", + ioc->name, ioc); + return -ENODEV; + } + + sh = scsi_host_alloc(&mptspi_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); + + /* 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( + */ + sh->max_id = MPT_MAX_SCSI_DEVICES; + + sh->max_lun = MPT_LAST_LUN + 1; + 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; + } + + /* 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; + + /* SCSI needs scsi_cmnd lookup table! + * (with size equal to req_depth*PtrSz!) + */ + sz = ioc->req_depth * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptspi_probe_failed; + } + + memset(mem, 0, sz); + hd->ScsiLookup = (struct scsi_cmnd **) mem; + + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", + ioc->name, hd->ScsiLookup, sz)); + + /* 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 mptspi_probe_failed; + } + + memset(mem, 0, sz); + hd->Targets = (VirtDevice **) mem; + + dprintk((KERN_INFO + " Targets @ %p, sz=%d\n", hd->Targets, sz)); + + /* Clear the TM flags + */ + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + hd->resetPending = 0; + hd->abortSCpnt = NULL; + + /* Clear the pointer used to store + * single-threaded commands, i.e., those + * issued during a bus scan, dv and + * configuration pages. + */ + hd->cmdPtr = NULL; + + /* 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; + + ioc->spi_data.Saf_Te = mpt_saf_te; + hd->mpt_pq_filter = mpt_pq_filter; + +#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION + if (ioc->spi_data.maxBusWidth > mpt_width) + ioc->spi_data.maxBusWidth = mpt_width; + if (ioc->spi_data.minSyncFactor < mpt_factor) + ioc->spi_data.minSyncFactor = mpt_factor; + if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { + ioc->spi_data.maxSyncOffset = 0; + } + ioc->spi_data.mpt_dv = mpt_dv; + hd->negoNvram = 0; + + ddvprintk((MYIOC_s_INFO_FMT + "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n", + ioc->name, + mpt_dv, + mpt_width, + mpt_factor, + mpt_saf_te, + mpt_pq_filter)); +#else + hd->negoNvram = MPT_SCSICFG_USE_NVRAM; + ddvprintk((MYIOC_s_INFO_FMT + "saf_te %x mpt_pq_filter %x\n", + ioc->name, + mpt_saf_te, + mpt_pq_filter)); +#endif + + ioc->spi_data.forceDv = 0; + ioc->spi_data.noQas = 0; + + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) + ioc->spi_data.dvStatus[ii] = + MPT_SCSICFG_NEGOTIATE; + + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) + ioc->spi_data.dvStatus[ii] |= + MPT_SCSICFG_DV_NOT_DONE; + + init_waitqueue_head(&hd->scandv_waitq); + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; + + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { + dprintk((KERN_ERR MYNAM + "scsi_add_host failed\n")); + goto mptspi_probe_failed; + } + + scsi_scan_host(sh); + return 0; + +mptspi_probe_failed: + + mptscsih_remove(pdev); + return error; +} + +static struct pci_driver mptspi_driver = { + .name = "mptspi", + .id_table = mptspi_pci_table, + .probe = mptspi_probe, + .remove = __devexit_p(mptscsih_remove), + .driver = { + .shutdown = mptscsih_shutdown, + }, +#ifdef CONFIG_PM + .suspend = mptscsih_suspend, + .resume = mptscsih_resume, +#endif +}; + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mptspi_init - Register MPT adapter(s) as SCSI host(s) with + * linux scsi mid-layer. + * + * Returns 0 for success, non-zero for failure. + */ +static int __init +mptspi_init(void) +{ + + show_mptmod_ver(my_NAME, my_VERSION); + + mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); + mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); + mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); + + if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { + devtprintk((KERN_INFO MYNAM + ": Registered for IOC event notifications\n")); + } + + if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) { + dprintk((KERN_INFO MYNAM + ": Registered for IOC reset notifications\n")); + } + + return pci_register_driver(&mptspi_driver); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mptspi_exit - Unregisters MPT adapter(s) + * + */ +static void __exit +mptspi_exit(void) +{ + pci_unregister_driver(&mptspi_driver); + + mpt_reset_deregister(mptspiDoneCtx); + dprintk((KERN_INFO MYNAM + ": Deregistered for IOC reset notifications\n")); + + mpt_event_deregister(mptspiDoneCtx); + dprintk((KERN_INFO MYNAM + ": Deregistered for IOC event notifications\n")); + + mpt_deregister(mptspiInternalCtx); + mpt_deregister(mptspiTaskCtx); + mpt_deregister(mptspiDoneCtx); +} + +module_init(mptspi_init); +module_exit(mptspi_exit); diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index 8d132b0d6b12..06e8eb19a05c 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig @@ -24,10 +24,28 @@ config I2O If unsure, say N. +config I2O_EXT_ADAPTEC + bool "Enable Adaptec extensions" + depends on I2O + default y + ---help--- + Say Y for support of raidutils for Adaptec I2O controllers. You also + have to say Y to "I2O Configuration support", "I2O SCSI OSM" below + and to "SCSI generic support" under "SCSI device configuration". + +config I2O_EXT_ADAPTEC_DMA64 + bool "Enable 64-bit DMA" + depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G ) + default y + ---help--- + Say Y for support of 64-bit DMA transfer mode on Adaptec I2O + controllers. + Note: You need at least firmware version 3709. + config I2O_CONFIG tristate "I2O Configuration support" - depends on PCI && I2O - help + depends on I2O + ---help--- Say Y for support of the configuration interface for the I2O adapters. If you have a RAID controller from Adaptec and you want to use the raidutils to manage your RAID array, you have to say Y here. @@ -35,10 +53,28 @@ config I2O_CONFIG To compile this support as a module, choose M here: the module will be called i2o_config. +config I2O_CONFIG_OLD_IOCTL + bool "Enable ioctls (OBSOLETE)" + depends on I2O_CONFIG + default y + ---help--- + Enables old ioctls. + +config I2O_BUS + tristate "I2O Bus Adapter OSM" + depends on I2O + ---help--- + Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM + provides access to the busses on the I2O controller. The main purpose + is to rescan the bus to find new devices. + + To compile this support as a module, choose M here: the + module will be called i2o_bus. + config I2O_BLOCK tristate "I2O Block OSM" depends on I2O - help + ---help--- Include support for the I2O Block OSM. The Block OSM presents disk and other structured block devices to the operating system. If you are using an RAID controller, you could access the array only by @@ -51,7 +87,7 @@ config I2O_BLOCK config I2O_SCSI tristate "I2O SCSI OSM" depends on I2O && SCSI - help + ---help--- Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel I2O controller. You can use both the SCSI and Block OSM together if you wish. To access a RAID array, you must use the Block OSM driver. @@ -63,7 +99,7 @@ config I2O_SCSI config I2O_PROC tristate "I2O /proc support" depends on I2O - help + ---help--- If you say Y here and to "/proc file system support", you will be able to read I2O related information from the virtual directory /proc/i2o. diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile index aabc6cdc3fce..2c2e39aa1efa 100644 --- a/drivers/message/i2o/Makefile +++ b/drivers/message/i2o/Makefile @@ -6,8 +6,11 @@ # i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o +i2o_bus-y += bus-osm.o +i2o_config-y += config-osm.o obj-$(CONFIG_I2O) += i2o_core.o obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o +obj-$(CONFIG_I2O_BUS) += i2o_bus.o obj-$(CONFIG_I2O_BLOCK) += i2o_block.o obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o obj-$(CONFIG_I2O_PROC) += i2o_proc.o diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c new file mode 100644 index 000000000000..151b228e1cb3 --- /dev/null +++ b/drivers/message/i2o/bus-osm.c @@ -0,0 +1,164 @@ +/* + * Bus Adapter OSM + * + * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +#include <linux/module.h> +#include <linux/i2o.h> + +#define OSM_NAME "bus-osm" +#define OSM_VERSION "$Rev$" +#define OSM_DESCRIPTION "I2O Bus Adapter OSM" + +static struct i2o_driver i2o_bus_driver; + +/* Bus OSM class handling definition */ +static struct i2o_class_id i2o_bus_class_id[] = { + {I2O_CLASS_BUS_ADAPTER}, + {I2O_CLASS_END} +}; + +/** + * i2o_bus_scan - Scan the bus for new devices + * @dev: I2O device of the bus, which should be scanned + * + * Scans the bus dev for new / removed devices. After the scan a new LCT + * will be fetched automatically. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_bus_scan(struct i2o_device *dev) +{ + struct i2o_message __iomem *msg; + u32 m; + + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + + return i2o_msg_post_wait(dev->iop, m, 60); +}; + +/** + * i2o_bus_store_scan - Scan the I2O Bus Adapter + * @d: device which should be scanned + * + * Returns count. + */ +static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf, + size_t count) +{ + struct i2o_device *i2o_dev = to_i2o_device(d); + int rc; + + if ((rc = i2o_bus_scan(i2o_dev))) + osm_warn("bus scan failed %d\n", rc); + + return count; +} + +/* Bus Adapter OSM device attributes */ +static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan); + +/** + * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it + * @dev: device to verify if it is a I2O Bus Adapter device + * + * Because we want all Bus Adapters always return 0. + * + * Returns 0. + */ +static int i2o_bus_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(get_device(dev)); + + device_create_file(dev, &dev_attr_scan); + + osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid); + + return 0; +}; + +/** + * i2o_bus_remove - remove the I2O Bus Adapter device from the system again + * @dev: I2O Bus Adapter device which should be removed + * + * Always returns 0. + */ +static int i2o_bus_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + device_remove_file(dev, &dev_attr_scan); + + put_device(dev); + + osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); + + return 0; +}; + +/* Bus Adapter OSM driver struct */ +static struct i2o_driver i2o_bus_driver = { + .name = OSM_NAME, + .classes = i2o_bus_class_id, + .driver = { + .probe = i2o_bus_probe, + .remove = i2o_bus_remove, + }, +}; + +/** + * i2o_bus_init - Bus Adapter OSM initialization function + * + * Only register the Bus Adapter OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_bus_init(void) +{ + int rc; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + /* Register Bus Adapter OSM into I2O core */ + rc = i2o_driver_register(&i2o_bus_driver); + if (rc) { + osm_err("Could not register Bus Adapter OSM\n"); + return rc; + } + + return 0; +}; + +/** + * i2o_bus_exit - Bus Adapter OSM exit function + * + * Unregisters Bus Adapter OSM from I2O core. + */ +static void __exit i2o_bus_exit(void) +{ + i2o_driver_unregister(&i2o_bus_driver); +}; + +MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_bus_init); +module_exit(i2o_bus_exit); diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c new file mode 100644 index 000000000000..d0267609a949 --- /dev/null +++ b/drivers/message/i2o/config-osm.c @@ -0,0 +1,579 @@ +/* + * Configuration OSM + * + * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +#include <linux/module.h> +#include <linux/i2o.h> +#include <linux/namei.h> + +#include <asm/uaccess.h> + +#define OSM_NAME "config-osm" +#define OSM_VERSION "1.248" +#define OSM_DESCRIPTION "I2O Configuration OSM" + +/* access mode user rw */ +#define S_IWRSR (S_IRUSR | S_IWUSR) + +static struct i2o_driver i2o_config_driver; + +/* Special file operations for sysfs */ +struct fops_attribute { + struct bin_attribute bin; + struct file_operations fops; +}; + +/** + * sysfs_read_dummy + */ +static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset, + size_t count) +{ + return 0; +}; + +/** + * sysfs_write_dummy + */ +static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset, + size_t count) +{ + return 0; +}; + +/** + * sysfs_create_fops_file - Creates attribute with special file operations + * @kobj: kobject which should contains the attribute + * @attr: attributes which should be used to create file + * + * First creates attribute @attr in kobject @kobj. If it is the first time + * this function is called, merge old fops from sysfs with new one and + * write it back. Afterwords the new fops will be set for the created + * attribute. + * + * Returns 0 on success or negative error code on failure. + */ +static int sysfs_create_fops_file(struct kobject *kobj, + struct fops_attribute *attr) +{ + struct file_operations tmp, *fops; + struct dentry *d; + struct qstr qstr; + int rc; + + fops = &attr->fops; + + if (fops->read) + attr->bin.read = sysfs_read_dummy; + + if (fops->write) + attr->bin.write = sysfs_write_dummy; + + if ((rc = sysfs_create_bin_file(kobj, &attr->bin))) + return rc; + + qstr.name = attr->bin.attr.name; + qstr.len = strlen(qstr.name); + qstr.hash = full_name_hash(qstr.name, qstr.len); + + if ((d = lookup_hash(&qstr, kobj->dentry))) { + if (!fops->owner) { + memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp)); + if (fops->read) + tmp.read = fops->read; + if (fops->write) + tmp.write = fops->write; + memcpy(fops, &tmp, sizeof(tmp)); + } + + d->d_inode->i_fop = fops; + } else + sysfs_remove_bin_file(kobj, &attr->bin); + + return -ENOENT; +}; + +/** + * sysfs_remove_fops_file - Remove attribute with special file operations + * @kobj: kobject which contains the attribute + * @attr: attributes which are used to create file + * + * Only wrapper arround sysfs_remove_bin_file() + * + * Returns 0 on success or negative error code on failure. + */ +static inline int sysfs_remove_fops_file(struct kobject *kobj, + struct fops_attribute *attr) +{ + return sysfs_remove_bin_file(kobj, &attr->bin); +}; + +/** + * i2o_config_read_hrt - Returns the HRT of the controller + * @kob: kernel object handle + * @buf: buffer into which the HRT should be copied + * @off: file offset + * @count: number of bytes to read + * + * Put @count bytes starting at @off into @buf from the HRT of the I2O + * controller corresponding to @kobj. + * + * Returns number of bytes copied into buffer. + */ +static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf, + loff_t offset, size_t count) +{ + struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; + i2o_hrt *hrt = c->hrt.virt; + + u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4; + + if (offset > size) + return 0; + + if (offset + count > size) + count = size - offset; + + memcpy(buf, (u8 *) hrt + offset, count); + + return count; +}; + +/** + * i2o_config_read_lct - Returns the LCT of the controller + * @kob: kernel object handle + * @buf: buffer into which the LCT should be copied + * @off: file offset + * @count: number of bytes to read + * + * Put @count bytes starting at @off into @buf from the LCT of the I2O + * controller corresponding to @kobj. + * + * Returns number of bytes copied into buffer. + */ +static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf, + loff_t offset, size_t count) +{ + struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; + u32 size = c->lct->table_size * 4; + + if (offset > size) + return 0; + + if (offset + count > size) + count = size - offset; + + memcpy(buf, (u8 *) c->lct + offset, count); + + return count; +}; + +#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \ +static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \ + return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \ +};\ +\ +static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \ + return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \ +}; \ +\ +static struct fops_attribute i2o_config_attr_##_name = { \ + .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \ + .owner = THIS_MODULE }, \ + .size = 0, }, \ + .fops = { .write = i2o_config_##_name##_write, \ + .read = i2o_config_##_name##_read} \ +}; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + +/** + * i2o_config_dpt_reagion - Converts type and id to flash region + * @swtype: type of software module reading + * @swid: id of software which should be read + * + * Converts type and id from I2O spec to the matching region for DPT / + * Adaptec controllers. + * + * Returns region which match type and id or -1 on error. + */ +static u32 i2o_config_dpt_region(u8 swtype, u8 swid) +{ + switch (swtype) { + case I2O_SOFTWARE_MODULE_IRTOS: + /* + * content: operation firmware + * region size: + * 0xbc000 for 2554, 3754, 2564, 3757 + * 0x170000 for 2865 + * 0x17c000 for 3966 + */ + if (!swid) + return 0; + + break; + + case I2O_SOFTWARE_MODULE_IOP_PRIVATE: + /* + * content: BIOS and SMOR + * BIOS size: first 0x8000 bytes + * region size: + * 0x40000 for 2554, 3754, 2564, 3757 + * 0x80000 for 2865, 3966 + */ + if (!swid) + return 1; + + break; + + case I2O_SOFTWARE_MODULE_IOP_CONFIG: + switch (swid) { + case 0: + /* + * content: NVRAM defaults + * region size: 0x2000 bytes + */ + return 2; + case 1: + /* + * content: serial number + * region size: 0x2000 bytes + */ + return 3; + } + break; + } + + return -1; +}; + +#endif + +/** + * i2o_config_sw_read - Read a software module from controller + * @file: file pointer + * @buf: buffer into which the data should be copied + * @count: number of bytes to read + * @off: file offset + * @swtype: type of software module reading + * @swid: id of software which should be read + * + * Transfers @count bytes at offset @offset from IOP into buffer using + * type @swtype and id @swid as described in I2O spec. + * + * Returns number of bytes copied into buffer or error code on failure. + */ +static ssize_t i2o_config_sw_read(struct file *file, char __user * buf, + size_t count, loff_t * offset, u8 swtype, + u32 swid) +{ + struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; + struct kobject *kobj = sd->s_element; + struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; + u32 m, function = I2O_CMD_SW_UPLOAD; + struct i2o_dma buffer; + struct i2o_message __iomem *msg; + u32 __iomem *mptr; + int rc, status; + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; + + mptr = &msg->body[3]; + + if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) { + i2o_msg_nop(c, m); + return rc; + } +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + mptr = &msg->body[4]; + function = I2O_CMD_PRIVATE; + + writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); + + writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ, + &msg->body[0]); + writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); + writel(*offset, &msg->body[2]); + writel(count, &msg->body[3]); + } else +#endif + writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); + + writel(0xD0000000 | count, mptr++); + writel(buffer.phys, mptr); + + writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (!c->adaptec) +#endif + { + writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); + writel(0, &msg->body[1]); + writel(swid, &msg->body[2]); + } + + status = i2o_msg_post_wait_mem(c, m, 60, &buffer); + + if (status == I2O_POST_WAIT_OK) { + if (!(rc = copy_to_user(buf, buffer.virt, count))) { + rc = count; + *offset += count; + } + } else + rc = -EIO; + + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + return rc; +}; + +/** + * i2o_config_sw_write - Write a software module to controller + * @file: file pointer + * @buf: buffer into which the data should be copied + * @count: number of bytes to read + * @off: file offset + * @swtype: type of software module writing + * @swid: id of software which should be written + * + * Transfers @count bytes at offset @offset from buffer to IOP using + * type @swtype and id @swid as described in I2O spec. + * + * Returns number of bytes copied from buffer or error code on failure. + */ +static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf, + size_t count, loff_t * offset, u8 swtype, + u32 swid) +{ + struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; + struct kobject *kobj = sd->s_element; + struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; + u32 m, function = I2O_CMD_SW_DOWNLOAD; + struct i2o_dma buffer; + struct i2o_message __iomem *msg; + u32 __iomem *mptr; + int rc, status; + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; + + mptr = &msg->body[3]; + + if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) + goto nop_msg; + + if ((rc = copy_from_user(buffer.virt, buf, count))) + goto free_buffer; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + mptr = &msg->body[4]; + function = I2O_CMD_PRIVATE; + + writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); + + writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE, + &msg->body[0]); + writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); + writel(*offset, &msg->body[2]); + writel(count, &msg->body[3]); + } else +#endif + writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); + + writel(0xD4000000 | count, mptr++); + writel(buffer.phys, mptr); + + writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (!c->adaptec) +#endif + { + writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); + writel(0, &msg->body[1]); + writel(swid, &msg->body[2]); + } + + status = i2o_msg_post_wait_mem(c, m, 60, &buffer); + + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + if (status != I2O_POST_WAIT_OK) + return -EIO; + + *offset += count; + + return count; + + free_buffer: + i2o_dma_free(&c->pdev->dev, &buffer); + + nop_msg: + i2o_msg_nop(c, m); + + return rc; +}; + +/* attribute for HRT in sysfs */ +static struct bin_attribute i2o_config_hrt_attr = { + .attr = { + .name = "hrt", + .mode = S_IRUGO, + .owner = THIS_MODULE}, + .size = 0, + .read = i2o_config_read_hrt +}; + +/* attribute for LCT in sysfs */ +static struct bin_attribute i2o_config_lct_attr = { + .attr = { + .name = "lct", + .mode = S_IRUGO, + .owner = THIS_MODULE}, + .size = 0, + .read = i2o_config_read_lct +}; + +/* IRTOS firmware access */ +I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0); + +#ifdef CONFIG_I2O_EXT_ADAPTEC + +/* + * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec + * controllers + */ +I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0); +I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0); +I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1); + +#endif + +/** + * i2o_config_notify_controller_add - Notify of added controller + * @c: the controller which was added + * + * If a I2O controller is added, we catch the notification to add sysfs + * entries. + */ +static void i2o_config_notify_controller_add(struct i2o_controller *c) +{ + struct kobject *kobj = &c->exec->device.kobj; + + sysfs_create_bin_file(kobj, &i2o_config_hrt_attr); + sysfs_create_bin_file(kobj, &i2o_config_lct_attr); + + sysfs_create_fops_file(kobj, &i2o_config_attr_irtos); +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + sysfs_create_fops_file(kobj, &i2o_config_attr_bios); + sysfs_create_fops_file(kobj, &i2o_config_attr_nvram); + sysfs_create_fops_file(kobj, &i2o_config_attr_serial); + } +#endif +}; + +/** + * i2o_config_notify_controller_remove - Notify of removed controller + * @c: the controller which was removed + * + * If a I2O controller is removed, we catch the notification to remove the + * sysfs entries. + */ +static void i2o_config_notify_controller_remove(struct i2o_controller *c) +{ + struct kobject *kobj = &c->exec->device.kobj; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + sysfs_remove_fops_file(kobj, &i2o_config_attr_serial); + sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram); + sysfs_remove_fops_file(kobj, &i2o_config_attr_bios); + } +#endif + sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos); + + sysfs_remove_bin_file(kobj, &i2o_config_lct_attr); + sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr); +}; + +/* Config OSM driver struct */ +static struct i2o_driver i2o_config_driver = { + .name = OSM_NAME, + .notify_controller_add = i2o_config_notify_controller_add, + .notify_controller_remove = i2o_config_notify_controller_remove +}; + +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL +#include "i2o_config.c" +#endif + +/** + * i2o_config_init - Configuration OSM initialization function + * + * Registers Configuration OSM in the I2O core and if old ioctl's are + * compiled in initialize them. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_config_init(void) +{ + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + if (i2o_driver_register(&i2o_config_driver)) { + osm_err("handler register failed.\n"); + return -EBUSY; + } +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL + if (i2o_config_old_init()) + i2o_driver_unregister(&i2o_config_driver); +#endif + + return 0; +} + +/** + * i2o_config_exit - Configuration OSM exit function + * + * If old ioctl's are compiled in exit remove them and unregisters + * Configuration OSM from I2O core. + */ +static void i2o_config_exit(void) +{ +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL + i2o_config_old_exit(); +#endif + + i2o_driver_unregister(&i2o_config_driver); +} + +MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_config_init); +module_exit(i2o_config_exit); diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h new file mode 100644 index 000000000000..c5bcfd70f711 --- /dev/null +++ b/drivers/message/i2o/core.h @@ -0,0 +1,58 @@ +/* + * I2O core internal declarations + * + * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com> + * + * 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. + * + * Fixes/additions: + * Markus Lidel <Markus.Lidel@shadowconnect.com> + * initial version. + */ + +/* Exec-OSM */ +extern struct bus_type i2o_bus_type; + +extern struct i2o_driver i2o_exec_driver; +extern int i2o_exec_lct_get(struct i2o_controller *); + +extern int __init i2o_exec_init(void); +extern void __exit i2o_exec_exit(void); + +/* driver */ +extern int i2o_driver_dispatch(struct i2o_controller *, u32); + +extern int __init i2o_driver_init(void); +extern void __exit i2o_driver_exit(void); + +/* PCI */ +extern int __init i2o_pci_init(void); +extern void __exit i2o_pci_exit(void); + +/* device */ +extern void i2o_device_remove(struct i2o_device *); +extern int i2o_device_parse_lct(struct i2o_controller *); + +extern int i2o_device_init(void); +extern void i2o_device_exit(void); + +/* IOP */ +extern struct i2o_controller *i2o_iop_alloc(void); +extern void i2o_iop_free(struct i2o_controller *); + +extern int i2o_iop_add(struct i2o_controller *); +extern void i2o_iop_remove(struct i2o_controller *); + +/* config */ +extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); + +/* control registers relative to c->base */ +#define I2O_IRQ_STATUS 0x30 +#define I2O_IRQ_MASK 0x34 +#define I2O_IN_PORT 0x40 +#define I2O_OUT_PORT 0x44 + +#define I2O_IRQ_OUTBOUND_POST 0x00000008 diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index 2a5d478fc60e..018ca887ca85 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c @@ -4,8 +4,6 @@ #include <linux/pci.h> #include <linux/i2o.h> -extern struct i2o_driver **i2o_drivers; -extern unsigned int i2o_max_drivers; static void i2o_report_util_cmd(u8 cmd); static void i2o_report_exec_cmd(u8 cmd); static void i2o_report_fail_status(u8 req_status, u32 * msg); @@ -23,7 +21,6 @@ void i2o_report_status(const char *severity, const char *str, u8 cmd = (msg[1] >> 24) & 0xFF; u8 req_status = (msg[4] >> 24) & 0xFF; u16 detailed_status = msg[4] & 0xFFFF; - //struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)]; if (cmd == I2O_CMD_UTIL_EVT_REGISTER) return; // No status in this reply diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index eb907e87bc7b..21f16ba3ac38 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -16,9 +16,7 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> - -/* Exec OSM functions */ -extern struct bus_type i2o_bus_type; +#include "core.h" /** * i2o_device_issue_claim - claim or release a device @@ -282,8 +280,7 @@ int i2o_device_parse_lct(struct i2o_controller *c) down(&c->lct_lock); - if (c->lct) - kfree(c->lct); + kfree(c->lct); lct = c->dlct.virt; @@ -294,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c) } if (lct->table_size * 4 > c->dlct.len) { - memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len); + memcpy(c->lct, c->dlct.virt, c->dlct.len); up(&c->lct_lock); return -EAGAIN; } - memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4); + memcpy(c->lct, c->dlct.virt, lct->table_size * 4); lct = c->lct; @@ -354,7 +351,7 @@ static ssize_t i2o_device_class_show_class_id(struct class_device *cd, { struct i2o_device *dev = to_i2o_device(cd->dev); - sprintf(buf, "%03x\n", dev->lct_data.class_id); + sprintf(buf, "0x%03x\n", dev->lct_data.class_id); return strlen(buf) + 1; }; @@ -369,7 +366,7 @@ static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf) { struct i2o_device *dev = to_i2o_device(cd->dev); - sprintf(buf, "%03x\n", dev->lct_data.tid); + sprintf(buf, "0x%03x\n", dev->lct_data.tid); return strlen(buf) + 1; }; @@ -401,25 +398,27 @@ static int i2o_device_class_add(struct class_device *cd) /* create user entries for this device */ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); - if (tmp) + if (tmp && (tmp != i2o_dev)) sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, "user"); /* create user entries refering to this device */ list_for_each_entry(tmp, &c->devices, list) - if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) sysfs_create_link(&tmp->device.kobj, &i2o_dev->device.kobj, "user"); /* create parent entries for this device */ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); - if (tmp) + if (tmp && (tmp != i2o_dev)) sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, "parent"); /* create parent entries refering to this device */ list_for_each_entry(tmp, &c->devices, list) - if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) sysfs_create_link(&tmp->device.kobj, &i2o_dev->device.kobj, "parent"); @@ -444,9 +443,8 @@ static struct class_interface i2o_device_class_interface = { * Note that the minimum sized reslist is 8 bytes and contains * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. */ - int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, - int oplen, void *reslist, int reslen) + int oplen, void *reslist, int reslen) { struct i2o_message __iomem *msg; u32 m; @@ -489,7 +487,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, if (rc == -ETIMEDOUT) return rc; - memcpy_fromio(reslist, res.virt, res.len); + memcpy(reslist, res.virt, res.len); i2o_dma_free(dev, &res); /* Query failed */ @@ -531,17 +529,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 resblk[8 + buflen]; /* 8 bytes for header */ + u8 *resblk; /* 8 bytes for header */ int size; if (field == -1) /* whole group */ opblk[4] = -1; + resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC); + if (!resblk) + return -ENOMEM; + size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, - sizeof(opblk), resblk, sizeof(resblk)); + sizeof(opblk), resblk, buflen + 8); memcpy(buf, resblk + 8, buflen); /* cut off header */ + kfree(resblk); + if (size > buflen) return buflen; diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 91f4edbb2a27..739bfdef0c6d 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -17,9 +17,12 @@ #include <linux/module.h> #include <linux/rwsem.h> #include <linux/i2o.h> +#include "core.h" + +#define OSM_NAME "i2o" /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ -unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; +static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; module_param_named(max_drivers, i2o_max_drivers, uint, 0); MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); @@ -76,17 +79,16 @@ int i2o_driver_register(struct i2o_driver *drv) int rc = 0; unsigned long flags; - pr_debug("i2o: Register driver %s\n", drv->name); + osm_debug("Register driver %s\n", drv->name); if (drv->event) { drv->event_queue = create_workqueue(drv->name); if (!drv->event_queue) { - printk(KERN_ERR "i2o: Could not initialize event queue " - "for driver %s\n", drv->name); + osm_err("Could not initialize event queue for driver " + "%s\n", drv->name); return -EFAULT; } - pr_debug("i2o: Event queue initialized for driver %s\n", - drv->name); + osm_debug("Event queue initialized for driver %s\n", drv->name); } else drv->event_queue = NULL; @@ -97,8 +99,8 @@ int i2o_driver_register(struct i2o_driver *drv) for (i = 0; i2o_drivers[i]; i++) if (i >= i2o_max_drivers) { - printk(KERN_ERR "i2o: too many drivers registered, " - "increase max_drivers\n"); + osm_err("too many drivers registered, increase " + "max_drivers\n"); spin_unlock_irqrestore(&i2o_drivers_lock, flags); return -EFAULT; } @@ -108,18 +110,16 @@ int i2o_driver_register(struct i2o_driver *drv) spin_unlock_irqrestore(&i2o_drivers_lock, flags); - pr_debug("i2o: driver %s gets context id %d\n", drv->name, - drv->context); + osm_debug("driver %s gets context id %d\n", drv->name, drv->context); list_for_each_entry(c, &i2o_controllers, list) { struct i2o_device *i2o_dev; i2o_driver_notify_controller_add(drv, c); list_for_each_entry(i2o_dev, &c->devices, list) - i2o_driver_notify_device_add(drv, i2o_dev); + i2o_driver_notify_device_add(drv, i2o_dev); } - rc = driver_register(&drv->driver); if (rc) destroy_workqueue(drv->event_queue); @@ -139,7 +139,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) struct i2o_controller *c; unsigned long flags; - pr_debug("i2o: unregister driver %s\n", drv->name); + osm_debug("unregister driver %s\n", drv->name); driver_unregister(&drv->driver); @@ -159,7 +159,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) if (drv->event_queue) { destroy_workqueue(drv->event_queue); drv->event_queue = NULL; - pr_debug("i2o: event queue removed for %s\n", drv->name); + osm_debug("event queue removed for %s\n", drv->name); } }; @@ -176,68 +176,70 @@ void i2o_driver_unregister(struct i2o_driver *drv) * on success and if the message should be flushed afterwords. Returns * negative error code on failure (the message will be flushed too). */ -int i2o_driver_dispatch(struct i2o_controller *c, u32 m, - struct i2o_message __iomem *msg) +int i2o_driver_dispatch(struct i2o_controller *c, u32 m) { struct i2o_driver *drv; - u32 context = readl(&msg->u.s.icntxt); + struct i2o_message *msg = i2o_msg_out_to_virt(c, m); + u32 context = le32_to_cpu(msg->u.s.icntxt); + unsigned long flags; - if (likely(context < i2o_max_drivers)) { - spin_lock(&i2o_drivers_lock); - drv = i2o_drivers[context]; - spin_unlock(&i2o_drivers_lock); + if (unlikely(context >= i2o_max_drivers)) { + osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, + context); + return -EIO; + } - if (unlikely(!drv)) { - printk(KERN_WARNING "%s: Spurious reply to unknown " - "driver %d\n", c->name, context); - return -EIO; - } + spin_lock_irqsave(&i2o_drivers_lock, flags); + drv = i2o_drivers[context]; + spin_unlock_irqrestore(&i2o_drivers_lock, flags); - if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { - struct i2o_device *dev, *tmp; - struct i2o_event *evt; - u16 size; - u16 tid; + if (unlikely(!drv)) { + osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, + context); + return -EIO; + } - tid = readl(&msg->u.head[1]) & 0x1fff; + if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { + struct i2o_device *dev, *tmp; + struct i2o_event *evt; + u16 size; + u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; - pr_debug("%s: event received from device %d\n", c->name, - tid); + osm_debug("event received from device %d\n", tid); - /* cut of header from message size (in 32-bit words) */ - size = (readl(&msg->u.head[0]) >> 16) - 5; + if (!drv->event) + return -EIO; - evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); - if (!evt) - return -ENOMEM; - memset(evt, 0, size * 4 + sizeof(*evt)); + /* cut of header from message size (in 32-bit words) */ + size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; - evt->size = size; - memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, - (size + 2) * 4); + evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); + if (!evt) + return -ENOMEM; - list_for_each_entry_safe(dev, tmp, &c->devices, list) - if (dev->lct_data.tid == tid) { - evt->i2o_dev = dev; - break; - } + evt->size = size; + evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); + evt->event_indicator = le32_to_cpu(msg->body[0]); + memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); - INIT_WORK(&evt->work, (void (*)(void *))drv->event, - evt); - queue_work(drv->event_queue, &evt->work); - return 1; + list_for_each_entry_safe(dev, tmp, &c->devices, list) + if (dev->lct_data.tid == tid) { + evt->i2o_dev = dev; + break; } - if (likely(drv->reply)) - return drv->reply(c, m, msg); - else - pr_debug("%s: Reply to driver %s, but no reply function" - " defined!\n", c->name, drv->name); + INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); + queue_work(drv->event_queue, &evt->work); + return 1; + } + + if (unlikely(!drv->reply)) { + osm_debug("%s: Reply to driver %s, but no reply function" + " defined!\n", c->name, drv->name); return -EIO; - } else - printk(KERN_WARNING "%s: Spurious reply to unknown driver " - "%d\n", c->name, readl(&msg->u.s.icntxt)); - return -EIO; + } + + return drv->reply(c, m, msg); } /** @@ -334,11 +336,11 @@ int __init i2o_driver_init(void) if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != (2 * i2o_max_drivers - 1))) { - printk(KERN_WARNING "i2o: max_drivers set to %d, but must be " - ">=2 and <= 64 and a power of 2\n", i2o_max_drivers); + osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and " + "a power of 2\n", i2o_max_drivers); i2o_max_drivers = I2O_MAX_DRIVERS; } - printk(KERN_INFO "i2o: max drivers = %d\n", i2o_max_drivers); + osm_info("max drivers = %d\n", i2o_max_drivers); i2o_drivers = kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 79c1cbfb8f44..bda2c62648ba 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -30,6 +30,7 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> +#include "core.h" #define OSM_NAME "exec-osm" @@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver; static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); -/* Module internal functions from other sources */ -extern int i2o_device_parse_lct(struct i2o_controller *); - /* global wait list for POST WAIT */ static LIST_HEAD(i2o_exec_wait_list); @@ -50,7 +48,7 @@ struct i2o_exec_wait { u32 tcntxt; /* transaction context from reply */ int complete; /* 1 if reply received otherwise 0 */ u32 m; /* message id */ - struct i2o_message __iomem *msg; /* pointer to the reply message */ + struct i2o_message *msg; /* pointer to the reply message */ struct list_head list; /* node in global wait list */ }; @@ -108,7 +106,8 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) * buffer must not be freed. Instead the event completion will free them * for you. In all other cases the buffer are your problem. * - * Returns 0 on success or negative error code on failure. + * Returns 0 on success, negative error code on timeout or positive error + * code from reply. */ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long timeout, struct i2o_dma *dma) @@ -116,7 +115,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long DECLARE_WAIT_QUEUE_HEAD(wq); struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; - struct i2o_message __iomem *msg = c->in_queue.virt + m; + struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); int rc = 0; wait = i2o_exec_wait_alloc(); @@ -153,7 +152,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long list_add(&wait->list, &i2o_exec_wait_list); wait_event_interruptible_timeout(wq, wait->complete, - timeout * HZ); + timeout * HZ); wait->wq = NULL; } @@ -161,8 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long barrier(); if (wait->complete) { - if (readl(&wait->msg->body[0]) >> 24) - rc = readl(&wait->msg->body[0]) & 0xff; + rc = le32_to_cpu(wait->msg->body[0]) >> 24; i2o_flush_reply(c, wait->m); i2o_exec_wait_free(wait); } else { @@ -187,6 +185,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long * @c: I2O controller which answers * @m: message id * @msg: pointer to the I2O reply message + * @context: transaction context of request * * This function is called in interrupt context only. If the reply reached * before the timeout, the i2o_exec_wait struct is filled with the message @@ -201,16 +200,12 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long * message must also be given back to the controller. */ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, - struct i2o_message __iomem *msg) + struct i2o_message *msg, u32 context) { struct i2o_exec_wait *wait, *tmp; - static spinlock_t lock; + unsigned long flags; + static spinlock_t lock = SPIN_LOCK_UNLOCKED; int rc = 1; - u32 context; - - spin_lock_init(&lock); - - context = readl(&msg->u.s.tcntxt); /* * We need to search through the i2o_exec_wait_list to see if the given @@ -219,11 +214,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, * already expired. Not much we can do about that except log it for * debug purposes, increase timeout, and recompile. */ - spin_lock(&lock); + spin_lock_irqsave(&lock, flags); list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { if (wait->tcntxt == context) { list_del(&wait->list); + spin_unlock_irqrestore(&lock, flags); + wait->m = m; wait->msg = msg; wait->complete = 1; @@ -245,21 +242,63 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, rc = -1; } - spin_unlock(&lock); - return rc; } } - spin_unlock(&lock); + spin_unlock_irqrestore(&lock, flags); - pr_debug("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, + osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, context); return -1; }; /** + * i2o_exec_show_vendor_id - Displays Vendor ID of controller + * @d: device of which the Vendor ID should be displayed + * @buf: buffer into which the Vendor ID should be printed + * + * Returns number of bytes printed into buffer. + */ +static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf) +{ + struct i2o_device *dev = to_i2o_device(d); + u16 id; + + if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { + sprintf(buf, "0x%04x", id); + return strlen(buf) + 1; + } + + return 0; +}; + +/** + * i2o_exec_show_product_id - Displays Product ID of controller + * @d: device of which the Product ID should be displayed + * @buf: buffer into which the Product ID should be printed + * + * Returns number of bytes printed into buffer. + */ +static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf) +{ + struct i2o_device *dev = to_i2o_device(d); + u16 id; + + if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { + sprintf(buf, "0x%04x", id); + return strlen(buf) + 1; + } + + return 0; +}; + +/* Exec-OSM device attributes */ +static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL); +static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); + +/** * i2o_exec_probe - Called if a new I2O device (executive class) appears * @dev: I2O device which should be probed * @@ -271,10 +310,16 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, static int i2o_exec_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); - i2o_dev->iop->exec = i2o_dev; + c->exec = i2o_dev; + + i2o_exec_lct_notify(c, c->lct->change_ind + 1); + + device_create_file(dev, &dev_attr_vendor_id); + device_create_file(dev, &dev_attr_product_id); return 0; }; @@ -289,6 +334,9 @@ static int i2o_exec_probe(struct device *dev) */ static int i2o_exec_remove(struct device *dev) { + device_remove_file(dev, &dev_attr_product_id); + device_remove_file(dev, &dev_attr_vendor_id); + i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); return 0; @@ -300,12 +348,16 @@ static int i2o_exec_remove(struct device *dev) * * This function handles asynchronus LCT NOTIFY replies. It parses the * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY - * again. + * again, otherwise send LCT NOTIFY to get informed on next LCT change. */ static void i2o_exec_lct_modified(struct i2o_controller *c) { - if (i2o_device_parse_lct(c) == -EAGAIN) - i2o_exec_lct_notify(c, 0); + u32 change_ind = 0; + + if (i2o_device_parse_lct(c) != -EAGAIN) + change_ind = c->lct->change_ind + 1; + + i2o_exec_lct_notify(c, change_ind); }; /** @@ -325,8 +377,14 @@ static void i2o_exec_lct_modified(struct i2o_controller *c) static int i2o_exec_reply(struct i2o_controller *c, u32 m, struct i2o_message *msg) { - if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set - struct i2o_message __iomem *pmsg; /* preserved message */ + u32 context; + + if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { + /* + * If Fail bit is set we must take the transaction context of + * the preserved message to find the right request again. + */ + struct i2o_message __iomem *pmsg; u32 pm; pm = le32_to_cpu(msg->body[3]); @@ -335,15 +393,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, i2o_report_status(KERN_INFO, "i2o_core", msg); - /* Release the preserved msg by resubmitting it as a NOP */ - i2o_msg_nop(c, pm); + context = readl(&pmsg->u.s.tcntxt); - /* If reply to i2o_post_wait failed, return causes a timeout */ - return -1; - } + /* Release the preserved msg */ + i2o_msg_nop(c, pm); + } else + context = le32_to_cpu(msg->u.s.tcntxt); - if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000) - return i2o_msg_post_wait_complete(c, m, msg); + if (context & 0x80000000) + return i2o_msg_post_wait_complete(c, m, msg, context); if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { struct work_struct *work; @@ -381,8 +439,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, */ static void i2o_exec_event(struct i2o_event *evt) { - osm_info("Event received from device: %d\n", - evt->i2o_dev->lct_data.tid); + if (likely(evt->i2o_dev)) + osm_debug("Event received from device: %d\n", + evt->i2o_dev->lct_data.tid); kfree(evt); }; diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 7b74c87b569e..f283b5bafdd3 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -62,7 +62,7 @@ #include "i2o_block.h" #define OSM_NAME "block-osm" -#define OSM_VERSION "$Rev$" +#define OSM_VERSION "1.287" #define OSM_DESCRIPTION "I2O Block Device OSM" static struct i2o_driver i2o_block_driver; @@ -104,7 +104,8 @@ static int i2o_block_remove(struct device *dev) struct i2o_device *i2o_dev = to_i2o_device(dev); struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); - osm_info("Device removed %s\n", i2o_blk_dev->gd->disk_name); + osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid, + i2o_blk_dev->gd->disk_name); i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); @@ -146,6 +147,29 @@ static int i2o_block_device_flush(struct i2o_device *dev) }; /** + * i2o_block_issue_flush - device-flush interface for block-layer + * @queue: the request queue of the device which should be flushed + * @disk: gendisk + * @error_sector: error offset + * + * Helper function to provide flush functionality to block-layer. + * + * Returns 0 on success or negative error code on failure. + */ + +static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk, + sector_t * error_sector) +{ + struct i2o_block_device *i2o_blk_dev = queue->queuedata; + int rc = -ENODEV; + + if (likely(i2o_blk_dev)) + rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev); + + return rc; +} + +/** * i2o_block_device_mount - Mount (load) the media of device dev * @dev: I2O device which should receive the mount request * @media_id: Media Identifier @@ -298,28 +322,31 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq) /** * i2o_block_sglist_alloc - Allocate the SG list and map it + * @c: I2O controller to which the request belongs * @ireq: I2O block request * - * Builds the SG list and map it into to be accessable by the controller. + * Builds the SG list and map it to be accessable by the controller. * - * Returns the number of elements in the SG list or 0 on failure. + * Returns 0 on failure or 1 on success. */ -static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) +static inline int i2o_block_sglist_alloc(struct i2o_controller *c, + struct i2o_block_request *ireq, + u32 __iomem ** mptr) { - struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; int nents; + enum dma_data_direction direction; + ireq->dev = &c->pdev->dev; nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); if (rq_data_dir(ireq->req) == READ) - ireq->sg_dma_direction = PCI_DMA_FROMDEVICE; + direction = PCI_DMA_FROMDEVICE; else - ireq->sg_dma_direction = PCI_DMA_TODEVICE; + direction = PCI_DMA_TODEVICE; - ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents, - ireq->sg_dma_direction); + ireq->sg_nents = nents; - return ireq->sg_nents; + return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr); }; /** @@ -330,10 +357,14 @@ static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) */ static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) { - struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; + enum dma_data_direction direction; - dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents, - ireq->sg_dma_direction); + if (rq_data_dir(ireq->req) == READ) + direction = PCI_DMA_FROMDEVICE; + else + direction = PCI_DMA_TODEVICE; + + dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction); }; /** @@ -351,6 +382,11 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) struct i2o_block_device *i2o_blk_dev = q->queuedata; struct i2o_block_request *ireq; + if (unlikely(!i2o_blk_dev)) { + osm_err("block device already removed\n"); + return BLKPREP_KILL; + } + /* request is already processed by us, so return */ if (req->flags & REQ_SPECIAL) { osm_debug("REQ_SPECIAL already set!\n"); @@ -400,71 +436,65 @@ static void i2o_block_delayed_request_fn(void *delayed_request) }; /** - * i2o_block_reply - Block OSM reply handler. - * @c: I2O controller from which the message arrives - * @m: message id of reply - * qmsg: the actuall I2O message reply + * i2o_block_end_request - Post-processing of completed commands + * @req: request which should be completed + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error + * @nr_bytes: number of bytes to complete * - * This function gets all the message replies. + * Mark the request as complete. The lock must not be held when entering. * */ -static int i2o_block_reply(struct i2o_controller *c, u32 m, - struct i2o_message *msg) +static void i2o_block_end_request(struct request *req, int uptodate, + int nr_bytes) { - struct i2o_block_request *ireq; - struct request *req; - struct i2o_block_device *dev; - struct request_queue *q; - u8 st; + struct i2o_block_request *ireq = req->special; + struct i2o_block_device *dev = ireq->i2o_blk_dev; + request_queue_t *q = req->q; unsigned long flags; - /* FAILed message */ - if (unlikely(le32_to_cpu(msg->u.head[0]) & (1 << 13))) { - struct i2o_message *pmsg; - u32 pm; + if (end_that_request_chunk(req, uptodate, nr_bytes)) { + int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT); - /* - * FAILed message from controller - * We increment the error count and abort it - * - * In theory this will never happen. The I2O block class - * specification states that block devices never return - * FAILs but instead use the REQ status field...but - * better be on the safe side since no one really follows - * the spec to the book :) - */ - pm = le32_to_cpu(msg->body[3]); - pmsg = i2o_msg_in_to_virt(c, pm); + if (blk_pc_request(req)) + leftover = req->data_len; - req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt)); - if (unlikely(!req)) { - osm_err("NULL reply received!\n"); - return -1; - } + if (end_io_error(uptodate)) + end_that_request_chunk(req, 0, leftover); + } - ireq = req->special; - dev = ireq->i2o_blk_dev; - q = dev->gd->queue; + add_disk_randomness(req->rq_disk); - req->errors++; - - spin_lock_irqsave(q->queue_lock, flags); + spin_lock_irqsave(q->queue_lock, flags); - while (end_that_request_chunk(req, !req->errors, - le32_to_cpu(pmsg->body[1]))) ; - end_that_request_last(req); + end_that_request_last(req); + if (likely(dev)) { dev->open_queue_depth--; list_del(&ireq->queue); - blk_start_queue(q); + } - spin_unlock_irqrestore(q->queue_lock, flags); + blk_start_queue(q); - /* Now flush the message by making it a NOP */ - i2o_msg_nop(c, pm); + spin_unlock_irqrestore(q->queue_lock, flags); - return -1; - } + i2o_block_sglist_free(ireq); + i2o_block_request_free(ireq); +}; + +/** + * i2o_block_reply - Block OSM reply handler. + * @c: I2O controller from which the message arrives + * @m: message id of reply + * qmsg: the actuall I2O message reply + * + * This function gets all the message replies. + * + */ +static int i2o_block_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) +{ + struct request *req; + int uptodate = 1; req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); if (unlikely(!req)) { @@ -472,61 +502,13 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, return -1; } - ireq = req->special; - dev = ireq->i2o_blk_dev; - q = dev->gd->queue; - - if (unlikely(!dev->i2o_dev)) { - /* - * This is HACK, but Intel Integrated RAID allows user - * to delete a volume that is claimed, locked, and in use - * by the OS. We have to check for a reply from a - * non-existent device and flag it as an error or the system - * goes kaput... - */ - req->errors++; - osm_warn("Data transfer to deleted device!\n"); - spin_lock_irqsave(q->queue_lock, flags); - while (end_that_request_chunk - (req, !req->errors, le32_to_cpu(msg->body[1]))) ; - end_that_request_last(req); - - dev->open_queue_depth--; - list_del(&ireq->queue); - blk_start_queue(q); - - spin_unlock_irqrestore(q->queue_lock, flags); - return -1; - } - /* * Lets see what is cooking. We stuffed the * request in the context. */ - st = le32_to_cpu(msg->body[0]) >> 24; - - if (st != 0) { - int err; - char *bsa_errors[] = { - "Success", - "Media Error", - "Failure communicating to device", - "Device Failure", - "Device is not ready", - "Media not present", - "Media is locked by another user", - "Media has failed", - "Failure communicating to device", - "Device bus failure", - "Device is locked by another user", - "Device is write protected", - "Device has reset", - "Volume has changed, waiting for acknowledgement" - }; - - err = le32_to_cpu(msg->body[0]) & 0xffff; - + if ((le32_to_cpu(msg->body[0]) >> 24) != 0) { + u32 status = le32_to_cpu(msg->body[0]); /* * Device not ready means two things. One is that the * the thing went offline (but not a removal media) @@ -539,40 +521,24 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, * Don't stick a supertrak100 into cache aggressive modes */ - osm_err("block-osm: /dev/%s error: %s", dev->gd->disk_name, - bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]); - if (le32_to_cpu(msg->body[0]) & 0x00ff0000) - printk(KERN_ERR " - DDM attempted %d retries", - (le32_to_cpu(msg->body[0]) >> 16) & 0x00ff); - printk(KERN_ERR ".\n"); - req->errors++; - } else - req->errors = 0; + osm_err("TID %03x error status: 0x%02x, detailed status: " + "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff), + status >> 24, status & 0xffff); - if (!end_that_request_chunk - (req, !req->errors, le32_to_cpu(msg->body[1]))) { - add_disk_randomness(req->rq_disk); - spin_lock_irqsave(q->queue_lock, flags); - - end_that_request_last(req); + req->errors++; - dev->open_queue_depth--; - list_del(&ireq->queue); - blk_start_queue(q); + uptodate = 0; + } - spin_unlock_irqrestore(q->queue_lock, flags); - - i2o_block_sglist_free(ireq); - i2o_block_request_free(ireq); - } else - osm_err("still remaining chunks\n"); + i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1])); return 1; }; static void i2o_block_event(struct i2o_event *evt) { - osm_info("block-osm: event received\n"); + osm_debug("event received\n"); + kfree(evt); }; /* @@ -777,18 +743,25 @@ static int i2o_block_media_changed(struct gendisk *disk) static int i2o_block_transfer(struct request *req) { struct i2o_block_device *dev = req->rq_disk->private_data; - struct i2o_controller *c = dev->i2o_dev->iop; + struct i2o_controller *c; int tid = dev->i2o_dev->lct_data.tid; struct i2o_message __iomem *msg; - void __iomem *mptr; + u32 __iomem *mptr; struct i2o_block_request *ireq = req->special; - struct scatterlist *sg; - int sgnum; - int i; u32 m; u32 tcntxt; - u32 sg_flags; + u32 sgl_offset = SGL_OFFSET_8; + u32 ctl_flags = 0x00000000; int rc; + u32 cmd; + + if (unlikely(!dev->i2o_dev)) { + osm_err("transfer to removed drive\n"); + rc = -ENODEV; + goto exit; + } + + c = dev->i2o_dev->iop; m = i2o_msg_get(c, &msg); if (m == I2O_QUEUE_EMPTY) { @@ -802,82 +775,109 @@ static int i2o_block_transfer(struct request *req) goto nop_msg; } - if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) { - rc = -ENOMEM; - goto context_remove; - } - - /* Build the message based on the request. */ writel(i2o_block_driver.context, &msg->u.s.icntxt); writel(tcntxt, &msg->u.s.tcntxt); - writel(req->nr_sectors << 9, &msg->body[1]); - - writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]); - writel(req->sector >> 23, &msg->body[3]); - mptr = &msg->body[4]; - - sg = ireq->sg_table; + mptr = &msg->body[0]; if (rq_data_dir(req) == READ) { - writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid, - &msg->u.head[1]); - sg_flags = 0x10000000; + cmd = I2O_CMD_BLOCK_READ << 24; + switch (dev->rcache) { - case CACHE_NULL: - writel(0, &msg->body[0]); - break; case CACHE_PREFETCH: - writel(0x201F0008, &msg->body[0]); + ctl_flags = 0x201F0008; break; + case CACHE_SMARTFETCH: if (req->nr_sectors > 16) - writel(0x201F0008, &msg->body[0]); + ctl_flags = 0x201F0008; else - writel(0x001F0000, &msg->body[0]); + ctl_flags = 0x001F0000; + break; + + default: break; } } else { - writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid, - &msg->u.head[1]); - sg_flags = 0x14000000; + cmd = I2O_CMD_BLOCK_WRITE << 24; + switch (dev->wcache) { - case CACHE_NULL: - writel(0, &msg->body[0]); - break; case CACHE_WRITETHROUGH: - writel(0x001F0008, &msg->body[0]); + ctl_flags = 0x001F0008; break; case CACHE_WRITEBACK: - writel(0x001F0010, &msg->body[0]); + ctl_flags = 0x001F0010; break; case CACHE_SMARTBACK: if (req->nr_sectors > 16) - writel(0x001F0004, &msg->body[0]); + ctl_flags = 0x001F0004; else - writel(0x001F0010, &msg->body[0]); + ctl_flags = 0x001F0010; break; case CACHE_SMARTTHROUGH: if (req->nr_sectors > 16) - writel(0x001F0004, &msg->body[0]); + ctl_flags = 0x001F0004; else - writel(0x001F0010, &msg->body[0]); + ctl_flags = 0x001F0010; + default: + break; + } + } + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u8 cmd[10]; + u32 scsi_flags; + u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT; + + memset(cmd, 0, 10); + + sgl_offset = SGL_OFFSET_12; + + writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid, + &msg->u.head[1]); + + writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); + writel(tid, mptr++); + + /* + * ENABLE_DISCONNECT + * SIMPLE_TAG + * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME + */ + if (rq_data_dir(req) == READ) { + cmd[0] = 0x28; + scsi_flags = 0x60a0000a; + } else { + cmd[0] = 0x2A; + scsi_flags = 0xa0a0000a; } + + writel(scsi_flags, mptr++); + + *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec); + *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec); + + memcpy_toio(mptr, cmd, 10); + mptr += 4; + writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); + } else +#endif + { + writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); + writel(ctl_flags, mptr++); + writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); + writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++); + writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++); } - for (i = sgnum; i > 0; i--) { - if (i == 1) - sg_flags |= 0x80000000; - writel(sg_flags | sg_dma_len(sg), mptr); - writel(sg_dma_address(sg), mptr + 4); - mptr += 8; - sg++; + if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { + rc = -ENOMEM; + goto context_remove; } - writel(I2O_MESSAGE_SIZE - (((unsigned long)mptr - - (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8, - &msg->u.head[0]); + writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | + sgl_offset, &msg->u.head[0]); list_add_tail(&ireq->queue, &dev->open_queue); dev->open_queue_depth++; @@ -920,11 +920,13 @@ static void i2o_block_request_fn(struct request_queue *q) queue_depth = ireq->i2o_blk_dev->open_queue_depth; - if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) + if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { if (!i2o_block_transfer(req)) { blkdev_dequeue_request(req); continue; - } + } else + osm_info("transfer error\n"); + } if (queue_depth) break; @@ -938,7 +940,6 @@ static void i2o_block_request_fn(struct request_queue *q) INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, dreq); - osm_info("transfer error\n"); if (!queue_delayed_work(i2o_block_driver.event_queue, &dreq->work, I2O_BLOCK_RETRY_TIME)) @@ -1007,6 +1008,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void) } blk_queue_prep_rq(queue, i2o_block_prep_req_fn); + blk_queue_issue_flush_fn(queue, i2o_block_issue_flush); gd->major = I2O_MAJOR; gd->queue = queue; @@ -1039,17 +1041,27 @@ static struct i2o_block_device *i2o_block_device_alloc(void) static int i2o_block_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_block_device *i2o_blk_dev; struct i2o_controller *c = i2o_dev->iop; + struct i2o_block_device *i2o_blk_dev; struct gendisk *gd; struct request_queue *queue; static int unit = 0; int rc; u64 size; u32 blocksize; - u16 power; u32 flags, status; - int segments; + u16 body_size = 4; + unsigned short max_sectors; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) + body_size = 8; +#endif + + if (c->limit_sectors) + max_sectors = I2O_MAX_SECTORS_LIMITED; + else + max_sectors = I2O_MAX_SECTORS; /* skip devices which are used by IOP */ if (i2o_dev->lct_data.user_tid != 0xfff) { @@ -1057,8 +1069,6 @@ static int i2o_block_probe(struct device *dev) return -ENODEV; } - osm_info("New device detected (TID: %03x)\n", i2o_dev->lct_data.tid); - if (i2o_device_claim(i2o_dev)) { osm_warn("Unable to claim device. Installation aborted\n"); rc = -EFAULT; @@ -1086,50 +1096,44 @@ static int i2o_block_probe(struct device *dev) queue = gd->queue; queue->queuedata = i2o_blk_dev; - blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS); - blk_queue_max_sectors(queue, I2O_MAX_SECTORS); - - if (c->short_req) - segments = 8; - else { - i2o_status_block *sb; + blk_queue_max_phys_segments(queue, I2O_MAX_PHYS_SEGMENTS); + blk_queue_max_sectors(queue, max_sectors); + blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size)); - sb = c->status_block.virt; - - segments = (sb->inbound_frame_size - - sizeof(struct i2o_message) / 4 - 4) / 2; - } - - blk_queue_max_hw_segments(queue, segments); - - osm_debug("max sectors = %d\n", I2O_MAX_SECTORS); - osm_debug("phys segments = %d\n", I2O_MAX_SEGMENTS); - osm_debug("hw segments = %d\n", segments); + osm_debug("max sectors = %d\n", queue->max_phys_segments); + osm_debug("phys segments = %d\n", queue->max_sectors); + osm_debug("max hw segments = %d\n", queue->max_hw_segments); /* * Ask for the current media data. If that isn't supported * then we ask for the device capacity data */ - if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0 - || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) { - i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4); - i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8); - } - osm_debug("blocksize = %d\n", blocksize); + if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || + i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { + blk_queue_hardsect_size(queue, blocksize); + } else + osm_warn("unable to get blocksize of %s\n", gd->disk_name); - if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) - power = 0; + if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || + i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { + set_capacity(gd, size >> KERNEL_SECTOR_SHIFT); + } else + osm_warn("could not get size of %s\n", gd->disk_name); + + if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2)) + i2o_blk_dev->power = 0; i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); - set_capacity(gd, size >> 9); - i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); add_disk(gd); unit++; + osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid, + i2o_blk_dev->gd->disk_name); + return 0; claim_release: @@ -1177,7 +1181,7 @@ static int __init i2o_block_init(void) goto exit; } - i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE, + i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE, mempool_alloc_slab, mempool_free_slab, i2o_blk_req_pool.slab); diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index ddd9a15679c0..4fdaa5bda412 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h @@ -56,42 +56,46 @@ #define I2O_BLOCK_RETRY_TIME HZ/4 #define I2O_BLOCK_MAX_OPEN_REQUESTS 50 +/* request queue sizes */ +#define I2O_BLOCK_REQ_MEMPOOL_SIZE 32 + +#define KERNEL_SECTOR_SHIFT 9 +#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT) + /* I2O Block OSM mempool struct */ struct i2o_block_mempool { - kmem_cache_t *slab; - mempool_t *pool; + kmem_cache_t *slab; + mempool_t *pool; }; /* I2O Block device descriptor */ struct i2o_block_device { struct i2o_device *i2o_dev; /* pointer to I2O device */ struct gendisk *gd; - spinlock_t lock; /* queue lock */ + spinlock_t lock; /* queue lock */ struct list_head open_queue; /* list of transfered, but unfinished requests */ unsigned int open_queue_depth; /* number of requests in the queue */ - int rcache; /* read cache flags */ - int wcache; /* write cache flags */ + int rcache; /* read cache flags */ + int wcache; /* write cache flags */ int flags; - int power; /* power state */ - int media_change_flag; /* media changed flag */ + u16 power; /* power state */ + int media_change_flag; /* media changed flag */ }; /* I2O Block device request */ -struct i2o_block_request -{ +struct i2o_block_request { struct list_head queue; - struct request *req; /* corresponding request */ + struct request *req; /* corresponding request */ struct i2o_block_device *i2o_blk_dev; /* I2O block device */ - int sg_dma_direction; /* direction of DMA buffer read/write */ - int sg_nents; /* number of SG elements */ - struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */ + struct device *dev; /* device used for DMA */ + int sg_nents; /* number of SG elements */ + struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */ }; /* I2O Block device delayed request */ -struct i2o_block_delayed_request -{ +struct i2o_block_delayed_request { struct work_struct work; struct request_queue *queue; }; diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 1fb5cdf67f8f..3c3a7abebb1b 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -30,29 +30,15 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/i2o.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> #include <linux/miscdevice.h> -#include <linux/mm.h> -#include <linux/spinlock.h> #include <linux/smp_lock.h> -#include <linux/ioctl32.h> #include <linux/compat.h> -#include <linux/syscalls.h> #include <asm/uaccess.h> -#include <asm/io.h> -#define OSM_NAME "config-osm" -#define OSM_VERSION "$Rev$" -#define OSM_DESCRIPTION "I2O Configuration OSM" +#include "core.h" -extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); +#define SG_TABLESIZE 30 static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, unsigned long arg); @@ -80,15 +66,6 @@ struct i2o_cfg_info { static struct i2o_cfg_info *open_files = NULL; static ulong i2o_cfg_info_id = 0; -/* - * Each of these describes an i2o message handler. They are - * multiplexed by the i2o_core code - */ - -static struct i2o_driver i2o_config_driver = { - .name = OSM_NAME -}; - static int i2o_cfg_getiops(unsigned long arg) { struct i2o_controller *c; @@ -391,9 +368,9 @@ static int i2o_cfg_swul(unsigned long arg) i2o_dma_free(&c->pdev->dev, &buffer); -return_ret: + return_ret: return ret; -return_fault: + return_fault: ret = -EFAULT; goto return_ret; }; @@ -540,8 +517,10 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) return 0; } +#ifdef CONFIG_I2O_EXT_ADAPTEC #ifdef CONFIG_COMPAT -static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg) +static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, + unsigned long arg) { struct i2o_cmd_passthru32 __user *cmd; struct i2o_controller *c; @@ -555,6 +534,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar u32 sg_offset = 0; u32 sg_count = 0; u32 i = 0; + u32 sg_index = 0; i2o_status_block *sb; struct i2o_message *msg; u32 m; @@ -634,8 +614,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar if (sg_count > SG_TABLESIZE) { printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", c->name, sg_count); - kfree(reply); - return -EINVAL; + rcode = -EINVAL; + goto cleanup; } for (i = 0; i < sg_count; i++) { @@ -651,7 +631,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar goto cleanup; } sg_size = sg[i].flag_count & 0xffffff; - p = &(sg_list[i]); + p = &(sg_list[sg_index++]); /* Allocate memory for the transfer */ if (i2o_dma_alloc (&c->pdev->dev, p, sg_size, @@ -660,20 +640,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name, sg_size, i, sg_count); rcode = -ENOMEM; - goto cleanup; + goto sg_list_cleanup; } /* Copy in the user's SG buffer if necessary */ if (sg[i]. flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { // TODO 64bit fix if (copy_from_user - (p->virt, (void __user *)(unsigned long)sg[i].addr_bus, - sg_size)) { + (p->virt, + (void __user *)(unsigned long)sg[i]. + addr_bus, sg_size)) { printk(KERN_DEBUG "%s: Could not copy SG buf %d FROM user\n", c->name, i); rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } } //TODO 64bit fix @@ -683,10 +664,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar rcode = i2o_msg_post_wait(c, m, 60); if (rcode) - goto cleanup; + goto sg_list_cleanup; if (sg_offset) { - u32 msg[128]; + u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE]; /* Copy back the Scatter Gather buffers back to user space */ u32 j; // TODO 64bit fix @@ -694,18 +675,18 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar int sg_size; // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, MSG_FRAME_SIZE * 4); + memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); // get user msg size in u32s if (get_user(size, &user_msg[0])) { rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } size = size >> 16; size *= 4; /* Copy in the user's I2O command */ if (copy_from_user(msg, user_msg, size)) { rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } sg_count = (size - sg_offset * 4) / sizeof(struct sg_simple_element); @@ -727,7 +708,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar c->name, sg_list[j].virt, sg[j].addr_bus); rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } } } @@ -741,6 +722,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar "%s: Could not copy message context FROM user\n", c->name); rcode = -EFAULT; + goto sg_list_cleanup; } if (copy_to_user(user_reply, reply, reply_size)) { printk(KERN_WARNING @@ -749,16 +731,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar } } + sg_list_cleanup: + for (i = 0; i < sg_index; i++) + i2o_dma_free(&c->pdev->dev, &sg_list[i]); + cleanup: kfree(reply); return rcode; } -static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) +static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, + unsigned long arg) { int ret; - lock_kernel(); - switch (cmd) { + lock_kernel(); + switch (cmd) { case I2OGETIOPS: ret = i2o_cfg_ioctl(NULL, file, cmd, arg); break; @@ -862,8 +849,8 @@ static int i2o_cfg_passthru(unsigned long arg) if (sg_count > SG_TABLESIZE) { printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", c->name, sg_count); - kfree(reply); - return -EINVAL; + rcode = -EINVAL; + goto cleanup; } for (i = 0; i < sg_count; i++) { @@ -875,7 +862,7 @@ static int i2o_cfg_passthru(unsigned long arg) "%s:Bad SG element %d - not simple (%x)\n", c->name, i, sg[i].flag_count); rcode = -EINVAL; - goto cleanup; + goto sg_list_cleanup; } sg_size = sg[i].flag_count & 0xffffff; /* Allocate memory for the transfer */ @@ -885,7 +872,7 @@ static int i2o_cfg_passthru(unsigned long arg) "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name, sg_size, i, sg_count); rcode = -ENOMEM; - goto cleanup; + goto sg_list_cleanup; } sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. /* Copy in the user's SG buffer if necessary */ @@ -899,7 +886,7 @@ static int i2o_cfg_passthru(unsigned long arg) "%s: Could not copy SG buf %d FROM user\n", c->name, i); rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } } //TODO 64bit fix @@ -909,7 +896,7 @@ static int i2o_cfg_passthru(unsigned long arg) rcode = i2o_msg_post_wait(c, m, 60); if (rcode) - goto cleanup; + goto sg_list_cleanup; if (sg_offset) { u32 msg[128]; @@ -920,18 +907,18 @@ static int i2o_cfg_passthru(unsigned long arg) int sg_size; // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, MSG_FRAME_SIZE * 4); + memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); // get user msg size in u32s if (get_user(size, &user_msg[0])) { rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } size = size >> 16; size *= 4; /* Copy in the user's I2O command */ if (copy_from_user(msg, user_msg, size)) { rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } sg_count = (size - sg_offset * 4) / sizeof(struct sg_simple_element); @@ -953,7 +940,7 @@ static int i2o_cfg_passthru(unsigned long arg) c->name, sg_list[j], sg[j].addr_bus); rcode = -EFAULT; - goto cleanup; + goto sg_list_cleanup; } } } @@ -975,10 +962,15 @@ static int i2o_cfg_passthru(unsigned long arg) } } + sg_list_cleanup: + for (i = 0; i < sg_index; i++) + kfree(sg_list[i]); + cleanup: kfree(reply); return rcode; } +#endif /* * IOCTL Handler @@ -1033,9 +1025,11 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, ret = i2o_cfg_evt_get(arg, fp); break; +#ifdef CONFIG_I2O_EXT_ADAPTEC case I2OPASSTHRU: ret = i2o_cfg_passthru(arg); break; +#endif default: osm_debug("unknown ioctl called!\n"); @@ -1137,37 +1131,21 @@ static struct miscdevice i2o_miscdev = { &config_fops }; -static int __init i2o_config_init(void) +static int __init i2o_config_old_init(void) { - printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - spin_lock_init(&i2o_config_lock); if (misc_register(&i2o_miscdev) < 0) { osm_err("can't register device.\n"); return -EBUSY; } - /* - * Install our handler - */ - if (i2o_driver_register(&i2o_config_driver)) { - osm_err("handler register failed.\n"); - misc_deregister(&i2o_miscdev); - return -EBUSY; - } + return 0; } -static void i2o_config_exit(void) +static void i2o_config_old_exit(void) { misc_deregister(&i2o_miscdev); - i2o_driver_unregister(&i2o_config_driver); } MODULE_AUTHOR("Red Hat Software"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(OSM_DESCRIPTION); -MODULE_VERSION(OSM_VERSION); - -module_init(i2o_config_init); -module_exit(i2o_config_exit); diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index b176d0eeff7f..d559a1758363 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -28,7 +28,7 @@ */ #define OSM_NAME "proc-osm" -#define OSM_VERSION "$Rev$" +#define OSM_VERSION "1.145" #define OSM_DESCRIPTION "I2O ProcFS OSM" #define I2O_MAX_MODULES 4 @@ -228,7 +228,7 @@ static const char *i2o_get_class_name(int class) case I2O_CLASS_FLOPPY_DEVICE: idx = 12; break; - case I2O_CLASS_BUS_ADAPTER_PORT: + case I2O_CLASS_BUS_ADAPTER: idx = 13; break; case I2O_CLASS_PEER_TRANSPORT_AGENT: @@ -490,7 +490,7 @@ static int i2o_seq_show_lct(struct seq_file *seq, void *v) seq_printf(seq, ", Unknown Device Type"); break; - case I2O_CLASS_BUS_ADAPTER_PORT: + case I2O_CLASS_BUS_ADAPTER: if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) seq_printf(seq, ", %s", bus_ports[lct->lct_entry[i]. diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 43f5875e0be5..9f1744c3933b 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -54,6 +54,7 @@ #include <linux/pci.h> #include <linux/blkdev.h> #include <linux/i2o.h> +#include <linux/scatterlist.h> #include <asm/dma.h> #include <asm/system.h> @@ -64,19 +65,23 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> +#include <scsi/scsi_request.h> +#include <scsi/sg.h> +#include <scsi/sg_request.h> #define OSM_NAME "scsi-osm" -#define OSM_VERSION "$Rev$" +#define OSM_VERSION "1.282" #define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" static struct i2o_driver i2o_scsi_driver; -static int i2o_scsi_max_id = 16; -static int i2o_scsi_max_lun = 8; +static unsigned int i2o_scsi_max_id = 16; +static unsigned int i2o_scsi_max_lun = 255; struct i2o_scsi_host { struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ struct i2o_controller *iop; /* pointer to the I2O controller */ + unsigned int lun; /* lun's used for block devices */ struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ }; @@ -99,11 +104,17 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) u8 type; int i; size_t size; - i2o_status_block *sb; + u16 body_size = 6; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) + body_size = 8; +#endif list_for_each_entry(i2o_dev, &c->devices, list) - if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { - if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* SCSI bus */ + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { + if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + && (type == 0x01)) /* SCSI bus */ max_channel++; } @@ -125,20 +136,18 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) scsi_host->max_id = i2o_scsi_max_id; scsi_host->max_lun = i2o_scsi_max_lun; scsi_host->this_id = c->unit; - - sb = c->status_block.virt; - - scsi_host->sg_tablesize = (sb->inbound_frame_size - - sizeof(struct i2o_message) / 4 - 6) / 2; + scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size); i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; i2o_shost->scsi_host = scsi_host; i2o_shost->iop = c; + i2o_shost->lun = 1; i = 0; list_for_each_entry(i2o_dev, &c->devices, list) - if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { - if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* only SCSI bus */ + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { + if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + && (type == 0x01)) /* only SCSI bus */ i2o_shost->channel[i++] = i2o_dev; if (i >= max_channel) @@ -178,10 +187,13 @@ static int i2o_scsi_remove(struct device *dev) struct i2o_scsi_host *i2o_shost; struct scsi_device *scsi_dev; + osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); + i2o_shost = i2o_scsi_get_host(c); shost_for_each_device(scsi_dev, i2o_shost->scsi_host) if (scsi_dev->hostdata == i2o_dev) { + sysfs_remove_link(&i2o_dev->device.kobj, "scsi"); scsi_remove_device(scsi_dev); scsi_device_put(scsi_dev); break; @@ -207,8 +219,8 @@ static int i2o_scsi_probe(struct device *dev) struct Scsi_Host *scsi_host; struct i2o_device *parent; struct scsi_device *scsi_dev; - u32 id; - u64 lun; + u32 id = -1; + u64 lun = -1; int channel = -1; int i; @@ -218,8 +230,56 @@ static int i2o_scsi_probe(struct device *dev) scsi_host = i2o_shost->scsi_host; - if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0) + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + case I2O_CLASS_EXECUTIVE: +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u8 type; + struct i2o_device *d = i2o_shost->channel[0]; + + if (i2o_parm_field_get(d, 0x0000, 0, &type, 1) + && (type == 0x01)) /* SCSI bus */ + if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { + channel = 0; + if (i2o_dev->lct_data.class_id == + I2O_CLASS_RANDOM_BLOCK_STORAGE) + lun = i2o_shost->lun++; + else + lun = 0; + } + } +#endif + break; + + case I2O_CLASS_SCSI_PERIPHERAL: + if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0) + return -EFAULT; + + if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0) + return -EFAULT; + + parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); + if (!parent) { + osm_warn("can not find parent of device %03x\n", + i2o_dev->lct_data.tid); + return -EFAULT; + } + + for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) + if (i2o_shost->channel[i] == parent) + channel = i; + break; + + default: return -EFAULT; + } + + if (channel == -1) { + osm_warn("can not find channel of device %03x\n", + i2o_dev->lct_data.tid); + return -EFAULT; + } if (id >= scsi_host->max_id) { osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, @@ -227,42 +287,26 @@ static int i2o_scsi_probe(struct device *dev) return -EFAULT; } - if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0) - return -EFAULT; if (lun >= scsi_host->max_lun) { osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", (unsigned int)lun, scsi_host->max_lun); return -EFAULT; } - parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); - if (!parent) { - osm_warn("can not find parent of device %03x\n", - i2o_dev->lct_data.tid); - return -EFAULT; - } - - for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) - if (i2o_shost->channel[i] == parent) - channel = i; - - if (channel == -1) { - osm_warn("can not find channel of device %03x\n", - i2o_dev->lct_data.tid); - return -EFAULT; - } - scsi_dev = __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); - if (!scsi_dev) { + if (IS_ERR(scsi_dev)) { osm_warn("can not add SCSI device %03x\n", i2o_dev->lct_data.tid); - return -EFAULT; + return PTR_ERR(scsi_dev); } - osm_debug("added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n", - i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); + sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj, + "scsi"); + + osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n", + i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); return 0; }; @@ -293,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, struct i2o_message *msg) { struct scsi_cmnd *cmd; + u32 error; struct device *dev; - u8 as, ds, st; cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); - - if (msg->u.head[0] & (1 << 13)) { - struct i2o_message __iomem *pmsg; /* preserved message */ - u32 pm; - int err = DID_ERROR; - - pm = le32_to_cpu(msg->body[3]); - - pmsg = i2o_msg_in_to_virt(c, pm); - - osm_err("IOP fail.\n"); - osm_err("From %d To %d Cmd %d.\n", - (msg->u.head[1] >> 12) & 0xFFF, - msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24); - osm_err("Failure Code %d.\n", msg->body[0] >> 24); - if (msg->body[0] & (1 << 16)) - osm_err("Format error.\n"); - if (msg->body[0] & (1 << 17)) - osm_err("Path error.\n"); - if (msg->body[0] & (1 << 18)) - osm_err("Path State.\n"); - if (msg->body[0] & (1 << 18)) - { - osm_err("Congestion.\n"); - err = DID_BUS_BUSY; - } - - osm_debug("Failing message is %p.\n", pmsg); - - cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt)); - if (!cmd) - return 1; - - cmd->result = err << 16; - cmd->scsi_done(cmd); - - /* Now flush the message by making it a NOP */ - i2o_msg_nop(c, pm); - - return 1; + if (unlikely(!cmd)) { + osm_err("NULL reply received!\n"); + return -1; } /* * Low byte is device status, next is adapter status, * (then one byte reserved), then request status. */ - ds = (u8) le32_to_cpu(msg->body[0]); - as = (u8) (le32_to_cpu(msg->body[0]) >> 8); - st = (u8) (le32_to_cpu(msg->body[0]) >> 24); + error = le32_to_cpu(msg->body[0]); + + osm_debug("Completed %ld\n", cmd->serial_number); + cmd->result = error & 0xff; /* - * Is this a control request coming back - eg an abort ? + * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let + * the SCSI layer handle the error */ + if (cmd->result) + memcpy(cmd->sense_buffer, &msg->body[3], + min(sizeof(cmd->sense_buffer), (size_t) 40)); - if (!cmd) { - if (st) - osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0])); - osm_info("SCSI abort completed.\n"); - return -EFAULT; - } + /* only output error code if AdapterStatus is not HBA_SUCCESS */ + if ((error >> 8) & 0xff) + osm_err("SCSI error %08x\n", error); - osm_debug("Completed %ld\n", cmd->serial_number); + dev = &c->pdev->dev; + if (cmd->use_sg) + dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg, + cmd->sc_data_direction); + else if (cmd->SCp.dma_handle) + dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen, + cmd->sc_data_direction); - if (st) { - u32 count, error; - /* An error has occurred */ - - switch (st) { - case 0x06: - count = le32_to_cpu(msg->body[1]); - if (count < cmd->underflow) { - int i; - - osm_err("SCSI underflow 0x%08X 0x%08X\n", count, - cmd->underflow); - osm_debug("Cmd: "); - for (i = 0; i < 15; i++) - pr_debug("%02X ", cmd->cmnd[i]); - pr_debug(".\n"); - cmd->result = (DID_ERROR << 16); - } - break; + cmd->scsi_done(cmd); - default: - error = le32_to_cpu(msg->body[0]); - - osm_err("SCSI error %08x\n", error); - - if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) { - int i; - u32 len = sizeof(cmd->sense_buffer); - len = (len > 40) ? 40 : len; - // Copy over the sense data - memcpy(cmd->sense_buffer, (void *)&msg->body[3], - len); - for (i = 0; i <= len; i++) - osm_info("%02x\n", - cmd->sense_buffer[i]); - if (cmd->sense_buffer[0] == 0x70 - && cmd->sense_buffer[2] == DATA_PROTECT) { - /* This is to handle an array failed */ - cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING "%s: SCSI Data " - "Protect-Device (%d,%d,%d) " - "hba_status=0x%x, dev_status=" - "0x%x, cmd=0x%x\n", c->name, - (u32) cmd->device->channel, - (u32) cmd->device->id, - (u32) cmd->device->lun, - (error >> 8) & 0xff, - error & 0xff, cmd->cmnd[0]); - } else - cmd->result = (DID_ERROR << 16); - - break; - } - - switch (as) { - case 0x0E: - /* SCSI Reset */ - cmd->result = DID_RESET << 16; - break; - - case 0x0F: - cmd->result = DID_PARITY << 16; - break; - - default: - cmd->result = DID_ERROR << 16; - break; - } + return 1; +}; - break; - } +/** + * i2o_scsi_notify_device_add - Retrieve notifications of added devices + * @i2o_dev: the I2O device which was added + * + * If a I2O device is added we catch the notification, because I2O classes + * other then SCSI peripheral will not be received through + * i2o_scsi_probe(). + */ +static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_probe(&i2o_dev->device); + break; - cmd->scsi_done(cmd); - return 1; + default: + break; } +}; - cmd->result = DID_OK << 16 | ds; - - cmd->scsi_done(cmd); - - dev = &c->pdev->dev; - if (cmd->use_sg) - dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer, - cmd->use_sg, cmd->sc_data_direction); - else if (cmd->request_bufflen) - dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr), - cmd->request_bufflen, cmd->sc_data_direction); +/** + * i2o_scsi_notify_device_remove - Retrieve notifications of removed + * devices + * @i2o_dev: the I2O device which was removed + * + * If a I2O device is removed, we catch the notification to remove the + * corresponding SCSI device. + */ +static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_remove(&i2o_dev->device); + break; - return 1; + default: + break; + } }; /** @@ -501,7 +472,7 @@ static void i2o_scsi_notify_controller_remove(struct i2o_controller *c) scsi_remove_host(i2o_shost->scsi_host); scsi_host_put(i2o_shost->scsi_host); - pr_info("I2O SCSI host removed\n"); + osm_debug("I2O SCSI host removed\n"); }; /* SCSI OSM driver struct */ @@ -509,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = { .name = OSM_NAME, .reply = i2o_scsi_reply, .classes = i2o_scsi_class_id, + .notify_device_add = i2o_scsi_notify_device_add, + .notify_device_remove = i2o_scsi_notify_device_remove, .notify_controller_add = i2o_scsi_notify_controller_add, .notify_controller_remove = i2o_scsi_notify_controller_remove, .driver = { @@ -535,26 +508,26 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, void (*done) (struct scsi_cmnd *)) { struct i2o_controller *c; - struct Scsi_Host *host; struct i2o_device *i2o_dev; - struct device *dev; int tid; struct i2o_message __iomem *msg; u32 m; - u32 scsi_flags, sg_flags; + /* + * ENABLE_DISCONNECT + * SIMPLE_TAG + * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME + */ + u32 scsi_flags = 0x20a00000; + u32 sgl_offset; u32 __iomem *mptr; - u32 __iomem *lenptr; - u32 len, reqlen; - int i; + u32 cmd = I2O_CMD_SCSI_EXEC << 24; + int rc = 0; /* * Do the incoming paperwork */ - i2o_dev = SCpnt->device->hostdata; - host = SCpnt->device->host; c = i2o_dev->iop; - dev = &c->pdev->dev; SCpnt->scsi_done = done; @@ -562,7 +535,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, osm_warn("no I2O device in request\n"); SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); - return 0; + goto exit; } tid = i2o_dev->lct_data.tid; @@ -571,44 +544,85 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, osm_debug("Real scsi messages.\n"); /* - * Obtain an I2O message. If there are none free then - * throw it back to the scsi layer - */ - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return SCSI_MLQUEUE_HOST_BUSY; - - /* * Put together a scsi execscb message */ - - len = SCpnt->request_bufflen; - switch (SCpnt->sc_data_direction) { case PCI_DMA_NONE: - scsi_flags = 0x00000000; // DATA NO XFER - sg_flags = 0x00000000; + /* DATA NO XFER */ + sgl_offset = SGL_OFFSET_0; break; case PCI_DMA_TODEVICE: - scsi_flags = 0x80000000; // DATA OUT (iop-->dev) - sg_flags = 0x14000000; + /* DATA OUT (iop-->dev) */ + scsi_flags |= 0x80000000; + sgl_offset = SGL_OFFSET_10; break; case PCI_DMA_FROMDEVICE: - scsi_flags = 0x40000000; // DATA IN (iop<--dev) - sg_flags = 0x10000000; + /* DATA IN (iop<--dev) */ + scsi_flags |= 0x40000000; + sgl_offset = SGL_OFFSET_10; break; default: /* Unknown - kill the command */ SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); - return 0; + goto exit; } - writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]); + /* + * Obtain an I2O message. If there are none free then + * throw it back to the scsi layer + */ + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) { + rc = SCSI_MLQUEUE_HOST_BUSY; + goto exit; + } + + mptr = &msg->body[0]; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u32 adpt_flags = 0; + + if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) { + i2o_sg_io_hdr_t __user *usr_ptr = + ((Sg_request *) (SCpnt->sc_request-> + upper_private_data))->header. + usr_ptr; + + if (usr_ptr) + get_user(adpt_flags, &usr_ptr->flags); + } + + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + /* interpret flag has to be set for executive */ + adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET; + break; + + default: + break; + } + + /* + * for Adaptec controllers we use the PRIVATE command, because + * the normal SCSI EXEC doesn't support all SCSI commands on + * all controllers (for example READ CAPACITY). + */ + if (sgl_offset == SGL_OFFSET_10) + sgl_offset = SGL_OFFSET_12; + cmd = I2O_CMD_PRIVATE << 24; + writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); + writel(adpt_flags | tid, mptr++); + } +#endif + + writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); writel(i2o_scsi_driver.context, &msg->u.s.icntxt); /* We want the SCSI control block back */ @@ -626,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, */ /* Attach tags to the devices */ - /* + /* FIXME: implement if(SCpnt->device->tagged_supported) { if(SCpnt->tag == HEAD_OF_QUEUE_TAG) scsi_flags |= 0x01000000; @@ -635,67 +649,35 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, } */ - /* Direction, disconnect ok, tag, CDBLen */ - writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]); - - mptr = &msg->body[1]; + writel(scsi_flags | SCpnt->cmd_len, mptr++); /* Write SCSI command into the message - always 16 byte block */ memcpy_toio(mptr, SCpnt->cmnd, 16); mptr += 4; - lenptr = mptr++; /* Remember me - fill in when we know */ - - reqlen = 12; // SINGLE SGE - - /* Now fill in the SGList and command */ - if (SCpnt->use_sg) { - struct scatterlist *sg; - int sg_count; - - sg = SCpnt->request_buffer; - len = 0; - - sg_count = dma_map_sg(dev, sg, SCpnt->use_sg, - SCpnt->sc_data_direction); - if (unlikely(sg_count <= 0)) - return -ENOMEM; - - for (i = SCpnt->use_sg; i > 0; i--) { - if (i == 1) - sg_flags |= 0xC0000000; - writel(sg_flags | sg_dma_len(sg), mptr++); - writel(sg_dma_address(sg), mptr++); - len += sg_dma_len(sg); - sg++; + if (sgl_offset != SGL_OFFSET_0) { + /* write size of data addressed by SGL */ + writel(SCpnt->request_bufflen, mptr++); + + /* Now fill in the SGList and command */ + if (SCpnt->use_sg) { + if (!i2o_dma_map_sg(c, SCpnt->request_buffer, + SCpnt->use_sg, + SCpnt->sc_data_direction, &mptr)) + goto nomem; + } else { + SCpnt->SCp.dma_handle = + i2o_dma_map_single(c, SCpnt->request_buffer, + SCpnt->request_bufflen, + SCpnt->sc_data_direction, &mptr); + if (dma_mapping_error(SCpnt->SCp.dma_handle)) + goto nomem; } - - reqlen = mptr - &msg->u.head[0]; - writel(len, lenptr); - } else { - len = SCpnt->request_bufflen; - - writel(len, lenptr); - - if (len > 0) { - dma_addr_t dma_addr; - - dma_addr = dma_map_single(dev, SCpnt->request_buffer, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - if (!dma_addr) - return -ENOMEM; - - SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr; - sg_flags |= 0xC0000000; - writel(sg_flags | SCpnt->request_bufflen, mptr++); - writel(dma_addr, mptr++); - } else - reqlen = 9; } /* Stick the headers on */ - writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]); + writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset, + &msg->u.head[0]); /* Queue the message */ i2o_msg_post(c, m); @@ -703,6 +685,13 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, osm_debug("Issued %ld\n", SCpnt->serial_number); return 0; + + nomem: + rc = -ENOMEM; + i2o_msg_nop(c, m); + + exit: + return rc; }; /** diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 50c8cedf7a2d..42f8b810d6e5 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -28,8 +28,10 @@ #include <linux/module.h> #include <linux/i2o.h> #include <linux/delay.h> +#include "core.h" -#define OSM_VERSION "$Rev$" +#define OSM_NAME "i2o" +#define OSM_VERSION "1.288" #define OSM_DESCRIPTION "I2O subsystem" /* global I2O controller list */ @@ -43,20 +45,6 @@ static struct i2o_dma i2o_systab; static int i2o_hrt_get(struct i2o_controller *c); -/* Module internal functions from other sources */ -extern struct i2o_driver i2o_exec_driver; -extern int i2o_exec_lct_get(struct i2o_controller *); -extern void i2o_device_remove(struct i2o_device *); - -extern int __init i2o_driver_init(void); -extern void __exit i2o_driver_exit(void); -extern int __init i2o_exec_init(void); -extern void __exit i2o_exec_exit(void); -extern int __init i2o_pci_init(void); -extern void __exit i2o_pci_exit(void); -extern int i2o_device_init(void); -extern void i2o_device_exit(void); - /** * i2o_msg_nop - Returns a message which is not used * @c: I2O controller from which the message was created @@ -68,7 +56,7 @@ extern void i2o_device_exit(void); */ void i2o_msg_nop(struct i2o_controller *c, u32 m) { - struct i2o_message __iomem *msg = c->in_queue.virt + m; + struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, @@ -92,16 +80,16 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m) * address from the read port (see the i2o spec). If no message is * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ -u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg, - int wait) +u32 i2o_msg_get_wait(struct i2o_controller *c, + struct i2o_message __iomem ** msg, int wait) { unsigned long timeout = jiffies + wait * HZ; u32 m; while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { if (time_after(jiffies, timeout)) { - pr_debug("%s: Timeout waiting for message frame.\n", - c->name); + osm_debug("%s: Timeout waiting for message frame.\n", + c->name); return I2O_QUEUE_EMPTY; } set_current_state(TASK_UNINTERRUPTIBLE); @@ -129,13 +117,13 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) unsigned long flags; if (!ptr) - printk(KERN_ERR "%s: couldn't add NULL pointer to context list!" - "\n", c->name); + osm_err("%s: couldn't add NULL pointer to context list!\n", + c->name); entry = kmalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) { - printk(KERN_ERR "%s: Could not allocate memory for context " - "list element\n", c->name); + osm_err("%s: Could not allocate memory for context list element" + "\n", c->name); return 0; } @@ -154,7 +142,7 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) spin_unlock_irqrestore(&c->context_list_lock, flags); - pr_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); + osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); return entry->context; }; @@ -186,11 +174,11 @@ u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) spin_unlock_irqrestore(&c->context_list_lock, flags); if (!context) - printk(KERN_WARNING "%s: Could not remove nonexistent ptr " - "%p\n", c->name, ptr); + osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name, + ptr); - pr_debug("%s: remove ptr from context list %d -> %p\n", c->name, - context, ptr); + osm_debug("%s: remove ptr from context list %d -> %p\n", c->name, + context, ptr); return context; }; @@ -220,11 +208,10 @@ void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) spin_unlock_irqrestore(&c->context_list_lock, flags); if (!ptr) - printk(KERN_WARNING "%s: context id %d not found\n", c->name, - context); + osm_warn("%s: context id %d not found\n", c->name, context); - pr_debug("%s: get ptr from context list %d -> %p\n", c->name, context, - ptr); + osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context, + ptr); return ptr; }; @@ -252,11 +239,11 @@ u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) spin_unlock_irqrestore(&c->context_list_lock, flags); if (!context) - printk(KERN_WARNING "%s: Could not find nonexistent ptr " - "%p\n", c->name, ptr); + osm_warn("%s: Could not find nonexistent ptr %p\n", c->name, + ptr); - pr_debug("%s: get context id from context list %p -> %d\n", c->name, - ptr, context); + osm_debug("%s: get context id from context list %p -> %d\n", c->name, + ptr, context); return context; }; @@ -336,10 +323,9 @@ static int i2o_iop_quiesce(struct i2o_controller *c) /* Long timeout needed for quiesce if lots of devices */ if ((rc = i2o_msg_post_wait(c, m, 240))) - printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n", - c->name, -rc); + osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); else - pr_debug("%s: Quiesced.\n", c->name); + osm_debug("%s: Quiesced.\n", c->name); i2o_status_get(c); // Entered READY state @@ -377,10 +363,9 @@ static int i2o_iop_enable(struct i2o_controller *c) /* How long of a timeout do we need? */ if ((rc = i2o_msg_post_wait(c, m, 240))) - printk(KERN_ERR "%s: Could not enable (status=%#x).\n", - c->name, -rc); + osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); else - pr_debug("%s: Enabled.\n", c->name); + osm_debug("%s: Enabled.\n", c->name); i2o_status_get(c); // entered OPERATIONAL state @@ -444,20 +429,78 @@ static int i2o_iop_clear(struct i2o_controller *c) &msg->u.head[1]); if ((rc = i2o_msg_post_wait(c, m, 30))) - printk(KERN_INFO "%s: Unable to clear (status=%#x).\n", - c->name, -rc); + osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); else - pr_debug("%s: Cleared.\n", c->name); + osm_debug("%s: Cleared.\n", c->name); /* Enable all IOPs */ i2o_iop_enable_all(); - i2o_status_get(c); - return rc; } /** + * i2o_iop_init_outbound_queue - setup the outbound message queue + * @c: I2O controller + * + * Clear and (re)initialize IOP's outbound queue and post the message + * frames to the IOP. + * + * Returns 0 on success or a negative errno code on failure. + */ +static int i2o_iop_init_outbound_queue(struct i2o_controller *c) +{ + volatile u8 *status = c->status.virt; + u32 m; + struct i2o_message __iomem *msg; + ulong timeout; + int i; + + osm_debug("%s: Initializing Outbound Queue...\n", c->name); + + memset(c->status.virt, 0, 4); + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); + writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_exec_driver.context, &msg->u.s.icntxt); + writel(0x00000000, &msg->u.s.tcntxt); + writel(PAGE_SIZE, &msg->body[0]); + /* Outbound msg frame size in words and Initcode */ + writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); + writel(0xd0000004, &msg->body[2]); + writel(i2o_dma_low(c->status.phys), &msg->body[3]); + writel(i2o_dma_high(c->status.phys), &msg->body[4]); + + i2o_msg_post(c, m); + + timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; + while (*status <= I2O_CMD_IN_PROGRESS) { + if (time_after(jiffies, timeout)) { + osm_warn("%s: Timeout Initializing\n", c->name); + return -ETIMEDOUT; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + + m = c->out_queue.phys; + + /* Post frames */ + for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) { + i2o_flush_reply(c, m); + udelay(1); /* Promise */ + m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32); + } + + return 0; +} + +/** * i2o_iop_reset - reset an I2O controller * @c: controller to reset * @@ -468,20 +511,20 @@ static int i2o_iop_clear(struct i2o_controller *c) */ static int i2o_iop_reset(struct i2o_controller *c) { - u8 *status = c->status.virt; + volatile u8 *status = c->status.virt; struct i2o_message __iomem *msg; u32 m; unsigned long timeout; i2o_status_block *sb = c->status_block.virt; int rc = 0; - pr_debug("%s: Resetting controller\n", c->name); + osm_debug("%s: Resetting controller\n", c->name); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; - memset(status, 0, 8); + memset(c->status_block.virt, 0, 8); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); @@ -493,49 +536,43 @@ static int i2o_iop_reset(struct i2o_controller *c) writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context writel(0, &msg->body[0]); writel(0, &msg->body[1]); - writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]); - writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]); + writel(i2o_dma_low(c->status.phys), &msg->body[2]); + writel(i2o_dma_high(c->status.phys), &msg->body[3]); i2o_msg_post(c, m); /* Wait for a reply */ timeout = jiffies + I2O_TIMEOUT_RESET * HZ; while (!*status) { - if (time_after(jiffies, timeout)) { - printk(KERN_ERR "%s: IOP reset timeout.\n", c->name); - rc = -ETIMEDOUT; - goto exit; - } - - /* Promise bug */ - if (status[1] || status[4]) { - *status = 0; + if (time_after(jiffies, timeout)) break; - } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); - - rmb(); } - if (*status == I2O_CMD_IN_PROGRESS) { + switch (*status) { + case I2O_CMD_REJECTED: + osm_warn("%s: IOP reset rejected\n", c->name); + rc = -EPERM; + break; + + case I2O_CMD_IN_PROGRESS: /* * Once the reset is sent, the IOP goes into the INIT state - * which is indeterminate. We need to wait until the IOP - * has rebooted before we can let the system talk to - * it. We read the inbound Free_List until a message is - * available. If we can't read one in the given ammount of - * time, we assume the IOP could not reboot properly. + * which is indeterminate. We need to wait until the IOP has + * rebooted before we can let the system talk to it. We read + * the inbound Free_List until a message is available. If we + * can't read one in the given ammount of time, we assume the + * IOP could not reboot properly. */ - pr_debug("%s: Reset in progress, waiting for reboot...\n", - c->name); + osm_debug("%s: Reset in progress, waiting for reboot...\n", + c->name); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); while (m == I2O_QUEUE_EMPTY) { if (time_after(jiffies, timeout)) { - printk(KERN_ERR "%s: IOP reset timeout.\n", - c->name); + osm_err("%s: IOP reset timeout.\n", c->name); rc = -ETIMEDOUT; goto exit; } @@ -545,19 +582,26 @@ static int i2o_iop_reset(struct i2o_controller *c) m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); } i2o_msg_nop(c, m); - } - /* from here all quiesce commands are safe */ - c->no_quiesce = 0; + /* from here all quiesce commands are safe */ + c->no_quiesce = 0; - /* If IopReset was rejected or didn't perform reset, try IopClear */ - i2o_status_get(c); - if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) { - printk(KERN_WARNING "%s: Reset rejected, trying to clear\n", - c->name); - i2o_iop_clear(c); - } else - pr_debug("%s: Reset completed.\n", c->name); + /* verify if controller is in state RESET */ + i2o_status_get(c); + + if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET)) + osm_warn("%s: reset completed, but adapter not in RESET" + " state.\n", c->name); + else + osm_debug("%s: reset completed.\n", c->name); + + break; + + default: + osm_err("%s: IOP reset timeout.\n", c->name); + rc = -ETIMEDOUT; + break; + } exit: /* Enable all IOPs */ @@ -567,88 +611,6 @@ static int i2o_iop_reset(struct i2o_controller *c) }; /** - * i2o_iop_init_outbound_queue - setup the outbound message queue - * @c: I2O controller - * - * Clear and (re)initialize IOP's outbound queue and post the message - * frames to the IOP. - * - * Returns 0 on success or a negative errno code on failure. - */ -static int i2o_iop_init_outbound_queue(struct i2o_controller *c) -{ - u8 *status = c->status.virt; - u32 m; - struct i2o_message __iomem *msg; - ulong timeout; - int i; - - pr_debug("%s: Initializing Outbound Queue...\n", c->name); - - memset(status, 0, 4); - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; - - writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]); - writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_exec_driver.context, &msg->u.s.icntxt); - writel(0x0106, &msg->u.s.tcntxt); /* FIXME: why 0x0106, maybe in - Spec? */ - writel(PAGE_SIZE, &msg->body[0]); - writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame - size in words and Initcode */ - writel(0xd0000004, &msg->body[2]); - writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]); - writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]); - - i2o_msg_post(c, m); - - timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; - while (*status <= I2O_CMD_IN_PROGRESS) { - if (time_after(jiffies, timeout)) { - printk(KERN_WARNING "%s: Timeout Initializing\n", - c->name); - return -ETIMEDOUT; - } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - - rmb(); - } - - m = c->out_queue.phys; - - /* Post frames */ - for (i = 0; i < NMBR_MSG_FRAMES; i++) { - i2o_flush_reply(c, m); - udelay(1); /* Promise */ - m += MSG_FRAME_SIZE * 4; - } - - return 0; -} - -/** - * i2o_iop_send_nop - send a core NOP message - * @c: controller - * - * Send a no-operation message with a reply set to cause no - * action either. Needed for bringing up promise controllers. - */ -static int i2o_iop_send_nop(struct i2o_controller *c) -{ - struct i2o_message __iomem *msg; - u32 m = i2o_msg_get_wait(c, &msg, HZ); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; - i2o_msg_nop(c, m); - return 0; -} - -/** * i2o_iop_activate - Bring controller up to HOLD * @c: controller * @@ -659,78 +621,62 @@ static int i2o_iop_send_nop(struct i2o_controller *c) */ static int i2o_iop_activate(struct i2o_controller *c) { - struct pci_dev *i960 = NULL; i2o_status_block *sb = c->status_block.virt; int rc; - - if (c->promise) { - /* Beat up the hardware first of all */ - i960 = - pci_find_slot(c->pdev->bus->number, - PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); - if (i960) - pci_write_config_word(i960, 0x42, 0); - - /* Follow this sequence precisely or the controller - ceases to perform useful functions until reboot */ - if ((rc = i2o_iop_send_nop(c))) - return rc; - - if ((rc = i2o_iop_reset(c))) - return rc; - } + int state; /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ /* In READY state, Get status */ rc = i2o_status_get(c); if (rc) { - printk(KERN_INFO "%s: Unable to obtain status, " - "attempting a reset.\n", c->name); - if (i2o_iop_reset(c)) + osm_info("%s: Unable to obtain status, attempting a reset.\n", + c->name); + rc = i2o_iop_reset(c); + if (rc) return rc; } if (sb->i2o_version > I2OVER15) { - printk(KERN_ERR "%s: Not running version 1.5 of the I2O " - "Specification.\n", c->name); + osm_err("%s: Not running version 1.5 of the I2O Specification." + "\n", c->name); return -ENODEV; } switch (sb->iop_state) { case ADAPTER_STATE_FAULTED: - printk(KERN_CRIT "%s: hardware fault\n", c->name); - return -ENODEV; + osm_err("%s: hardware fault\n", c->name); + return -EFAULT; case ADAPTER_STATE_READY: case ADAPTER_STATE_OPERATIONAL: case ADAPTER_STATE_HOLD: case ADAPTER_STATE_FAILED: - pr_debug("%s: already running, trying to reset...\n", c->name); - if (i2o_iop_reset(c)) - return -ENODEV; + osm_debug("%s: already running, trying to reset...\n", c->name); + rc = i2o_iop_reset(c); + if (rc) + return rc; } + /* preserve state */ + state = sb->iop_state; + rc = i2o_iop_init_outbound_queue(c); if (rc) return rc; - if (c->promise) { - if ((rc = i2o_iop_send_nop(c))) - return rc; + /* if adapter was not in RESET state clear now */ + if (state != ADAPTER_STATE_RESET) + i2o_iop_clear(c); - if ((rc = i2o_status_get(c))) - return rc; + i2o_status_get(c); - if (i960) - pci_write_config_word(i960, 0x42, 0x3FF); + if (sb->iop_state != ADAPTER_STATE_HOLD) { + osm_err("%s: failed to bring IOP into HOLD state\n", c->name); + return -EIO; } - /* In HOLD state */ - - rc = i2o_hrt_get(c); - - return rc; + return i2o_hrt_get(c); }; /** @@ -756,20 +702,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c) res->flags = IORESOURCE_MEM; res->start = 0; res->end = 0; - printk(KERN_INFO "%s: requires private memory resources.\n", - c->name); + osm_info("%s: requires private memory resources.\n", c->name); root = pci_find_parent_resource(c->pdev, res); if (root == NULL) - printk(KERN_WARNING "%s: Can't find parent resource!\n", - c->name); + osm_warn("%s: Can't find parent resource!\n", c->name); if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ NULL, NULL) >= 0) { c->mem_alloc = 1; sb->current_mem_size = 1 + res->end - res->start; sb->current_mem_base = res->start; - printk(KERN_INFO "%s: allocated %ld bytes of PCI memory" - " at 0x%08lX.\n", c->name, - 1 + res->end - res->start, res->start); + osm_info("%s: allocated %ld bytes of PCI memory at " + "0x%08lX.\n", c->name, + 1 + res->end - res->start, res->start); } } @@ -779,20 +723,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c) res->flags = IORESOURCE_IO; res->start = 0; res->end = 0; - printk(KERN_INFO "%s: requires private memory resources.\n", - c->name); + osm_info("%s: requires private memory resources.\n", c->name); root = pci_find_parent_resource(c->pdev, res); if (root == NULL) - printk(KERN_WARNING "%s: Can't find parent resource!\n", - c->name); + osm_warn("%s: Can't find parent resource!\n", c->name); if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ NULL, NULL) >= 0) { c->io_alloc = 1; sb->current_io_size = 1 + res->end - res->start; sb->current_mem_base = res->start; - printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at" - " 0x%08lX.\n", c->name, - 1 + res->end - res->start, res->start); + osm_info("%s: allocated %ld bytes of PCI I/O at 0x%08lX" + ".\n", c->name, 1 + res->end - res->start, + res->start); } } @@ -836,10 +778,10 @@ static int i2o_iop_systab_set(struct i2o_controller *c) PCI_DMA_TODEVICE); if (rc < 0) - printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", - c->name, -rc); + osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name, + -rc); else - pr_debug("%s: SysTab set.\n", c->name); + osm_debug("%s: SysTab set.\n", c->name); i2o_status_get(c); // Entered READY state @@ -863,7 +805,7 @@ static int i2o_iop_online(struct i2o_controller *c) return rc; /* In READY state */ - pr_debug("%s: Attempting to enable...\n", c->name); + osm_debug("%s: Attempting to enable...\n", c->name); rc = i2o_iop_enable(c); if (rc) return rc; @@ -882,7 +824,7 @@ void i2o_iop_remove(struct i2o_controller *c) { struct i2o_device *dev, *tmp; - pr_debug("%s: deleting controller\n", c->name); + osm_debug("%s: deleting controller\n", c->name); i2o_driver_notify_controller_remove_all(c); @@ -891,8 +833,12 @@ void i2o_iop_remove(struct i2o_controller *c) list_for_each_entry_safe(dev, tmp, &c->devices, list) i2o_device_remove(dev); + device_del(&c->device); + /* Ask the IOP to switch to RESET state */ i2o_iop_reset(c); + + put_device(&c->device); } /** @@ -927,8 +873,7 @@ static int i2o_systab_build(void) systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL); if (!systab) { - printk(KERN_ERR "i2o: unable to allocate memory for System " - "Table\n"); + osm_err("unable to allocate memory for System Table\n"); return -ENOMEM; } memset(systab, 0, i2o_systab.len); @@ -940,8 +885,8 @@ static int i2o_systab_build(void) i2o_status_block *sb; if (count >= num_controllers) { - printk(KERN_ERR "i2o: controller added while building " - "system table\n"); + osm_err("controller added while building system table" + "\n"); break; } @@ -955,9 +900,8 @@ static int i2o_systab_build(void) * it is techninically not part of the I2O subsystem... */ if (unlikely(i2o_status_get(c))) { - printk(KERN_ERR "%s: Deleting b/c could not get status" - " while attempting to build system table\n", - c->name); + osm_err("%s: Deleting b/c could not get status while " + "attempting to build system table\n", c->name); i2o_iop_remove(c); continue; // try the next one } @@ -971,8 +915,10 @@ static int i2o_systab_build(void) systab->iops[count].frame_size = sb->inbound_frame_size; systab->iops[count].last_changed = change_ind; systab->iops[count].iop_capabilities = sb->iop_capabilities; - systab->iops[count].inbound_low = i2o_ptr_low(c->post_port); - systab->iops[count].inbound_high = i2o_ptr_high(c->post_port); + systab->iops[count].inbound_low = + i2o_dma_low(c->base.phys + I2O_IN_PORT); + systab->iops[count].inbound_high = + i2o_dma_high(c->base.phys + I2O_IN_PORT); count++; } @@ -1010,11 +956,11 @@ int i2o_status_get(struct i2o_controller *c) { struct i2o_message __iomem *msg; u32 m; - u8 *status_block; + volatile u8 *status_block; unsigned long timeout; status_block = (u8 *) c->status_block.virt; - memset(status_block, 0, sizeof(i2o_status_block)); + memset(c->status_block.virt, 0, sizeof(i2o_status_block)); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); if (m == I2O_QUEUE_EMPTY) @@ -1027,8 +973,8 @@ int i2o_status_get(struct i2o_controller *c) writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context writel(0, &msg->body[0]); writel(0, &msg->body[1]); - writel(i2o_ptr_low((void *)c->status_block.phys), &msg->body[2]); - writel(i2o_ptr_high((void *)c->status_block.phys), &msg->body[3]); + writel(i2o_dma_low(c->status_block.phys), &msg->body[2]); + writel(i2o_dma_high(c->status_block.phys), &msg->body[3]); writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */ i2o_msg_post(c, m); @@ -1037,14 +983,12 @@ int i2o_status_get(struct i2o_controller *c) timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; while (status_block[87] != 0xFF) { if (time_after(jiffies, timeout)) { - printk(KERN_ERR "%s: Get status timeout.\n", c->name); + osm_err("%s: Get status timeout.\n", c->name); return -ETIMEDOUT; } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); - - rmb(); } #ifdef DEBUG @@ -1088,8 +1032,8 @@ static int i2o_hrt_get(struct i2o_controller *c) rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt); if (rc < 0) { - printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n", - c->name, -rc); + osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, + -rc); return rc; } @@ -1103,13 +1047,41 @@ static int i2o_hrt_get(struct i2o_controller *c) return i2o_parse_hrt(c); } - printk(KERN_ERR "%s: Unable to get HRT after %d tries, giving up\n", - c->name, I2O_HRT_GET_TRIES); + osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name, + I2O_HRT_GET_TRIES); return -EBUSY; } /** + * i2o_iop_free - Free the i2o_controller struct + * @c: I2O controller to free + */ +void i2o_iop_free(struct i2o_controller *c) +{ + kfree(c); +}; + +/** + * i2o_iop_release - release the memory for a I2O controller + * @dev: I2O controller which should be released + * + * Release the allocated memory. This function is called if refcount of + * device reaches 0 automatically. + */ +static void i2o_iop_release(struct device *dev) +{ + struct i2o_controller *c = to_i2o_controller(dev); + + i2o_iop_free(c); +}; + +/* I2O controller class */ +static struct class i2o_controller_class = { + .name = "i2o_controller", +}; + +/** * i2o_iop_alloc - Allocate and initialize a i2o_controller struct * * Allocate the necessary memory for a i2o_controller struct and @@ -1125,8 +1097,8 @@ struct i2o_controller *i2o_iop_alloc(void) c = kmalloc(sizeof(*c), GFP_KERNEL); if (!c) { - printk(KERN_ERR "i2o: Insufficient memory to allocate a I2O " - "controller.\n"); + osm_err("i2o: Insufficient memory to allocate a I2O controller." + "\n"); return ERR_PTR(-ENOMEM); } memset(c, 0, sizeof(*c)); @@ -1137,6 +1109,16 @@ struct i2o_controller *i2o_iop_alloc(void) c->unit = unit++; sprintf(c->name, "iop%d", c->unit); + device_initialize(&c->device); + class_device_initialize(&c->classdev); + + c->device.release = &i2o_iop_release; + c->classdev.class = &i2o_controller_class; + c->classdev.dev = &c->device; + + snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit); + snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit); + #if BITS_PER_LONG == 64 spin_lock_init(&c->context_list_lock); atomic_set(&c->context_list_counter, 0); @@ -1147,15 +1129,6 @@ struct i2o_controller *i2o_iop_alloc(void) }; /** - * i2o_iop_free - Free the i2o_controller struct - * @c: I2O controller to free - */ -void i2o_iop_free(struct i2o_controller *c) -{ - kfree(c); -}; - -/** * i2o_iop_add - Initialize the I2O controller and add him to the I2O core * @c: controller * @@ -1168,45 +1141,58 @@ int i2o_iop_add(struct i2o_controller *c) { int rc; - printk(KERN_INFO "%s: Activating I2O controller...\n", c->name); - printk(KERN_INFO "%s: This may take a few minutes if there are many " - "devices\n", c->name); + if ((rc = device_add(&c->device))) { + osm_err("%s: could not add controller\n", c->name); + goto iop_reset; + } - if ((rc = i2o_iop_activate(c))) { - printk(KERN_ERR "%s: could not activate controller\n", - c->name); - i2o_iop_reset(c); - return rc; + if ((rc = class_device_add(&c->classdev))) { + osm_err("%s: could not add controller class\n", c->name); + goto device_del; } - pr_debug("%s: building sys table...\n", c->name); + osm_info("%s: Activating I2O controller...\n", c->name); + osm_info("%s: This may take a few minutes if there are many devices\n", + c->name); - if ((rc = i2o_systab_build())) { - i2o_iop_reset(c); - return rc; + if ((rc = i2o_iop_activate(c))) { + osm_err("%s: could not activate controller\n", c->name); + goto class_del; } - pr_debug("%s: online controller...\n", c->name); + osm_debug("%s: building sys table...\n", c->name); - if ((rc = i2o_iop_online(c))) { - i2o_iop_reset(c); - return rc; - } + if ((rc = i2o_systab_build())) + goto class_del; - pr_debug("%s: getting LCT...\n", c->name); + osm_debug("%s: online controller...\n", c->name); - if ((rc = i2o_exec_lct_get(c))) { - i2o_iop_reset(c); - return rc; - } + if ((rc = i2o_iop_online(c))) + goto class_del; + + osm_debug("%s: getting LCT...\n", c->name); + + if ((rc = i2o_exec_lct_get(c))) + goto class_del; list_add(&c->list, &i2o_controllers); i2o_driver_notify_controller_add_all(c); - printk(KERN_INFO "%s: Controller added\n", c->name); + osm_info("%s: Controller added\n", c->name); return 0; + + class_del: + class_device_del(&c->classdev); + + device_del: + device_del(&c->device); + + iop_reset: + i2o_iop_reset(c); + + return rc; }; /** @@ -1264,16 +1250,18 @@ static int __init i2o_iop_init(void) if (rc) goto exit; - rc = i2o_driver_init(); - if (rc) + if ((rc = class_register(&i2o_controller_class))) { + osm_err("can't register class i2o_controller\n"); goto device_exit; + } - rc = i2o_exec_init(); - if (rc) + if ((rc = i2o_driver_init())) + goto class_exit; + + if ((rc = i2o_exec_init())) goto driver_exit; - rc = i2o_pci_init(); - if (rc < 0) + if ((rc = i2o_pci_init())) goto exec_exit; return 0; @@ -1284,6 +1272,9 @@ static int __init i2o_iop_init(void) driver_exit: i2o_driver_exit(); + class_exit: + class_unregister(&i2o_controller_class); + device_exit: i2o_device_exit(); @@ -1301,6 +1292,7 @@ static void __exit i2o_iop_exit(void) i2o_pci_exit(); i2o_exec_exit(); i2o_driver_exit(); + class_unregister(&i2o_controller_class); i2o_device_exit(); }; diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index e772752f056d..7a60fd7be8ad 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -30,53 +30,18 @@ #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/i2o.h> - -#ifdef CONFIG_MTRR -#include <asm/mtrr.h> -#endif // CONFIG_MTRR - -/* Module internal functions from other sources */ -extern struct i2o_controller *i2o_iop_alloc(void); -extern void i2o_iop_free(struct i2o_controller *); - -extern int i2o_iop_add(struct i2o_controller *); -extern void i2o_iop_remove(struct i2o_controller *); - -extern int i2o_driver_dispatch(struct i2o_controller *, u32, - struct i2o_message *); +#include "core.h" /* PCI device id table for all I2O controllers */ static struct pci_device_id __devinitdata i2o_pci_ids[] = { {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, + {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, + .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID}, {0} }; /** - * i2o_dma_realloc - Realloc DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: pointer to a i2o_dma struct DMA buffer - * @len: new length of memory - * @gfp_mask: GFP mask - * - * If there was something allocated in the addr, free it first. If len > 0 - * than try to allocate it and write the addresses back to the addr - * structure. If len == 0 set the virtual address to NULL. - * - * Returns the 0 on success or negative error code on failure. - */ -int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len, - unsigned int gfp_mask) -{ - i2o_dma_free(dev, addr); - - if (len) - return i2o_dma_alloc(dev, addr, len, gfp_mask); - - return 0; -}; - -/** * i2o_pci_free - Frees the DMA memory for the I2O controller * @c: I2O controller to free * @@ -91,19 +56,11 @@ static void i2o_pci_free(struct i2o_controller *c) i2o_dma_free(dev, &c->out_queue); i2o_dma_free(dev, &c->status_block); - if (c->lct) - kfree(c->lct); + kfree(c->lct); i2o_dma_free(dev, &c->dlct); i2o_dma_free(dev, &c->hrt); i2o_dma_free(dev, &c->status); -#ifdef CONFIG_MTRR - if (c->mtrr_reg0 >= 0) - mtrr_del(c->mtrr_reg0, 0, 0); - if (c->mtrr_reg1 >= 0) - mtrr_del(c->mtrr_reg1, 0, 0); -#endif - if (c->raptor && c->in_queue.virt) iounmap(c->in_queue.virt); @@ -178,14 +135,15 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) c->name, (unsigned long)c->base.phys, (unsigned long)c->base.len); - c->base.virt = ioremap(c->base.phys, c->base.len); + c->base.virt = ioremap_nocache(c->base.phys, c->base.len); if (!c->base.virt) { printk(KERN_ERR "%s: Unable to map controller.\n", c->name); return -ENOMEM; } if (c->raptor) { - c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len); + c->in_queue.virt = + ioremap_nocache(c->in_queue.phys, c->in_queue.len); if (!c->in_queue.virt) { printk(KERN_ERR "%s: Unable to map controller.\n", c->name); @@ -195,43 +153,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) } else c->in_queue = c->base; - c->irq_mask = c->base.virt + 0x34; - c->post_port = c->base.virt + 0x40; - c->reply_port = c->base.virt + 0x44; - -#ifdef CONFIG_MTRR - /* Enable Write Combining MTRR for IOP's memory region */ - c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len, - MTRR_TYPE_WRCOMB, 1); - c->mtrr_reg1 = -1; - - if (c->mtrr_reg0 < 0) - printk(KERN_WARNING "%s: could not enable write combining " - "MTRR\n", c->name); - else - printk(KERN_INFO "%s: using write combining MTRR\n", c->name); - - /* - * If it is an INTEL i960 I/O processor then set the first 64K to - * Uncacheable since the region contains the messaging unit which - * shouldn't be cached. - */ - if ((pdev->vendor == PCI_VENDOR_ID_INTEL || - pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) { - printk(KERN_INFO "%s: MTRR workaround for Intel i960 processor" - "\n", c->name); - c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000, - MTRR_TYPE_UNCACHABLE, 1); - - if (c->mtrr_reg1 < 0) { - printk(KERN_WARNING "%s: Error in setting " - "MTRR_TYPE_UNCACHABLE\n", c->name); - mtrr_del(c->mtrr_reg0, c->in_queue.phys, - c->in_queue.len); - c->mtrr_reg0 = -1; - } - } -#endif + c->irq_status = c->base.virt + I2O_IRQ_STATUS; + c->irq_mask = c->base.virt + I2O_IRQ_MASK; + c->in_port = c->base.virt + I2O_IN_PORT; + c->out_port = c->base.virt + I2O_OUT_PORT; if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { i2o_pci_free(c); @@ -254,7 +179,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) return -ENOMEM; } - if (i2o_dma_alloc(dev, &c->out_queue, MSG_POOL_SIZE, GFP_KERNEL)) { + if (i2o_dma_alloc + (dev, &c->out_queue, + I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * + sizeof(u32), GFP_KERNEL)) { i2o_pci_free(c); return -ENOMEM; } @@ -276,51 +204,30 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) { struct i2o_controller *c = dev_id; - struct device *dev = &c->pdev->dev; - struct i2o_message *m; - u32 mv; - - /* - * Old 960 steppings had a bug in the I2O unit that caused - * the queue to appear empty when it wasn't. - */ - mv = I2O_REPLY_READ32(c); - if (mv == I2O_QUEUE_EMPTY) { - mv = I2O_REPLY_READ32(c); - if (unlikely(mv == I2O_QUEUE_EMPTY)) { - return IRQ_NONE; - } else - pr_debug("%s: 960 bug detected\n", c->name); - } - - while (mv != I2O_QUEUE_EMPTY) { - /* - * Map the message from the page frame map to kernel virtual. - * Because bus_to_virt is deprecated, we have calculate the - * location by ourself! - */ - m = i2o_msg_out_to_virt(c, mv); - - /* - * Ensure this message is seen coherently but cachably by - * the processor - */ - dma_sync_single_for_cpu(dev, mv, MSG_FRAME_SIZE * 4, - PCI_DMA_FROMDEVICE); + u32 m; + irqreturn_t rc = IRQ_NONE; + + while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) { + m = readl(c->out_port); + if (m == I2O_QUEUE_EMPTY) { + /* + * Old 960 steppings had a bug in the I2O unit that + * caused the queue to appear empty when it wasn't. + */ + m = readl(c->out_port); + if (unlikely(m == I2O_QUEUE_EMPTY)) + break; + } /* dispatch it */ - if (i2o_driver_dispatch(c, mv, m)) + if (i2o_driver_dispatch(c, m)) /* flush it if result != 0 */ - i2o_flush_reply(c, mv); + i2o_flush_reply(c, m); - /* - * That 960 bug again... - */ - mv = I2O_REPLY_READ32(c); - if (mv == I2O_QUEUE_EMPTY) - mv = I2O_REPLY_READ32(c); + rc = IRQ_HANDLED; } - return IRQ_HANDLED; + + return rc; } /** @@ -336,7 +243,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) struct pci_dev *pdev = c->pdev; int rc; - I2O_IRQ_WRITE32(c, 0xffffffff); + writel(0xffffffff, c->irq_mask); if (pdev->irq) { rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ, @@ -348,7 +255,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) } } - I2O_IRQ_WRITE32(c, 0x00000000); + writel(0x00000000, c->irq_mask); printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); @@ -363,7 +270,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) */ static void i2o_pci_irq_disable(struct i2o_controller *c) { - I2O_IRQ_WRITE32(c, 0xffffffff); + writel(0xffffffff, c->irq_mask); if (c->pdev->irq > 0) free_irq(c->pdev->irq, c); @@ -385,28 +292,25 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, { struct i2o_controller *c; int rc; + struct pci_dev *i960 = NULL; printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); if ((pdev->class & 0xff) > 1) { - printk(KERN_WARNING "i2o: I2O controller found but does not " - "support I2O 1.5 (skipping).\n"); + printk(KERN_WARNING "i2o: %s does not support I2O 1.5 " + "(skipping).\n", pci_name(pdev)); return -ENODEV; } if ((rc = pci_enable_device(pdev))) { - printk(KERN_WARNING "i2o: I2O controller found but could not be" - " enabled.\n"); + printk(KERN_WARNING "i2o: couldn't enable device %s\n", + pci_name(pdev)); return rc; } - printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n", - pdev->bus->number, pdev->devfn); - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No " - "suitable DMA available!\n", pdev->bus->number, - pdev->devfn); + printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", + pci_name(pdev)); rc = -ENODEV; goto disable; } @@ -415,14 +319,16 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, c = i2o_iop_alloc(); if (IS_ERR(c)) { - printk(KERN_ERR "i2o: memory for I2O controller could not be " - "allocated\n"); + printk(KERN_ERR "i2o: couldn't allocate memory for %s\n", + pci_name(pdev)); rc = PTR_ERR(c); goto disable; - } + } else + printk(KERN_INFO "%s: controller found (%s)\n", c->name, + pci_name(pdev)); c->pdev = pdev; - c->device = pdev->dev; + c->device.parent = get_device(&pdev->dev); /* Cards that fall apart if you hit them with large I/O loads... */ if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { @@ -432,16 +338,48 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, } if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { + /* + * Expose the ship behind i960 for initialization, or it will + * failed + */ + i960 = + pci_find_slot(c->pdev->bus->number, + PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); + + if (i960) + pci_write_config_word(i960, 0x42, 0); + c->promise = 1; - printk(KERN_INFO "%s: Promise workarounds activated.\n", - c->name); + c->limit_sectors = 1; } + if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT) + c->adaptec = 1; + /* Cards that go bananas if you quiesce them before you reset them. */ if (pdev->vendor == PCI_VENDOR_ID_DPT) { c->no_quiesce = 1; if (pdev->device == 0xa511) c->raptor = 1; + + if (pdev->subsystem_device == 0xc05a) { + c->limit_sectors = 1; + printk(KERN_INFO + "%s: limit sectors per request to %d\n", c->name, + I2O_MAX_SECTORS_LIMITED); + } +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if (sizeof(dma_addr_t) > 4) { + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)) + printk(KERN_INFO "%s: 64-bit DMA unavailable\n", + c->name); + else { + c->pae_support = 1; + printk(KERN_INFO "%s: using 64-bit DMA\n", + c->name); + } + } +#endif } if ((rc = i2o_pci_alloc(c))) { @@ -459,6 +397,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, if ((rc = i2o_iop_add(c))) goto uninstall; + get_device(&c->device); + + if (i960) + pci_write_config_word(i960, 0x42, 0x03ff); + return 0; uninstall: @@ -469,6 +412,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, free_controller: i2o_iop_free(c); + put_device(c->device.parent); disable: pci_disable_device(pdev); @@ -492,15 +436,17 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev) i2o_pci_irq_disable(c); i2o_pci_free(c); + pci_disable_device(pdev); + printk(KERN_INFO "%s: Controller removed.\n", c->name); - i2o_iop_free(c); - pci_disable_device(pdev); + put_device(c->device.parent); + put_device(&c->device); }; /* PCI driver for I2O controller */ static struct pci_driver i2o_pci_driver = { - .name = "I2O controller", + .name = "PCI_I2O", .id_table = i2o_pci_ids, .probe = i2o_pci_probe, .remove = __devexit_p(i2o_pci_remove), @@ -523,6 +469,4 @@ void __exit i2o_pci_exit(void) { pci_unregister_driver(&i2o_pci_driver); }; - -EXPORT_SYMBOL(i2o_dma_realloc); MODULE_DEVICE_TABLE(pci, i2o_pci_ids); |