diff -Nur linux-2.4.20.org/drivers/scsi/i2odef.h linux-2.4.20/drivers/scsi/i2odef.h --- linux-2.4.20.org/drivers/scsi/i2odef.h Wed Nov 5 08:47:58 2003 +++ linux-2.4.20/drivers/scsi/i2odef.h Wed Oct 16 00:00:00 2002 @@ -1,1102 +1,1119 @@ - -#if !defined(_I2ODEF_H_) - -#define _I2ODEF_H - -#if !defined(_I2OTYPES_) - -#define _I2OTYPES_ - -/* - * Pragma macros. These are to assure appropriate alignment between - * host/IOP as defined by the I2O Specification. Each one of the shared - * header files includes these macros. - */ - -#define PRAGMA_ALIGN_PUSH \ -#pragma align 4 -#define PRAGMA_ALIGN_POP \ -#pragma align 0 -#define PRAGMA_PACK_PUSH \ -#pragma pack 1 -#define PRAGMA_PACK_POP \ -#pragma pack 0 - -/* Setup the basics */ - -typedef char S8; -typedef short S16; - -typedef unsigned char U8; -typedef unsigned short U16; - -//typedef unsigned int U32; -//typedef int S32; -typedef unsigned long U32; -typedef long S32; - -/* Bitfields */ - -typedef U32 BF; - - -/* VOID */ - -#ifndef __VOID -typedef void VOID; -#define __VOID -#endif - - -/* Boolean */ - -#ifndef __BOOL -#define __BOOL - -#ifdef FALSE -#undef FALSE -#undef TRUE -#endif - -typedef enum - { - FALSE = 0, - TRUE = 1 - } BOOL; -#endif - -/**************************************************************************/ - -/* 64 bit defines */ - -typedef struct _S64 { - U32 LowPart; - S32 HighPart; -} S64; - -typedef struct _U64 { - U32 LowPart; - U32 HighPart; -} U64; - -/* Pointer to Basics */ - -typedef VOID *PVOID; -typedef S8 *PS8; -typedef S16 *PS16; -typedef S32 *PS32; -typedef S64 *PS64; - -/* Pointer to Unsigned Basics */ - -typedef U8 *PU8; -typedef U16 *PU16; -typedef U32 *PU32; -typedef U64 *PU64; - -/* misc */ - -typedef S32 I2O_ARG; -typedef U32 I2O_COUNT; -typedef U32 I2O_USECS; -typedef U32 I2O_ADDR32; -typedef U32 I2O_SIZE; - -#endif /* _I2OTYPES_ */ - -/**************************************************************************/ - -/* I2O BSA Block Read Message Control Flags */ - -typedef U16 I2O_BSA_READ_FLAGS; -#define I2O_BSA_RD_FLAG_DONT_RETRY 0x0001 -#define I2O_BSA_RD_FLAG_SOLO 0x0002 -#define I2O_BSA_RD_FLAG_CACHE_READ 0x0004 -#define I2O_BSA_RD_FLAG_READ_PREFETCH 0x0008 -#define I2O_BSA_RD_FLAG_CACHE_DATA 0x0010 - -/* I2O BSA Block Write Message Control Flags */ - -typedef U16 I2O_BSA_WRITE_FLAGS; -#define I2O_BSA_WR_FLAG_DONT_RETRY 0x0001 -#define I2O_BSA_WR_FLAG_SOLO 0x0002 -#define I2O_BSA_WR_FLAG_DONT_CACHE 0x0004 -#define I2O_BSA_WR_FLAG_WRITE_THRU 0x0008 -#define I2O_BSA_WR_FLAG_WRITE_TO 0x0010 - -/****************************************************************************/ - -typedef U32 I2O_INITIATOR_CONTEXT; -typedef U32 I2O_TRANSACTION_CONTEXT; - -typedef U32 I2O_PARAMETER_TID; - -/****************************************************************************/ -/* Message Frame defines and structures */ - -/* Defines for the Version_Status field. */ - -#define I2O_VERSION_10 0x00 -#define I2O_VERSION_11 0x01 - -#define I2O_VERSION_OFFSET_NUMBER_MASK 0x07 -#define I2O_VERSION_OFFSET_SGL_TRL_OFFSET_MASK 0xF0 - -/* Defines for the Message Flags Field. */ -/* Please Note the the FAIL bit is only set in the Transport Fail Message. */ -#define I2O_MESSAGE_FLAGS_STATIC 0x01 -#define I2O_MESSAGE_FLAGS_64BIT_CONTEXT 0x02 -#define I2O_MESSAGE_FLAGS_MULTIPLE 0x10 -#define I2O_MESSAGE_FLAGS_FAIL 0x20 -#define I2O_MESSAGE_FLAGS_LAST 0x40 -#define I2O_MESSAGE_FLAGS_REPLY 0x80 - -/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */ - -#define I2O_REPLY_STATUS_SUCCESS 0x00 -#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 -#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 -#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 -#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 -#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 -#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 -#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 -#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 -#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A -#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B -#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 - -/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes. */ - -#define I2O_DETAIL_STATUS_SUCCESS 0x0000 -#define I2O_DETAIL_STATUS_BAD_KEY 0x0002 -#define I2O_DETAIL_STATUS_TCL_ERROR 0x0003 -#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0004 -#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0005 -#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0006 -#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0007 -#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0009 -#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A -#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x000B -#define I2O_DETAIL_STATUS_DEVICE_RESET 0x000C -#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x000D -#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000E -#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000F -#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x0010 -#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x0011 -#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x0012 -#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x0013 -#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0014 -#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0015 -#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0016 -#define I2O_DETAIL_STATUS_TIMEOUT 0x0017 -#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0018 -#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0019 -#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A -#define I2O_DEATIL_STATUS_DEVICE_BUSY 0x001B -#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x001C - -/* Common I2O Field sizes */ - -#define I2O_TID_SZ 12 -#define I2O_FUNCTION_SZ 8 -#define I2O_UNIT_ID_SZ 16 -#define I2O_SEGMENT_NUMBER_SZ 12 - -#define I2O_IOP_ID_SZ 12 -#define I2O_GROUP_ID_SZ 16 -#define I2O_IOP_STATE_SZ 8 -#define I2O_MESSENGER_TYPE_SZ 8 - -#define I2O_CLASS_ID_SZ 12 -#define I2O_CLASS_ORGANIZATION_ID_SZ 16 - -#define I2O_4BIT_VERSION_SZ 4 -#define I2O_8BIT_FLAGS_SZ 8 -#define I2O_COMMON_LENGTH_FIELD_SZ 16 - - -#define I2O_DEVID_DESCRIPTION_SZ 16 -#define I2O_DEVID_VENDOR_INFO_SZ 16 -#define I2O_DEVID_PRODUCT_INFO_SZ 16 -#define I2O_DEVID_REV_LEVEL_SZ 8 -#define I2O_MODULE_NAME_SZ 24 - -#define I2O_BIOS_INFO_SZ 8 - -#define I2O_RESERVED_4BITS 4 -#define I2O_RESERVED_8BITS 8 -#define I2O_RESERVED_12BITS 12 -#define I2O_RESERVED_16BITS 16 -#define I2O_RESERVED_20BITS 20 -#define I2O_RESERVED_24BITS 24 -#define I2O_RESERVED_28BITS 28 - -/****************************************************************************/ - -/* Common functions accross all classes. */ - -#define I2O_PRIVATE_MESSAGE 0xFF - -/****************************************************************************/ -/* Class ID and Code Assignments */ - - -#define I2O_CLASS_VERSION_10 0x00 -#define I2O_CLASS_VERSION_11 0x01 - -/* Class Code Names: Table 6-1 Class Code Assignments. */ -#define I2O_CLASS_EXECUTIVE 0x000 -#define I2O_CLASS_DDM 0x001 -#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 -#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011 -#define I2O_CLASS_LAN 0x020 -#define I2O_CLASS_WAN 0x030 -#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040 -#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041 -#define I2O_CLASS_SCSI_PERIPHERAL 0x051 -#define I2O_CLASS_ATE_PORT 0x060 -#define I2O_CLASS_ATE_PERIPHERAL 0x061 -#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 -#define I2O_CLASS_FLOPPY_DEVICE 0x071 -#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 -/* Class Codes 0x090 - 0x09f are reserved for Peer-to-Peer classes */ -#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff - -#define I2O_SUBCLASS_i960 0x001 -#define I2O_SUBCLASS_HDM 0x020 -#define I2O_SUBCLASS_ISM 0x021 - - -/*********************************************************************/ - -#define I2O_MAX_SERIAL_NUMBER_SZ 256 - -/****************************************************************************/ - -/* I2O Message Frame common for all messages */ - -typedef struct _I2O_MESSAGE_FRAME { - U8 VersionOffset; - U8 MsgFlags; - U16 MessageSize; - BF TargetAddress:I2O_TID_SZ; - BF InitiatorAddress:I2O_TID_SZ; - BF Function:I2O_FUNCTION_SZ; - I2O_INITIATOR_CONTEXT InitiatorContext; -} I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME; - - -/****************************************************************************/ - -/* I2O Successful Single Transaction Reply Message Frame structure. */ - -typedef struct _I2O_SINGLE_REPLY_MESSAGE_FRAME { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - U16 DetailedStatusCode; - U8 reserved; - U8 ReqStatus; -/* ReplyPayload */ -} I2O_SINGLE_REPLY_MESSAGE_FRAME, *PI2O_SINGLE_REPLY_MESSAGE_FRAME; - - -/****************************************************************************/ - -/* I2O Private Message Frame structure. */ -typedef struct _I2O_PRIVATE_MESSAGE_FRAME { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - U16 XFunctionCode; - U16 OrganizationID; -/* PrivatePayload[] */ -} I2O_PRIVATE_MESSAGE_FRAME, *PI2O_PRIVATE_MESSAGE_FRAME; - -/****************************************************************************/ - -/* - Random Block Storage Class specific functions - - Although the names are block storage class specific, the values - assigned are common with other classes when applicable. -*/ - -#define I2O_BSA_BLOCK_READ 0x30 -#define I2O_BSA_BLOCK_REASSIGN 0x71 -#define I2O_BSA_BLOCK_WRITE 0x31 -#define I2O_BSA_BLOCK_WRITE_VERIFY 0x33 -#define I2O_BSA_CACHE_FLUSH 0x37 -#define I2O_BSA_DEVICE_RESET 0x27 -#define I2O_BSA_MEDIA_EJECT 0x43 -#define I2O_BSA_MEDIA_FORMAT 0x45 -#define I2O_BSA_MEDIA_LOCK 0x49 -#define I2O_BSA_MEDIA_MOUNT 0x41 -#define I2O_BSA_MEDIA_UNLOCK 0x4B -#define I2O_BSA_MEDIA_VERIFY 0x35 -#define I2O_BSA_POWER_MANAGEMENT 0x70 -#define I2O_BSA_STATUS_CHECK 0x25 - -/****************************************************************************/ - -/* Memory Addressing structures and defines. */ - -/* SglFlags defines. */ - -#define I2O_SGL_FLAGS_LAST_ELEMENT 0x80 -#define I2O_SGL_FLAGS_END_OF_BUFFER 0x40 - -#define I2O_SGL_FLAGS_IGNORE_ELEMENT 0x00 -#define I2O_SGL_FLAGS_TRANSPORT_ELEMENT 0x04 -#define I2O_SGL_FLAGS_BIT_BUCKET_ELEMENT 0x08 -#define I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT 0x0C -#define I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT 0x10 -#define I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT 0x20 -#define I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT 0x30 -#define I2O_SGL_FLAGS_LONG_TRANSACTION_ELEMENT 0x40 -#define I2O_SGL_FLAGS_SHORT_TRANSACTION_ELEMENT 0x70 -#define I2O_SGL_FLAGS_SGL_ATTRIBUTES_ELEMENT 0x7C - -#define I2O_SGL_FLAGS_BC0 0x01 -#define I2O_SGL_FLAGS_BC1 0x02 -#define I2O_SGL_FLAGS_DIR 0x04 -#define I2O_SGL_FLAGS_LOCAL_ADDRESS 0x08 - -#define I2O_SGL_FLAGS_CONTEXT_COUNT_MASK 0x03 -#define I2O_SGL_FLAGS_ADDRESS_MODE_MASK 0x3C -#define I2O_SGL_FLAGS_NO_CONTEXT 0x00 - -/* 32 Bit Context Field defines */ - -#define I2O_SGL_FLAGS_CONTEXT32_NULL 0x00 -#define I2O_SGL_FLAGS_CONTEXT32_U32 0x01 -#define I2O_SGL_FLAGS_CONTEXT32_U64 0x02 -#define I2O_SGL_FLAGS_CONTEXT32_U96 0x03 - -#define I2O_SGL_FLAGS_CONTEXT32_NULL_SZ 0x00 -#define I2O_SGL_FLAGS_CONTEXT32_U32_SZ 0x04 -#define I2O_SGL_FLAGS_CONTEXT32_U64_SZ 0x08 -#define I2O_SGL_FLAGS_CONTEXT32_U96_SZ 0x0C - -/* 64 Bit Context Field defines */ - -#define I2O_SGL_FLAGS_CONTEXT64_NULL 0x00 -#define I2O_SGL_FLAGS_CONTEXT64_U64 0x01 -#define I2O_SGL_FLAGS_CONTEXT64_U128 0x02 -#define I2O_SGL_FLAGS_CONTEXT64_U192 0x03 - -#define I2O_SGL_FLAGS_CONTEXT64_NULL_SZ 0x00 -#define I2O_SGL_FLAGS_CONTEXT64_U64_SZ 0x08 -#define I2O_SGL_FLAGS_CONTEXT64_U128_SZ 0x10 -#define I2O_SGL_FLAGS_CONTEXT64_U192_SZ 0x18 - -/* SGL Attribute Element defines */ - -#define I2O_SGL_ATTRIBUTE_FLAGS_BIT_BUCKET_HINT 0x0400 -#define I2O_SGL_ATTRIBUTE_FLAGS_IMMEDIATE_DATA_HINT 0x0200 -#define I2O_SGL_ATTRIBUTE_FLAGS_LOCAL_ADDRESS_HINT 0x0100 -#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_TRANSACTION 0x0000 -#define I2O_SGL_ATTRIBUTE_FLAGS_64BIT_TRANSACTION 0x0004 -#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_LOCAL_ADDRESS 0x0000 - -/* SG Size defines */ - -#define I2O_SG_COUNT_SZ 24 -#define I2O_SG_FLAGS_SZ 8 - -/* Standard Flags and Count fields for SG Elements */ - -typedef struct _I2O_FLAGS_COUNT { - BF Count:I2O_SG_COUNT_SZ; - BF Flags:I2O_SG_FLAGS_SZ; -} I2O_FLAGS_COUNT, *PI2O_FLAGS_COUNT; - -/* Bit Bucket Element */ -typedef struct _I2O_SGE_BIT_BUCKET_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 BufferContext; -} I2O_SGE_BIT_BUCKET_ELEMENT, *PI2O_SGE_BIT_BUCKET_ELEMENT; - -/* Chain Addressing Scatter-Gather Element */ - -typedef struct _I2O_SGE_CHAIN_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 PhysicalAddress; -} I2O_SGE_CHAIN_ELEMENT, *PI2O_SGE_CHAIN_ELEMENT; - -/* Chain Addressing with Context Scatter-Gather Element */ - -typedef struct _I2O_SGE_CHAIN_CONTEXT_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 Context[1]; - U32 PhysicalAddress; -} I2O_SGE_CHAIN_CONTEXT_ELEMENT, *PI2O_SGE_CHAIN_CONTEXT_ELEMENT; - -/* Ignore Scatter-Gather Element */ - -typedef struct _I2O_SGE_IGNORE_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; -} I2O_SGE_IGNORE_ELEMENT, *PI2O_SGE_IGNORE_ELEMENT; - -/* Immediate Data Element */ - -typedef struct _I2O_SGE_IMMEDIATE_DATA_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; -} I2O_SGE_IMMEDIATE_DATA_ELEMENT, *PI2O_SGE_IMMEDIATE_DATA_ELEMENT; - -/* Immediate Data with Context Element */ - -typedef struct _I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 BufferContext; -} I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT, *PI2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT; - -/* Long Transaction Parameters Element */ - -typedef struct _I2O_SGE_LONG_TRANSACTION_ELEMENT { - BF LongElementLength:I2O_SG_COUNT_SZ; - BF Flags:I2O_SG_FLAGS_SZ; - U32 BufferContext; -} I2O_SGE_LONG_TRANSACTION_ELEMENT, *PI2O_SGE_LONG_TRANSACTION_ELEMENT; - -/* Page List Scatter-Gather Element */ - -typedef struct _I2O_SGE_PAGE_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 PhysicalAddress[1]; -} I2O_SGE_PAGE_ELEMENT , *PI2O_SGE_PAGE_ELEMENT ; - -/* Page List with Context Scatter-Gather Element */ - -typedef struct _I2O_SGE_PAGE_CONTEXT_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 BufferContext[1]; - U32 PhysicalAddress[1]; -} I2O_SGE_PAGE_CONTEXT_ELEMENT, *PI2O_SGE_PAGE_CONTEXT_ELEMENT; - -/* SGL Attribute Element */ - -typedef struct _I2O_SGE_SGL_ATTRIBUTES_ELEMENT { - U16 SglAttributeFlags; - U8 ElementLength; - U8 Flags; - U32 PageFrameSize; -} I2O_SGE_SGL_ATTRIBUTES_ELEMENT, *PI2O_SGE_SGL_ATTRIBUTES_ELEMENT; - -/* Short Transaction Parameters Element */ - -typedef struct _I2O_SGE_SHORT_TRANSACTION_ELEMENT { - U16 ClassFields; - U8 ElementLength; - U8 Flags; - U32 BufferContext; -} I2O_SGE_SHORT_TRANSACTION_ELEMENT, *PI2O_SGE_SHORT_TRANSACTION_ELEMENT; - -/* Simple Addressing Scatter-Gather Element */ - -typedef struct _I2O_SGE_SIMPLE_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 PhysicalAddress; -} I2O_SGE_SIMPLE_ELEMENT, *PI2O_SGE_SIMPLE_ELEMENT; - -/* Simple Addressing with Context Scatter-Gather Element */ - -typedef struct _I2O_SGE_SIMPLE_CONTEXT_ELEMENT { - I2O_FLAGS_COUNT FlagsCount; - U32 BufferContext[1]; - U32 PhysicalAddress; -} I2O_SGE_SIMPLE_CONTEXT_ELEMENT, *PI2O_SGE_SIMPLE_CONTEXT_ELEMENT; - -/* Transport Detail Element */ - -typedef struct _I2O_SGE_TRANSPORT_ELEMENT { - BF LongElementLength:I2O_SG_COUNT_SZ; - BF Flags:I2O_SG_FLAGS_SZ; -} I2O_SGE_TRANSPORT_ELEMENT, *PI2O_SGE_TRANSPORT_ELEMENT; - - -typedef struct _I2O_SG_ELEMENT { - union { - /* Bit Bucket Element */ - I2O_SGE_BIT_BUCKET_ELEMENT BitBucket; - - /* Chain Addressing Element */ - I2O_SGE_CHAIN_ELEMENT Chain; - - /* Chain Addressing with Context Element */ - I2O_SGE_CHAIN_CONTEXT_ELEMENT ChainContext; - - /* Ignore Scatter-Gather Element */ - I2O_SGE_IGNORE_ELEMENT Ignore; - - /* Immediate Data Element */ - I2O_SGE_IMMEDIATE_DATA_ELEMENT ImmediateData; - - /* Immediate Data with Context Element */ - I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT ImmediateDataContext; - - /* Long Transaction Parameters Element */ - I2O_SGE_LONG_TRANSACTION_ELEMENT LongTransaction; - - /* Page List Element */ - I2O_SGE_PAGE_ELEMENT Page; - - /* Page List with Context Element */ - I2O_SGE_PAGE_CONTEXT_ELEMENT PageContext; - - /* SGL Attribute Element */ - I2O_SGE_SGL_ATTRIBUTES_ELEMENT SGLAttribute; - - /* Short Transaction Parameters Element */ - I2O_SGE_SHORT_TRANSACTION_ELEMENT ShortTransaction; - - /* Simple Addressing Element */ - I2O_SGE_SIMPLE_ELEMENT Simple[1]; - - /* Simple Addressing with Context Element */ - I2O_SGE_SIMPLE_CONTEXT_ELEMENT SimpleContext[1]; - - /* Transport Detail Element */ - I2O_SGE_TRANSPORT_ELEMENT Transport; - }u; -} I2O_SG_ELEMENT, *PI2O_SG_ELEMENT; - -/* I2O BSA Block Read Message Frame */ -typedef struct _I2O_BSA_READ_MESSAGE { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - I2O_BSA_READ_FLAGS ControlFlags; - U8 TimeMultiplier; - U8 FetchAhead; - U32 TransferByteCount; - U64 LogicalByteAddress; - I2O_SG_ELEMENT SGL; -} I2O_BSA_READ_MESSAGE, *PI2O_BSA_READ_MESSAGE; - - -/***********************************************************************/ - -/* Class ID Block */ - -typedef struct _I2O_CLASS_ID { - BF Class:I2O_CLASS_ID_SZ; - BF Version:I2O_4BIT_VERSION_SZ; - BF OrganizationID:I2O_CLASS_ORGANIZATION_ID_SZ; -} I2O_CLASS_ID, *PI2O_CLASS_ID; - - -/****************************************************************************/ -/* Logical Configuration Table */ -/****************************************************************************/ - -/* I2O Logical Configuration Table structures. */ - -#define I2O_IDENTITY_TAG_SZ 8 - -/* I2O Logical Configuration Table Device Flags */ - -#define I2O_LCT_DEVICE_FLAGS_CONF_DIALOG_REQUEST 0x01 -#define I2O_LCT_DEVICE_FLAGS_MORE_THAN_1_USER 0x02 -#define I2O_LCT_DEVICE_FLAGS_PEER_SERVICE_DISABLED 0x10 -#define I2O_LCT_DEVICE_FLAGS_MANAGEMENT_SERVICE_DISABLED 0x20 - -/* LCT Entry Block */ - -typedef struct _I2O_LCT_ENTRY { - BF TableEntrySize:I2O_COMMON_LENGTH_FIELD_SZ; - BF LocalTID:I2O_TID_SZ; - BF reserved:I2O_4BIT_VERSION_SZ; - U32 ChangeIndicator; - U32 DeviceFlags; - I2O_CLASS_ID ClassID; - U32 SubClassInfo; - BF UserTID:I2O_TID_SZ; - BF ParentTID:I2O_TID_SZ; - BF BiosInfo:I2O_BIOS_INFO_SZ; - U8 IdentityTag[I2O_IDENTITY_TAG_SZ]; - U32 EventCapabilities; -} I2O_LCT_ENTRY, *PI2O_LCT_ENTRY; - -/* I2O Logical Configuration Table structure. */ -typedef struct _I2O_LCT { - BF TableSize:I2O_COMMON_LENGTH_FIELD_SZ; - BF BootDeviceTID:I2O_TID_SZ; - BF LctVer:I2O_4BIT_VERSION_SZ; - U32 IopFlags; - U32 CurrentChangeIndicator; - I2O_LCT_ENTRY LCTEntry[1]; -} I2O_LCT, *PI2O_LCT; - - -/****************************************************************************/ - -/* I2O Executive Function Codes. */ - -#define I2O_EXEC_ADAPTER_ASSIGN 0xB3 -#define I2O_EXEC_ADAPTER_READ 0xB2 -#define I2O_EXEC_ADAPTER_RELEASE 0xB5 -#define I2O_EXEC_BIOS_INFO_SET 0xA5 -#define I2O_EXEC_BOOT_DEVICE_SET 0xA7 -#define I2O_EXEC_CONFIG_VALIDATE 0xBB -#define I2O_EXEC_CONN_SETUP 0xCA -#define I2O_EXEC_DDM_DESTROY 0xB1 -#define I2O_EXEC_DDM_ENABLE 0xD5 -#define I2O_EXEC_DDM_QUIESCE 0xC7 -#define I2O_EXEC_DDM_RESET 0xD9 -#define I2O_EXEC_DDM_SUSPEND 0xAF -#define I2O_EXEC_DEVICE_ASSIGN 0xB7 -#define I2O_EXEC_DEVICE_RELEASE 0xB9 -#define I2O_EXEC_HRT_GET 0xA8 -#define I2O_EXEC_IOP_CLEAR 0xBE -#define I2O_EXEC_IOP_CONNECT 0xC9 -#define I2O_EXEC_IOP_RESET 0xBD -#define I2O_EXEC_LCT_NOTIFY 0xA2 -#define I2O_EXEC_OUTBOUND_INIT 0xA1 -#define I2O_EXEC_PATH_ENABLE 0xD3 -#define I2O_EXEC_PATH_QUIESCE 0xC5 -#define I2O_EXEC_PATH_RESET 0xD7 -#define I2O_EXEC_STATIC_MF_CREATE 0xDD -#define I2O_EXEC_STATIC_MF_RELEASE 0xDF -#define I2O_EXEC_STATUS_GET 0xA0 -#define I2O_EXEC_SW_DOWNLOAD 0xA9 -#define I2O_EXEC_SW_UPLOAD 0xAB -#define I2O_EXEC_SW_REMOVE 0xAD -#define I2O_EXEC_SYS_ENABLE 0xD1 -#define I2O_EXEC_SYS_MODIFY 0xC1 -#define I2O_EXEC_SYS_QUIESCE 0xC3 -#define I2O_EXEC_SYS_TAB_SET 0xA3 - - -/* I2O Get Status State values */ - -#define I2O_IOP_STATE_INITIALIZING 0x01 -#define I2O_IOP_STATE_RESET 0x02 -#define I2O_IOP_STATE_HOLD 0x04 -#define I2O_IOP_STATE_READY 0x05 -#define I2O_IOP_STATE_OPERATIONAL 0x08 -#define I2O_IOP_STATE_FAILED 0x10 -#define I2O_IOP_STATE_FAULTED 0x11 - - -#define I2O_EXEC_STATUS_GET_RESERVED_SZ 16 - -/* ExecStatusGet Function Message Frame structure. */ - -typedef struct _I2O_EXEC_STATUS_GET_MESSAGE { - U8 VersionOffset; - U8 MsgFlags; - U16 MessageSize; - BF TargetAddress:I2O_TID_SZ; - BF InitiatorAddress:I2O_TID_SZ; - BF Function:I2O_FUNCTION_SZ; - U8 Reserved[I2O_EXEC_STATUS_GET_RESERVED_SZ]; - U32 ReplyBufferAddressLow; - U32 ReplyBufferAddressHigh; - U32 ReplyBufferLength; -} I2O_EXEC_STATUS_GET_MESSAGE, *PI2O_EXEC_STATUS_GET_MESSAGE; - - -#define I2O_IOP_STATUS_PROD_ID_STR_SZ 24 -#define I2O_EXEC_STATUS_GET_REPLY_RESERVED_SZ 6 - -/* ExecStatusGet reply Structure */ - -#define I2O_IOP_CAP_CONTEXT_32_ONLY 0x00000000 -#define I2O_IOP_CAP_CONTEXT_64_ONLY 0x00000001 -#define I2O_IOP_CAP_CONTEXT_32_64_NOT_CURRENTLY 0x00000002 -#define I2O_IOP_CAP_CONTEXT_32_64_CURRENTLY 0x00000003 -#define I2O_IOP_CAP_CURRENT_CONTEXT_NOT_CONFIG 0x00000000 -#define I2O_IOP_CAP_CURRENT_CONTEXT_32_ONLY 0x00000004 -#define I2O_IOP_CAP_CURRENT_CONTEXT_64_ONLY 0x00000008 -#define I2O_IOP_CAP_CURRENT_CONTEXT_32_64 0x0000000C -#define I2O_IOP_CAP_INBOUND_PEER_SUPPORT 0x00000010 -#define I2O_IOP_CAP_OUTBOUND_PEER_SUPPORT 0x00000020 -#define I2O_IOP_CAP_PEER_TO_PEER_SUPPORT 0x00000040 - -typedef struct _I2O_EXEC_STATUS_GET_REPLY { - U16 OrganizationID; - U16 reserved; - BF IOP_ID:I2O_IOP_ID_SZ; - BF reserved1:I2O_RESERVED_4BITS; - BF HostUnitID:I2O_UNIT_ID_SZ; - BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; - BF I2oVersion:I2O_4BIT_VERSION_SZ; - BF IopState:I2O_IOP_STATE_SZ; - BF MessengerType:I2O_MESSENGER_TYPE_SZ; - U16 InboundMFrameSize; - U8 InitCode; - U8 reserved2; - U32 MaxInboundMFrames; - U32 CurrentInboundMFrames; - U32 MaxOutboundMFrames; - U8 ProductIDString[I2O_IOP_STATUS_PROD_ID_STR_SZ]; - U32 ExpectedLCTSize; - U32 IopCapabilities; - U32 DesiredPrivateMemSize; - U32 CurrentPrivateMemSize; - U32 CurrentPrivateMemBase; - U32 DesiredPrivateIOSize; - U32 CurrentPrivateIOSize; - U32 CurrentPrivateIOBase; - U8 reserved3[3]; - U8 SyncByte; -} I2O_EXEC_STATUS_GET_REPLY, *PI2O_EXEC_STATUS_GET_REPLY; - - -/***************************************************************************/ - -/* ExecSysTabSet (System Table) Function Message Frame structure. */ - -#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_IOP 0x000 -#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST 0x001 -#define I2O_EXEC_SYS_TAB_IOP_ID_UNKNOWN_IOP 0xFFF -#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT 0x0000 -#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_UNKNOWN_UNIT 0xffff -#define I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT 0x000 -#define I2O_EXEC_SYS_TAB_SEG_NUMBER_UNKNOWN_SEGMENT 0xfff - -typedef struct _I2O_EXEC_SYS_TAB_SET_MESSAGE { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - BF IOP_ID:I2O_IOP_ID_SZ; - BF reserved:I2O_RESERVED_4BITS; - BF HostUnitID:I2O_UNIT_ID_SZ; - BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; - BF reserved2:I2O_RESERVED_20BITS; - I2O_SG_ELEMENT SGL; -} I2O_EXEC_SYS_TAB_SET_MESSAGE, *PI2O_EXEC_SYS_TAB_SET_MESSAGE; - - -/****************************************************************************/ - -/* Operation Function Numbers */ - -#define I2O_PARAMS_OPERATION_FIELD_GET 0x0001 -#define I2O_PARAMS_OPERATION_LIST_GET 0x0002 -#define I2O_PARAMS_OPERATION_MORE_GET 0x0003 -#define I2O_PARAMS_OPERATION_SIZE_GET 0x0004 -#define I2O_PARAMS_OPERATION_TABLE_GET 0x0005 -#define I2O_PARAMS_OPERATION_FIELD_SET 0x0006 -#define I2O_PARAMS_OPERATION_LIST_SET 0x0007 -#define I2O_PARAMS_OPERATION_ROW_ADD 0x0008 -#define I2O_PARAMS_OPERATION_ROW_DELETE 0x0009 -#define I2O_PARAMS_OPERATION_TABLE_CLEAR 0x000A - -/* Operations List Header */ - -typedef struct _I2O_PARAM_OPERATIONS_LIST_HEADER { - U16 OperationCount; - U16 Reserved; -} I2O_PARAM_OPERATIONS_LIST_HEADER, *PI2O_PARAM_OPERATIONS_LIST_HEADER; - -/* Results List Header */ - -typedef struct _I2O_PARAM_RESULTS_LIST_HEADER { - U16 ResultCount; - U16 Reserved; -} I2O_PARAM_RESULTS_LIST_HEADER, *PI2O_PARAM_RESULTS_LIST_HEADER; - -/* Read Operation Result Block Template Structure */ - -typedef struct _I2O_PARAM_READ_OPERATION_RESULT { - U16 BlockSize; - U8 BlockStatus; - U8 ErrorInfoSize; - /* Operations Results */ - /* Pad (if any) */ - /* ErrorInformation (if any) */ -} I2O_PARAM_READ_OPERATION_RESULT, *PI2O_PARAM_READ_OPERATION_RESULT; - -/* Operation Template for Specific Fields */ - -typedef struct _I2O_PARAM_OPERATION_SPECIFIC_TEMPLATE { - U16 Operation; - U16 GroupNumber; - U16 FieldCount; - U16 FieldIdx[1]; - /* Pad (if any) */ -} I2O_PARAM_OPERATION_SPECIFIC_TEMPLATE, *PI2O_PARAM_OPERATION_SPECIFIC_TEMPLATE; - -/* Operation Template for All Fields */ - -typedef struct _I2O_PARAM_OPERATION_ALL_TEMPLATE { - U16 Operation; - U16 GroupNumber; - U16 FieldCount; - /* Pad (if any) */ -} I2O_PARAM_OPERATION_ALL_TEMPLATE, *PI2O_PARAM_OPERATION_ALL_TEMPLATE; - -/****************************************************************************/ - -/* Utility Message class functions. */ - -#define I2O_UTIL_NOP 0x00 -#define I2O_UTIL_ABORT 0x01 -#define I2O_UTIL_CLAIM 0x09 -#define I2O_UTIL_CLAIM_RELEASE 0x0B -#define I2O_UTIL_CONFIG_DIALOG 0x10 -#define I2O_UTIL_DEVICE_RESERVE 0x0D -#define I2O_UTIL_DEVICE_RELEASE 0x0F -#define I2O_UTIL_EVENT_ACKNOWLEDGE 0x14 -#define I2O_UTIL_EVENT_REGISTER 0x13 -#define I2O_UTIL_LOCK 0x17 -#define I2O_UTIL_LOCK_RELEASE 0x19 -#define I2O_UTIL_PARAMS_GET 0x06 -#define I2O_UTIL_PARAMS_SET 0x05 -#define I2O_UTIL_REPLY_FAULT_NOTIFY 0x15 - -/****************************************************************************/ - -/* UtilNOP Function Message Frame structure. */ - -typedef struct _I2O_UTIL_NOP_MESSAGE { - I2O_MESSAGE_FRAME StdMessageFrame; -} I2O_UTIL_NOP_MESSAGE, *PI2O_UTIL_NOP_MESSAGE; - - -/*************************************************************************/ - -/* UtilParamsGet Message Frame structure. */ - -typedef struct _I2O_UTIL_PARAMS_GET_MESSAGE { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - U32 OperationFlags; - I2O_SG_ELEMENT SGL; -} I2O_UTIL_PARAMS_GET_MESSAGE, *PI2O_UTIL_PARAMS_GET_MESSAGE; - - -/****************************************************************************/ -/* GROUP Parameter Groups */ -/****************************************************************************/ - -/* GROUP Configuration and Operating Structures and Defines */ - -/* Groups Numbers */ - -#define I2O_UTIL_PARAMS_DESCRIPTOR_GROUP_NO 0xF000 -#define I2O_UTIL_PHYSICAL_DEVICE_TABLE_GROUP_NO 0xF001 -#define I2O_UTIL_CLAIMED_TABLE_GROUP_NO 0xF002 -#define I2O_UTIL_USER_TABLE_GROUP_NO 0xF003 -#define I2O_UTIL_PRIVATE_MESSAGE_EXTENSIONS_GROUP_NO 0xF005 -#define I2O_UTIL_AUTHORIZED_USER_TABLE_GROUP_NO 0xF006 -#define I2O_UTIL_DEVICE_IDENTITY_GROUP_NO 0xF100 -#define I2O_UTIL_DDM_IDENTITY_GROUP_NO 0xF101 -#define I2O_UTIL_USER_INFORMATION_GROUP_NO 0xF102 -#define I2O_UTIL_SGL_OPERATING_LIMITS_GROUP_NO 0xF103 -#define I2O_UTIL_SENSORS_GROUP_NO 0xF200 - -/* UTIL Group F000h - GROUP DESCRIPTORS Parameter Group */ - -#define I2O_UTIL_GROUP_PROPERTIES_GROUP_TABLE 0x01 -#define I2O_UTIL_GROUP_PROPERTIES_ROW_ADDITION 0x02 -#define I2O_UTIL_GROUP_PROPERTIES_ROW_DELETION 0x04 -#define I2O_UTIL_GROUP_PROPERTIES_CLEAR_OPERATION 0x08 - -/* UTIL Group F100h - Device Identity Parameter Group */ - -typedef struct _I2O_UTIL_DEVICE_IDENTITY_SCALAR { - U32 ClassID; - U16 OwnerTID; - U16 ParentTID; - U8 VendorInfo[I2O_DEVID_VENDOR_INFO_SZ]; - U8 ProductInfo[I2O_DEVID_PRODUCT_INFO_SZ]; - U8 Description[I2O_DEVID_DESCRIPTION_SZ]; - U8 ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ]; - U8 SNFormat; - U8 SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; -} I2O_UTIL_DEVICE_IDENTITY_SCALAR, *PI2O_UTIL_DEVICE_IDENTITY_SCALAR; - -/* UTIL Group F101h - DDM Identity Parameter Group */ - -typedef struct _I2O_UTIL_DDM_IDENTITY_SCALAR { - U16 DdmTID; - U8 ModuleName[I2O_MODULE_NAME_SZ]; - U8 ModuleRevLevel[I2O_DEVID_REV_LEVEL_SZ]; - U8 SNFormat; - U8 SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; -} I2O_UTIL_DDM_IDENTITY_SCALAR, *PI2O_UTIL_DDM_IDENTITY_SCALAR; - -/****************************************************************************/ - -/* Block Storage Parameter Groups */ - -#define I2O_BSA_DEVICE_INFO_GROUP_NO 0x0000 -#define I2O_BSA_OPERATIONAL_CONTROL_GROUP_NO 0x0001 -#define I2O_BSA_POWER_CONTROL_GROUP_NO 0x0002 -#define I2O_BSA_CACHE_CONTROL_GROUP_NO 0x0003 -#define I2O_BSA_MEDIA_INFO_GROUP_NO 0x0004 -#define I2O_BSA_ERROR_LOG_GROUP_NO 0x0005 - -/***************************************************************************/ - -/* I2O Block Storage Reply Message Frame Template */ - -typedef struct _I2O_BSA_REPLY_MESSAGE_FRAME { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - U16 DetailedStatusCode; - U8 RetryCount; - U8 ReqStatus; -/* ReplyPayload */ -} I2O_BSA_REPLY_MESSAGE_FRAME, *PI2O_BSA_REPLY_MESSAGE_FRAME; - -/**************************************************************************/ - -/* Block Storage Group 0000h - Device Information Parameter Group */ - -typedef struct _I2O_BSA_DEVICE_INFO_SCALAR { - U8 DeviceType; - U8 NumberOfPaths; - U16 PowerState; - U32 BlockSize; - U64 DeviceCapacity; - U32 DeviceCapabilitySupport; - U32 DeviceState; -} I2O_BSA_DEVICE_INFO_SCALAR, *PI2O_BSA_DEVICE_INFO_SCALAR; - - -/****************************************************************************/ - - -/* ExecOutboundInit Function Message Frame structure. */ - -typedef struct _I2O_EXEC_OUTBOUND_INIT_MESSAGE { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - U32 HostPageFrameSize; - U8 InitCode; - U8 reserved; - U16 OutboundMFrameSize; - I2O_SG_ELEMENT SGL; -} I2O_EXEC_OUTBOUND_INIT_MESSAGE, *PI2O_EXEC_OUTBOUND_INIT_MESSAGE; - - -#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01 -#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02 -#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03 -#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04 - -#define I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ 3 - - -typedef struct _I2O_EXEC_OUTBOUND_INIT_STATUS { - U8 InitStatus; - U8 reserved[I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ]; -} I2O_EXEC_OUTBOUND_INIT_STATUS, *PI2O_EXEC_OUTBOUND_INIT_STATUS; - - -typedef struct _I2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST { - U32 MFACount; - U32 MFAReleaseCount; - U32 MFAAddress[1]; -} I2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST, *PI2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST; - -/****************************************************************************/ - - -/* ExecSysEnable Function Message Frame structure. */ - -typedef struct _I2O_EXEC_SYS_ENABLE_MESSAGE { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; -} I2O_EXEC_SYS_ENABLE_MESSAGE, *PI2O_EXEC_SYS_ENABLE_MESSAGE; - - -/****************************************************************************/ - -/* ExecLCTNotify Function Message Frame structure. */ - -typedef struct _I2O_EXEC_LCT_NOTIFY_MESSAGE { - I2O_MESSAGE_FRAME StdMessageFrame; - I2O_TRANSACTION_CONTEXT TransactionContext; - U32 ClassIdentifier; - U32 LastReportedChangeIndicator; - I2O_SG_ELEMENT SGL; -} I2O_EXEC_LCT_NOTIFY_MESSAGE, *PI2O_EXEC_LCT_NOTIFY_MESSAGE; - -/****************************************************************************/ - -/* ExecSysTabSet (System Table) Header Reply structure. */ - -#define I2O_SET_SYSTAB_RESERVED_SZ 8 - -typedef struct _I2O_SET_SYSTAB_HEADER { - U8 NumberEntries; - U8 SysTabVersion; - U16 reserved; - U32 CurrentChangeIndicator; - U8 reserved1[I2O_SET_SYSTAB_RESERVED_SZ]; -/* I2O_SYSTAB_ENTRY SysTabEntry[1]; */ -} I2O_SET_SYSTAB_HEADER, *PI2O_SET_SYSTAB_HEADER; - - -#define I2O_RESOURCE_MANAGER_VERSION 0 - -typedef struct _MESSENGER_INFO { - U32 InboundMessagePortAddressLow; - U32 InboundMessagePortAddressHigh; - } I2O_MESSENGER_INFO, *PI2O_MESSENGER_INFO; - -/* ExecSysTabSet IOP Descriptor Entry structure. */ - -typedef struct _I2O_IOP_ENTRY { - U16 OrganizationID; - U16 reserved; - BF IOP_ID:I2O_IOP_ID_SZ; - BF reserved1:I2O_RESERVED_20BITS; - BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; - BF I2oVersion:I2O_4BIT_VERSION_SZ; - BF IopState:I2O_IOP_STATE_SZ; - BF MessengerType:I2O_MESSENGER_TYPE_SZ; - U16 InboundMessageFrameSize; - U16 reserved2; - U32 LastChanged; - U32 IopCapabilities; - I2O_MESSENGER_INFO MessengerInfo; -} I2O_IOP_ENTRY, *PI2O_IOP_ENTRY; - - -/****************************************************************************/ - - -#define I2O_EXEC_IOP_RESET_RESERVED_SZ 16 - -#define I2O_EXEC_IOP_RESET_IN_PROGRESS 0x01 -#define I2O_EXEC_IOP_RESET_REJECTED 0x02 - -#define I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ 3 - -typedef struct _I2O_EXEC_IOP_RESET_STATUS { - U8 ResetStatus; - U8 reserved[I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ]; -} I2O_EXEC_IOP_RESET_STATUS, *PI2O_EXEC_IOP_RESET_STATUS; - - -/* ExecIopReset Function Message Frame structure. */ - -typedef struct _I2O_EXEC_IOP_RESET_MESSAGE { - U8 VersionOffset; - U8 MsgFlags; - U16 MessageSize; - BF TargetAddress:I2O_TID_SZ; - BF InitiatorAddress:I2O_TID_SZ; - BF Function:I2O_FUNCTION_SZ; - U8 Reserved[I2O_EXEC_IOP_RESET_RESERVED_SZ]; - U32 StatusWordLowAddress; - U32 StatusWordHighAddress; -} I2O_EXEC_IOP_RESET_MESSAGE, *PI2O_EXEC_IOP_RESET_MESSAGE; - - -/****************************************************************************/ -/* EXEC Group 0001h - IOP Message Interface Parameter Group */ - -/* InitCode defines */ -#define I2O_MESSAGE_IF_INIT_CODE_NO_OWNER 0x00 -#define I2O_MESSAGE_IF_INIT_CODE_BIOS 0x10 -#define I2O_MESSAGE_IF_INIT_CODE_OEM_BIOS_EXTENSION 0x20 -#define I2O_MESSAGE_IF_INIT_CODE_ROM_BIOS_EXTENSION 0x30 -#define I2O_MESSAGE_IF_INIT_CODE_OS 0x80 - -/****************************************************************************/ - -#endif /* _I2ODEF_H_ */ + +#if !defined(_I2ODEF_H_) + +#define _I2ODEF_H + +#if !defined(_I2OTYPES_) + +#define _I2OTYPES_ + +/* + * Pragma macros. These are to assure appropriate alignment between + * host/IOP as defined by the I2O Specification. Each one of the shared + * header files includes these macros. + */ + +#define PRAGMA_ALIGN_PUSH \ +#pragma align 4 +#define PRAGMA_ALIGN_POP \ +#pragma align 0 +#define PRAGMA_PACK_PUSH \ +#pragma pack 1 +#define PRAGMA_PACK_POP \ +#pragma pack 0 + +/* Setup the basics */ + +typedef char S8; +typedef short S16; + +typedef unsigned char U8; +typedef unsigned short U16; + +//typedef unsigned int U32; +//typedef int S32; +typedef unsigned long U32; +typedef long S32; + +/* Bitfields */ + +typedef U32 BF; + + +/* VOID */ + +#ifndef __VOID +typedef void VOID; +#define __VOID +#endif + + +/* Boolean */ + +#ifndef __BOOL +#define __BOOL + +#ifdef FALSE +#undef FALSE +#undef TRUE +#endif + +typedef enum + { + FALSE = 0, + TRUE = 1 + } BOOL; +#endif + +/**************************************************************************/ + +/* 64 bit defines */ + +typedef struct _S64 { + U32 LowPart; + S32 HighPart; +} S64; + +typedef struct _U64 { + U32 LowPart; + U32 HighPart; +} U64; + +/* Pointer to Basics */ + +typedef VOID *PVOID; +typedef S8 *PS8; +typedef S16 *PS16; +typedef S32 *PS32; +typedef S64 *PS64; + +/* Pointer to Unsigned Basics */ + +typedef U8 *PU8; +typedef U16 *PU16; +typedef U32 *PU32; +typedef U64 *PU64; + +/* misc */ + +typedef S32 I2O_ARG; +typedef U32 I2O_COUNT; +typedef U32 I2O_USECS; +typedef U32 I2O_ADDR32; +typedef U32 I2O_SIZE; + +#endif /* _I2OTYPES_ */ + +/**************************************************************************/ + +/* I2O BSA Block Read Message Control Flags */ + +typedef U16 I2O_BSA_READ_FLAGS; +#define I2O_BSA_RD_FLAG_DONT_RETRY 0x0001 +#define I2O_BSA_RD_FLAG_SOLO 0x0002 +#define I2O_BSA_RD_FLAG_CACHE_READ 0x0004 +#define I2O_BSA_RD_FLAG_READ_PREFETCH 0x0008 +#define I2O_BSA_RD_FLAG_CACHE_DATA 0x0010 + +/* I2O BSA Block Write Message Control Flags */ + +typedef U16 I2O_BSA_WRITE_FLAGS; +#define I2O_BSA_WR_FLAG_DONT_RETRY 0x0001 +#define I2O_BSA_WR_FLAG_SOLO 0x0002 +#define I2O_BSA_WR_FLAG_DONT_CACHE 0x0004 +#define I2O_BSA_WR_FLAG_WRITE_THRU 0x0008 +#define I2O_BSA_WR_FLAG_WRITE_TO 0x0010 + +/****************************************************************************/ + +typedef U32 I2O_INITIATOR_CONTEXT; +typedef U32 I2O_TRANSACTION_CONTEXT; + +typedef U32 I2O_PARAMETER_TID; + +/****************************************************************************/ +/* Message Frame defines and structures */ + +/* Defines for the Version_Status field. */ + +#define I2O_VERSION_10 0x00 +#define I2O_VERSION_11 0x01 + +#define I2O_VERSION_OFFSET_NUMBER_MASK 0x07 +#define I2O_VERSION_OFFSET_SGL_TRL_OFFSET_MASK 0xF0 + +/* Defines for the Message Flags Field. */ +/* Please Note the the FAIL bit is only set in the Transport Fail Message. */ +#define I2O_MESSAGE_FLAGS_STATIC 0x01 +#define I2O_MESSAGE_FLAGS_64BIT_CONTEXT 0x02 +#define I2O_MESSAGE_FLAGS_MULTIPLE 0x10 +#define I2O_MESSAGE_FLAGS_FAIL 0x20 +#define I2O_MESSAGE_FLAGS_LAST 0x40 +#define I2O_MESSAGE_FLAGS_REPLY 0x80 + +/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */ + +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 +#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 +#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 +#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 +#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 +#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 +#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A +#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B +#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 + +/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes. */ + +#define I2O_DETAIL_STATUS_SUCCESS 0x0000 +#define I2O_DETAIL_STATUS_BAD_KEY 0x0002 +#define I2O_DETAIL_STATUS_TCL_ERROR 0x0003 +#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0004 +#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0005 +#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0006 +#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0007 +#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0009 +#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A +#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x000B +#define I2O_DETAIL_STATUS_DEVICE_RESET 0x000C +#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x000D +#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000E +#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000F +#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x0010 +#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x0011 +#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x0012 +#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x0013 +#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0014 +#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0015 +#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0016 +#define I2O_DETAIL_STATUS_TIMEOUT 0x0017 +#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0018 +#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0019 +#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A +#define I2O_DEATIL_STATUS_DEVICE_BUSY 0x001B +#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x001C + +/* Common I2O Field sizes */ + +#define I2O_TID_SZ 12 +#define I2O_FUNCTION_SZ 8 +#define I2O_UNIT_ID_SZ 16 +#define I2O_SEGMENT_NUMBER_SZ 12 + +#define I2O_IOP_ID_SZ 12 +#define I2O_GROUP_ID_SZ 16 +#define I2O_IOP_STATE_SZ 8 +#define I2O_MESSENGER_TYPE_SZ 8 + +#define I2O_CLASS_ID_SZ 12 +#define I2O_CLASS_ORGANIZATION_ID_SZ 16 + +#define I2O_4BIT_VERSION_SZ 4 +#define I2O_8BIT_FLAGS_SZ 8 +#define I2O_COMMON_LENGTH_FIELD_SZ 16 + + +#define I2O_DEVID_DESCRIPTION_SZ 16 +#define I2O_DEVID_VENDOR_INFO_SZ 16 +#define I2O_DEVID_PRODUCT_INFO_SZ 16 +#define I2O_DEVID_REV_LEVEL_SZ 8 +#define I2O_MODULE_NAME_SZ 24 + +#define I2O_BIOS_INFO_SZ 8 + +#define I2O_RESERVED_4BITS 4 +#define I2O_RESERVED_8BITS 8 +#define I2O_RESERVED_12BITS 12 +#define I2O_RESERVED_16BITS 16 +#define I2O_RESERVED_20BITS 20 +#define I2O_RESERVED_24BITS 24 +#define I2O_RESERVED_28BITS 28 + +/****************************************************************************/ + +/* Common functions accross all classes. */ + +#define I2O_PRIVATE_MESSAGE 0xFF + +/****************************************************************************/ +/* Class ID and Code Assignments */ + + +#define I2O_CLASS_VERSION_10 0x00 +#define I2O_CLASS_VERSION_11 0x01 + +/* Class Code Names: Table 6-1 Class Code Assignments. */ +#define I2O_CLASS_EXECUTIVE 0x000 +#define I2O_CLASS_DDM 0x001 +#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 +#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011 +#define I2O_CLASS_LAN 0x020 +#define I2O_CLASS_WAN 0x030 +#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040 +#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041 +#define I2O_CLASS_SCSI_PERIPHERAL 0x051 +#define I2O_CLASS_ATE_PORT 0x060 +#define I2O_CLASS_ATE_PERIPHERAL 0x061 +#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 +#define I2O_CLASS_FLOPPY_DEVICE 0x071 +#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 +/* Class Codes 0x090 - 0x09f are reserved for Peer-to-Peer classes */ +#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff + +#define I2O_SUBCLASS_i960 0x001 +#define I2O_SUBCLASS_HDM 0x020 +#define I2O_SUBCLASS_ISM 0x021 + + +/*********************************************************************/ + +#define I2O_MAX_SERIAL_NUMBER_SZ 256 + +/****************************************************************************/ + +/* I2O Message Frame common for all messages */ + +typedef struct _I2O_MESSAGE_FRAME { + U8 VersionOffset; + U8 MsgFlags; + U16 MessageSize; + BF TargetAddress:I2O_TID_SZ; + BF InitiatorAddress:I2O_TID_SZ; + BF Function:I2O_FUNCTION_SZ; + I2O_INITIATOR_CONTEXT InitiatorContext; +} I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME; + + +/****************************************************************************/ + +/* I2O Successful Single Transaction Reply Message Frame structure. */ + +typedef struct _I2O_SINGLE_REPLY_MESSAGE_FRAME { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U16 DetailedStatusCode; + U8 reserved; + U8 ReqStatus; +/* ReplyPayload */ +} I2O_SINGLE_REPLY_MESSAGE_FRAME, *PI2O_SINGLE_REPLY_MESSAGE_FRAME; + + +/****************************************************************************/ + +/* I2O Private Message Frame structure. */ +typedef struct _I2O_PRIVATE_MESSAGE_FRAME { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U16 XFunctionCode; + U16 OrganizationID; +/* PrivatePayload[] */ +} I2O_PRIVATE_MESSAGE_FRAME, *PI2O_PRIVATE_MESSAGE_FRAME; + +/****************************************************************************/ + +/* + Random Block Storage Class specific functions + + Although the names are block storage class specific, the values + assigned are common with other classes when applicable. +*/ + +#define I2O_BSA_BLOCK_READ 0x30 +#define I2O_BSA_BLOCK_REASSIGN 0x71 +#define I2O_BSA_BLOCK_WRITE 0x31 +#define I2O_BSA_BLOCK_WRITE_VERIFY 0x33 +#define I2O_BSA_CACHE_FLUSH 0x37 +#define I2O_BSA_DEVICE_RESET 0x27 +#define I2O_BSA_MEDIA_EJECT 0x43 +#define I2O_BSA_MEDIA_FORMAT 0x45 +#define I2O_BSA_MEDIA_LOCK 0x49 +#define I2O_BSA_MEDIA_MOUNT 0x41 +#define I2O_BSA_MEDIA_UNLOCK 0x4B +#define I2O_BSA_MEDIA_VERIFY 0x35 +#define I2O_BSA_POWER_MANAGEMENT 0x70 +#define I2O_BSA_STATUS_CHECK 0x25 + +/****************************************************************************/ + +/* Memory Addressing structures and defines. */ + +/* SglFlags defines. */ + +#define I2O_SGL_FLAGS_LAST_ELEMENT 0x80 +#define I2O_SGL_FLAGS_END_OF_BUFFER 0x40 + +#define I2O_SGL_FLAGS_IGNORE_ELEMENT 0x00 +#define I2O_SGL_FLAGS_TRANSPORT_ELEMENT 0x04 +#define I2O_SGL_FLAGS_BIT_BUCKET_ELEMENT 0x08 +#define I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT 0x0C +#define I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT 0x10 +#define I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT 0x20 +#define I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT 0x30 +#define I2O_SGL_FLAGS_LONG_TRANSACTION_ELEMENT 0x40 +#define I2O_SGL_FLAGS_SHORT_TRANSACTION_ELEMENT 0x70 +#define I2O_SGL_FLAGS_SGL_ATTRIBUTES_ELEMENT 0x7C + +#define I2O_SGL_FLAGS_BC0 0x01 +#define I2O_SGL_FLAGS_BC1 0x02 +#define I2O_SGL_FLAGS_DIR 0x04 +#define I2O_SGL_FLAGS_LOCAL_ADDRESS 0x08 + +#define I2O_SGL_FLAGS_CONTEXT_COUNT_MASK 0x03 +#define I2O_SGL_FLAGS_ADDRESS_MODE_MASK 0x3C +#define I2O_SGL_FLAGS_NO_CONTEXT 0x00 + +/* 32 Bit Context Field defines */ + +#define I2O_SGL_FLAGS_CONTEXT32_NULL 0x00 +#define I2O_SGL_FLAGS_CONTEXT32_U32 0x01 +#define I2O_SGL_FLAGS_CONTEXT32_U64 0x02 +#define I2O_SGL_FLAGS_CONTEXT32_U96 0x03 + +#define I2O_SGL_FLAGS_CONTEXT32_NULL_SZ 0x00 +#define I2O_SGL_FLAGS_CONTEXT32_U32_SZ 0x04 +#define I2O_SGL_FLAGS_CONTEXT32_U64_SZ 0x08 +#define I2O_SGL_FLAGS_CONTEXT32_U96_SZ 0x0C + +/* 64 Bit Context Field defines */ + +#define I2O_SGL_FLAGS_CONTEXT64_NULL 0x00 +#define I2O_SGL_FLAGS_CONTEXT64_U64 0x01 +#define I2O_SGL_FLAGS_CONTEXT64_U128 0x02 +#define I2O_SGL_FLAGS_CONTEXT64_U192 0x03 + +#define I2O_SGL_FLAGS_CONTEXT64_NULL_SZ 0x00 +#define I2O_SGL_FLAGS_CONTEXT64_U64_SZ 0x08 +#define I2O_SGL_FLAGS_CONTEXT64_U128_SZ 0x10 +#define I2O_SGL_FLAGS_CONTEXT64_U192_SZ 0x18 + +/* SGL Attribute Element defines */ + +#define I2O_SGL_ATTRIBUTE_FLAGS_BIT_BUCKET_HINT 0x0400 +#define I2O_SGL_ATTRIBUTE_FLAGS_IMMEDIATE_DATA_HINT 0x0200 +#define I2O_SGL_ATTRIBUTE_FLAGS_LOCAL_ADDRESS_HINT 0x0100 +#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_TRANSACTION 0x0000 +#define I2O_SGL_ATTRIBUTE_FLAGS_64BIT_TRANSACTION 0x0004 +#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_LOCAL_ADDRESS 0x0000 + +/* SG Size defines */ + +#define I2O_SG_COUNT_SZ 24 +#define I2O_SG_FLAGS_SZ 8 + +/* Standard Flags and Count fields for SG Elements */ + +typedef struct _I2O_FLAGS_COUNT { + BF Count:I2O_SG_COUNT_SZ; + BF Flags:I2O_SG_FLAGS_SZ; +} I2O_FLAGS_COUNT, *PI2O_FLAGS_COUNT; + +/* Bit Bucket Element */ +typedef struct _I2O_SGE_BIT_BUCKET_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext; +} I2O_SGE_BIT_BUCKET_ELEMENT, *PI2O_SGE_BIT_BUCKET_ELEMENT; + +/* Chain Addressing Scatter-Gather Element */ + +typedef struct _I2O_SGE_CHAIN_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 PhysicalAddress; +} I2O_SGE_CHAIN_ELEMENT, *PI2O_SGE_CHAIN_ELEMENT; + +/* Chain Addressing with Context Scatter-Gather Element */ + +typedef struct _I2O_SGE_CHAIN_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 Context[1]; + U32 PhysicalAddress; +} I2O_SGE_CHAIN_CONTEXT_ELEMENT, *PI2O_SGE_CHAIN_CONTEXT_ELEMENT; + +/* Ignore Scatter-Gather Element */ + +typedef struct _I2O_SGE_IGNORE_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; +} I2O_SGE_IGNORE_ELEMENT, *PI2O_SGE_IGNORE_ELEMENT; + +/* Immediate Data Element */ + +typedef struct _I2O_SGE_IMMEDIATE_DATA_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; +} I2O_SGE_IMMEDIATE_DATA_ELEMENT, *PI2O_SGE_IMMEDIATE_DATA_ELEMENT; + +/* Immediate Data with Context Element */ + +typedef struct _I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext; +} I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT, *PI2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT; + +/* Long Transaction Parameters Element */ + +typedef struct _I2O_SGE_LONG_TRANSACTION_ELEMENT { + BF LongElementLength:I2O_SG_COUNT_SZ; + BF Flags:I2O_SG_FLAGS_SZ; + U32 BufferContext; +} I2O_SGE_LONG_TRANSACTION_ELEMENT, *PI2O_SGE_LONG_TRANSACTION_ELEMENT; + +/* Page List Scatter-Gather Element */ + +typedef struct _I2O_SGE_PAGE_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 PhysicalAddress[1]; +} I2O_SGE_PAGE_ELEMENT , *PI2O_SGE_PAGE_ELEMENT ; + +/* Page List with Context Scatter-Gather Element */ + +typedef struct _I2O_SGE_PAGE_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext[1]; + U32 PhysicalAddress[1]; +} I2O_SGE_PAGE_CONTEXT_ELEMENT, *PI2O_SGE_PAGE_CONTEXT_ELEMENT; + +/* SGL Attribute Element */ + +typedef struct _I2O_SGE_SGL_ATTRIBUTES_ELEMENT { + U16 SglAttributeFlags; + U8 ElementLength; + U8 Flags; + U32 PageFrameSize; +} I2O_SGE_SGL_ATTRIBUTES_ELEMENT, *PI2O_SGE_SGL_ATTRIBUTES_ELEMENT; + +/* Short Transaction Parameters Element */ + +typedef struct _I2O_SGE_SHORT_TRANSACTION_ELEMENT { + U16 ClassFields; + U8 ElementLength; + U8 Flags; + U32 BufferContext; +} I2O_SGE_SHORT_TRANSACTION_ELEMENT, *PI2O_SGE_SHORT_TRANSACTION_ELEMENT; + +/* Simple Addressing Scatter-Gather Element */ + +typedef struct _I2O_SGE_SIMPLE_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 PhysicalAddress; +} I2O_SGE_SIMPLE_ELEMENT, *PI2O_SGE_SIMPLE_ELEMENT; + +/* Simple Addressing with Context Scatter-Gather Element */ + +typedef struct _I2O_SGE_SIMPLE_CONTEXT_ELEMENT { + I2O_FLAGS_COUNT FlagsCount; + U32 BufferContext[1]; + U32 PhysicalAddress; +} I2O_SGE_SIMPLE_CONTEXT_ELEMENT, *PI2O_SGE_SIMPLE_CONTEXT_ELEMENT; + +/* Transport Detail Element */ + +typedef struct _I2O_SGE_TRANSPORT_ELEMENT { + BF LongElementLength:I2O_SG_COUNT_SZ; + BF Flags:I2O_SG_FLAGS_SZ; +} I2O_SGE_TRANSPORT_ELEMENT, *PI2O_SGE_TRANSPORT_ELEMENT; + + +typedef struct _I2O_SG_ELEMENT { + union { + /* Bit Bucket Element */ + I2O_SGE_BIT_BUCKET_ELEMENT BitBucket; + + /* Chain Addressing Element */ + I2O_SGE_CHAIN_ELEMENT Chain; + + /* Chain Addressing with Context Element */ + I2O_SGE_CHAIN_CONTEXT_ELEMENT ChainContext; + + /* Ignore Scatter-Gather Element */ + I2O_SGE_IGNORE_ELEMENT Ignore; + + /* Immediate Data Element */ + I2O_SGE_IMMEDIATE_DATA_ELEMENT ImmediateData; + + /* Immediate Data with Context Element */ + I2O_SGE_IMMEDIATE_DATA_CONTEXT_ELEMENT ImmediateDataContext; + + /* Long Transaction Parameters Element */ + I2O_SGE_LONG_TRANSACTION_ELEMENT LongTransaction; + + /* Page List Element */ + I2O_SGE_PAGE_ELEMENT Page; + + /* Page List with Context Element */ + I2O_SGE_PAGE_CONTEXT_ELEMENT PageContext; + + /* SGL Attribute Element */ + I2O_SGE_SGL_ATTRIBUTES_ELEMENT SGLAttribute; + + /* Short Transaction Parameters Element */ + I2O_SGE_SHORT_TRANSACTION_ELEMENT ShortTransaction; + + /* Simple Addressing Element */ + I2O_SGE_SIMPLE_ELEMENT Simple[1]; + + /* Simple Addressing with Context Element */ + I2O_SGE_SIMPLE_CONTEXT_ELEMENT SimpleContext[1]; + + /* Transport Detail Element */ + I2O_SGE_TRANSPORT_ELEMENT Transport; + }u; +} I2O_SG_ELEMENT, *PI2O_SG_ELEMENT; + +/* I2O BSA Block Read Message Frame */ +typedef struct _I2O_BSA_READ_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + I2O_BSA_READ_FLAGS ControlFlags; + U8 TimeMultiplier; + U8 FetchAhead; + U32 TransferByteCount; + U64 LogicalByteAddress; + I2O_SG_ELEMENT SGL; +} I2O_BSA_READ_MESSAGE, *PI2O_BSA_READ_MESSAGE; + + +/***********************************************************************/ + +/* Class ID Block */ + +typedef struct _I2O_CLASS_ID { + BF Class:I2O_CLASS_ID_SZ; + BF Version:I2O_4BIT_VERSION_SZ; + BF OrganizationID:I2O_CLASS_ORGANIZATION_ID_SZ; +} I2O_CLASS_ID, *PI2O_CLASS_ID; + + +/****************************************************************************/ +/* Logical Configuration Table */ +/****************************************************************************/ + +/* I2O Logical Configuration Table structures. */ + +#define I2O_IDENTITY_TAG_SZ 8 + +/* I2O Logical Configuration Table Device Flags */ + +#define I2O_LCT_DEVICE_FLAGS_CONF_DIALOG_REQUEST 0x01 +#define I2O_LCT_DEVICE_FLAGS_MORE_THAN_1_USER 0x02 +#define I2O_LCT_DEVICE_FLAGS_PEER_SERVICE_DISABLED 0x10 +#define I2O_LCT_DEVICE_FLAGS_MANAGEMENT_SERVICE_DISABLED 0x20 + +/* LCT Entry Block */ + +typedef struct _I2O_LCT_ENTRY { + BF TableEntrySize:I2O_COMMON_LENGTH_FIELD_SZ; + BF LocalTID:I2O_TID_SZ; + BF reserved:I2O_4BIT_VERSION_SZ; + U32 ChangeIndicator; + U32 DeviceFlags; + I2O_CLASS_ID ClassID; + U32 SubClassInfo; + BF UserTID:I2O_TID_SZ; + BF ParentTID:I2O_TID_SZ; + BF BiosInfo:I2O_BIOS_INFO_SZ; + U8 IdentityTag[I2O_IDENTITY_TAG_SZ]; + U32 EventCapabilities; +} I2O_LCT_ENTRY, *PI2O_LCT_ENTRY; + +/* I2O Logical Configuration Table structure. */ +typedef struct _I2O_LCT { + BF TableSize:I2O_COMMON_LENGTH_FIELD_SZ; + BF BootDeviceTID:I2O_TID_SZ; + BF LctVer:I2O_4BIT_VERSION_SZ; + U32 IopFlags; + U32 CurrentChangeIndicator; + I2O_LCT_ENTRY LCTEntry[1]; +} I2O_LCT, *PI2O_LCT; + + +/****************************************************************************/ + +/* I2O Executive Function Codes. */ + +#define I2O_EXEC_ADAPTER_ASSIGN 0xB3 +#define I2O_EXEC_ADAPTER_READ 0xB2 +#define I2O_EXEC_ADAPTER_RELEASE 0xB5 +#define I2O_EXEC_BIOS_INFO_SET 0xA5 +#define I2O_EXEC_BOOT_DEVICE_SET 0xA7 +#define I2O_EXEC_CONFIG_VALIDATE 0xBB +#define I2O_EXEC_CONN_SETUP 0xCA +#define I2O_EXEC_DDM_DESTROY 0xB1 +#define I2O_EXEC_DDM_ENABLE 0xD5 +#define I2O_EXEC_DDM_QUIESCE 0xC7 +#define I2O_EXEC_DDM_RESET 0xD9 +#define I2O_EXEC_DDM_SUSPEND 0xAF +#define I2O_EXEC_DEVICE_ASSIGN 0xB7 +#define I2O_EXEC_DEVICE_RELEASE 0xB9 +#define I2O_EXEC_HRT_GET 0xA8 +#define I2O_EXEC_IOP_CLEAR 0xBE +#define I2O_EXEC_IOP_CONNECT 0xC9 +#define I2O_EXEC_IOP_RESET 0xBD +#define I2O_EXEC_LCT_NOTIFY 0xA2 +#define I2O_EXEC_OUTBOUND_INIT 0xA1 +#define I2O_EXEC_PATH_ENABLE 0xD3 +#define I2O_EXEC_PATH_QUIESCE 0xC5 +#define I2O_EXEC_PATH_RESET 0xD7 +#define I2O_EXEC_STATIC_MF_CREATE 0xDD +#define I2O_EXEC_STATIC_MF_RELEASE 0xDF +#define I2O_EXEC_STATUS_GET 0xA0 +#define I2O_EXEC_SW_DOWNLOAD 0xA9 +#define I2O_EXEC_SW_UPLOAD 0xAB +#define I2O_EXEC_SW_REMOVE 0xAD +#define I2O_EXEC_SYS_ENABLE 0xD1 +#define I2O_EXEC_SYS_MODIFY 0xC1 +#define I2O_EXEC_SYS_QUIESCE 0xC3 +#define I2O_EXEC_SYS_TAB_SET 0xA3 + + +/* I2O Get Status State values */ + +#define I2O_IOP_STATE_INITIALIZING 0x01 +#define I2O_IOP_STATE_RESET 0x02 +#define I2O_IOP_STATE_HOLD 0x04 +#define I2O_IOP_STATE_READY 0x05 +#define I2O_IOP_STATE_OPERATIONAL 0x08 +#define I2O_IOP_STATE_FAILED 0x10 +#define I2O_IOP_STATE_FAULTED 0x11 + + +#define I2O_EXEC_STATUS_GET_RESERVED_SZ 16 + +/* ExecStatusGet Function Message Frame structure. */ + +typedef struct _I2O_EXEC_STATUS_GET_MESSAGE { + U8 VersionOffset; + U8 MsgFlags; + U16 MessageSize; + BF TargetAddress:I2O_TID_SZ; + BF InitiatorAddress:I2O_TID_SZ; + BF Function:I2O_FUNCTION_SZ; + U8 Reserved[I2O_EXEC_STATUS_GET_RESERVED_SZ]; + U32 ReplyBufferAddressLow; + U32 ReplyBufferAddressHigh; + U32 ReplyBufferLength; +} I2O_EXEC_STATUS_GET_MESSAGE, *PI2O_EXEC_STATUS_GET_MESSAGE; + + +#define I2O_IOP_STATUS_PROD_ID_STR_SZ 24 +#define I2O_EXEC_STATUS_GET_REPLY_RESERVED_SZ 6 + +/* ExecStatusGet reply Structure */ + +#define I2O_IOP_CAP_CONTEXT_32_ONLY 0x00000000 +#define I2O_IOP_CAP_CONTEXT_64_ONLY 0x00000001 +#define I2O_IOP_CAP_CONTEXT_32_64_NOT_CURRENTLY 0x00000002 +#define I2O_IOP_CAP_CONTEXT_32_64_CURRENTLY 0x00000003 +#define I2O_IOP_CAP_CURRENT_CONTEXT_NOT_CONFIG 0x00000000 +#define I2O_IOP_CAP_CURRENT_CONTEXT_32_ONLY 0x00000004 +#define I2O_IOP_CAP_CURRENT_CONTEXT_64_ONLY 0x00000008 +#define I2O_IOP_CAP_CURRENT_CONTEXT_32_64 0x0000000C +#define I2O_IOP_CAP_INBOUND_PEER_SUPPORT 0x00000010 +#define I2O_IOP_CAP_OUTBOUND_PEER_SUPPORT 0x00000020 +#define I2O_IOP_CAP_PEER_TO_PEER_SUPPORT 0x00000040 + +typedef struct _I2O_EXEC_STATUS_GET_REPLY { + U16 OrganizationID; + U16 reserved; + BF IOP_ID:I2O_IOP_ID_SZ; + BF reserved1:I2O_RESERVED_4BITS; + BF HostUnitID:I2O_UNIT_ID_SZ; + BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; + BF I2oVersion:I2O_4BIT_VERSION_SZ; + BF IopState:I2O_IOP_STATE_SZ; + BF MessengerType:I2O_MESSENGER_TYPE_SZ; + U16 InboundMFrameSize; + U8 InitCode; + U8 reserved2; + U32 MaxInboundMFrames; + U32 CurrentInboundMFrames; + U32 MaxOutboundMFrames; + U8 ProductIDString[I2O_IOP_STATUS_PROD_ID_STR_SZ]; + U32 ExpectedLCTSize; + U32 IopCapabilities; + U32 DesiredPrivateMemSize; + U32 CurrentPrivateMemSize; + U32 CurrentPrivateMemBase; + U32 DesiredPrivateIOSize; + U32 CurrentPrivateIOSize; + U32 CurrentPrivateIOBase; + U8 reserved3[3]; + U8 SyncByte; +} I2O_EXEC_STATUS_GET_REPLY, *PI2O_EXEC_STATUS_GET_REPLY; + + +/***************************************************************************/ + +/* ExecSysTabSet (System Table) Function Message Frame structure. */ + +#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_IOP 0x000 +#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST 0x001 +#define I2O_EXEC_SYS_TAB_IOP_ID_UNKNOWN_IOP 0xFFF +#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT 0x0000 +#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_UNKNOWN_UNIT 0xffff +#define I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT 0x000 +#define I2O_EXEC_SYS_TAB_SEG_NUMBER_UNKNOWN_SEGMENT 0xfff + +typedef struct _I2O_EXEC_SYS_TAB_SET_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + BF IOP_ID:I2O_IOP_ID_SZ; + BF reserved:I2O_RESERVED_4BITS; + BF HostUnitID:I2O_UNIT_ID_SZ; + BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; + BF reserved2:I2O_RESERVED_20BITS; + I2O_SG_ELEMENT SGL; +} I2O_EXEC_SYS_TAB_SET_MESSAGE, *PI2O_EXEC_SYS_TAB_SET_MESSAGE; + + +/****************************************************************************/ + +/* Operation Function Numbers */ + +#define I2O_PARAMS_OPERATION_FIELD_GET 0x0001 +#define I2O_PARAMS_OPERATION_LIST_GET 0x0002 +#define I2O_PARAMS_OPERATION_MORE_GET 0x0003 +#define I2O_PARAMS_OPERATION_SIZE_GET 0x0004 +#define I2O_PARAMS_OPERATION_TABLE_GET 0x0005 +#define I2O_PARAMS_OPERATION_FIELD_SET 0x0006 +#define I2O_PARAMS_OPERATION_LIST_SET 0x0007 +#define I2O_PARAMS_OPERATION_ROW_ADD 0x0008 +#define I2O_PARAMS_OPERATION_ROW_DELETE 0x0009 +#define I2O_PARAMS_OPERATION_TABLE_CLEAR 0x000A + +/* Operations List Header */ + +typedef struct _I2O_PARAM_OPERATIONS_LIST_HEADER { + U16 OperationCount; + U16 Reserved; +} I2O_PARAM_OPERATIONS_LIST_HEADER, *PI2O_PARAM_OPERATIONS_LIST_HEADER; + +/* Results List Header */ + +typedef struct _I2O_PARAM_RESULTS_LIST_HEADER { + U16 ResultCount; + U16 Reserved; +} I2O_PARAM_RESULTS_LIST_HEADER, *PI2O_PARAM_RESULTS_LIST_HEADER; + +/* Read Operation Result Block Template Structure */ + +typedef struct _I2O_PARAM_READ_OPERATION_RESULT { + U16 BlockSize; + U8 BlockStatus; + U8 ErrorInfoSize; + /* Operations Results */ + /* Pad (if any) */ + /* ErrorInformation (if any) */ +} I2O_PARAM_READ_OPERATION_RESULT, *PI2O_PARAM_READ_OPERATION_RESULT; + +/* Operation Template for Specific Fields */ + +typedef struct _I2O_PARAM_OPERATION_SPECIFIC_TEMPLATE { + U16 Operation; + U16 GroupNumber; + U16 FieldCount; + U16 FieldIdx[1]; + /* Pad (if any) */ +} I2O_PARAM_OPERATION_SPECIFIC_TEMPLATE, *PI2O_PARAM_OPERATION_SPECIFIC_TEMPLATE; + +/* Operation Template for All Fields */ + +typedef struct _I2O_PARAM_OPERATION_ALL_TEMPLATE { + U16 Operation; + U16 GroupNumber; + U16 FieldCount; + /* Pad (if any) */ +} I2O_PARAM_OPERATION_ALL_TEMPLATE, *PI2O_PARAM_OPERATION_ALL_TEMPLATE; + +/****************************************************************************/ + +/* Utility Message class functions. */ + +#define I2O_UTIL_NOP 0x00 +#define I2O_UTIL_ABORT 0x01 +#define I2O_UTIL_CLAIM 0x09 +#define I2O_UTIL_CLAIM_RELEASE 0x0B +#define I2O_UTIL_CONFIG_DIALOG 0x10 +#define I2O_UTIL_DEVICE_RESERVE 0x0D +#define I2O_UTIL_DEVICE_RELEASE 0x0F +#define I2O_UTIL_EVENT_ACKNOWLEDGE 0x14 +#define I2O_UTIL_EVENT_REGISTER 0x13 +#define I2O_UTIL_LOCK 0x17 +#define I2O_UTIL_LOCK_RELEASE 0x19 +#define I2O_UTIL_PARAMS_GET 0x06 +#define I2O_UTIL_PARAMS_SET 0x05 +#define I2O_UTIL_REPLY_FAULT_NOTIFY 0x15 + +/****************************************************************************/ + +/* UtilNOP Function Message Frame structure. */ + +typedef struct _I2O_UTIL_NOP_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; +} I2O_UTIL_NOP_MESSAGE, *PI2O_UTIL_NOP_MESSAGE; + + +/*************************************************************************/ + +/* UtilParamsGet Message Frame structure. */ + +typedef struct _I2O_UTIL_PARAMS_GET_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U32 OperationFlags; + I2O_SG_ELEMENT SGL; +} I2O_UTIL_PARAMS_GET_MESSAGE, *PI2O_UTIL_PARAMS_GET_MESSAGE; + + +/****************************************************************************/ +/* GROUP Parameter Groups */ +/****************************************************************************/ + +/* GROUP Configuration and Operating Structures and Defines */ + +/* Groups Numbers */ + +#define I2O_UTIL_PARAMS_DESCRIPTOR_GROUP_NO 0xF000 +#define I2O_UTIL_PHYSICAL_DEVICE_TABLE_GROUP_NO 0xF001 +#define I2O_UTIL_CLAIMED_TABLE_GROUP_NO 0xF002 +#define I2O_UTIL_USER_TABLE_GROUP_NO 0xF003 +#define I2O_UTIL_PRIVATE_MESSAGE_EXTENSIONS_GROUP_NO 0xF005 +#define I2O_UTIL_AUTHORIZED_USER_TABLE_GROUP_NO 0xF006 +#define I2O_UTIL_DEVICE_IDENTITY_GROUP_NO 0xF100 +#define I2O_UTIL_DDM_IDENTITY_GROUP_NO 0xF101 +#define I2O_UTIL_USER_INFORMATION_GROUP_NO 0xF102 +#define I2O_UTIL_SGL_OPERATING_LIMITS_GROUP_NO 0xF103 +#define I2O_UTIL_SENSORS_GROUP_NO 0xF200 + +/* UTIL Group F000h - GROUP DESCRIPTORS Parameter Group */ + +#define I2O_UTIL_GROUP_PROPERTIES_GROUP_TABLE 0x01 +#define I2O_UTIL_GROUP_PROPERTIES_ROW_ADDITION 0x02 +#define I2O_UTIL_GROUP_PROPERTIES_ROW_DELETION 0x04 +#define I2O_UTIL_GROUP_PROPERTIES_CLEAR_OPERATION 0x08 + +/* UTIL Group F100h - Device Identity Parameter Group */ + +typedef struct _I2O_UTIL_DEVICE_IDENTITY_SCALAR { + U32 ClassID; + U16 OwnerTID; + U16 ParentTID; + U8 VendorInfo[I2O_DEVID_VENDOR_INFO_SZ]; + U8 ProductInfo[I2O_DEVID_PRODUCT_INFO_SZ]; + U8 Description[I2O_DEVID_DESCRIPTION_SZ]; + U8 ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ]; + U8 SNFormat; + U8 SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; +} I2O_UTIL_DEVICE_IDENTITY_SCALAR, *PI2O_UTIL_DEVICE_IDENTITY_SCALAR; + +/* UTIL Group F101h - DDM Identity Parameter Group */ + +typedef struct _I2O_UTIL_DDM_IDENTITY_SCALAR { + U16 DdmTID; + U8 ModuleName[I2O_MODULE_NAME_SZ]; + U8 ModuleRevLevel[I2O_DEVID_REV_LEVEL_SZ]; + U8 SNFormat; + U8 SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; +} I2O_UTIL_DDM_IDENTITY_SCALAR, *PI2O_UTIL_DDM_IDENTITY_SCALAR; + +/****************************************************************************/ + +/* Block Storage Parameter Groups */ + +#define I2O_BSA_DEVICE_INFO_GROUP_NO 0x0000 +#define I2O_BSA_OPERATIONAL_CONTROL_GROUP_NO 0x0001 +#define I2O_BSA_POWER_CONTROL_GROUP_NO 0x0002 +#define I2O_BSA_CACHE_CONTROL_GROUP_NO 0x0003 +#define I2O_BSA_MEDIA_INFO_GROUP_NO 0x0004 +#define I2O_BSA_ERROR_LOG_GROUP_NO 0x0005 + +/***************************************************************************/ + +/* I2O Block Storage Reply Message Frame Template */ + +typedef struct _I2O_BSA_REPLY_MESSAGE_FRAME { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U16 DetailedStatusCode; + U8 RetryCount; + U8 ReqStatus; +/* ReplyPayload */ +} I2O_BSA_REPLY_MESSAGE_FRAME, *PI2O_BSA_REPLY_MESSAGE_FRAME; + +/**************************************************************************/ + +/* Block Storage Group 0000h - Device Information Parameter Group */ + +typedef struct _I2O_BSA_DEVICE_INFO_SCALAR { + U8 DeviceType; + U8 NumberOfPaths; + U16 PowerState; + U32 BlockSize; + U64 DeviceCapacity; + U32 DeviceCapabilitySupport; + U32 DeviceState; +} I2O_BSA_DEVICE_INFO_SCALAR, *PI2O_BSA_DEVICE_INFO_SCALAR; + + +/****************************************************************************/ + +/* I2O BSA Control Flags */ + +typedef U16 I2O_BSA_CTL_FLAGS; + +/* I2O BSA Cache Flush Message Frame */ + +typedef struct _I2O_BSA_CACHE_FLUSH_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + I2O_BSA_CTL_FLAGS ControlFlags; + U8 TimeMultiplier; + U8 Reserved; +} I2O_BSA_CACHE_FLUSH_MESSAGE, *PI2O_BSA_CACHE_FLUSH_MESSAGE; + + +/****************************************************************************/ + + +/* ExecOutboundInit Function Message Frame structure. */ + +typedef struct _I2O_EXEC_OUTBOUND_INIT_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U32 HostPageFrameSize; + U8 InitCode; + U8 reserved; + U16 OutboundMFrameSize; + I2O_SG_ELEMENT SGL; +} I2O_EXEC_OUTBOUND_INIT_MESSAGE, *PI2O_EXEC_OUTBOUND_INIT_MESSAGE; + + +#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01 +#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02 +#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03 +#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04 + +#define I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ 3 + + +typedef struct _I2O_EXEC_OUTBOUND_INIT_STATUS { + U8 InitStatus; + U8 reserved[I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ]; +} I2O_EXEC_OUTBOUND_INIT_STATUS, *PI2O_EXEC_OUTBOUND_INIT_STATUS; + + +typedef struct _I2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST { + U32 MFACount; + U32 MFAReleaseCount; + U32 MFAAddress[1]; +} I2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST, *PI2O_EXEC_OUTBOUND_INIT_RECLAIM_LIST; + +/****************************************************************************/ + + +/* ExecSysEnable Function Message Frame structure. */ + +typedef struct _I2O_EXEC_SYS_ENABLE_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; +} I2O_EXEC_SYS_ENABLE_MESSAGE, *PI2O_EXEC_SYS_ENABLE_MESSAGE; + + +/****************************************************************************/ + +/* ExecLCTNotify Function Message Frame structure. */ + +typedef struct _I2O_EXEC_LCT_NOTIFY_MESSAGE { + I2O_MESSAGE_FRAME StdMessageFrame; + I2O_TRANSACTION_CONTEXT TransactionContext; + U32 ClassIdentifier; + U32 LastReportedChangeIndicator; + I2O_SG_ELEMENT SGL; +} I2O_EXEC_LCT_NOTIFY_MESSAGE, *PI2O_EXEC_LCT_NOTIFY_MESSAGE; + +/****************************************************************************/ + +/* ExecSysTabSet (System Table) Header Reply structure. */ + +#define I2O_SET_SYSTAB_RESERVED_SZ 8 + +typedef struct _I2O_SET_SYSTAB_HEADER { + U8 NumberEntries; + U8 SysTabVersion; + U16 reserved; + U32 CurrentChangeIndicator; + U8 reserved1[I2O_SET_SYSTAB_RESERVED_SZ]; +/* I2O_SYSTAB_ENTRY SysTabEntry[1]; */ +} I2O_SET_SYSTAB_HEADER, *PI2O_SET_SYSTAB_HEADER; + + +#define I2O_RESOURCE_MANAGER_VERSION 0 + +typedef struct _MESSENGER_INFO { + U32 InboundMessagePortAddressLow; + U32 InboundMessagePortAddressHigh; + } I2O_MESSENGER_INFO, *PI2O_MESSENGER_INFO; + +/* ExecSysTabSet IOP Descriptor Entry structure. */ + +typedef struct _I2O_IOP_ENTRY { + U16 OrganizationID; + U16 reserved; + BF IOP_ID:I2O_IOP_ID_SZ; + BF reserved1:I2O_RESERVED_20BITS; + BF SegmentNumber:I2O_SEGMENT_NUMBER_SZ; + BF I2oVersion:I2O_4BIT_VERSION_SZ; + BF IopState:I2O_IOP_STATE_SZ; + BF MessengerType:I2O_MESSENGER_TYPE_SZ; + U16 InboundMessageFrameSize; + U16 reserved2; + U32 LastChanged; + U32 IopCapabilities; + I2O_MESSENGER_INFO MessengerInfo; +} I2O_IOP_ENTRY, *PI2O_IOP_ENTRY; + + +/****************************************************************************/ + + +#define I2O_EXEC_IOP_RESET_RESERVED_SZ 16 + +#define I2O_EXEC_IOP_RESET_IN_PROGRESS 0x01 +#define I2O_EXEC_IOP_RESET_REJECTED 0x02 + +#define I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ 3 + +typedef struct _I2O_EXEC_IOP_RESET_STATUS { + U8 ResetStatus; + U8 reserved[I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ]; +} I2O_EXEC_IOP_RESET_STATUS, *PI2O_EXEC_IOP_RESET_STATUS; + + +/* ExecIopReset Function Message Frame structure. */ + +typedef struct _I2O_EXEC_IOP_RESET_MESSAGE { + U8 VersionOffset; + U8 MsgFlags; + U16 MessageSize; + BF TargetAddress:I2O_TID_SZ; + BF InitiatorAddress:I2O_TID_SZ; + BF Function:I2O_FUNCTION_SZ; + U8 Reserved[I2O_EXEC_IOP_RESET_RESERVED_SZ]; + U32 StatusWordLowAddress; + U32 StatusWordHighAddress; +} I2O_EXEC_IOP_RESET_MESSAGE, *PI2O_EXEC_IOP_RESET_MESSAGE; + + +/****************************************************************************/ +/* EXEC Group 0001h - IOP Message Interface Parameter Group */ + +/* InitCode defines */ +#define I2O_MESSAGE_IF_INIT_CODE_NO_OWNER 0x00 +#define I2O_MESSAGE_IF_INIT_CODE_BIOS 0x10 +#define I2O_MESSAGE_IF_INIT_CODE_OEM_BIOS_EXTENSION 0x20 +#define I2O_MESSAGE_IF_INIT_CODE_ROM_BIOS_EXTENSION 0x30 +#define I2O_MESSAGE_IF_INIT_CODE_OS 0x80 + +/****************************************************************************/ + +#endif /* _I2ODEF_H_ */ diff -Nur linux-2.4.20.org/drivers/scsi/pti_st.c linux-2.4.20/drivers/scsi/pti_st.c --- linux-2.4.20.org/drivers/scsi/pti_st.c Wed Nov 5 08:47:58 2003 +++ linux-2.4.20/drivers/scsi/pti_st.c Mon Oct 21 00:00:00 2002 @@ -1,3521 +1,3792 @@ -/*+M************************************************************************* - * Promise SuperTrak device driver for Linux. - * - * Copyright (c) 2001 Promise Technology, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * -------------------------------------------------------------------------- - * Copyright (c) 1999-2001 Promise Technology, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Where this Software is combined with software released under the terms of - * the GNU Public License ("GPL") and the terms of the GPL would require the - * combined work to also be released under the terms of the GPL, the terms - * and conditions of this License will apply in addition to those of the - * GPL with the exception of any terms or conditions of this License that - * conflict with, or are expressly prohibited by, the GPL. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - *-M*************************************************************************/ - -#include -#include - -#ifdef MODULE -#include -#endif - -#ifndef KERNEL_VERSION -# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -#if defined(MODULE) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) -#include -#endif -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#include -#endif -#include -#include -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#include -#endif -#include -#include /* for kmalloc() */ -#include /* for CONFIG_PCI */ -#include - -#ifdef mb -# undef mb -#endif -#define mb() \ - __asm__ __volatile__("lock ; addl $0,0(%%esp)": : :"memory") - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,16) -# include -#else -# include -#endif -# include -# define cpuid smp_processor_id() - -#if defined(__SMP__) -# if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) -# define DRIVER_LOCK_INIT \ - spin_lock_init(&p->spin_lock); -# define DRIVER_LOCK \ - if(!p->cpu_lock_count[cpuid]) { \ - spin_lock_irqsave(&p->spin_lock, cpu_flags); \ - p->cpu_lock_count[cpuid]++; \ - } else { \ - p->cpu_lock_count[cpuid]++; \ - } -# define DRIVER_UNLOCK \ - if(--p->cpu_lock_count[cpuid] == 0) \ - spin_unlock_irqrestore(&p->spin_lock, cpu_flags); -# else -# define DRIVER_LOCK_INIT spin_lock_init(&p->spin_lock); -# define DRIVER_LOCK spin_lock(&p->spin_lock); -# define DRIVER_UNLOCK spin_unlock(&p->spin_lock); -# endif -#else /* __SMP__ */ -#define DRIVER_LOCK_INIT -#define DRIVER_LOCK -#define DRIVER_UNLOCK -#endif /* __SMP__ */ - -#include - -#include "sd.h" -#include "scsi.h" -#include "hosts.h" - -#include "pti_st.h" -#include "pti_stdev.h" - -#define PTI_ST_VERBOSE_DEBUGGING - -#define PCI_DEVICE_ID_INTEL_i960 0x1960 -#define PCI_DEVICE_ID_INTEL_i962 0x1962 - -#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a)) - -#ifdef MODULE - -struct proc_dir_entry proc_root = -{ - PROC_ROOT_INO, - /* - * Inode number - ignore, it will be filled by - * proc_register[_dynamic] - */ - 4, - /* - * Length of the proc-file name - */ - "proc", - /* - * The proc-file name - */ - S_IFREG | S_IRUGO, - /* - * File mode - this is a regular - * file which can be read by its - * owner, its group, and everybody - * else - */ - 1, - /* - * Number of links (directories where the - * file is referenced) - */ - 0, 0, - /* - * The uid and gid for the file - we give it - * to root - */ - 0, - /* - * The size of the file reported by ls. - */ - NULL, - /* - * functions which can be done on the inode - * (linking, removing, etc.) - we don't - * support any. - */ - NULL, // procfile_read, - /* - * The read function for this file, - * the function called when somebody - * tries to read something from it. - */ - NULL - /* - * We could have here a function to fill the - * file's inode, to enable us to play with - * permissions, ownership, etc. - */ -}; - -#endif - -struct proc_dir_entry proc_scsi_pti_st = -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - PROC_SCSI_NOT_PRESENT, -#else - 0, - /* - * Inode number - ignore, it will be filled by - * proc_register[_dynamic] - */ -#endif - 6, - /* - * Length of the proc-file name - */ - "pti_st", - /* - * The proc-file name - */ - S_IFDIR | S_IRUGO | S_IXUGO, - /* - * File mode - this is a regular - * file which can be read by its - * owner, its group, and everybody - * else - */ - 2, - /* - * Number of links (directories where the - * file is referenced) - */ - 0, 0, - /* - * The uid and gid for the file - we give it - * to root - */ - 0, - /* - * The size of the file reported by ls. - */ - NULL, - /* - * functions which can be done on the inode - * (linking, removing, etc.) - we don't - * support any. - */ - NULL, - /* - * The read function for this file, - * the function called when somebody - * tries to read something from it. - */ - NULL - /* - * We could have here a function to fill the - * file's inode, to enable us to play with - * permissions, ownership, etc. - */ -}; - -#define ALL_TARGETS -1 -#define ALL_CHANNELS -1 -#define ALL_LUNS -1 - -#define MAX_ARRAYS 8 - -#define MAX_LUNS MAX_ARRAYS - -#define PTI_ST_CMDS_PER_LUN 24 - -/* - * The position of the SCSI commands scb within the scb array. - */ -#define pti_st_position(cmd) ((cmd)->SCp.have_data_in) - -/* This variable is global and very important, control all module !!! */ -struct pti_st_host *pti_st_hostp[MAX_ADAPTORS] = {0}; - -#define CTL_OF_CMD(cmd) ((cmd->channel) & 0x01), \ - ((cmd->target) & 0x0f), \ - ((cmd->lun) & 0x07) - -/* - * A nice little define to make doing our printks a little easier - */ - -#define WARN_LEAD KERN_WARNING "(scsi%d:%d:%d:%d) " -#define INFO_LEAD KERN_INFO "(scsi%d:%d:%d:%d) " - -#if 0 -#ifdef MODULE -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18) -MODULE_PARM(pti_st, "s"); -#endif -#endif -#endif - - -static int pti_st_install(Scsi_Host_Template *, struct pci_dev *, int *); -static void PTI_PrivateMessageCall(struct pti_st_host *, ULONG, U16, U16, ULONG, UCHAR *, ULONG, UCHAR *, UCHAR, ULONG); - -/* - * Declaration for EXECUTIVE Class Message - */ -static unsigned int GetStatusCall(struct pti_st_host *, void *); -static void OutboundInitCall(struct pti_st_host *); -static void SysTabSetCall(struct pti_st_host *, PI2O_EXEC_SYS_TAB_SET_MESSAGE, void *); -static int IOP_init(struct pti_st_host *); -static void EnableSysCall(struct pti_st_host *); -static void LCTNotifyCall(struct pti_st_host *); - -static unsigned long CreatSysTable(struct pti_st_host *, void *, PI2O_EXEC_STATUS_GET_REPLY); -static void ExecIOPReset(struct pti_st_host *); -static void PTI_UtilParamsGet(struct pti_st_host *, ULONG, ULONG, UCHAR, ULONG, UCHAR *); - -/* - * Declare Utility Message Functions: - */ -static unsigned long pti_st_waitreplymsg(struct pti_st_host *); -static void PTI_UtilParamGetCall(struct pti_st_host *, - PI2O_UTIL_PARAMS_GET_MESSAGE, - void *, void *, PI2ODISK); -static void UtilNOPCall(struct pti_st_host *); - -static int ComposeDiskInfo(struct pti_st_host *, void *, void *, PI2ODISK); -static void GetInfoFromLCT(struct pti_st_host *, void *, PI2ODISK, unsigned int *); -static void ZeroMemory(unsigned long *, unsigned int); - -#define ADDTOPROCBUFFER(d, s) { if((strlen(d)+strlen(s)) < 4095) strcat(d, s); else goto proc_out; } - -/* - * PTI_procfile_read: - * inout : decides on the direction of the dataflow and the meaning of the - * variables - * buffer: If inout==FALSE data is being written to it else read from it - * *start: If inout==FALSE start of the valid data in the buffer - * offset: If inout==FALSE offset from the beginning of the imaginary file - * from which we start writing into the buffer - * length: If inout==FALSE max number of bytes to be written into the buffer - * else number of bytes in the buffer - */ -int PTI_procfile_read(char *buffer, - char **buffer_location, - off_t offset, - int buffer_length, - int hostno, - int inout) -{ - /* - * The number of bytes actually used - */ - int len; - - /* - * This is static so it will still be in memory - * when we leave this function - */ - static char my_buffer[4096] = {0}; - char tmp_buffer[256] = {0}; - char *ptr = my_buffer; - int i, j; - - /* - * We give all of our information in one go, so if the - * user asks us if we have more information the - * answer should always be no. - * - * This is important because the standard read - * function from the library would continue to issue - * the read system call until the kernel replies - * that it has no more information, or until its - * buffer is filled. - */ - if (offset > 0) - return 0; - - /* - * Fill the buffer and get its length - */ - sprintf(ptr,"***** SuperTrak SX6000 Driver Version %2d.%2d *****\n", VERSIONHI, VERSIONLO); - ptr += strlen(ptr); - sprintf(ptr,"***** Copyright 1999-2001 by Promise Technology, Inc. *****\n\n"); - ptr += strlen(ptr); - - for(i = 0; i < MAX_ADAPTORS && (len = strlen(my_buffer)) < 4095; i++) { - if(!pti_st_hostp[i]) - continue; - sprintf(tmp_buffer, "\n\tIOP Number: %d\n", i); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tCapabilities: %d", - pti_st_hostp[i]->IopStatus.IopCapabilities); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\t\tState: %d\n", - pti_st_hostp[i]->IopStatus.IopState); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tI2OVersion: %d", - pti_st_hostp[i]->IopStatus.I2oVersion); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\t\t\tMessengerType: 0x%x\n", - pti_st_hostp[i]->IopStatus.MessengerType); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tMaxMessageFrameSize: 0x%x", - pti_st_hostp[i]->IopStatus.InboundMFrameSize); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tExpectedLCTSize: 0x%x\n", - pti_st_hostp[i]->IopStatus.ExpectedLCTSize); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tMaxInboundMFrames: 0x%x", - pti_st_hostp[i]->IopStatus.MaxInboundMFrames); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tInitialInboundMFrames: 0x%x\n", - pti_st_hostp[i]->IopStatus.CurrentInboundMFrames); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\n\tLCT Entry:\n"); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - - j = 0; - while(pti_st_hostp[i]->LctEntryTable[j].TableEntrySize == 0x09) - { - sprintf(tmp_buffer, "\n\tClass: 0x%x", - pti_st_hostp[i]->LctEntryTable[j].ClassID.Class); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\t\tVersion: %d\n", - pti_st_hostp[i]->LctEntryTable[j].ClassID.Version); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tOrganizationID: 0x%x", - pti_st_hostp[i]->LctEntryTable[j].ClassID.Version); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tLocalTID: 0x%x\n", - pti_st_hostp[i]->LctEntryTable[j].LocalTID); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tChangeIndicator: 0x%x", - pti_st_hostp[i]->LctEntryTable[j].ChangeIndicator); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tDeviceFlags: 0x%x\n", - pti_st_hostp[i]->LctEntryTable[j].DeviceFlags); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tSubClassInfo: 0x%x", - pti_st_hostp[i]->LctEntryTable[j].SubClassInfo); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tUserTID: 0x%x\n", - pti_st_hostp[i]->LctEntryTable[j].UserTID); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tParentTID: 0x%x", - pti_st_hostp[i]->LctEntryTable[j].ParentTID); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\t\tBiosInfo: 0x%x\n", - pti_st_hostp[i]->LctEntryTable[j].BiosInfo); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - sprintf(tmp_buffer, "\tEventCapabilities: 0x%x\n", - pti_st_hostp[i]->LctEntryTable[j].EventCapabilities); - ADDTOPROCBUFFER(my_buffer, tmp_buffer); - j++; - } - } - -proc_out: - /* - * Tell the function which called us where the - * buffer is - */ - len = strlen(my_buffer); - if(len < buffer_length) - buffer_length = len; - else if(len >= buffer_length) { - my_buffer[buffer_length-1] = 0; - len = buffer_length - 1; - } - - *buffer_location = my_buffer; - - /* - * Return the length - */ - return len; -} - -/*+F************************************************************************* - * Function: - * PTI_ST_info - * - * Description: - * Return a string describing the driver. - *-F*************************************************************************/ -const char *PTI_ST_info(struct Scsi_Host *dooh) -{ - static char buffer[256]; - char *bp; - - bp = &buffer[0]; - memset(bp, 0, sizeof(buffer)); - strcpy(bp, "PROMISE SuperTrak SX6000 Driver"); - return(bp); -} - - -/*++ - -Routine Description: - - This routine will write data specified by Buffer to PCIConfig Space - at Offset - -Arguments: - - -Return Values: - - Length of data which has been written - ---*/ - -static ULONG PTI_ST_SetBusDataByOffset( - ULONG BusNumber, - ULONG DeviceNumber, - ULONG FunctionNumber, - void *Buffer, - ULONG Offset, - ULONG Length -) -{ - ULONG cr; - - cr = 0x80000000 | - (BusNumber << 16) | - (DeviceNumber<<11) | - (FunctionNumber<<8) | - (Offset & 0xFC); - - outl(cr, 0xCf8); - - if (Length == 4) - outl(*((ULONG *)Buffer), 0xcfc); - else if (Length == 2) - { - ULONG data; - - data = (inl(0xCfC) & (Offset&0x3 ? 0xFFFF : 0xFFFF0000)); - data |= (((ULONG)(*(USHORT *)Buffer)) << (Offset&0x3 ? 16 : 0)); - outl(data, 0xcfc); - } - else - return(0); - - return(Length); - -} - - -/* - * Function: scbq_init(volatile scb_queue_type *queue) - * Description: SCB queue initialization. - */ -static void -scbq_init(volatile scb_queue_type *queue) -{ - queue->head = NULL; - queue->tail = NULL; -} - -/* - * Function: scbq_insert_head(volatile scb_queue_type, struct pti_st_scb) - * Description: Add an SCB to the head of the list. - */ -static inline void -scbq_insert_head(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) -{ - DRIVER_LOCK - scb->q_next = queue->head; - queue->head = scb; - if (queue->tail == NULL) /* If list was empty, update tail. */ - queue->tail = queue->head; - DRIVER_UNLOCK -} - -/* - * Function: scbq_remove_head(volatile scb_queue_type) - * Description: Remove an SCB from the head of the list. - */ -static inline struct pti_st_scb * -scbq_remove_head(struct pti_st_host *p, volatile scb_queue_type *queue) -{ - struct pti_st_scb * scbp; - - DRIVER_LOCK - scbp = queue->head; - if (queue->head != NULL) - queue->head = queue->head->q_next; - if (queue->head == NULL) /* If list is now empty, update tail. */ - queue->tail = NULL; - DRIVER_UNLOCK - return(scbp); -} - -/* - * Function: scbq_remove(volatile scb_queue_type, struct pti_st_scb) - * Description: Removes an SCB from the list. - */ -static inline void -scbq_remove(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags; -#endif - - DRIVER_LOCK - if (queue->head == scb) - { - /* At beginning of queue, remove from head. */ - scbq_remove_head(p, queue); - } - else - { - struct pti_st_scb *curscb = queue->head; - - /* - * Search until the next scb is the one we're looking for, or - * we run out of queue. - */ - while ((curscb != NULL) && (curscb->q_next != scb)) - { - curscb = curscb->q_next; - } - if (curscb != NULL) - { - /* Found it. */ - curscb->q_next = scb->q_next; - if (scb->q_next == NULL) - { - /* Update the tail when removing the tail. */ - queue->tail = curscb; - } - } - } - DRIVER_UNLOCK -} - -/* - * Function: scbq_insert_tail(volatile scb_queue_type, struct pti_st_scb) - * Description: Add an SCB at the tail of the list. - */ -static inline void -scbq_insert_tail(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags; -#endif - - DRIVER_LOCK - scb->q_next = NULL; - if (queue->tail != NULL) /* Add the scb at the end of the list. */ - queue->tail->q_next = scb; - queue->tail = scb; /* Update the tail. */ - if (queue->head == NULL) /* If list was empty, update head. */ - queue->head = queue->tail; - DRIVER_UNLOCK -} - -/* - * Function: pti_st_allocate_scb(struct pti_st_host *, struct pti_st_scb *) - * Description: Free the scb and insert into the free scb list. - */ -static int -pti_st_allocate_scb(struct pti_st_host *p) -{ - struct pti_st_scb *scbp = NULL; - int scb_size = sizeof(struct pti_st_scb); - int i; - unsigned long scb_count = 0; - struct pti_st_scb *scb_ap; - - scb_count = p->scb_data->maxscbs; - scb_ap = (struct pti_st_scb *)kmalloc(scb_size * scb_count, GFP_ATOMIC); - if (scb_ap != NULL) - { - memset(scb_ap, 0, scb_count * scb_size); - for (i=0; i < scb_count; i++) - { - scbp = &scb_ap[i]; - scbp->mf = NULL; - scbp->tag = i; - - /* - * Place in the scb array; never is removed - */ - p->scb_data->scb_array[i] = scbp; - scbq_insert_head(p, &p->scb_data->free_scbs, scbp); - } - scbp->kmalloc_ptr = scb_ap; - } - else - { - return(0); - } - return(scb_count); -} - -/* - * Function: pti_st_queue_cmd_complete(struct pti_st_host *, Scsi_Cmnd *) - * Description: Due to race conditions present in the SCSI subsystem, it is - * easier to queue completed commands, then call scsi_done() on - * them when we're finished. - * This function queues the completed commands. - */ -static void -pti_st_queue_cmd_complete(struct pti_st_host *p, Scsi_Cmnd *cmd) -{ - cmd->host_scribble = (char *)p->completeq.head; - p->completeq.head = cmd; -} - -/* - * Function: pti_st_done_cmds_complete(struct pti_st_host *) - * Description: Process the completed command queue. - */ -static void -pti_st_done_cmds_complete(struct pti_st_host *p) -{ - Scsi_Cmnd *cmd; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned int cpu_flags = 0; - - DRIVER_LOCK - while (p->completeq.head != NULL) - { - cmd = p->completeq.head; - p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble; - cmd->host_scribble = NULL; - sti(); - cmd->scsi_done(cmd); - cli(); - } - DRIVER_UNLOCK - -#else - - while (p->completeq.head != NULL) - { - cmd = p->completeq.head; - p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble; - cmd->host_scribble = NULL; - cmd->scsi_done(cmd); - } - -#endif -} - -/* - * Function: pti_st_free_scb(struct pti_st_host *, struct pti_st_scb *) - * Description: Free the scb and insert into the free scb list. - */ -static void -pti_st_free_scb(struct pti_st_host *p, struct pti_st_scb *scb) -{ - - scb->flags = SCB_FREE; - scb->cmd = NULL; - scb->sg_count = 0; - scb->sg_length = 0; - -// scb->mf->target_channel_lun = SCB_LIST_NULL; - - scbq_insert_head(p, &p->scb_data->free_scbs, scb); -} - -/* - * Function: pti_st_done(struct pti_st_host *, struct pti_st_scb *) - * Description: Calls the higher level scsi done function and frees the scb. - */ -static void -pti_st_done(struct pti_st_host *p, struct pti_st_scb *scb) -{ - Scsi_Cmnd *cmd = scb->cmd; - - if (scb->flags & SCB_RESET) - { - cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); - } - else if (scb->flags & SCB_ABORT) - { - cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); - } - - pti_st_free_scb(p, scb); - pti_st_queue_cmd_complete(p, cmd); -} - -/* - * Function: pti_st_run_done_queue(struct pti_st_host *, int) - * Description: Calls the pti_st_done() for the Scsi_Cmnd of each scb in the - * aborted list, and adds each scb to the free list. If complete - * is TRUE, we also process the commands complete list. - */ -static void -pti_st_run_done_queue(struct pti_st_host *p, int complete) -{ - struct pti_st_scb *scb; - int i; - - for (i = 0; i < p->scb_data->maxscbs; i++) - { - scb = p->scb_data->scb_array[i]; - if (scb->flags & SCB_QUEUED_FOR_DONE) - pti_st_done(p, scb); - } - if (complete) - { - pti_st_done_cmds_complete(p); - } -} - -/* - * Function: pti_st_isr(int, void, struct pt_regs) - * Description: i960 controller interrupt handler. - */ -static void -pti_st_isr(int irq, void *dev_id, struct pt_regs *regs) -{ - volatile U32 phyAddrMsg = 0xffffffff; - U32 scb_index; - Scsi_Cmnd *cmd; - struct pti_st_host *p; - struct pti_st_scb *scbp; - PI2O_BSA_REPLY_MESSAGE_FRAME rmfp = NULL; - int testtime = 0; - int i; - - p = (struct pti_st_host *)dev_id; - if(!p) - return; - - for(i = 0; i < MAX_ADAPTORS; i++) - if(pti_st_hostp[i] == p) - break; - - if(i >= MAX_ADAPTORS || !p->p_atu) - return; - - phyAddrMsg = p->p_atu->OutQueue; - - while (TRUE) - { - for(testtime = 1; - (phyAddrMsg == 0xffffffff) && (testtime < 3); - testtime++) - { - phyAddrMsg = p->p_atu->OutQueue; - } - - if(phyAddrMsg == 0xffffffff) { - return; - } - - rmfp = (PI2O_BSA_REPLY_MESSAGE_FRAME)(bus_to_virt(phyAddrMsg)); - - scb_index = rmfp->StdMessageFrame.InitiatorContext; - scbp = p->scb_data->scb_array[scb_index]; - if (!scbp) - { - /* return MFA to outbound free Q*/ - p->p_atu->OutQueue = phyAddrMsg; - - /* any more msgs? */ - phyAddrMsg = p->p_atu->OutQueue; - continue; - } - - cmd = scbp->cmd; - - //printk("return cmd= 0x%x, mfp= 0x%x, sno= 0x%x tag= 0x%x ind= 0x%x scb= 0x%x\n", - // cmd, rmfp, cmd->serial_number, scbp->tag, scb_index, scbp); - if (cmd->serial_number != rmfp->TransactionContext) - { - printk("Error in cmd%2x, mismatch sn 0x%x, mfp 0x%x scbi= %x\n", - cmd->cmnd[0], (int)cmd->serial_number, - (int)rmfp->TransactionContext, - (int)scb_index); - /* return MFA to outbound free Q*/ - p->p_atu->OutQueue = phyAddrMsg; - - /* any more msgs? */ - phyAddrMsg = p->p_atu->OutQueue; - continue; - } - - if (rmfp->ReqStatus != I2O_REPLY_STATUS_SUCCESS) { - cmd->result = DID_ERROR; -#if defined(DEBUG) - printk("pti_st_isr: Reply Status Fail, ReqStatus[%x], DetailedStatus[%x]\n", rmfp->ReqStatus, rmfp->DetailedStatusCode); -#endif - } - - pti_st_free_scb(p, scbp); - pti_st_queue_cmd_complete(p, cmd); - /* return MFA to outbound free Q*/ - p->p_atu->OutQueue = phyAddrMsg; - - /* any more msgs? */ - phyAddrMsg = p->p_atu->OutQueue; - } - - return; -} - -/* - * Function: do_pti_st_isr(int, void *, struct pt_regs *) - * Description: - * This is a gross hack to solve a problem in linux kernels 2.1.85 and - * above. Please, children, do not try this at home, and if you ever see - * anything like it, please inform the Gross Hack Police immediately - */ -void do_pti_st_isr( int irq, void *dev_id, struct pt_regs * regs ) -{ - unsigned long cpu_flags = 0; - struct pti_st_host *p; - U32 OutIntStat; - int i; - - p = (struct pti_st_host *)dev_id; - if(!p) - return; - - for(i = 0; i < MAX_ADAPTORS; i++) - if(p == pti_st_hostp[i]) - break; - - if(i >= MAX_ADAPTORS) - return; - - OutIntStat = p->p_atu->OutIntStat; - - if (OutIntStat==0) - return; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95) - if(test_and_set_bit(PSTC_IN_ISR_BIT, &p->flags)) - { - return; - } - spin_lock_irqsave(&io_request_lock, cpu_flags); - pti_st_isr(irq, dev_id, regs); - pti_st_done_cmds_complete(p); - clear_bit(PSTC_IN_ISR_BIT, &p->flags); - spin_unlock_irqrestore(&io_request_lock, cpu_flags); -#else - if(set_bit(PSTC_IN_ISR_BIT, (int *)&p->flags)) - { - return; - } - DRIVER_LOCK - pti_st_isr(irq, dev_id, regs); - DRIVER_UNLOCK - pti_st_done_cmds_complete(p); - clear_bit(PSTC_IN_ISR_BIT, (int *)&p->flags); -#endif -} - -/* - * Function: pti_st_register(Scsi_Host_Template *, struct pti_st_host *) - * Description: Register i960 controller with the kernel. - */ -static int -pti_st_register(Scsi_Host_Template *template, struct pti_st_host *p) -{ - int result; - struct Scsi_Host *host; - - host = p->host; - - p->scb_data->maxscbs = PTI_ST_MAXSCB; - host->can_queue = PTI_ST_MAXSCB; - host->cmd_per_lun = 3; - host->sg_tablesize = PTI_ST_MAX_SG; - host->this_id = p->scsi_id; - host->irq = p->pci_irq; - - p->host = host; - p->host_no = host->host_no; - p->completeq.head = NULL; - p->completeq.tail = NULL; - - /* - * Initialize the Super Track hardware controler, procedure as the - * typical system initialization of I2O - */ - p->maddr = ioremap(p->mbase, 4*1024*1024); - if(!(p->maddr)) - { - p->pci_irq = 0; - return (0); - } - - p->p_atu = (PATU)p->maddr; - p->LinBaseAddr = (PU8)p->maddr; - - p->outboundBufferp = (outboundBuff_t *)kmalloc((16*1024+256+32*32*4), GFP_ATOMIC); - if(p->outboundBufferp == NULL) { - p->pci_irq = 0; - printk("Allocating buffer fails!\n"); - return(0); - } - p->replyBufferp = (PU8)((PU8)p->outboundBufferp + 32*32*4); - p->messageBufferp = p->replyBufferp + (16*1024); - - p->outMsgBlockPhyAddr = virt_to_bus(p->outboundBufferp); - p->pLinOutMsgBlock = (PU8)(p->outboundBufferp); - - /* - * Allocate the set of scbs for this controller. This is to stream- - * line code elsewhere in the driver. If we have to check for the existence - * of scbs in certain code sections, it slows things down. However, as - * soon as we register the IRQ for this card, we could get an interrupt that - * includes possibly the SCSI_RSTI interrupt. If we catch that interrupt - * then we are likely to segfault if we don't have at least one chunk of - * SCBs allocated or add checks all through the reset code to make sure - * that the SCBs have been allocated which is an invalid running condition - * and therefore I think it's preferable to simply pre-allocate the first - * chunk of SCBs. - */ - - result = pti_st_allocate_scb(p); - if(!result) - { - p->pci_irq = 0; - printk("Allocating scbs fails!\n"); - return(0); - } - - /* - * Disable interrupt - */ - p->p_atu->OutIntMask = 0xffffffff; - - if(!IOP_init(p)) - { - p->pci_irq = 0; - return (0); - } - - /* - * Clear out any possible pending interrupts, again. - */ - /* pti_st_clear_intstat(p); */ - - /* - * Register IRQ with the kernel. Only allow sharing IRQs with - * PCI devices. - */ - result = (request_irq(p->pci_irq, do_pti_st_isr, SA_SHIRQ, "pti_st", p)); - if(result < 0) - { - result = (request_irq(p->pci_irq, do_pti_st_isr, - (SA_INTERRUPT | SA_SHIRQ), "pti_st", p)); - } - - if (result < 0) - { - printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring " - "controller.\n", p->host_no, p->pci_irq); - p->pci_irq = 0; - return (0); - } else { - /* - * Enable interrupt - */ - p->p_atu->OutIntMask = 0x00000000; - } - - host->max_id = MAX_ARRAYS; - host->max_channel = 0; - host->max_lun = p->max_lun = 1; - - return (1); -} - -/* - * Function: pti_st_free(struct pti_st_host *) - * Description: Frees and releases all resources associated with an instance of - * the driver (struct pti_st_host *). - */ -static void -pti_st_free(struct pti_st_host *p) -{ - int i; - - if (p->scb_data != NULL) - { - - /* - * Free the driver SCBs. These were allocated on an as-need - * basis. We allocated these in groups depending on how many - * we could fit into a given amount of RAM. The tail SCB for - * these allocations has a pointer to the alloced area. - */ - for (i = 0; i < p->scb_data->maxscbs; i++) - { - if (p->scb_data->scb_array[i]->kmalloc_ptr != NULL) - kfree(p->scb_data->scb_array[i]->kmalloc_ptr); - p->scb_data->scb_array[i] = NULL; - } - - /* - * Free the SCB data area. - */ - kfree(p->scb_data); - } -} - -/* - * Function: pti_st_release(struct Scsi_Host *) - * Description: Free the passed in Scsi_Host memory structures prior to - * unloading the module. - */ -int -pti_st_release(struct Scsi_Host *host) -{ - struct pti_st_host *p = (struct pti_st_host *) host->hostdata; - int i; - - for(i = 0; i < MAX_ADAPTORS; i++) - if(p == pti_st_hostp[i]) - break; - - if(!p || i >= MAX_ADAPTORS) - return(-1); - - if(p->pci_irq) { - free_irq(p->pci_irq, p); - p->pci_irq = 0; - /* - * Disbale interrupt - */ - p->p_atu->OutIntMask = 0x000000fc; - } - if(p->maddr) - { - iounmap((void *) (((unsigned long) p->maddr))); - p->maddr = 0; - } - if(p->outboundBufferp) { - kfree(p->outboundBufferp); - p->outboundBufferp = NULL; - } - if(p->pti_stdev_bufferp) { - kfree(p->pti_stdev_bufferp); - p->pti_stdev_bufferp = NULL; - } - pti_st_free(p); - pti_st_hostp[i] = NULL; - return(0); -} - -/* - * Function: pti_st_alloc(Scsi_Host_Template *, struct pti_st_host *) - * Description: Allocate and initialize a host structure. - * Returns NULL upon error and a pointer to a pti_st_host struct - * upon success. - */ -static struct pti_st_host * -pti_st_alloc(Scsi_Host_Template *sht, struct pti_st_host *temp) -{ - struct pti_st_host *p = NULL; - struct Scsi_Host *host; - - /* - * Allocate a storage area by registering us with the mid-level - * SCSI layer. - */ - host = scsi_register(sht, sizeof(struct pti_st_host)); - - if (host != NULL) - { - p = (struct pti_st_host *) host->hostdata; - memset(p, 0, sizeof(struct pti_st_host)); - *p = *temp; - p->host = host; - p->scsi_id = -1; - p->host_no = host->host_no; - p->scb_data = kmalloc(sizeof(scb_data_type), GFP_ATOMIC); - if (p->scb_data != NULL) - { - memset(p->scb_data, 0, sizeof(scb_data_type)); - scbq_init (&p->scb_data->free_scbs); - } - else - { - /* - * For some reason we don't have enough memory. Free the - * allocated memory for the pti_st_host struct, and return NULL. - */ - scsi_unregister(host); - return(NULL); - } - p->pti_stdev_bufferp = kmalloc(sizeof(PTI_STDEV_INBUFFER), GFP_ATOMIC); - if(p->pti_stdev_bufferp != NULL) - { - memset(p->pti_stdev_bufferp, 0, sizeof(PTI_STDEV_INBUFFER)); - } else { - scsi_unregister(host); - return(NULL); - } - } - return (p); -} - - -/* - * Function: pti_st_detect(Scsi_Host_Template *) - * Description: Try to detect and register i960 controller. - * This should really be called pti_st_probe(). A sequence of - * probe(), attach()/detach(), and init() makes more sense than - * one do-it-all function. This may be useful when (and if) the - * mid-level SCSI code is overhauled. - */ -int pti_st_detect(Scsi_Host_Template *template) -{ - struct pci_dev *pdev; - int found = 0; - - if (!pci_present()) - return 0; - - // printk("pti_st.c: PCI bios is present, checking for devices ...\n"); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_for_each_dev(pdev) -#else - for(pdev = pci_devices, found = 0; - found < MAX_ADAPTORS && pdev != NULL; - pdev = pdev->next) -#endif - { - if(pdev->vendor != PCI_VENDOR_ID_INTEL || - (pdev->device != PCI_DEVICE_ID_INTEL_i960 && /* ST100 */ - pdev->device != PCI_DEVICE_ID_INTEL_i962)) /* ST100SX6 */ - continue; - - pti_st_install(template, pdev, &found); - } - - return(found); -} - -static int pti_st_install(Scsi_Host_Template *template, struct pci_dev *pdev, int *aptno) -{ - struct pti_st_host *p = NULL; - struct pti_st_host *temp_p = NULL; - unsigned short command; - unsigned long cmd; - unsigned long devicenumber, functionnumber; - - devicenumber = PCI_SLOT(pdev->devfn); - functionnumber = 0; - - /* - * Expose the ship behind i960 for initialization, or it will failed - */ - cmd = 0x0000; - PTI_ST_SetBusDataByOffset(pdev->bus->number, - devicenumber, - functionnumber, - &cmd, - 0x42, - sizeof(U16)); - - template->sg_tablesize = PTI_ST_MAX_SG; - template->proc_dir = &proc_scsi_pti_st; - template->proc_info = PTI_procfile_read; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if(!template->proc_name) { - if(template->name) - template->proc_name = (char *)template->name; - else - template->proc_name = "pti_st"; - } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_enable_device(pdev); -#endif - - if ( !(temp_p = kmalloc(sizeof(struct pti_st_host), GFP_ATOMIC))) - { - printk("pti_st_host data structure memory alloc error!!!\n"); - cmd = 0x03ff; - PTI_ST_SetBusDataByOffset(pdev->bus->number, - devicenumber, - functionnumber, - &cmd, - 0x42, - sizeof(U16)); - return(0); - } - memset(temp_p, 0, sizeof(struct pti_st_host)); - - temp_p->pci_irq = pdev->irq; - temp_p->pdev = pdev; - temp_p->pci_bus = pdev->bus->number; - temp_p->pci_device_fn = pdev->devfn; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - temp_p->mbase = pci_resource_start(pdev, 0); - template->name = "pti_st"; -#else - temp_p->mbase = pdev->base_address[0]; -#endif - pci_read_config_word(pdev, PCI_COMMAND, &command); - - command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; - pci_write_config_word(pdev, PCI_COMMAND, command); - - temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; - - printk("Found PTI SuperTrak at mbase: %#x, irq %d.\n", - temp_p->mbase, temp_p->pci_irq); - - pti_st_hostp[*aptno] = p = pti_st_alloc(template, temp_p); - - if (p != NULL) - { - DRIVER_LOCK_INIT - (*aptno)++; - if (!pti_st_register(template, p)) - { - pti_st_release(p->host); - scsi_unregister(p->host); - (*aptno)--; - pti_st_hostp[*aptno] = NULL; - } - } - - cmd = 0x03ff; - PTI_ST_SetBusDataByOffset(pdev->bus->number, - devicenumber, - functionnumber, - &cmd, - 0x42, - sizeof(U16)); - - kfree(temp_p); - return (*aptno); -} - -/* - * Function: pti_st_copy_internal_data(Scsi_Cmnd *, char *, unsigned short) - * Description: Queue a SCB to the controller. - */ -static void -pti_st_copy_internal_data(Scsi_Cmnd *scp, char *buffer, unsigned short count) -{ - unsigned short cpcount,i; - unsigned short cpsum,cpnow; - struct scatterlist *sl; - - cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; - if (scp->use_sg) - { - sl = (struct scatterlist *)scp->request_buffer; - for (i=0,cpsum=0; iuse_sg; ++i,++sl) - { - cpnow = (ushort)sl->length; - if (cpsum+cpnow > cpcount) - cpnow = cpcount - cpsum; - cpsum += cpnow; - memcpy((char*)sl->address,buffer,cpnow); - if (cpsum == cpcount) - break; - buffer += cpnow; - } - } - else - { - memcpy((char*)scp->request_buffer,buffer,cpcount); - } -} - - -/* - * Function: pti_st_rw_cmd(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) * Description: Translate Scsi Command to I2O Message Frame. - */ -static int -pti_st_rw_cmd(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) -{ - struct pti_st_host *p; - struct pti_st_scb *scb; - unsigned long msgoffset; - unsigned long blk_nr = 0; - unsigned long blk_count = 0; - PI2O_BSA_RW_MESSAGE mfp; - unsigned char *cmnd; - unsigned long pBaseAddrReg; - int i; - - p = (struct pti_st_host *) cmd->host->hostdata; - - for(i = 0; i < MAX_ADAPTORS; i++) - if(p == pti_st_hostp[i]) - break; - - if(i >= MAX_ADAPTORS || !p) { - cmd->result = (DID_BAD_TARGET << 16); - fn(cmd); - return 0; - } - - scb = scbq_remove_head(p, &p->scb_data->free_scbs); - - if (scb == NULL) - { - cmd->result = (DID_BUS_BUSY << 16); - printk(WARN_LEAD"Couldn't get a free SCB.\n", p->host_no, - CTL_OF_CMD(cmd)); - fn(cmd); - return 0; - } - - if (cmd->target >= MAX_DRIVES || p->I2ODisk[cmd->target].present != TRUE) - { - cmd->result = (DID_BAD_TARGET << 16); - fn(cmd); - return 0; - } - - DRIVER_LOCK - - pBaseAddrReg = (U32)p->maddr; - msgoffset = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); - if (msgoffset == 0xFFFFFFFF) - { - printk(INFO_LEAD"Couldn't get a free MF from inboundqport.\n", - p->host_no, CTL_OF_CMD(cmd)); - cmd->result = (DID_BUS_BUSY << 16); -/* - * DRIVER_LOCK - */ - scbq_insert_head(p, &p->scb_data->free_scbs, scb); - DRIVER_UNLOCK - fn(cmd); - return 0; - } - scb->cmd = cmd; - pti_st_position(cmd) = scb->tag; - - p->scb_data->scb_array[scb->tag] = scb; - - /* - * Make sure the Scsi_Cmnd pointer is saved, the struct it points to - * is set up properly, and the parity error flag is reset, then send - * the SCB to the sequencer and watch the fun begin. - */ - cmd->scsi_done = fn; - cmd->result = DID_OK; - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - cmd->host_scribble = NULL; - - scb->flags |= SCB_ACTIVE; - mfp = (PI2O_BSA_RW_MESSAGE)(pBaseAddrReg + msgoffset); - memset((char *)mfp, 0, sizeof(I2O_BSA_READ_MESSAGE)); - cmnd = (unsigned char *)cmd->cmnd; - switch (*cmnd) - { - case READ_6: - { - blk_nr = cmnd[3] + (cmnd[2] << 8) + ((cmnd[1] & 0x1f) << 16); - blk_count = cmnd[4]; - } - mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_READ; - mfp->FetchAhead = 0; - break; - - case READ_10: - { - blk_nr = ntohl(*(PU32)&cmnd[2]); - blk_count = cmnd[8] + (cmnd[7] << 8); - } - mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_READ; - mfp->FetchAhead = 0; - break; - - case WRITE_6: - { - blk_nr = cmnd[3] + (cmnd[2] << 8) + ((cmnd[1] & 0x1f) << 16); - blk_count = cmnd[4]; - } - mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_WRITE; - break; - - case WRITE_10: - { - blk_nr = ntohl(*(PU32)&cmnd[2]); - blk_count = cmnd[8] + (cmnd[7] << 8); - } - mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_WRITE; - break; - } - mfp->LogicalByteAddress.HighPart = blk_nr >> (32 - 9); - mfp->LogicalByteAddress.LowPart = blk_nr << 9; - mfp->TransferByteCount = blk_count << 9; - mfp->TransactionContext = cmd->serial_number; - mfp->StdMessageFrame.InitiatorContext = scb->tag; - mfp->StdMessageFrame.VersionOffset=0x81; - mfp->StdMessageFrame.MsgFlags=0; - mfp->StdMessageFrame.MessageSize=sizeof(I2O_BSA_READ_MESSAGE)>>2; - mfp->StdMessageFrame.TargetAddress=p->I2ODisk[cmd->target].LocalTID; - mfp->StdMessageFrame.InitiatorAddress = 0x01; - mfp->ControlFlags = 0; - mfp->TimeMultiplier = 0x31; /*0;*/ - - { - //printk("Issue cmd= %x, mfp 0x%x, sno= 0x%x tag= 0x%x scb=0x%x\n", - // cmd, mfp, cmd->serial_number, scb->tag, scb); - } - /* - * The interpretation of request_buffer and request_bufflen - * changes depending on whether or not use_sg is zero; a - * non-zero use_sg indicates the number of elements in the - * scatter-gather array. - */ - - if (cmd->use_sg) - { - struct scatterlist *sg; /* Must be mid-level SCSI code scatterlist */ - - /* - * We must build an SG list in I2O SGL format, as the kernel's SG list - * cannot be used directly - */ - int i; - - sg = (struct scatterlist *)cmd->request_buffer; - /* - * Copy the segments into the SG array. NOTE!!! - We used to - * have the first entry both in the data_pointer area and the first - * SG element. That has changed somewhat. We still have the first - * entry in both places, but now we download the address of - * scb->sg_list[1] instead of 0 to the sg pointer in the mf. - */ - for (i = 0; i < (cmd->use_sg); i++) - { - mfp->SGL.u.Simple[i].FlagsCount.Count = cpu_to_le32(sg[i].length); - mfp->SGL.u.Simple[i].FlagsCount.Flags = - (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); - mfp->SGL.u.Simple[i].PhysicalAddress = - cpu_to_le32(VIRT_TO_BUS(sg[i].address)); - } - mfp->SGL.u.Simple[cmd->use_sg - 1].FlagsCount.Flags |= - ( I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER); - } - else - { - mfp->SGL.u.Simple[0].FlagsCount.Count = - cpu_to_le32(cmd->request_bufflen); - mfp->SGL.u.Simple[0].FlagsCount.Flags = - ( I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_TRANSPORT_ELEMENT | - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); - mfp->SGL.u.Simple[0].PhysicalAddress = - cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer)); - } - - * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgoffset; - - DRIVER_UNLOCK - - return (0); -} - -/* - * Function: pti_st_internal_cmd(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) - * Description: Excuting TEST_UNIT_READY, INQUIRY, READ_CAPACITY, etc. - * scsi command. - */ -static int -pti_st_internal_cmd(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) -{ - struct pti_st_host *p; - - // struct pti_st_scb *scb; - // unsigned long cpu_flags = 0; - pti_inq_data inq; - pti_rdcap_data rdc; - int i; - - p = (struct pti_st_host *) cmd->host->hostdata; - - for(i = 0; i < MAX_ADAPTORS; i++) - if(p == pti_st_hostp[i]) - break; - - if(i >= MAX_ADAPTORS) { - cmd->result = (DID_BAD_TARGET << 16); - fn(cmd); - return 0; - } - - switch (cmd->cmnd[0]) - { - case TEST_UNIT_READY: - cmd->result = DID_OK << 16; - break; - - case INQUIRY: - memset((void *)&inq, 0, sizeof(inq)); - inq.type_qual = TYPE_DISK; - /* - * you can here set all disks to removable, if you want to do - * a flush using the ALLOW_MEDIUM_REMOVAL command - */ - inq.modif_rmb = 0x00; - inq.version = 2; - inq.resp_aenc = 2; - inq.add_length= 32; - strcpy(inq.vendor,"PTI "); - strcpy(inq.product,"SuperTrak"); - strcpy(inq.revision," "); - if(cmd->target < MAX_DRIVES && p->I2ODisk[cmd->target].present == TRUE) - { - pti_st_copy_internal_data(cmd,(char*)&inq, sizeof(pti_inq_data)); - cmd->result = DID_OK << 16; - } else { - pti_st_copy_internal_data(cmd,(char*)&inq, sizeof(pti_inq_data)); - cmd->result = DID_BAD_TARGET << 16; - } - break; - -#if 0 - case REQUEST_SENSE: - sd.errorcode = 0x70; - sd.segno = 0x00; - sd.key = NO_SENSE; - sd.info = 0; - sd.add_length= 0; - pti_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); - cmd->result = DID_OK << 16; - break; - case MODE_SENSE: - memset((char*)&mpd,0,sizeof(gdth_modep_data)); - mpd.hd.data_length = sizeof(gdth_modep_data); - mpd.hd.dev_par = (ha->id[b][t].devtype&2) ? 0x80:0; - mpd.hd.bd_length = sizeof(mpd.bd); - mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; - mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; - mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); - pti_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); - cmd->result = DID_OK << 16; - break; -#endif - - case READ_CAPACITY: - if(cmd->target < MAX_DRIVES && p->I2ODisk[cmd->target].present) - { - rdc.last_block_no = ntohl(p->I2ODisk[cmd->target].lastLBA); - rdc.block_length = ntohl(SECTOR_SIZE); - pti_st_copy_internal_data(cmd,(char*)&rdc, sizeof(pti_rdcap_data)); - cmd->result = DID_OK << 16; - } else { - cmd->result = DID_BAD_TARGET; - } - break; - - default: - printk("!!!!!!!!PTI: Unknown SCSI command 0x%x to cache service !\n", - cmd->cmnd[0]); - cmd->result = DID_ABORT << 16; - break; - } - - fn(cmd); - return 0; -} - -/* - * Function: pti_st_queue(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) - * Description: Queue a SCB to the controller. - */ -int -pti_st_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) -{ - int ret; - - switch (cmd->cmnd[0]) - { - case READ_6: - case READ_10: - case WRITE_6: - case WRITE_10: -// case VERIFY: - ret = pti_st_rw_cmd(cmd, fn); - return(ret); - case TEST_UNIT_READY: - case INQUIRY: - case READ_CAPACITY: - return(pti_st_internal_cmd(cmd, fn)); -// case VERIFY: -// case START_STOP: -// case REQUEST_SENSE: -// case MODE_SENSE: - - default: - break; - } - printk("PTI: Unknown SCSI command 0x%x to cache service!\n", cmd->cmnd[0]); - cmd->result = DID_ABORT << 16; - fn(cmd); - return 0; -} - -/* - * Function: pti_st_abort(Scsi_Cmnd *) - * Description: Abort the current SCSI command(s). - */ -int -pti_st_abort(Scsi_Cmnd *cmd) -{ - struct pti_st_scb *scb = NULL; - struct pti_st_host *p; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - Scsi_Cmnd *cmd_next, *cmd_prev; - int i; - - p = (struct pti_st_host *) cmd->host->hostdata; - for(i = 0; i < MAX_ADAPTORS; i++) - if(p == pti_st_hostp[i]) - break; - - if(i >= MAX_ADAPTORS || !p) { - return(SCSI_ABORT_NOT_RUNNING); - } - - scb = (p->scb_data->scb_array[pti_st_position(cmd)]); - - - DRIVER_LOCK - -/* - * Run the isr to grab any command in the QOUTFIFO and any other misc. - * assundry tasks. This should also set up the bh handler if there is - * anything to be done, but it won't run until we are done here since - * we are following a straight code path without entering the scheduler - * code. - */ - - { - pti_st_isr(p->pci_irq, p, (void *)NULL); - pti_st_done_cmds_complete(p); - } - - if ((scb == NULL) || (cmd->serial_number != cmd->serial_number_at_timeout)) - /* Totally bogus cmd since it points beyond our */ - { /* valid SCB range or doesn't even match it's own*/ - /* timeout serial number. */ - DRIVER_UNLOCK - return(SCSI_ABORT_NOT_RUNNING); - } - - if (scb->cmd != cmd) /* Hmmm...either this SCB is currently free with a */ - { /* NULL cmd pointer (NULLed out when freed) or it */ - /* has already been recycled for another command */ - /* Either way, this SCB has nothing to do with this*/ - /* command and we need to deal with cmd without */ - /* touching the SCB. */ - /* The theory here is to return a value that will */ - /* make the queued for complete command actually */ - /* finish successfully, or to indicate that we */ - /* don't have this cmd any more and the mid level */ - /* code needs to find it. */ - cmd_next = p->completeq.head; - cmd_prev = NULL; - while (cmd_next != NULL) - { - if (cmd_next == cmd) - { -// if (pti_st_verbose & VERBOSE_ABORT_PROCESS) - printk(INFO_LEAD "Abort called for command " - "on completeq, completing.\n", p->host_no, CTL_OF_CMD(cmd)); - if ( cmd_prev == NULL ) - p->completeq.head = (Scsi_Cmnd *)cmd_next->host_scribble; - else - cmd_prev->host_scribble = cmd_next->host_scribble; - cmd_next->scsi_done(cmd_next); - DRIVER_UNLOCK - - return(SCSI_ABORT_NOT_RUNNING); /* It's already back as a successful - * completion */ - } - cmd_prev = cmd_next; - cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; - } - -// if (pti_st_verbose & VERBOSE_ABORT_MID) - printk(INFO_LEAD "Abort called for already completed" - " command.\n", p->host_no, CTL_OF_CMD(cmd)); - DRIVER_UNLOCK - return(SCSI_ABORT_NOT_RUNNING); - } - -/* - * Hmmm...completeq, QOUTFIFO, QINFIFO, WAITING_SCBH, waitingq all checked. - * OK...the sequencer's paused, interrupts are off, and we haven't found the - * command anyplace where it could be easily aborted. Time for the hard - * work. We also know the command is valid. This essentially means the - * command is disconnected, or connected but not into any phases yet, which - * we know due to the tests we ran earlier on the current active scb phase. - * At this point we can queue the abort tag and go on with life. - */ - if (scb->flags & SCB_WAITINGQ) - { - scbq_remove(p, &p->waiting_scbs, scb); - } - scb->flags &= ~(SCB_WAITINGQ | SCB_ACTIVE); - scb->flags |= SCB_ABORT; - pti_st_done(p, scb); - pti_st_done_cmds_complete(p); -// pti_st_run_waiting_queues(p); - DRIVER_UNLOCK - -/* - * On the return value. If we found the command and aborted it, then we know - * it's already sent back and there is no reason for a further timeout, so - * we use SCSI_ABORT_SUCCESS. On the queued abort side, we aren't so certain - * there hasn't been a bus hang or something that might keep the abort from - * from completing. Therefore, we use SCSI_ABORT_PENDING. The first time -this - * is passed back, the timeout on the command gets extended, the second time - * we pass this back, the mid level SCSI code calls our reset function, which - * would shake loose a hung bus. - */ - return(SCSI_ABORT_SUCCESS); -} - -/* - * Function: pti_st_reset(Scsi_Cmnd *, unsigned int) - * Description: Resetting the bus always succeeds - is has to, otherwise the - * kernel will panic! Try a surgical technique: sending ARRAY - * RESET message frame - */ -int -pti_st_reset(Scsi_Cmnd *cmd, unsigned int flags) -{ - struct pti_st_scb *scb = NULL; - struct pti_st_host *p; - int i; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) - unsigned long cpu_flags = 0; -#endif - Scsi_Cmnd *cmd_prev, *cmd_next; - - - if ( cmd == NULL ) - { - return(SCSI_RESET_SNOOZE); - } - - p = (struct pti_st_host *) cmd->host->hostdata; - for(i = 0; i < MAX_ADAPTORS; i++) - if(p == pti_st_hostp[i]) - break; - - if(!p || i >= MAX_ADAPTORS) - return(SCSI_RESET_NOT_RUNNING); - - scb = (p->scb_data->scb_array[pti_st_position(cmd)]); - - DRIVER_LOCK - - pti_st_isr(p->pci_irq, p, (void *)NULL ); - pti_st_done_cmds_complete(p); - - if (scb == NULL) - { -// if (pti_st_verbose & VERBOSE_RESET_MID) - printk(INFO_LEAD "Reset called with bogus Scsi_Cmnd" - "->SCB mapping, improvising.\n", p->host_no, CTL_OF_CMD(cmd)); - } - else if (scb->cmd != cmd) - { -// if (pti_st_verbose & VERBOSE_RESET_MID) - printk(INFO_LEAD "Reset called with recycled SCB " - "for cmd.\n", p->host_no, CTL_OF_CMD(cmd)); - cmd_prev = NULL; - cmd_next = p->completeq.head; - while ( cmd_next != NULL ) - { - if (cmd_next == cmd) - { -// if (pti_st_verbose & VERBOSE_RESET_RETURN) - printk(INFO_LEAD "Reset, found cmd on completeq" - ", completing.\n", p->host_no, CTL_OF_CMD(cmd)); - DRIVER_UNLOCK - return(SCSI_RESET_NOT_RUNNING); - } - cmd_prev = cmd_next; - cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; - } - } -/* - * By this point, we want to already know what we are going to do and - * only have the following code implement our course of action. - */ - for (i = 0; i < p->scb_data->maxscbs; i++) - { - scb = p->scb_data->scb_array[i]; - if (scb->flags & SCB_ACTIVE) - { - scb->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE; - scb->flags &= ~(SCB_ACTIVE | SCB_WAITINGQ); - } - } - scbq_init(&p->waiting_scbs); - pti_st_run_done_queue(p, TRUE); - /* We can't rely on run_waiting_queues to unpause the sequencer for - * PCI based controllers since we use AAP */ - DRIVER_UNLOCK - return (SCSI_RESET_SUCCESS); -} - -/* - * Function: pti_st_biosparam(Disk *, kdev_t, int[]) - * Description: Return the disk geometry for the given SCSI device. - */ -int -pti_st_biosparam(Disk *disk, kdev_t dev, int geom[]) -{ - int heads; - int sectors; - int cylinders; - struct pti_st_host *p; - - p = (struct pti_st_host *) disk->device->host->hostdata; - - /* - * XXX - if I could portably find the card's configuration - * information, then this could be autodetected instead - * of left to a boot-time switch. - */ - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); - - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - - return (0); -} - - - - -/*************************************************************************** - Hardware Interface Functions -****************************************************************************/ - -/* - * Function : static int IOP_init(struct pti_st_host *); - * Description: just initialize the hardware, fetch parameters from PCI. - */ -static int IOP_init(struct pti_st_host *hostp) -{ - int index; - int IopStatus; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - unsigned long pMFA_Inbound; - - // printk("Initializing i960! pBaseAddrReg :%lx\n", pBaseAddrReg); - - // Until the Inbound Queue is available: - pMFA_Inbound = *(U32 *)(pBaseAddrReg+INBOUNDQPORT); - while (((U32) pMFA_Inbound == -1)) - pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); - UtilNOPCall(hostp); - - ExecIOPReset(hostp); - - IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); - - OutboundInitCall(hostp); - - UtilNOPCall(hostp); - IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); - - /* Outbound Queue is now available! */ - - SysTabSetCall(hostp, (PI2O_EXEC_SYS_TAB_SET_MESSAGE)hostp->messageBufferp, - (void *)hostp->replyBufferp); - if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) - { - printk("!BAD reply after sending ExecSysTabSet Message!\n"); - return(FALSE); - } - - IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); - - if (IopStatus == I2O_IOP_STATE_READY) - { - /* - * Send ExecSysEnable message, wait for reply - * - */ - EnableSysCall(hostp); - if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) - { - printk("!BAD reply after sending ExecSysEnable Message!\n"); - return(FALSE); - } - if (GetStatusCall(hostp, (void *)hostp->replyBufferp) != I2O_IOP_STATE_OPERATIONAL) - return(FALSE); - - } - - - /* IOP is in OPERATIONAL state! */ - - LCTNotifyCall(hostp); - if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) - { - printk("!BAD reply after sending ExecLctNotify Message!\n"); - return(FALSE); - } - - - /* IOP is now initialized! */ - - GetInfoFromLCT(hostp, - (void *)hostp->replyBufferp, - (PI2ODISK)hostp->I2ODisk, - (unsigned int *)&hostp->TotalDiskCount); - - for (index = 0; index < hostp->TotalDiskCount; index++) - { - ComposeDiskInfo(hostp, - (PI2O_UTIL_PARAMS_GET_MESSAGE)hostp->messageBufferp, - (void *)hostp->replyBufferp, - (PI2ODISK)&hostp->I2ODisk[index] ); - hostp->I2ODisk[index].present = TRUE; - } - - return(TRUE); -} - -/* - * Function: unsigned int GetStatusCall(void *) - * Description: get IOP's state. - * Return : IOP's current state. - */ -static unsigned int GetStatusCall(struct pti_st_host *hostp, void * replyBuffer) -{ - int i; - volatile int state; - U32 timeout; - U32 msgOffset; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - PI2O_EXEC_STATUS_GET_MESSAGE pMsg; - PI2O_EXEC_STATUS_GET_REPLY reply = - (PI2O_EXEC_STATUS_GET_REPLY)replyBuffer; - - msgOffset = hostp->p_atu->InQueue; - pMsg = (PI2O_EXEC_STATUS_GET_MESSAGE)(hostp->LinBaseAddr + msgOffset); - - memset((void *)reply, 0, sizeof(PI2O_EXEC_STATUS_GET_REPLY)); - - pMsg->ReplyBufferLength=0x100; - pMsg->ReplyBufferAddressLow = virt_to_bus(reply); - pMsg->VersionOffset=0x01; - pMsg->MsgFlags=0; /* No flag to set */ - pMsg->MessageSize=(sizeof(I2O_EXEC_STATUS_GET_MESSAGE)>>2); - pMsg->TargetAddress=0; - pMsg->InitiatorAddress=0x1; /* from host */ - pMsg->Function=I2O_EXEC_STATUS_GET; - - *(U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; /* YBM: ... = pMFA_Inbound;*/ - - timeout = 100000; - while(1) - { - for (i=0; i<1000; i++) /* please don't hog the bus! */ - ; - if ((state=reply->IopState) != 0) - break; - if (!timeout--) - { - printk(" Timeout wait for IOP Status Get Ready!\n"); - return -1; - } - } - - memcpy((void *)(&hostp->IopStatus), - (void *)reply, - sizeof(I2O_EXEC_STATUS_GET_REPLY)); - - return (unsigned int) reply->IopState; -} - - -/* -** ========================================================================= -** SendI2OOutboundQInitMsg() -** -** ========================================================================= -*/ -/* -static int -SendI2OOutboundQInitMsg(PPAB pPab) -{ - U32 msgOffset, timeout, phyOutQFrames, i; - volatile PU32 pMsg; - volatile PU32 p32; - - - - msgOffset = pPab->p_atu->InQueue; - - - if (msgOffset == 0xFFFFFFFF) - { -#ifdef DEBUG - kprintf("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n"); -#endif - return RC_RTN_FREE_Q_EMPTY; - } - - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - -#ifdef DEBUG - kprintf("SendI2OOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset); -#endif - - pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6; - pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = 0x106; - pMsg[4] = 4096; - pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; - pMsg[6] = 0xD0000004; - pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); - - p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB)); - p32[0] = 0; - - pPab->p_atu->InQueue = msgOffset; - - timeout = 100000; - while(1) - { - for (i = 0; i < 1000; i++) - ; - - if (p32[0]) - break; - - if (!timeout--) - { -#ifdef DEBUG - kprintf("Timeout wait for InitOutQ InPrgress status from IOP\n"); -#endif - return RC_RTN_NO_I2O_STATUS; - } - } - - timeout = 100000; - while(1) - { - for (i = 0; i < 1000; i++) - ; - - if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE) - break; - - if (!timeout--) - { -#ifdef DEBUG - kprintf("Timeout wait for InitOutQ Complete status from IOP\n"); -#endif - return RC_RTN_NO_I2O_STATUS; - } - } - - phyOutQFrames = pPab->outMsgBlockPhyAddr; - - for (i = 0; i < NMBR_MSG_FRAMES; i++) - { - pPab->p_atu->OutQueue = phyOutQFrames; - phyOutQFrames += MSG_FRAME_SIZE; - } - return RC_RTN_NO_ERROR; -} -*/ - -/* - * - */ -static void OutboundInitCall(struct pti_st_host *hostp) -{ - U32 i; - U32 x; - U32 msgOffset; - U32 timeout; - PI2O_EXEC_OUTBOUND_INIT_MESSAGE pMsg; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - unsigned long pMFA_Outbound = 0; - - msgOffset = hostp->p_atu->InQueue; - pMsg = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)(hostp->LinBaseAddr+msgOffset); - - memset((void *)hostp->replyBufferp, 0, 16*1024); - - pMsg->StdMessageFrame.VersionOffset=0x61; // 32 bit frame - pMsg->StdMessageFrame.MsgFlags=0; - pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)>>2; - - pMsg->StdMessageFrame.TargetAddress=0; // IXWork - pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host - pMsg->StdMessageFrame.Function = I2O_EXEC_OUTBOUND_INIT; - pMsg->HostPageFrameSize = 4096; - pMsg->InitCode = I2O_MESSAGE_IF_INIT_CODE_NO_OWNER; - pMsg->OutboundMFrameSize = 0x20; //each frame 32 * 4 bytes - // the sgl for OutboundInitStatus Word, only 4 bytes. - pMsg->SGL.u.Simple[0].FlagsCount.Count=4; - pMsg->SGL.u.Simple[0].FlagsCount.Flags=(I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); - - pMsg->SGL.u.Simple[0].PhysicalAddress=virt_to_bus(hostp->replyBufferp); - - * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; - - // wait for response: - timeout = 0x100000; - while(1) - { - for (i=0; i<1000; i++) // please don't hog the bus!!! - ; - if (*((U8*)hostp->replyBufferp) != 0) - break; - - if (!timeout--) - { - printk("Timeout wait for I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS status!\n"); - return; - } - } - - timeout = 100000; - while(1) - { - for (i= 0; i<1000; i++) // please don't hog the bus!!! - ; - if (*((U8*)hostp->replyBufferp) == I2O_EXEC_OUTBOUND_INIT_COMPLETE) - break; - - if (!timeout--) - { - printk("Timeout wait for I2O_EXEC_OUTBOUND_INIT_COMPLETE status!\n"); - return; - } - } - - for(x=0; x < 32; x++) - { - pMFA_Outbound = (U32)&(hostp->outboundBufferp->outboundBuff[x]); - *((U32 *)(pBaseAddrReg+OUTBOUNDQPORT))=virt_to_bus((void *)pMFA_Outbound); - for (i=0; i<1000; i++) // just for waitting! - ; - if (DEBUG) - { - printk("Write to Outbound port, MFAs are : \n"); - printk("%lx", pMFA_Outbound); - } - } - // printk(" DONE!\n"); -} - -/* - * - */ -static void SysTabSetCall(struct pti_st_host *hostp, - PI2O_EXEC_SYS_TAB_SET_MESSAGE MF, - void *lsgl) -{ - U8 tempMemPool[0x200]; - int count=0x200; - void *tlsgl = lsgl; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - unsigned long pMFA_Inbound; - - PI2O_EXEC_STATUS_GET_REPLY ptReplyMemPool = - (PI2O_EXEC_STATUS_GET_REPLY)tempMemPool; - - PI2O_SGE_SIMPLE_ELEMENT ptsgl = - (PI2O_SGE_SIMPLE_ELEMENT)MF->SGL.u.Simple; - - while(count--) - tempMemPool[count] = ((char*)tlsgl)[count]; - - pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); - - ZeroMemory((U32*) MF, sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE)+0x10); - ZeroMemory((U32*) lsgl, 0x200); - - MF->StdMessageFrame.VersionOffset=0x61; // 32 bit frame - MF->StdMessageFrame.MsgFlags=0; - MF->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) >> 2; - - MF->StdMessageFrame.TargetAddress=0; // IXWork - MF->StdMessageFrame.InitiatorAddress = 0x01; // from Host - MF->StdMessageFrame.Function = I2O_EXEC_SYS_TAB_SET; - - MF->IOP_ID = MY_IOP_ID; //I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST; - MF->HostUnitID = I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT; - MF->SegmentNumber = I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT; - - MF->SGL.u.Simple[0].FlagsCount.Count= - CreatSysTable(hostp, lsgl, (PI2O_EXEC_STATUS_GET_REPLY)tempMemPool); - - // 1st element: YBM: need I2O_SGL_FLAGS_END_OF_BUFFER ? - ptsgl->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER) ; - - MF->SGL.u.Simple[0].PhysicalAddress = (U32)(virt_to_bus(lsgl)); - - // 2nd element: YBM: need I2O_SGL_FLAGS_END_OF_BUFFER ? - ptsgl++; - ptsgl->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER) ; - ptsgl->FlagsCount.Count = ptReplyMemPool->CurrentPrivateMemSize; - ptsgl->PhysicalAddress = ptReplyMemPool->CurrentPrivateMemBase; - - // 3rd element: -#if defined(MYDEBUG) && 0 - MF->SGL.u.SimpleContext[0].FlagsCount.Count= - ptReplyMemPool->CurrentPrivateIOSize; - - MF->SGL.u.SimpleContext[0].FlagsCount.Flags = - (I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); - - MF->SGL.u.SimpleContext[0].PhysicalAddress = ptReplyMemPool->CurrentPrivateIOBase; -#else - ptsgl++; - ptsgl->FlagsCount.Count= - ptReplyMemPool->CurrentPrivateIOSize; - - ptsgl->FlagsCount.Flags = - (I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); - - ptsgl->PhysicalAddress = ptReplyMemPool->CurrentPrivateIOBase; -#endif - - memcpy( (void *)(pMFA_Inbound+pBaseAddrReg), (void *)MF, - (sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)+ - (sizeof(I2O_SGE_SIMPLE_ELEMENT) * 2)) ); - - * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = pMFA_Inbound; - -} - -/* - * - */ -static void EnableSysCall(struct pti_st_host *hostp) -{ - U32 msgOffset; - PI2O_EXEC_SYS_ENABLE_MESSAGE pMsg; - - msgOffset = hostp->p_atu->InQueue; - - pMsg = (PI2O_EXEC_SYS_ENABLE_MESSAGE)(hostp->LinBaseAddr + msgOffset); - - pMsg->StdMessageFrame.VersionOffset=0x1; - pMsg->StdMessageFrame.MsgFlags=0; - pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE) >> 2; - - pMsg->StdMessageFrame.TargetAddress=0; // IXWork - pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host - pMsg->StdMessageFrame.Function = I2O_EXEC_SYS_ENABLE; - - *(U32 *)(hostp->LinBaseAddr+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; -} - -/* - * - */ -static void LCTNotifyCall(struct pti_st_host *hostp) -{ - U32 msgOffset; - PI2O_EXEC_LCT_NOTIFY_MESSAGE pMsg; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - - msgOffset = hostp->p_atu->InQueue; - - pMsg = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)(hostp->LinBaseAddr + msgOffset); - pMsg->StdMessageFrame.VersionOffset=0x61; - pMsg->StdMessageFrame.MsgFlags=0; - pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE)>>2; - - pMsg->StdMessageFrame.TargetAddress=0; // IXWork - pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host - pMsg->StdMessageFrame.Function = I2O_EXEC_LCT_NOTIFY; - pMsg->ClassIdentifier = 0xffffffff; // all class - // I2O_CLASS_RANDOM_BLOCK_STORAGE; - pMsg->LastReportedChangeIndicator = 0; - pMsg->SGL.u.Simple[0].FlagsCount.Count=0x1000; - pMsg->SGL.u.Simple[0].FlagsCount.Flags=(I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); - pMsg->SGL.u.Simple[0].PhysicalAddress=virt_to_bus(hostp->replyBufferp); - - * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; -} - -/* - * - */ -static U32 CreatSysTable(struct pti_st_host *hostp, - void *llsgl, - PI2O_EXEC_STATUS_GET_REPLY ltMemPool) -{ - PI2O_SET_SYSTAB_HEADER pPacket = (PI2O_SET_SYSTAB_HEADER) llsgl; - PI2O_IOP_ENTRY pEntry = (PI2O_IOP_ENTRY) ((U8 *) llsgl + sizeof(PI2O_SET_SYSTAB_HEADER)); - - pPacket->NumberEntries=0x1; - pPacket->SysTabVersion=I2O_RESOURCE_MANAGER_VERSION; - pPacket->CurrentChangeIndicator=0; - - // pEntry->OrganizationID = ltMemPool->OrganizationID; - pEntry->OrganizationID = PROMISE_ORG_ID; - pEntry->IOP_ID = MY_IOP_ID; //ltMemPool->IOP_ID; - pEntry->SegmentNumber = ltMemPool->SegmentNumber; - pEntry->I2oVersion = ltMemPool->I2oVersion; - pEntry->IopState = ltMemPool->IopState; - pEntry->MessengerType = ltMemPool->MessengerType; - pEntry->InboundMessageFrameSize = ltMemPool->InboundMFrameSize; - pEntry->LastChanged = 0; - pEntry->IopCapabilities = ltMemPool->IopCapabilities; - pEntry->MessengerInfo.InboundMessagePortAddressLow = (U32)hostp->maddr; - pEntry->MessengerInfo.InboundMessagePortAddressHigh = 0; - - return sizeof(I2O_IOP_ENTRY)+sizeof(I2O_SET_SYSTAB_HEADER); -} - - -/***************************************************************************** - I2O EXECUTIVE CLASS MESSAGE -*****************************************************************************/ - -/* - * - */ -static void ExecIOPReset(struct pti_st_host *hostp) -{ - U32 msgOffset; - U32 timeout; - PI2O_EXEC_IOP_RESET_MESSAGE pMsg; - volatile PU32 p32; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - - msgOffset = hostp->p_atu->InQueue; - - pMsg = (PI2O_EXEC_IOP_RESET_MESSAGE)(hostp->LinBaseAddr + msgOffset); - memset((void *)hostp->replyBufferp, 0, 16*1024); - - pMsg->VersionOffset=0x01; - pMsg->MsgFlags=0; - pMsg->MessageSize= sizeof(I2O_EXEC_IOP_RESET_MESSAGE) >> 2; - - pMsg->TargetAddress=0; // IXWork - pMsg->InitiatorAddress = 0x01; // from Host - pMsg->Function = I2O_EXEC_IOP_RESET; - - pMsg->StatusWordHighAddress = 0; - pMsg->StatusWordLowAddress = - (U32)(virt_to_bus((void *)hostp->replyBufferp)); - - p32 = (volatile PU32)hostp->replyBufferp; - - *(U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; - - /* wait for response: */ - timeout = 1000000; - while(1) - { - int i; - for (i=0; i<1000; i++) /* please don't hog the bus ! */ - ; - if(p32[0] || p32[1]) - break; - if (!timeout--) - { - printk("Timeout while Resetting IOP !\n"); - return; - } - } -} - -static void PTI_StringCutBlank(char * strBuffer, U32 strLength) -{ - U32 i = strLength - 2; - - while (i >= 0 && strBuffer[i] == ' ') - { - strBuffer[i] = '\0'; - i--; - } -} - -/* - * - */ -static void GetInfoFromLCT(struct pti_st_host *hostp, - void *lMemPool, - PI2ODISK pmydisk, - unsigned int *diskcount) -{ - PI2O_LCT pTable = (PI2O_LCT)lMemPool; - PI2O_LCT_ENTRY pLCTEntry; - PI2O_LCT_ENTRY HeadpLCTEntry = pTable->LCTEntry; - U16 ParentID=0xffff; - - int i; - - *diskcount = 0; // initial count - memset((void *)hostp->LctEntryTable, 0, (sizeof(I2O_LCT_ENTRY) * MAX_LCT_ENTRY)); - - while(pTable->TableSize==0) // wait ready - ; - pLCTEntry=HeadpLCTEntry; - - /* get ISM: */ - while (pLCTEntry->TableEntrySize==0x9) - { - if(pLCTEntry->ClassID.Class==I2O_CLASS_DDM && - pLCTEntry->SubClassInfo==I2O_SUBCLASS_ISM) - { - ParentID=(U16) pLCTEntry->LocalTID; - break; - } - pLCTEntry++; - } - - if (ParentID == 0xffff) - { - printk("ISM DDM ID not found!\n"); - return; - } - - /* scan all ISM children first: */ - pLCTEntry=HeadpLCTEntry; - i = 0; - - while(pLCTEntry->TableEntrySize == 0x9) - { - /* - * Insert the LCT Entry to LCT Entry Description - */ - memcpy((void*)&hostp->LctEntryTable[i], - (void *)pLCTEntry, - sizeof(I2O_LCT_ENTRY)); - - if((pLCTEntry->ClassID.Class==I2O_CLASS_RANDOM_BLOCK_STORAGE) && - (pLCTEntry->ParentTID==ParentID)) - { - pmydisk->LocalTID = (unsigned int) pLCTEntry->LocalTID; - pmydisk++; - (*diskcount)++; - } - pLCTEntry++; - i++; - } - - /* if no ISM child: */ - if(*diskcount == 0) - { /* parent not exist */ - pLCTEntry = HeadpLCTEntry; - while(pLCTEntry->TableEntrySize == 0x9) - { - if(pLCTEntry->ClassID.Class==I2O_CLASS_RANDOM_BLOCK_STORAGE) - { - pmydisk->LocalTID = (unsigned int) pLCTEntry->LocalTID; - pmydisk++; - (*diskcount)++; - } - pLCTEntry++; - } - } - -} - -/* - * Starting lMemBuf = 0 - * 0 ~ 3 bytes -- Request Header (0-1) Op Cnt (2-3) Res - * 4 ~ 9 bytes -- first operation list - * a ~10 bytes -- second operation list - * - * Result starts at lMemBuf+4+6+6 - * 0 ~ 3 -- result header (0-1) Result Cnt - * 4 ~ n -- first result (first 4 byte, byte cnt in result+status) - */ -static int ComposeDiskInfo(struct pti_st_host *hostp, - void *MF, - void *lMemBuf, - PI2ODISK pmydisk) -{ - PI2O_UTIL_DEVICE_IDENTITY_SCALAR pResult1; - PI2O_BSA_DEVICE_INFO_SCALAR pResult2; - PI2O_PARAM_READ_OPERATION_RESULT pOpResult; - PI2O_PARAM_RESULTS_LIST_HEADER pResHeader = - (PI2O_PARAM_RESULTS_LIST_HEADER) (((U8 *) lMemBuf)+8+4); - - void * ptMemBuf = lMemBuf; - PI2O_PARAM_OPERATION_ALL_TEMPLATE ptsgl = - (PI2O_PARAM_OPERATION_ALL_TEMPLATE) (((U8*) lMemBuf) + 4); - - U32 wSize; - unsigned int Hd; - unsigned int Sctr = 0x3f; - - /* - * Note:General and Specific parameter get must invoke separately - * General Parameter Get - */ - ZeroMemory(lMemBuf, 0x200); - - *((unsigned int *) ptMemBuf) = 0x1; - ptsgl->Operation = I2O_PARAMS_OPERATION_FIELD_GET; - ptsgl->GroupNumber = I2O_UTIL_DEVICE_IDENTITY_GROUP_NO; - ptsgl->FieldCount = 0xffff; - - PTI_UtilParamGetCall(hostp, - (PI2O_UTIL_PARAMS_GET_MESSAGE) MF, - (void *) ptMemBuf, - (void *) (((U8 *) ptMemBuf)+0x4+0x8), - pmydisk); - if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) - { - printk("!BAD reply after sending UtilParamsGetMessage!\n"); - return(FALSE); - } - - pOpResult = (PI2O_PARAM_READ_OPERATION_RESULT) (++pResHeader); - if(pOpResult->ErrorInfoSize != 0) - { - return(FALSE); /* Error Action */ - } - pResult1 = (PI2O_UTIL_DEVICE_IDENTITY_SCALAR) (++pOpResult); - - memcpy( &(pmydisk->Vendor), &(pResult1->VendorInfo), - I2O_DEVID_VENDOR_INFO_SZ ); - - pmydisk->Vendor[I2O_DEVID_VENDOR_INFO_SZ] = (char) 0; - - PTI_StringCutBlank(pmydisk->Vendor, I2O_DEVID_VENDOR_INFO_SZ); - - memcpy( &(pmydisk->DiskModel), &(pResult1->ProductInfo), - I2O_DEVID_PRODUCT_INFO_SZ ); - - pmydisk->DiskModel[I2O_DEVID_PRODUCT_INFO_SZ] = (char) 0; - - PTI_StringCutBlank(pmydisk->DiskModel, I2O_DEVID_PRODUCT_INFO_SZ); - - memcpy( &(pmydisk->ProductRevLevel), &(pResult1->ProductRevLevel), - I2O_DEVID_REV_LEVEL_SZ ); - pmydisk->ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ] = '\0'; - - PTI_StringCutBlank(pmydisk->ProductRevLevel, I2O_DEVID_REV_LEVEL_SZ); - - /* - * Device Information (Storage Parameter Get) - */ - ZeroMemory(lMemBuf, 0x200); - - *((unsigned int *) ptMemBuf) = 0x1; - - ptsgl->Operation = I2O_PARAMS_OPERATION_FIELD_GET; - ptsgl->GroupNumber = I2O_BSA_DEVICE_INFO_GROUP_NO; - ptsgl->FieldCount = 0xffff; - - PTI_UtilParamGetCall(hostp, - (PI2O_UTIL_PARAMS_GET_MESSAGE) MF, - (void *) ptMemBuf, - (void *) (((U8 *) ptMemBuf)+0x4+0x8), - pmydisk); - if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) - { - printk("!BAD reply after sending UtilParamsGetMessage!\n"); - return(FALSE); - } - - pResHeader=(PI2O_PARAM_RESULTS_LIST_HEADER) (((U8 *) lMemBuf)+8+4); - pOpResult = (PI2O_PARAM_READ_OPERATION_RESULT) (++pResHeader); - if(pOpResult->ErrorInfoSize != 0) - { - return(FALSE); // Error Action - } - pResult2 = (PI2O_BSA_DEVICE_INFO_SCALAR) (++pOpResult); - - wSize = (long) ((pResult2->DeviceCapacity.HighPart << (32-9)) | - (pResult2->DeviceCapacity.LowPart >> 9)); - - pmydisk->lastLBA = (U32) wSize - 1; - - // convert LBA to CHS - if(wSize <= (U32) 0x3f*0x10*0x400) - { - Hd = 0x10; - while((wSize/(Hd*Sctr) > 0x400) && (Hd < 0x80)) - Hd <<=1; - } - else if (wSize <= (U32) (0x3fl*0x20l*0x400l)) Hd = 0x20; - else if (wSize <= (U32) (0x3fl*0x40l*0x400l)) Hd = 0x40; - else if (wSize <= (U32) (0x3fl*0x80l*0x400l)) Hd = 0x80; - else Hd = 0xff; - - pmydisk->lastcyl = (unsigned int) ((wSize/ (Hd*Sctr)) - 1);/*starting from 0*/ - pmydisk->lasthead = (U8) (Hd - 1); /*starting from 0*/ - pmydisk->sector = (U8) Sctr; /*starting from 0*/ - - return(TRUE); -} - -/* - * Function: unsigned long pti_st_waitreplymsg(struct pti_st_host *) - * Description: wait reply message from i960. - * Return : Error code (0 represent I2O_REPLY_STATUS_SUCCESS) - */ -unsigned long pti_st_waitreplymsg(struct pti_st_host *hostp) -{ - U8 ReqStatus; - U32 timeout=0; - int i; - PI2O_SINGLE_REPLY_MESSAGE_FRAME replyPointer; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - unsigned long pMFA_Outbound; - - // wait for response: - timeout = 0x1000000; - while(1) - { - for (i=0; i<1000; i++) // please don't hog the bus!!! - ; - if((pMFA_Outbound=(*(volatile U32 *)(pBaseAddrReg+OUTBOUNDQPORT)))!=-1) - break; - - if (!timeout--) - { - printk("Timeout wait for Reply Message from IOP!\n"); - return -1; - } - } - - replyPointer=(PI2O_SINGLE_REPLY_MESSAGE_FRAME)(bus_to_virt(pMFA_Outbound)); - - ReqStatus = replyPointer->ReqStatus; - - * (U32 *)(pBaseAddrReg+OUTBOUNDQPORT) = pMFA_Outbound; - - return (unsigned long) ReqStatus; -} - - -/***************************************************************************** - I2O UTILITY CLASS MESSAGE -*****************************************************************************/ -/* - * THis is used for ComposeDiskInfo() - */ -static void PTI_UtilParamGetCall(struct pti_st_host *hostp, - PI2O_UTIL_PARAMS_GET_MESSAGE MF, - void *req, - void *buf, - PI2ODISK mydisk) -{ - PI2O_SGE_SIMPLE_ELEMENT sglentry = - (PI2O_SGE_SIMPLE_ELEMENT)MF->SGL.u.Simple; // YBM: )&MF->SGL.u.Simple; - unsigned long pBaseAddrReg = (U32)hostp->maddr; - unsigned long pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); - - ZeroMemory((U32*) MF, sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+0x10); - - MF->StdMessageFrame.VersionOffset=0x51; - MF->StdMessageFrame.MsgFlags=0; - MF->StdMessageFrame.MessageSize= - (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+sizeof(I2O_SG_ELEMENT)) >> 2; - - MF->StdMessageFrame.TargetAddress=mydisk->LocalTID; - MF->StdMessageFrame.InitiatorAddress = 0x01; // from Host - MF->StdMessageFrame.Function = I2O_UTIL_PARAMS_GET; - - MF->OperationFlags = 0; // reserved - - // First buffer: - sglentry->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER ); - sglentry->FlagsCount.Count = 0x0c ; - sglentry->PhysicalAddress = (U32)(virt_to_bus(req)); // YBM: *(U32 *)req ; - - // Sencond buffer: - sglentry++; - sglentry->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER ); - sglentry->FlagsCount.Count = 0x100; - //sizeof(I2O_UTIL_DEVICE_IDENTITY_SCALAR); - sglentry->PhysicalAddress = (U32)(virt_to_bus(buf)); // YBM: *(U32 *)buf; - - memcpy( (void *)(pMFA_Inbound+pBaseAddrReg), (void *)MF, - (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+16) ); - - * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = pMFA_Inbound; -} - - -/* - * This is used for pti_stdev_ioctl() - * - * Routine Description: - * - * message allows parameter values to be retrieved from - * device parameter groups. - */ -static void PTI_UtilParamsGet( - struct pti_st_host *hostp, - ULONG LocalTID, - ULONG FieldCount, - UCHAR SrbTag, - ULONG SrbID, - UCHAR *Address -) -{ - PI2O_UTIL_PARAMS_GET_MESSAGE MsgPtr; - PI2O_SGE_SIMPLE_ELEMENT SGLPtr; - ULONG msgOffset; - ULONG ParamOffset = 0; - - - msgOffset = hostp->p_atu->InQueue; - MsgPtr = (PI2O_UTIL_PARAMS_GET_MESSAGE)(hostp->LinBaseAddr+msgOffset); - memset((ULONG *)MsgPtr,0,sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+0x10); - SGLPtr = (PI2O_SGE_SIMPLE_ELEMENT)MsgPtr->SGL.u.Simple; - - ParamOffset = sizeof(I2O_PARAM_SCALAR_OPERATION); - if (FieldCount != (USHORT)-1) - ParamOffset = ParamOffset + (FieldCount-1)*sizeof(USHORT); - - /* - * fill the message frame - */ - MsgPtr->StdMessageFrame.VersionOffset = 0x51; - MsgPtr->StdMessageFrame.MsgFlags = 0; - MsgPtr->StdMessageFrame.MessageSize = - (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+sizeof(I2O_SG_ELEMENT)) >> 2; - MsgPtr->StdMessageFrame.TargetAddress = LocalTID; - MsgPtr->StdMessageFrame.InitiatorAddress = 0x01; /* from Host */ - MsgPtr->StdMessageFrame.Function = I2O_UTIL_PARAMS_GET; - MsgPtr->StdMessageFrame.InitiatorContext = SrbTag; - - MsgPtr->TransactionContext = SrbID; - MsgPtr->OperationFlags = 0; /* reserved */ - - /* - * fill the SGL frame - * the first buffer contains the operation list that - * identifies which parameters are to be returned - */ - SGLPtr->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER ); - SGLPtr->FlagsCount.Count = ParamOffset; - SGLPtr->PhysicalAddress = cpu_to_le32(VIRT_TO_BUS(Address)); - - /* the second buffer is for target to place the results */ - SGLPtr++; - SGLPtr->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER ); - SGLPtr->FlagsCount.Count = 0x100; - SGLPtr->PhysicalAddress = cpu_to_le32(VIRT_TO_BUS(Address+ParamOffset)); - - /* - * send the message - */ - hostp->p_atu->InQueue = msgOffset; -} - - -/* - * - */ -static void UtilNOPCall(struct pti_st_host *hostp) -{ - U32 msgOffset; - PI2O_UTIL_NOP_MESSAGE pMsg; - - msgOffset = hostp->p_atu->InQueue; - - pMsg = (PI2O_UTIL_NOP_MESSAGE)(hostp->LinBaseAddr + msgOffset); - pMsg->StdMessageFrame.VersionOffset=0x1; - pMsg->StdMessageFrame.MsgFlags=0; - pMsg->StdMessageFrame.MessageSize= sizeof(I2O_UTIL_NOP_MESSAGE) >> 2; - pMsg->StdMessageFrame.TargetAddress=0; - pMsg->StdMessageFrame.InitiatorAddress = 0x1; // from Host - pMsg->StdMessageFrame.Function = I2O_UTIL_NOP; - - hostp->p_atu->InQueue = msgOffset; - -} - -/******************************************************************** - * - * Private Messages - * - ********************************************************************/ - -static void PTI_PrivateMessageCall( - struct pti_st_host *hostp, - ULONG TargetTID, - U16 XFunctionCode, - U16 OrganizationID, - ULONG InputCount, - UCHAR *InputAddr, - ULONG OutputCount, - UCHAR *OutputAddr, - UCHAR SrbTag, - ULONG SrbID -) -{ - PPTI_ST_PRIVATE_MESSAGE MsgPtr; - unsigned long msgOffset; - - msgOffset = hostp->p_atu->InQueue; - MsgPtr = (PPTI_ST_PRIVATE_MESSAGE)(hostp->LinBaseAddr+msgOffset); - memset((UCHAR *)MsgPtr,0,sizeof(PTI_ST_PRIVATE_MESSAGE)+0x10); - - /* - * Fill the message frame - */ - MsgPtr->MyStandMsg.StdMessageFrame.VersionOffset = 0x1; - MsgPtr->MyStandMsg.StdMessageFrame.MsgFlags = 0; - MsgPtr->MyStandMsg.StdMessageFrame.MessageSize = (sizeof(PTI_ST_PRIVATE_MESSAGE) >> 2); - - MsgPtr->MyStandMsg.StdMessageFrame.TargetAddress = TargetTID; /* IXWork */ - MsgPtr->MyStandMsg.StdMessageFrame.InitiatorAddress = 0x01; - MsgPtr->MyStandMsg.StdMessageFrame.Function = I2O_PRIVATE_MESSAGE; - MsgPtr->MyStandMsg.StdMessageFrame.InitiatorContext = SrbTag; - - MsgPtr->MyStandMsg.XFunctionCode = (U16)(((XFunctionCode >> 8) & 0x00ff) | ((XFunctionCode << 8) & 0xff00)); - - MsgPtr->MyStandMsg.OrganizationID = (U16)(((OrganizationID >> 8) & 0x00ff) | ((OrganizationID << 8) & 0xff00)); - - MsgPtr->MyStandMsg.TransactionContext = SrbID; - /* - * Fill the private Payload - */ - MsgPtr->InSGL.FlagsCount.Count = InputCount; - MsgPtr->InSGL.FlagsCount.Flags = I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER; - MsgPtr->InSGL.PhysicalAddress[0] = - cpu_to_le32(VIRT_TO_BUS(InputAddr)); - - MsgPtr->OutSGL.FlagsCount.Count = OutputCount; - MsgPtr->OutSGL.FlagsCount.Flags = I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT | I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER; - MsgPtr->OutSGL.PhysicalAddress[0] = - cpu_to_le32(VIRT_TO_BUS(OutputAddr)); - - /* - * send the message - */ - hostp->p_atu->InQueue = msgOffset; -} - - -/**************************************************************************** - Misc functions. -****************************************************************************/ -/* - * - */ -static void ZeroMemory(unsigned long *zeroBuffer, unsigned int count) -{ - count = count >> 2; // count/4 - while(count--) - { - * zeroBuffer = 0; - zeroBuffer ++; - } -} - -/************************************************************ - * Device File Function * - ************************************************************/ - -static int pti_stdev_strncmp(char *s, char *d, int n) -{ - /* check null */ - if(!s) { - if(!d) - return(0); - else - return(-1); - } else { - if(!d) - return(1); - } - /* both not null */ - - /* check length 0 */ - if(!s[0]) { - if(!d[0]) - return(0); - else - return(-1); - } else { - if(!d[0]) - return(-1); - } - - /* both length not 0 */ - - return(strncmp(s,d,n)); -} - -/* - * - */ -int pti_stdev_open(struct inode *inodep, struct file *filep) -{ - int aptno = MINOR(inodep->i_rdev); -#if defined(__SMP__) - struct pti_st_host *p = pti_st_hostp[aptno]; -#endif - - if(!pti_st_hostp[aptno] || - pti_st_hostp[aptno]->major <= 0 || - pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) - return(-ENODEV); - - DRIVER_LOCK - if(pti_st_hostp[aptno]->counter != 0) { - DRIVER_UNLOCK - return(-EBUSY); - } - pti_st_hostp[aptno]->counter++; - DRIVER_UNLOCK - - MOD_INC_USE_COUNT; - return(0); -} - -int pti_stdev_release(struct inode *inodep, struct file *filep) -{ - int aptno = MINOR(inodep->i_rdev); -#if defined(__SMP__) - struct pti_st_host *p = pti_st_hostp[aptno]; -#endif - - if(!pti_st_hostp[aptno] || - pti_st_hostp[aptno]->major <= 0 || - pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) - return(-ENODEV); - - DRIVER_LOCK - if(pti_st_hostp[aptno]->counter <= 0) { - DRIVER_UNLOCK - return(-EBADF); - } - pti_st_hostp[aptno]->counter = 0; - - DRIVER_UNLOCK - - MOD_DEC_USE_COUNT; - return(0); -} - -int pti_stdev_ioctl(struct inode *inodep, - struct file *filep, - unsigned int req, - unsigned long arg) -{ - SRB_IO_CONTROL *usr_srbp = (SRB_IO_CONTROL *)arg; - PTI_STDEV_GET_CONFIG_BUFFER *usr_confbufp = - (PTI_STDEV_GET_CONFIG_BUFFER *)arg; - PTI_STDEV_INBUFFER *usr_inbufp = (PTI_STDEV_INBUFFER *)arg; - - SRB_IO_CONTROL *srbp = NULL; - PTI_STDEV_GET_CONFIG_BUFFER *confbufp = NULL; - PTI_STDEV_INBUFFER *inbufp = NULL; - - PI2O_CONFIG_QUERY ConfigQuyPtr = NULL; - PI2O_DEVICE_DESCRIPTOR DevDescriptorPtr = NULL; - PI2O_PARAM_SCALAR_OPERATION ParamScalarPtr = NULL; - USHORT *TargetTIDp = NULL; - USHORT *OrganizationIDp = NULL; - USHORT *XFunctionCodep = NULL; - UCHAR *InputAddr = NULL; - UCHAR *OutputAddr = NULL; - - void *bufferp = NULL; - unsigned long offset; - unsigned long ret; - int i, retval; - int aptno = MINOR(inodep->i_rdev); - struct pti_st_host *p = pti_st_hostp[aptno]; - - if(!pti_st_hostp[aptno] || - pti_st_hostp[aptno]->major <= 0 || - pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) - return(-ENODEV); - - if(pti_st_hostp[aptno]->counter <= 0) { - return(-EIO); - } - - bufferp = pti_st_hostp[aptno]->pti_stdev_bufferp; - memset(bufferp, 0, sizeof(PTI_STDEV_INBUFFER)); - - srbp = (SRB_IO_CONTROL *)bufferp; - - switch (req) { - case IOCTL_SUPERTRAK_GETVERSION: - ret = copy_from_user(srbp, - usr_srbp, - sizeof(SRB_IO_CONTROL)); - if(ret) - return(-EFAULT); - break; - - case IOCTL_GET_CONFIG_INFO: - confbufp = (PTI_STDEV_GET_CONFIG_BUFFER *)bufferp; - - ret = copy_from_user(confbufp, - usr_confbufp, - sizeof(PTI_STDEV_GET_CONFIG_BUFFER)); - if(ret) - return(-EFAULT); - - break; - - case IOCTL_PRIVATE_MESSAGE_CODE: - case IOCTL_PARAMS_GET_REQUEST: - inbufp = (PTI_STDEV_INBUFFER *)bufferp; - - ret = copy_from_user(inbufp, - usr_inbufp, - sizeof(PTI_STDEV_INBUFFER)); - if(ret) - return(-EFAULT); - - break; - - default: - return(-EINVAL); - } - - if(pti_stdev_strncmp(srbp->Signature, SUPERTRAK_SIGNATURE, SUPERTRAK_SIG_LEN)) - return(-EINVAL); - - switch (req) { - case IOCTL_SUPERTRAK_GETVERSION: - srbp->ControlCode = (VERSIONHI | (VERSIONLO << 16)); - ret = copy_to_user(usr_srbp, - srbp, - sizeof(SRB_IO_CONTROL)); - if(ret) - return(-EINVAL); - else - return(0); - - case IOCTL_GET_CONFIG_INFO: - ConfigQuyPtr = (PI2O_CONFIG_QUERY)((UCHAR *)confbufp+sizeof(SRB_IO_CONTROL)); - DevDescriptorPtr = (PI2O_DEVICE_DESCRIPTOR)((UCHAR *)confbufp+ - + sizeof(SRB_IO_CONTROL) - + sizeof(I2O_CONFIG_QUERY)); - - /* - * fill the I2O_DEVICE_DESCRIPTOR structure - */ - - i = 0; - while(pti_st_hostp[aptno]->LctEntryTable[i].TableEntrySize == 0x09) - { - if (pti_st_hostp[aptno]->LctEntryTable[i].ClassID.Class==ConfigQuyPtr->ClassID.Class && - pti_st_hostp[aptno]->LctEntryTable[i].SubClassInfo==ConfigQuyPtr->SubClassID) - { - /* - * fill the LCT structure - */ - memcpy((void*)&DevDescriptorPtr->LCT, - (void*)&pti_st_hostp[aptno]->LctEntryTable[i], - sizeof(I2O_LCT_ENTRY)); - break; - } - else - i++; - } - - /* - * Get IOP Description - */ - DevDescriptorPtr->IOP.IOPNumber = ConfigQuyPtr->IOPNumber; - DevDescriptorPtr->IOP.IOPCapabilities = pti_st_hostp[aptno]->IopStatus.IopCapabilities; - DevDescriptorPtr->IOP.IOPState = pti_st_hostp[aptno]->IopStatus.IopState; - DevDescriptorPtr->IOP.I2OVersion = pti_st_hostp[aptno]->IopStatus.I2oVersion; - DevDescriptorPtr->IOP.MessengerType = pti_st_hostp[aptno]->IopStatus.MessengerType; - DevDescriptorPtr->IOP.MaxMessageFrameSize = pti_st_hostp[aptno]->IopStatus.InboundMFrameSize; - DevDescriptorPtr->IOP.ExpectedLCTSize = pti_st_hostp[aptno]->IopStatus.ExpectedLCTSize; - DevDescriptorPtr->IOP.MaxInboundMFrames = pti_st_hostp[aptno]->IopStatus.MaxInboundMFrames; - DevDescriptorPtr->IOP.InitialInboundMFrames = pti_st_hostp[aptno]->IopStatus.CurrentInboundMFrames; - DevDescriptorPtr->IOP.Reserved = pti_st_hostp[aptno]->IopStatus.reserved; - - ret = copy_to_user(usr_confbufp, - confbufp, - sizeof(PTI_STDEV_GET_CONFIG_BUFFER)); - if(ret) - return(-EINVAL); - else - return(0); - - case IOCTL_PRIVATE_MESSAGE_CODE: - /* - * read the TargetTID, OrganizationID and XFunctionCode - */ - offset = sizeof(SRB_IO_CONTROL) + sizeof(ULONG); - TargetTIDp = (USHORT *)((UCHAR *)inbufp + offset); - - offset += sizeof(USHORT); - OrganizationIDp = (USHORT *) ((UCHAR *)inbufp + offset); - - offset += sizeof(USHORT); - XFunctionCodep = (USHORT *) ((UCHAR *)inbufp + offset); - - offset += sizeof(USHORT); - InputAddr = (UCHAR *)inbufp + offset; - OutputAddr = InputAddr + 0x800; - - /* - * Send Private Message - */ - - - for(ret = 0; ret < 5; ret++) - { - for(i = 0; i < p->scb_data->maxscbs; i++) - if(p->scb_data->scb_array[i]->flags&SCB_ACTIVE) - break; - if(i >= p->scb_data->maxscbs) { /* card is idel */ - DRIVER_LOCK - break; - } - } - - if(ret >= 5) { /* the cards is busy */ - return(-EIO); - } - - /* - * Disable interrupt - */ - pti_st_hostp[aptno]->p_atu->OutIntMask = 0x000000fc; - - PTI_PrivateMessageCall(pti_st_hostp[aptno], - *TargetTIDp, - *XFunctionCodep, - *OrganizationIDp, - 0x800, InputAddr, - 0x800, OutputAddr, - -1, - -1); - if (pti_st_waitreplymsg(pti_st_hostp[aptno]) - != I2O_REPLY_STATUS_SUCCESS) - { - printk("!BAD reply after sending UtilParamsGetMessage!\n"); - retval = -EIO; - } - else - retval = 0; - - /* - * Enable interrupt - */ - pti_st_hostp[aptno]->p_atu->OutIntMask = 0x00000000; - - DRIVER_UNLOCK - - if(retval == 0) { - ret = copy_to_user(usr_inbufp, - inbufp, - sizeof(PTI_STDEV_INBUFFER)); - if(ret) - return(-EINVAL); - else - return(0); - } else { - return(retval); - } - - case IOCTL_PARAMS_GET_REQUEST: - offset = sizeof(SRB_IO_CONTROL) + sizeof(ULONG); - TargetTIDp = (USHORT *)((UCHAR *)inbufp + offset); - - offset += sizeof(USHORT); - ParamScalarPtr = (PI2O_PARAM_SCALAR_OPERATION)((UCHAR *)inbufp + offset); - - InputAddr = (UCHAR *)((UCHAR *)inbufp + offset); - - for(ret = 0; ret < 5; ret++) - { - for(i = 0; i < p->scb_data->maxscbs; i++) - if(p->scb_data->scb_array[i]->flags&SCB_ACTIVE) - break; - if(i >= p->scb_data->maxscbs) { /* card is idel */ - DRIVER_LOCK - break; - } - } - - if(ret >= 5) { /* the cards is busy */ - return(-EIO); - } - - DRIVER_LOCK - - /* - * Disable interrupt - */ - pti_st_hostp[aptno]->p_atu->OutIntMask = 0x000000fc; - - PTI_UtilParamsGet(pti_st_hostp[aptno], - *TargetTIDp, - ParamScalarPtr->OpBlock.FieldCount, - -1, - -1, - InputAddr); - if (pti_st_waitreplymsg(pti_st_hostp[aptno]) - != I2O_REPLY_STATUS_SUCCESS) - { - printk("!BAD reply after sending UtilParamsGetMessage!\n"); - retval = -EIO; - } - else - retval = 0; - - /* - * Enable interrupt - */ - pti_st_hostp[aptno]->p_atu->OutIntMask = 0x00000000; - - DRIVER_UNLOCK - - if(retval == 0) { - ret = copy_to_user(usr_inbufp, - inbufp, - sizeof(PTI_STDEV_INBUFFER)); - if(ret) - return(-EINVAL); - else - return(0); - } else { - return(retval); - } - - } - return(0); -} - -#ifdef MODULE - -/* - * Support for loading low-level scsi drivers using the linux kernel loadable - * module interface. - * - * To use, the host adapter should first define and initialize the variable - * driver_template (datatype Scsi_Host_Template), and then include this file. - * This should also be wrapped in a #ifdef MODULE/#endif. - * - * The low -level driver must also define a release function which will - * free any irq assignments, release any dma channels, release any I/O - * address space that might be reserved, and otherwise clean up after itself. - * The idea is that the same driver should be able to be reloaded without - * any difficulty. This makes debugging new drivers easier, as you should - * be able to load the driver, test it, unload, modify and reload. - * - * One *very* important caveat. If the driver may need to do DMA on the - * ISA bus, you must have unchecked_isa_dma set in the device template, - * even if this might be changed during the detect routine. This is - * because the shpnt structure will be allocated in a special way so that - * it will be below the appropriate DMA limit - thus if your driver uses - * the hostdata field of shpnt, and the board must be able to access this - * via DMA, the shpnt structure must be in a DMA accessible region of - * memory. This comment would be relevant for something like the buslogic - * driver where there are many boards, only some of which do DMA onto the - * ISA bus. There is no convenient way of specifying whether the host - * needs to be in a ISA DMA accessible region of memory when you call - * scsi_register. - */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) /* > 2.4.0 */ - -static Scsi_Host_Template pti_st_driver_template = PTI_ST; - -static int __init init_this_scsi_driver(void) -{ - int major, i; - pti_st_driver_template.module = THIS_MODULE; - scsi_register_module(MODULE_SCSI_HA, &pti_st_driver_template); - - if (!pti_st_driver_template.present || - (major = register_blkdev(0, PTCNTL_DEV_NAME, (struct block_device_operations *)&pti_stdev_fops)) < 0) - { - if(pti_st_driver_template.present) - scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); - return(-ENODEV); - } - - for(i = 0; i < MAX_ADAPTORS; i++) - { - if(pti_st_hostp[i]) - { - pti_st_hostp[i]->counter = 0; - pti_st_hostp[i]->major = major; - } - } - - return (0); - -} - -static void __exit exit_this_scsi_driver(void) -{ - int i; - - for(i = 0; i < MAX_ADAPTORS; i++) - if(pti_st_hostp[i]) - break; - - if(i < MAX_ADAPTORS) { - if(pti_st_hostp[i]->major > 0) - unregister_blkdev(pti_st_hostp[i]->major,PTCNTL_DEV_NAME); - if(pti_st_hostp[i]) { - scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); - } - } - -} - -module_init(init_this_scsi_driver); -module_exit(exit_this_scsi_driver); - -#else /* > 2.4.0 */ - -Scsi_Host_Template pti_st_driver_template = PTI_ST; - -int init_module(void) -{ - int major, i; - pti_st_driver_template.module = &__this_module; - scsi_register_module(MODULE_SCSI_HA, &pti_st_driver_template); - - if (!pti_st_driver_template.present || -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - (major = register_blkdev(0, PTCNTL_DEV_NAME, (struct file_operations *)&pti_stdev_fops)) < 0) -#else - (major = register_blkdev(0, PTCNTL_DEV_NAME, (struct block_device_operations *)&pti_stdev_fops)) < 0) -#endif - { - if(pti_st_driver_template.present) - scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); - return -1; - } - - for(i = 0; i < MAX_ADAPTORS; i++) - { - if(pti_st_hostp[i]) - { - pti_st_hostp[i]->counter = 0; - pti_st_hostp[i]->major = major; - } - } - - return (0); -} - -void cleanup_module(void) -{ - int i; - - for(i = 0; i < MAX_ADAPTORS; i++) - if(pti_st_hostp[i]) - break; - - if(i < MAX_ADAPTORS) { - if(pti_st_hostp[i]->major > 0) - unregister_blkdev(pti_st_hostp[i]->major,PTCNTL_DEV_NAME); - if(pti_st_hostp[i]) { - scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); - } - } - -} - -#endif /* > 2.4.0 */ - -#endif +/*+M************************************************************************* + * Promise SuperTrak device driver for Linux. + * + * Copyright (c) 2001 Promise Technology, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * Copyright (c) 1999-2001 Promise Technology, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + *-M*************************************************************************/ +#include +#include + +#ifdef MODULE +#include +#endif + +#ifndef KERNEL_VERSION +# define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#endif + +#if defined(MODULE) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) +#include +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#include +#endif +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#include +#include /* for kmalloc() */ +#else +#include /* for kmalloc() */ +#endif +#include +#include /* for CONFIG_PCI */ +#include +#include +#include +#include + +#ifdef mb +# undef mb +#endif +#define mb() \ + __asm__ __volatile__("lock ; addl $0,0(%%esp)": : :"memory") + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,16) +# include +#else +# include +#endif +# include +# define cpuid smp_processor_id() + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) + +# define DRIVER_LOCK_INIT spin_lock_init(&p->spin_lock); +# define DRIVER_LOCK spin_lock(&p->spin_lock); +# define DRIVER_UNLOCK spin_unlock(&p->spin_lock); + +#else /* < KERNEL_VERSION(2,4,0) */ + +#if defined(__SMP__) +# if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) +# define DRIVER_LOCK_INIT \ + spin_lock_init(&p->spin_lock); +# define DRIVER_LOCK \ + if(!p->cpu_lock_count[cpuid]) { \ + spin_lock_irqsave(&p->spin_lock, cpu_flags); \ + p->cpu_lock_count[cpuid]++; \ + } else { \ + p->cpu_lock_count[cpuid]++; \ + } +# define DRIVER_UNLOCK \ + if(--p->cpu_lock_count[cpuid] == 0) \ + spin_unlock_irqrestore(&p->spin_lock, cpu_flags); +# else +# define DRIVER_LOCK_INIT spin_lock_init(&p->spin_lock); +# define DRIVER_LOCK spin_lock(&p->spin_lock); +# define DRIVER_UNLOCK spin_unlock(&p->spin_lock); +# endif +#else /* __SMP__ */ +#define DRIVER_LOCK_INIT +#define DRIVER_LOCK +#define DRIVER_UNLOCK +#endif /* __SMP__ */ + +#endif /* < KERNEL(VERSION(2,4,0) */ + +#include + +#include "sd.h" +#include "scsi.h" +#include "hosts.h" + +#include "pti_st.h" +#include "pti_stdev.h" + +#define PTI_ST_VERBOSE_DEBUGGING + +#define PCI_DEVICE_ID_INTEL_i960 0x1960 +#define PCI_DEVICE_ID_INTEL_i962 0x1962 + +#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a)) + +#ifdef MODULE + +struct proc_dir_entry proc_root = +{ + PROC_ROOT_INO, + /* + * Inode number - ignore, it will be filled by + * proc_register[_dynamic] + */ + 4, + /* + * Length of the proc-file name + */ + "proc", + /* + * The proc-file name + */ + S_IFREG | S_IRUGO, + /* + * File mode - this is a regular + * file which can be read by its + * owner, its group, and everybody + * else + */ + 1, + /* + * Number of links (directories where the + * file is referenced) + */ + 0, 0, + /* + * The uid and gid for the file - we give it + * to root + */ + 0, + /* + * The size of the file reported by ls. + */ + NULL, + /* + * functions which can be done on the inode + * (linking, removing, etc.) - we don't + * support any. + */ + NULL, // procfile_read, + /* + * The read function for this file, + * the function called when somebody + * tries to read something from it. + */ + NULL + /* + * We could have here a function to fill the + * file's inode, to enable us to play with + * permissions, ownership, etc. + */ +}; + +#endif + +struct proc_dir_entry proc_scsi_pti_st = +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + PROC_SCSI_NOT_PRESENT, +#else + 0, + /* + * Inode number - ignore, it will be filled by + * proc_register[_dynamic] + */ +#endif + 6, + /* + * Length of the proc-file name + */ + "pti_st", + /* + * The proc-file name + */ + S_IFDIR | S_IRUGO | S_IXUGO, + /* + * File mode - this is a regular + * file which can be read by its + * owner, its group, and everybody + * else + */ + 2, + /* + * Number of links (directories where the + * file is referenced) + */ + 0, 0, + /* + * The uid and gid for the file - we give it + * to root + */ + 0, + /* + * The size of the file reported by ls. + */ + NULL, + /* + * functions which can be done on the inode + * (linking, removing, etc.) - we don't + * support any. + */ + NULL, + /* + * The read function for this file, + * the function called when somebody + * tries to read something from it. + */ + NULL + /* + * We could have here a function to fill the + * file's inode, to enable us to play with + * permissions, ownership, etc. + */ +}; + +#define ALL_TARGETS -1 +#define ALL_CHANNELS -1 +#define ALL_LUNS -1 + +#define MAX_ARRAYS 8 + +#define MAX_LUNS MAX_ARRAYS + +#define PTI_ST_CMDS_PER_LUN 24 + +/* + * The position of the SCSI commands scb within the scb array. + */ +#define pti_st_position(cmd) ((cmd)->SCp.have_data_in) + +/* This variable is global and very important, control all module !!! */ +struct pti_st_host *pti_st_hostp[MAX_ADAPTORS] = {0}; + +/* + * The following are used for Buffer Flush in ioctl + */ +static struct timer_list bufflsh_timer; +static struct timer_list priv_msg_timer; + +#define FLUSHCACHE_TIMEOUT_DEFULT 60 + + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) + static DECLARE_WAIT_QUEUE_HEAD(WaitQ); + static DECLARE_WAIT_QUEUE_HEAD(PrivMsgWaitQ); +#else + static struct wait_queue *WaitQ=NULL; + static struct wait_queue *PrivMsgWaitQ=NULL; +#endif + + +#define CTL_OF_CMD(cmd) ((cmd->channel) & 0x01), \ + ((cmd->target) & 0x0f), \ + ((cmd->lun) & 0x07) + +/* + * A nice little define to make doing our printks a little easier + */ + +#define WARN_LEAD KERN_WARNING "(scsi%d:%d:%d:%d) " +#define INFO_LEAD KERN_INFO "(scsi%d:%d:%d:%d) " + +#ifdef MODULE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,18) +MODULE_LICENSE("GPL"); +#endif +#endif + + +static int pti_st_install(Scsi_Host_Template *, struct pci_dev *, int *); +static int PTI_PrivateMessageCall(struct pti_st_host *, ULONG, U16, U16, ULONG, UCHAR *, ULONG, UCHAR *, UCHAR, ULONG); + +/* + * Declaration for EXECUTIVE Class Message + */ +static unsigned int GetStatusCall(struct pti_st_host *, void *); +static void OutboundInitCall(struct pti_st_host *); +static void SysTabSetCall(struct pti_st_host *, PI2O_EXEC_SYS_TAB_SET_MESSAGE, void *); +static int IOP_init(struct pti_st_host *); +static void EnableSysCall(struct pti_st_host *); +static void LCTNotifyCall(struct pti_st_host *); + +static unsigned long CreatSysTable(struct pti_st_host *, void *, PI2O_EXEC_STATUS_GET_REPLY); +static void ExecIOPReset(struct pti_st_host *); +static void PTI_UtilParamsGet(struct pti_st_host *, ULONG, ULONG, UCHAR, ULONG, UCHAR *); + +/* + * Declare Utility Message Functions: + */ +static unsigned long pti_st_waitreplymsg(struct pti_st_host *); +static void PTI_UtilParamGetCall(struct pti_st_host *, + PI2O_UTIL_PARAMS_GET_MESSAGE, + void *, void *, PI2ODISK); +static void UtilNOPCall(struct pti_st_host *); + +static int ComposeDiskInfo(struct pti_st_host *, void *, void *, PI2ODISK); +static void GetInfoFromLCT(struct pti_st_host *, void *, PI2ODISK, unsigned int *); +static void ZeroMemory(unsigned long *, unsigned int); +static int pti_st_flushcache(int); +static void pti_st_flushcache_respond(Scsi_Cmnd *); +static void pti_st_wait_flushcache(unsigned long); +static int pti_st_send_flushcache_cmd(struct pti_st_host *, struct pti_st_scb *, Scsi_Cmnd *, int); + +#define ADDTOPROCBUFFER(d, s) { if((strlen(d)+strlen(s)) < 4095) strcat(d, s); else goto proc_out; } + +/* + * PTI_procfile_read: + * inout : decides on the direction of the dataflow and the meaning of the + * variables + * buffer: If inout==FALSE data is being written to it else read from it + * *start: If inout==FALSE start of the valid data in the buffer + * offset: If inout==FALSE offset from the beginning of the imaginary file + * from which we start writing into the buffer + * length: If inout==FALSE max number of bytes to be written into the buffer + * else number of bytes in the buffer + */ +int PTI_procfile_read(char *buffer, + char **buffer_location, + off_t offset, + int buffer_length, + int hostno, + int inout) +{ + /* + * The number of bytes actually used + */ + int len; + + /* + * This is static so it will still be in memory + * when we leave this function + */ + static char my_buffer[4096] = {0}; + char tmp_buffer[256] = {0}; + char *ptr = my_buffer; + int i, j; + + /* + * We give all of our information in one go, so if the + * user asks us if we have more information the + * answer should always be no. + * + * This is important because the standard read + * function from the library would continue to issue + * the read system call until the kernel replies + * that it has no more information, or until its + * buffer is filled. + */ + if (offset > 0) + return 0; + + /* + * Fill the buffer and get its length + */ + sprintf(ptr,"***** SuperTrak SX6000 Driver Version %2d.%2d *****\n", VERSIONHI, VERSIONLO); + ptr += strlen(ptr); + sprintf(ptr,"***** Copyright 1999-2001 by Promise Technology, Inc. *****\n\n"); + ptr += strlen(ptr); + + for(i = 0; i < MAX_ADAPTORS && (len = strlen(my_buffer)) < 4095; i++) { + if(!pti_st_hostp[i]) + continue; + sprintf(tmp_buffer, "\n\tIOP Number: %d\n", i); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tCapabilities: %ld", + pti_st_hostp[i]->IopStatus.IopCapabilities); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\tState: %d\n", + pti_st_hostp[i]->IopStatus.IopState); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tI2OVersion: %d", + pti_st_hostp[i]->IopStatus.I2oVersion); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\t\tMessengerType: 0x%x\n", + pti_st_hostp[i]->IopStatus.MessengerType); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tMaxMessageFrameSize: 0x%x", + pti_st_hostp[i]->IopStatus.InboundMFrameSize); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tExpectedLCTSize: 0x%lx\n", + pti_st_hostp[i]->IopStatus.ExpectedLCTSize); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tMaxInboundMFrames: 0x%lx", + pti_st_hostp[i]->IopStatus.MaxInboundMFrames); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tInitialInboundMFrames: 0x%lx\n", + pti_st_hostp[i]->IopStatus.CurrentInboundMFrames); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\n\tLCT Entry:\n"); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + + j = 0; + while(pti_st_hostp[i]->LctEntryTable[j].TableEntrySize == 0x09) + { + sprintf(tmp_buffer, "\n\tClass: 0x%x", + pti_st_hostp[i]->LctEntryTable[j].ClassID.Class); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\tVersion: %d\n", + pti_st_hostp[i]->LctEntryTable[j].ClassID.Version); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tOrganizationID: 0x%x", + pti_st_hostp[i]->LctEntryTable[j].ClassID.Version); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tLocalTID: 0x%x\n", + pti_st_hostp[i]->LctEntryTable[j].LocalTID); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tChangeIndicator: 0x%lx", + pti_st_hostp[i]->LctEntryTable[j].ChangeIndicator); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tDeviceFlags: 0x%lx\n", + pti_st_hostp[i]->LctEntryTable[j].DeviceFlags); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tSubClassInfo: 0x%lx", + pti_st_hostp[i]->LctEntryTable[j].SubClassInfo); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tUserTID: 0x%x\n", + pti_st_hostp[i]->LctEntryTable[j].UserTID); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tParentTID: 0x%x", + pti_st_hostp[i]->LctEntryTable[j].ParentTID); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\t\tBiosInfo: 0x%x\n", + pti_st_hostp[i]->LctEntryTable[j].BiosInfo); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + sprintf(tmp_buffer, "\tEventCapabilities: 0x%lx\n", + pti_st_hostp[i]->LctEntryTable[j].EventCapabilities); + ADDTOPROCBUFFER(my_buffer, tmp_buffer); + j++; + } + } + +proc_out: + /* + * Tell the function which called us where the + * buffer is + */ + len = strlen(my_buffer); + if(len < buffer_length) + buffer_length = len; + else if(len >= buffer_length) { + my_buffer[buffer_length-1] = 0; + len = buffer_length - 1; + } + + *buffer_location = my_buffer; + + /* + * Return the length + */ + return len; +} + +/*+F************************************************************************* + * Function: + * PTI_ST_info + * + * Description: + * Return a string describing the driver. + *-F*************************************************************************/ +const char *PTI_ST_info(struct Scsi_Host *dooh) +{ + static char buffer[256]; + char *bp; + + bp = &buffer[0]; + memset(bp, 0, sizeof(buffer)); + strcpy(bp, "PROMISE SuperTrak SX6000 Driver"); + return(bp); +} + + +/*++ + +Routine Description: + + This routine will write data specified by Buffer to PCIConfig Space + at Offset + +Arguments: + + +Return Values: + + Length of data which has been written + +--*/ + +static ULONG PTI_ST_SetBusDataByOffset( + ULONG BusNumber, + ULONG DeviceNumber, + ULONG FunctionNumber, + void *Buffer, + ULONG Offset, + ULONG Length +) +{ + ULONG cr; + + cr = 0x80000000 | + (BusNumber << 16) | + (DeviceNumber<<11) | + (FunctionNumber<<8) | + (Offset & 0xFC); + + outl(cr, 0xCf8); + + if (Length == 4) + outl(*((ULONG *)Buffer), 0xcfc); + else if (Length == 2) + { + ULONG data; + + data = (inl(0xCfC) & (Offset&0x3 ? 0xFFFF : 0xFFFF0000)); + data |= (((ULONG)(*(USHORT *)Buffer)) << (Offset&0x3 ? 16 : 0)); + outl(data, 0xcfc); + } + else + return(0); + + return(Length); + +} + + +/* + * Function: scbq_init(volatile scb_queue_type *queue) + * Description: SCB queue initialization. + */ +static void +scbq_init(volatile scb_queue_type *queue) +{ + queue->head = NULL; + queue->tail = NULL; +} + +/* + * Function: scbq_insert_head(volatile scb_queue_type, struct pti_st_scb) + * Description: Add an SCB to the head of the list. + */ +static inline void +scbq_insert_head(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) +{ + DRIVER_LOCK + scb->q_next = queue->head; + queue->head = scb; + if (queue->tail == NULL) /* If list was empty, update tail. */ + queue->tail = queue->head; + DRIVER_UNLOCK +} + +/* + * Function: scbq_remove_head(volatile scb_queue_type) + * Description: Remove an SCB from the head of the list. + */ +static inline struct pti_st_scb * +scbq_remove_head(struct pti_st_host *p, volatile scb_queue_type *queue) +{ + struct pti_st_scb * scbp; + + DRIVER_LOCK + scbp = queue->head; + if (queue->head != NULL) + queue->head = queue->head->q_next; + if (queue->head == NULL) /* If list is now empty, update tail. */ + queue->tail = NULL; + DRIVER_UNLOCK + return(scbp); +} + +/* + * Function: scbq_remove(volatile scb_queue_type, struct pti_st_scb) + * Description: Removes an SCB from the list. + */ +static inline void +scbq_remove(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) + unsigned long cpu_flags; +#endif + + DRIVER_LOCK + if (queue->head == scb) + { + /* At beginning of queue, remove from head. */ + scbq_remove_head(p, queue); + } + else + { + struct pti_st_scb *curscb = queue->head; + + /* + * Search until the next scb is the one we're looking for, or + * we run out of queue. + */ + while ((curscb != NULL) && (curscb->q_next != scb)) + { + curscb = curscb->q_next; + } + if (curscb != NULL) + { + /* Found it. */ + curscb->q_next = scb->q_next; + if (scb->q_next == NULL) + { + /* Update the tail when removing the tail. */ + queue->tail = curscb; + } + } + } + DRIVER_UNLOCK +} + +/* + * Function: scbq_insert_tail(volatile scb_queue_type, struct pti_st_scb) + * Description: Add an SCB at the tail of the list. + */ +static inline void +scbq_insert_tail(struct pti_st_host *p, volatile scb_queue_type *queue, struct pti_st_scb *scb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) + unsigned long cpu_flags; +#endif + + DRIVER_LOCK + scb->q_next = NULL; + if (queue->tail != NULL) /* Add the scb at the end of the list. */ + queue->tail->q_next = scb; + queue->tail = scb; /* Update the tail. */ + if (queue->head == NULL) /* If list was empty, update head. */ + queue->head = queue->tail; + DRIVER_UNLOCK +} + +/* + * Function: pti_st_allocate_scb(struct pti_st_host *, struct pti_st_scb *) + * Description: Free the scb and insert into the free scb list. + */ +static int +pti_st_allocate_scb(struct pti_st_host *p) +{ + struct pti_st_scb *scbp = NULL; + int scb_size = sizeof(struct pti_st_scb); + int i; + unsigned long scb_count = 0; + struct pti_st_scb *scb_ap; + + scb_count = p->scb_data->maxscbs; + scb_ap = (struct pti_st_scb *)kmalloc(scb_size * scb_count, GFP_ATOMIC); + if (scb_ap != NULL) + { + memset(scb_ap, 0, scb_count * scb_size); + for (i=0; i < scb_count; i++) + { + scbp = &scb_ap[i]; + scbp->mf = NULL; + scbp->tag = i; + + /* + * Place in the scb array; never is removed + */ + p->scb_data->scb_array[i] = scbp; + scbq_insert_head(p, &p->scb_data->free_scbs, scbp); + } + scbp->kmalloc_ptr = scb_ap; + } + else + { + return(0); + } + return(scb_count); +} + +/* + * Function: pti_st_queue_cmd_complete(struct pti_st_host *, Scsi_Cmnd *) + * Description: Due to race conditions present in the SCSI subsystem, it is + * easier to queue completed commands, then call scsi_done() on + * them when we're finished. + * This function queues the completed commands. + */ +static void +pti_st_queue_cmd_complete(struct pti_st_host *p, Scsi_Cmnd *cmd) +{ + cmd->host_scribble = (char *)p->completeq.head; + p->completeq.head = cmd; +} + +/* + * Function: pti_st_done_cmds_complete(struct pti_st_host *) + * Description: Process the completed command queue. + */ +static void +pti_st_done_cmds_complete(struct pti_st_host *p) +{ + Scsi_Cmnd *cmd; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) + unsigned int cpu_flags = 0; + + DRIVER_LOCK + while (p->completeq.head != NULL) + { + cmd = p->completeq.head; + p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble; + cmd->host_scribble = NULL; + sti(); + cmd->scsi_done(cmd); + cli(); + } + DRIVER_UNLOCK + +#else + + while (p->completeq.head != NULL) + { + cmd = p->completeq.head; + p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble; + cmd->host_scribble = NULL; + cmd->scsi_done(cmd); + } + +#endif +} + +/* + * Function: pti_st_free_scb(struct pti_st_host *, struct pti_st_scb *) + * Description: Free the scb and insert into the free scb list. + */ +static void +pti_st_free_scb(struct pti_st_host *p, struct pti_st_scb *scb) +{ + + scb->flags = SCB_FREE; + scb->cmd = NULL; + scb->sg_count = 0; + scb->sg_length = 0; + +// scb->mf->target_channel_lun = SCB_LIST_NULL; + + scbq_insert_head(p, &p->scb_data->free_scbs, scb); +} + +/* + * Function: pti_st_done(struct pti_st_host *, struct pti_st_scb *) + * Description: Calls the higher level scsi done function and frees the scb. + */ +static void +pti_st_done(struct pti_st_host *p, struct pti_st_scb *scb) +{ + Scsi_Cmnd *cmd = scb->cmd; + + if (scb->flags & SCB_RESET) + { + cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); + } + else if (scb->flags & SCB_ABORT) + { + cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff); + } + + pti_st_free_scb(p, scb); + pti_st_queue_cmd_complete(p, cmd); +} + +/* + * Function: pti_st_run_done_queue(struct pti_st_host *, int) + * Description: Calls the pti_st_done() for the Scsi_Cmnd of each scb in the + * aborted list, and adds each scb to the free list. If complete + * is TRUE, we also process the commands complete list. + */ +static void +pti_st_run_done_queue(struct pti_st_host *p, int complete) +{ + struct pti_st_scb *scb; + int i; + + for (i = 0; i < p->scb_data->maxscbs; i++) + { + scb = p->scb_data->scb_array[i]; + if (scb->flags & SCB_QUEUED_FOR_DONE) + pti_st_done(p, scb); + } + if (complete) + { + pti_st_done_cmds_complete(p); + } +} + +/* + * Function: pti_st_isr(int, void, struct pt_regs) + * Description: i960 controller interrupt handler. + */ +static void +pti_st_isr(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile U32 phyAddrMsg = 0xffffffff; + U32 scb_index; + Scsi_Cmnd *cmd; + struct pti_st_host *p; + struct pti_st_scb *scbp; + PI2O_BSA_REPLY_MESSAGE_FRAME rmfp = NULL; + int testtime = 0; + int i; + U32 tmp; + + p = (struct pti_st_host *)dev_id; + if(!p) + return; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(pti_st_hostp[i] == p) + break; + + if(i >= MAX_ADAPTORS || !p->p_atu) + return; + + phyAddrMsg = p->p_atu->OutQueue; + + while (TRUE) + { + for(testtime = 1; + (phyAddrMsg == 0xffffffff) && (testtime < 3); + testtime++) + { + phyAddrMsg = p->p_atu->OutQueue; + } + + if(phyAddrMsg == 0xffffffff) { + return; + } + + rmfp = (PI2O_BSA_REPLY_MESSAGE_FRAME)(bus_to_virt(phyAddrMsg)); + + scb_index = rmfp->StdMessageFrame.InitiatorContext; + // we handle ioctl scsi command here, the command is sent by the + // InitiatorContext of standard message frame, we send the message + // in pti_st_send_private_message_code_cmd function. + tmp = rmfp->TransactionContext; + if(scb_index == 0xfd && tmp ){ + cmd = (Scsi_Cmnd *)tmp; + if(cmd->scsi_done && cmd->cmnd[0] == 0xfd){ + cmd->scsi_done(cmd); + } + else{ + printk("cmd->scsi_done is NULL in pti_st_isr.\n"); + } + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + continue; + } + /////////////////////////////////////// + scbp = p->scb_data->scb_array[scb_index]; + if (!scbp) + { + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + continue; + } + + cmd = scbp->cmd; + + //printk("return cmd= 0x%x, mfp= 0x%x, sno= 0x%x tag= 0x%x ind= 0x%x scb= 0x%x\n", + // cmd, rmfp, cmd->serial_number, scbp->tag, scb_index, scbp); + if (cmd->serial_number != rmfp->TransactionContext) + { + printk("Error in cmd%2x, mismatch sn 0x%x, mfp 0x%x scbi= %x\n", + cmd->cmnd[0], (int)cmd->serial_number, + (int)rmfp->TransactionContext, + (int)scb_index); + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + continue; + } + + if (rmfp->ReqStatus != I2O_REPLY_STATUS_SUCCESS) { + cmd->result = DID_ERROR; +#if defined(DEBUG) + printk("pti_st_isr: Reply Status Fail, ReqStatus[%x], DetailedStatus[%x]\n", rmfp->ReqStatus, rmfp->DetailedStatusCode); +#endif + } + + pti_st_free_scb(p, scbp); + pti_st_queue_cmd_complete(p, cmd); + /* return MFA to outbound free Q*/ + p->p_atu->OutQueue = phyAddrMsg; + + /* any more msgs? */ + phyAddrMsg = p->p_atu->OutQueue; + } + + return; +} + +/* + * Function: do_pti_st_isr(int, void *, struct pt_regs *) + * Description: + * This is a gross hack to solve a problem in linux kernels 2.1.85 and + * above. Please, children, do not try this at home, and if you ever see + * anything like it, please inform the Gross Hack Police immediately + */ +void do_pti_st_isr( int irq, void *dev_id, struct pt_regs * regs ) +{ + unsigned long cpu_flags = 0; + struct pti_st_host *p; + U32 OutIntStat; + int i; + + p = (struct pti_st_host *)dev_id; + if(!p) + return; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS) + return; + + OutIntStat = p->p_atu->OutIntStat; + + if (OutIntStat==0) + return; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95) + if(test_and_set_bit(PSTC_IN_ISR_BIT, &p->flags)) + { + return; + } + spin_lock_irqsave(&io_request_lock, cpu_flags); + pti_st_isr(irq, dev_id, regs); + pti_st_done_cmds_complete(p); + clear_bit(PSTC_IN_ISR_BIT, &p->flags); + spin_unlock_irqrestore(&io_request_lock, cpu_flags); +#else + if(set_bit(PSTC_IN_ISR_BIT, (int *)&p->flags)) + { + return; + } + DRIVER_LOCK + pti_st_isr(irq, dev_id, regs); + DRIVER_UNLOCK + pti_st_done_cmds_complete(p); + clear_bit(PSTC_IN_ISR_BIT, (int *)&p->flags); +#endif +} + +/* + * Function: pti_st_register(Scsi_Host_Template *, struct pti_st_host *) + * Description: Register i960 controller with the kernel. + */ +static int +pti_st_register(Scsi_Host_Template *template, struct pti_st_host *p) +{ + int result; + struct Scsi_Host *host; + + host = p->host; + + p->scb_data->maxscbs = PTI_ST_MAXSCB; + + /* + * On some new SMP motherboard, there are some problem when huge + * data are readed/written, so we should reduce the limit of request + * from 32 to 16 + */ +#if 0 + host->can_queue = PTI_ST_MAXSCB; +#else +// host->can_queue = 16; + host->can_queue = 12; +#endif + + host->cmd_per_lun = 3; + host->sg_tablesize = PTI_ST_MAX_SG; + host->this_id = p->scsi_id; + host->irq = p->pci_irq; + + p->host = host; + p->host_no = host->host_no; + p->completeq.head = NULL; + p->completeq.tail = NULL; + + /* + * Initialize the Super Track hardware controler, procedure as the + * typical system initialization of I2O + */ + p->maddr = ioremap(p->mbase, 4*1024*1024); + if(!(p->maddr)) + { + p->pci_irq = 0; + return (0); + } + + p->p_atu = (PATU)p->maddr; + p->LinBaseAddr = (PU8)p->maddr; + + p->outboundBufferp = (outboundBuff_t *)kmalloc((16*1024+256+32*32*4), GFP_ATOMIC); + if(p->outboundBufferp == NULL) { + p->pci_irq = 0; + printk("Allocating buffer fails!\n"); + return(0); + } + p->replyBufferp = (PU8)((PU8)p->outboundBufferp + 32*32*4); + p->messageBufferp = p->replyBufferp + (16*1024); + + p->outMsgBlockPhyAddr = virt_to_bus(p->outboundBufferp); + p->pLinOutMsgBlock = (PU8)(p->outboundBufferp); + + /* + * Allocate the set of scbs for this controller. This is to stream- + * line code elsewhere in the driver. If we have to check for the existence + * of scbs in certain code sections, it slows things down. However, as + * soon as we register the IRQ for this card, we could get an interrupt that + * includes possibly the SCSI_RSTI interrupt. If we catch that interrupt + * then we are likely to segfault if we don't have at least one chunk of + * SCBs allocated or add checks all through the reset code to make sure + * that the SCBs have been allocated which is an invalid running condition + * and therefore I think it's preferable to simply pre-allocate the first + * chunk of SCBs. + */ + + result = pti_st_allocate_scb(p); + if(!result) + { + p->pci_irq = 0; + printk("Allocating scbs fails!\n"); + return(0); + } + + /* + * Disable interrupt + */ + p->p_atu->OutIntMask = 0xffffffff; + + if(!IOP_init(p)) + { + p->pci_irq = 0; + return (0); + } + + /* + * Clear out any possible pending interrupts, again. + */ + /* pti_st_clear_intstat(p); */ + + /* + * Register IRQ with the kernel. Only allow sharing IRQs with + * PCI devices. + */ + result = (request_irq(p->pci_irq, do_pti_st_isr, SA_SHIRQ, "pti_st", p)); + if(result < 0) + { + result = (request_irq(p->pci_irq, do_pti_st_isr, + (SA_INTERRUPT | SA_SHIRQ), "pti_st", p)); + } + + if (result < 0) + { + printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring " + "controller.\n", p->host_no, p->pci_irq); + p->pci_irq = 0; + return (0); + } else { + /* + * Enable interrupt + */ + p->p_atu->OutIntMask = 0x00000000; + } + + host->max_id = MAX_ARRAYS; + host->max_channel = 0; + host->max_lun = p->max_lun = 1; + + return (1); +} + +/* + * Function: pti_st_free(struct pti_st_host *) + * Description: Frees and releases all resources associated with an instance of + * the driver (struct pti_st_host *). + */ +static void +pti_st_free(struct pti_st_host *p) +{ + int i; + + if (p->scb_data != NULL) + { + + /* + * Free the driver SCBs. These were allocated on an as-need + * basis. We allocated these in groups depending on how many + * we could fit into a given amount of RAM. The tail SCB for + * these allocations has a pointer to the alloced area. + */ + for (i = 0; i < p->scb_data->maxscbs; i++) + { + if (p->scb_data->scb_array[i]->kmalloc_ptr != NULL) + kfree(p->scb_data->scb_array[i]->kmalloc_ptr); + p->scb_data->scb_array[i] = NULL; + } + + /* + * Free the SCB data area. + */ + kfree(p->scb_data); + } +} + +/* + * Function: pti_st_release(struct Scsi_Host *) + * Description: Free the passed in Scsi_Host memory structures prior to + * unloading the module. + */ +int +pti_st_release(struct Scsi_Host *host) +{ + struct pti_st_host *p = (struct pti_st_host *) host->hostdata; + int i; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(!p || i >= MAX_ADAPTORS) + return(-1); + + if(p->pci_irq) { + free_irq(p->pci_irq, p); + p->pci_irq = 0; + /* + * Disbale interrupt + */ + p->p_atu->OutIntMask = 0x000000fc; + } + if(p->maddr) + { + iounmap((void *) (((unsigned long) p->maddr))); + p->maddr = 0; + } + if(p->outboundBufferp) { + kfree(p->outboundBufferp); + p->outboundBufferp = NULL; + } + if(p->pti_stdev_bufferp) { + kfree(p->pti_stdev_bufferp); + p->pti_stdev_bufferp = NULL; + } + pti_st_free(p); + pti_st_hostp[i] = NULL; + return(0); +} + +/* + * Function: pti_st_alloc(Scsi_Host_Template *, struct pti_st_host *) + * Description: Allocate and initialize a host structure. + * Returns NULL upon error and a pointer to a pti_st_host struct + * upon success. + */ +static struct pti_st_host * +pti_st_alloc(Scsi_Host_Template *sht, struct pti_st_host *temp) +{ + struct pti_st_host *p = NULL; + struct Scsi_Host *host; + + /* + * Allocate a storage area by registering us with the mid-level + * SCSI layer. + */ + host = scsi_register(sht, sizeof(struct pti_st_host)); + + if (host != NULL) + { + p = (struct pti_st_host *) host->hostdata; + memset(p, 0, sizeof(struct pti_st_host)); + *p = *temp; + p->host = host; + p->scsi_id = -1; + p->host_no = host->host_no; + p->scb_data = kmalloc(sizeof(scb_data_type), GFP_ATOMIC); + if (p->scb_data != NULL) + { + memset(p->scb_data, 0, sizeof(scb_data_type)); + scbq_init (&p->scb_data->free_scbs); + } + else + { + /* + * For some reason we don't have enough memory. Free the + * allocated memory for the pti_st_host struct, and return NULL. + */ + scsi_unregister(host); + return(NULL); + } + p->pti_stdev_bufferp = kmalloc(sizeof(PTI_STDEV_INBUFFER), GFP_ATOMIC); + if(p->pti_stdev_bufferp != NULL) + { + memset(p->pti_stdev_bufferp, 0, sizeof(PTI_STDEV_INBUFFER)); + } else { + scsi_unregister(host); + return(NULL); + } + } + return (p); +} + + +/* + * Function: pti_st_detect(Scsi_Host_Template *) + * Description: Try to detect and register i960 controller. + * This should really be called pti_st_probe(). A sequence of + * probe(), attach()/detach(), and init() makes more sense than + * one do-it-all function. This may be useful when (and if) the + * mid-level SCSI code is overhauled. + */ +int pti_st_detect(Scsi_Host_Template *template) +{ + struct pci_dev *pdev; + int found = 0; + + if (!pci_present()) + return 0; + + // printk("pti_st.c: PCI bios is present, checking for devices ...\n"); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + pci_for_each_dev(pdev) +#else + for(pdev = pci_devices, found = 0; + found < MAX_ADAPTORS && pdev != NULL; + pdev = pdev->next) +#endif + { + if(pdev->vendor != PCI_VENDOR_ID_INTEL || + (pdev->device != PCI_DEVICE_ID_INTEL_i960 && /* ST100 */ + pdev->device != PCI_DEVICE_ID_INTEL_i962)) /* ST100SX6 */ + continue; + + pti_st_install(template, pdev, &found); + } + + return(found); +} + +static int pti_st_install(Scsi_Host_Template *template, struct pci_dev *pdev, int *aptno) +{ + struct pti_st_host *p = NULL; + struct pti_st_host *temp_p = NULL; + unsigned short command; + unsigned long cmd; + unsigned long devicenumber, functionnumber; + + devicenumber = PCI_SLOT(pdev->devfn); + functionnumber = 0; + + /* + * Expose the ship behind i960 for initialization, or it will failed + */ + cmd = 0x0000; + PTI_ST_SetBusDataByOffset(pdev->bus->number, + devicenumber, + functionnumber, + &cmd, + 0x42, + sizeof(U16)); + + template->sg_tablesize = PTI_ST_MAX_SG; + template->proc_dir = &proc_scsi_pti_st; + template->proc_info = PTI_procfile_read; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + if(!template->proc_name) { + if(template->name) + template->proc_name = (char *)template->name; + else + template->proc_name = "pti_st"; + } +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + pci_enable_device(pdev); +#endif + + if ( !(temp_p = kmalloc(sizeof(struct pti_st_host), GFP_ATOMIC))) + { + printk("pti_st_host data structure memory alloc error!!!\n"); + cmd = 0x03ff; + PTI_ST_SetBusDataByOffset(pdev->bus->number, + devicenumber, + functionnumber, + &cmd, + 0x42, + sizeof(U16)); + return(0); + } + memset(temp_p, 0, sizeof(struct pti_st_host)); + + temp_p->pci_irq = pdev->irq; + temp_p->pdev = pdev; + temp_p->pci_bus = pdev->bus->number; + temp_p->pci_device_fn = pdev->devfn; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + temp_p->mbase = pci_resource_start(pdev, 0); + template->name = "pti_st"; +#else + temp_p->mbase = pdev->base_address[0]; +#endif + pci_read_config_word(pdev, PCI_COMMAND, &command); + + command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, command); + + temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; + + printk("Found PTI SuperTrak at mbase: %#x, irq %d.\n", + temp_p->mbase, temp_p->pci_irq); + + pti_st_hostp[*aptno] = p = pti_st_alloc(template, temp_p); + + if (p != NULL) + { + DRIVER_LOCK_INIT + (*aptno)++; + if (!pti_st_register(template, p)) + { + pti_st_release(p->host); + scsi_unregister(p->host); + (*aptno)--; + pti_st_hostp[*aptno] = NULL; + } + } + + cmd = 0x03ff; + PTI_ST_SetBusDataByOffset(pdev->bus->number, + devicenumber, + functionnumber, + &cmd, + 0x42, + sizeof(U16)); + + kfree(temp_p); + return (*aptno); +} + +/* + * Function: pti_st_copy_internal_data(Scsi_Cmnd *, char *, unsigned short) + * Description: Queue a SCB to the controller. + */ +static void +pti_st_copy_internal_data(Scsi_Cmnd *scp, char *buffer, unsigned short count) +{ + unsigned short cpcount,i; + unsigned short cpsum,cpnow; + struct scatterlist *sl; + + cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; + if (scp->use_sg) + { + sl = (struct scatterlist *)scp->request_buffer; + for (i=0,cpsum=0; iuse_sg; ++i,++sl) + { + cpnow = (ushort)sl->length; + if (cpsum+cpnow > cpcount) + cpnow = cpcount - cpsum; + cpsum += cpnow; + memcpy((char*)sl->address,buffer,cpnow); + if (cpsum == cpcount) + break; + buffer += cpnow; + } + } + else + { + memcpy((char*)scp->request_buffer,buffer,cpcount); + } +} + +/* + * Function: pti_st_rw_cmd(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) * Description: Translate Scsi Command to I2O Message Frame. + */ +static int +pti_st_rw_cmd(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + struct pti_st_host *p; + struct pti_st_scb *scb; + unsigned long msgoffset; + unsigned long blk_nr = 0; + unsigned long blk_count = 0; + PI2O_BSA_RW_MESSAGE mfp; + unsigned char *cmnd; + unsigned long pBaseAddrReg; + int i; + unsigned long cpuflags; + + p = (struct pti_st_host *) cmd->host->hostdata; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS || !p) { + cmd->result = (DID_BAD_TARGET << 16); + fn(cmd); + return 0; + } + + scb = scbq_remove_head(p, &p->scb_data->free_scbs); + + if (scb == NULL) + { + cmd->result = (DID_BUS_BUSY << 16); + printk(WARN_LEAD"Couldn't get a free SCB.\n", p->host_no, + CTL_OF_CMD(cmd)); + fn(cmd); + return 0; + } + + if (cmd->target >= MAX_DRIVES || p->I2ODisk[cmd->target].present != TRUE) + { + cmd->result = (DID_BAD_TARGET << 16); + fn(cmd); + return 0; + } + + spin_lock_irqsave(&p->spin_lock, cpuflags); + + pBaseAddrReg = (U32)p->maddr; + msgoffset = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + if (msgoffset == 0xFFFFFFFF) + { + printk(INFO_LEAD"Couldn't get a free MF from inboundqport.\n", + p->host_no, CTL_OF_CMD(cmd)); + cmd->result = (DID_BUS_BUSY << 16); + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + scbq_insert_head(p, &p->scb_data->free_scbs, scb); + fn(cmd); + return 0; + } + scb->cmd = cmd; + pti_st_position(cmd) = scb->tag; + + p->scb_data->scb_array[scb->tag] = scb; + + /* + * Make sure the Scsi_Cmnd pointer is saved, the struct it points to + * is set up properly, and the parity error flag is reset, then send + * the SCB to the sequencer and watch the fun begin. + */ + cmd->scsi_done = fn; + cmd->result = DID_OK; + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + cmd->host_scribble = NULL; + + scb->flags |= SCB_ACTIVE; + mfp = (PI2O_BSA_RW_MESSAGE)(pBaseAddrReg + msgoffset); + memset((char *)mfp, 0, sizeof(I2O_BSA_READ_MESSAGE)); + cmnd = (unsigned char *)cmd->cmnd; + switch (*cmnd) + { + case READ_6: + { + blk_nr = cmnd[3] + (cmnd[2] << 8) + ((cmnd[1] & 0x1f) << 16); + blk_count = cmnd[4]; + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_READ; + mfp->FetchAhead = 0; + break; + + case READ_10: + { + blk_nr = ntohl(*(PU32)&cmnd[2]); + blk_count = cmnd[8] + (cmnd[7] << 8); + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_READ; + mfp->FetchAhead = 0; + break; + + case WRITE_6: + { + blk_nr = cmnd[3] + (cmnd[2] << 8) + ((cmnd[1] & 0x1f) << 16); + blk_count = cmnd[4]; + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_WRITE; + break; + + case WRITE_10: + { + blk_nr = ntohl(*(PU32)&cmnd[2]); + blk_count = cmnd[8] + (cmnd[7] << 8); + } + mfp->StdMessageFrame.Function = I2O_BSA_BLOCK_WRITE; + break; + } + mfp->LogicalByteAddress.HighPart = blk_nr >> (32 - 9); + mfp->LogicalByteAddress.LowPart = blk_nr << 9; + mfp->TransferByteCount = blk_count << 9; + mfp->TransactionContext = cmd->serial_number; + mfp->StdMessageFrame.InitiatorContext = scb->tag; + mfp->StdMessageFrame.VersionOffset=0x81; + mfp->StdMessageFrame.MsgFlags=0; + mfp->StdMessageFrame.MessageSize=sizeof(I2O_BSA_READ_MESSAGE)>>2; + mfp->StdMessageFrame.TargetAddress=p->I2ODisk[cmd->target].LocalTID; + mfp->StdMessageFrame.InitiatorAddress = 0x01; + mfp->ControlFlags = 0; + mfp->TimeMultiplier = 0x31; /*0;*/ + + { + //printk("Issue cmd= %x, mfp 0x%x, sno= 0x%x tag= 0x%x scb=0x%x\n", + // cmd, mfp, cmd->serial_number, scb->tag, scb); + } + /* + * The interpretation of request_buffer and request_bufflen + * changes depending on whether or not use_sg is zero; a + * non-zero use_sg indicates the number of elements in the + * scatter-gather array. + */ + + if (cmd->use_sg) + { + struct scatterlist *sg; /* Must be mid-level SCSI code scatterlist */ + + /* + * We must build an SG list in I2O SGL format, as the kernel's SG list + * cannot be used directly + */ + int i; + + sg = (struct scatterlist *)cmd->request_buffer; + /* + * Copy the segments into the SG array. NOTE!!! - We used to + * have the first entry both in the data_pointer area and the first + * SG element. That has changed somewhat. We still have the first + * entry in both places, but now we download the address of + * scb->sg_list[1] instead of 0 to the sg pointer in the mf. + */ + for (i = 0; i < (cmd->use_sg); i++) + { + mfp->SGL.u.Simple[i].FlagsCount.Count = cpu_to_le32(sg[i].length); + mfp->SGL.u.Simple[i].FlagsCount.Flags = + (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + mfp->SGL.u.Simple[i].PhysicalAddress = + cpu_to_le32(VIRT_TO_BUS(sg[i].address)); + } + mfp->SGL.u.Simple[cmd->use_sg - 1].FlagsCount.Flags |= + ( I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER); + } + else + { + mfp->SGL.u.Simple[0].FlagsCount.Count = + cpu_to_le32(cmd->request_bufflen); + mfp->SGL.u.Simple[0].FlagsCount.Flags = + ( I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_TRANSPORT_ELEMENT | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + mfp->SGL.u.Simple[0].PhysicalAddress = + cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer)); + } + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgoffset; + + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + + return (0); +} + +/* + * Function: pti_st_internal_cmd(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) + * Description: Excuting TEST_UNIT_READY, INQUIRY, READ_CAPACITY, etc. + * scsi command. + */ +static int +pti_st_internal_cmd(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + struct pti_st_host *p; + + // struct pti_st_scb *scb; + // unsigned long cpu_flags = 0; + pti_inq_data inq; + pti_rdcap_data rdc; + int i; + + p = (struct pti_st_host *) cmd->host->hostdata; + + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS) { + cmd->result = (DID_BAD_TARGET << 16); + fn(cmd); + return 0; + } + + switch (cmd->cmnd[0]) + { + case TEST_UNIT_READY: + cmd->result = DID_OK << 16; + break; + + case INQUIRY: + memset((void *)&inq, 0, sizeof(inq)); + inq.type_qual = TYPE_DISK; + /* + * you can here set all disks to removable, if you want to do + * a flush using the ALLOW_MEDIUM_REMOVAL command + */ + inq.modif_rmb = 0x00; + inq.version = 2; + inq.resp_aenc = 2; + inq.add_length= 32; + strcpy(inq.vendor,"PTI "); + strcpy(inq.product,"SuperTrak"); + strcpy(inq.revision," "); + if(cmd->target < MAX_DRIVES && p->I2ODisk[cmd->target].present == TRUE) + { + pti_st_copy_internal_data(cmd,(char*)&inq, sizeof(pti_inq_data)); + cmd->result = DID_OK << 16; + } else { + pti_st_copy_internal_data(cmd,(char*)&inq, sizeof(pti_inq_data)); + cmd->result = DID_BAD_TARGET << 16; + } + break; + +#if 0 + case REQUEST_SENSE: + sd.errorcode = 0x70; + sd.segno = 0x00; + sd.key = NO_SENSE; + sd.info = 0; + sd.add_length= 0; + pti_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); + cmd->result = DID_OK << 16; + break; + case MODE_SENSE: + memset((char*)&mpd,0,sizeof(gdth_modep_data)); + mpd.hd.data_length = sizeof(gdth_modep_data); + mpd.hd.dev_par = (ha->id[b][t].devtype&2) ? 0x80:0; + mpd.hd.bd_length = sizeof(mpd.bd); + mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; + mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; + mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); + pti_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); + cmd->result = DID_OK << 16; + break; +#endif + + case READ_CAPACITY: + if(cmd->target < MAX_DRIVES && p->I2ODisk[cmd->target].present) + { + rdc.last_block_no = ntohl(p->I2ODisk[cmd->target].lastLBA); + rdc.block_length = ntohl(SECTOR_SIZE); + pti_st_copy_internal_data(cmd,(char*)&rdc, sizeof(pti_rdcap_data)); + cmd->result = DID_OK << 16; + } else { + cmd->result = DID_BAD_TARGET; + } + break; + + default: + printk("!!!!!!!!PTI: Unknown SCSI command 0x%x to cache service !\n", + cmd->cmnd[0]); + cmd->result = DID_ABORT << 16; + break; + } + + fn(cmd); + return 0; +} + +/* + * Function: pti_st_queue(Scsi_Cmnd *, void (*fn)(Scsi_Cmnd *)) + * Description: Queue a SCB to the controller. + */ +int +pti_st_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) +{ + int ret; + + switch (cmd->cmnd[0]) + { + case READ_6: + case READ_10: + case WRITE_6: + case WRITE_10: +// case VERIFY: + ret = pti_st_rw_cmd(cmd, fn); + return(ret); + case TEST_UNIT_READY: + case INQUIRY: + case READ_CAPACITY: + return(pti_st_internal_cmd(cmd, fn)); +// case VERIFY: +// case START_STOP: +// case REQUEST_SENSE: +// case MODE_SENSE: + + default: + break; + } + printk("PTI: Unknown SCSI command 0x%x to cache service!\n", cmd->cmnd[0]); + cmd->result = DID_ABORT << 16; + fn(cmd); + return 0; +} + +/* + * Function: pti_st_abort(Scsi_Cmnd *) + * Description: Abort the current SCSI command(s). + */ +int +pti_st_abort(Scsi_Cmnd *cmd) +{ + struct pti_st_scb *scb = NULL; + struct pti_st_host *p; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) + unsigned long cpu_flags = 0; +#endif + Scsi_Cmnd *cmd_next, *cmd_prev; + int i; + + p = (struct pti_st_host *) cmd->host->hostdata; + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(i >= MAX_ADAPTORS || !p) { + return(SCSI_ABORT_NOT_RUNNING); + } + + scb = (p->scb_data->scb_array[pti_st_position(cmd)]); + + + DRIVER_LOCK + +/* + * Run the isr to grab any command in the QOUTFIFO and any other misc. + * assundry tasks. This should also set up the bh handler if there is + * anything to be done, but it won't run until we are done here since + * we are following a straight code path without entering the scheduler + * code. + */ + + { + pti_st_isr(p->pci_irq, p, (void *)NULL); + pti_st_done_cmds_complete(p); + } + + if ((scb == NULL) || (cmd->serial_number != cmd->serial_number_at_timeout)) + /* Totally bogus cmd since it points beyond our */ + { /* valid SCB range or doesn't even match it's own*/ + /* timeout serial number. */ + DRIVER_UNLOCK + return(SCSI_ABORT_NOT_RUNNING); + } + + if (scb->cmd != cmd) /* Hmmm...either this SCB is currently free with a */ + { /* NULL cmd pointer (NULLed out when freed) or it */ + /* has already been recycled for another command */ + /* Either way, this SCB has nothing to do with this*/ + /* command and we need to deal with cmd without */ + /* touching the SCB. */ + /* The theory here is to return a value that will */ + /* make the queued for complete command actually */ + /* finish successfully, or to indicate that we */ + /* don't have this cmd any more and the mid level */ + /* code needs to find it. */ + cmd_next = p->completeq.head; + cmd_prev = NULL; + while (cmd_next != NULL) + { + if (cmd_next == cmd) + { +// if (pti_st_verbose & VERBOSE_ABORT_PROCESS) + printk(INFO_LEAD "Abort called for command " + "on completeq, completing.\n", p->host_no, CTL_OF_CMD(cmd)); + if ( cmd_prev == NULL ) + p->completeq.head = (Scsi_Cmnd *)cmd_next->host_scribble; + else + cmd_prev->host_scribble = cmd_next->host_scribble; + cmd_next->scsi_done(cmd_next); + DRIVER_UNLOCK + + return(SCSI_ABORT_NOT_RUNNING); /* It's already back as a successful + * completion */ + } + cmd_prev = cmd_next; + cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; + } + +// if (pti_st_verbose & VERBOSE_ABORT_MID) + printk(INFO_LEAD "Abort called for already completed" + " command.\n", p->host_no, CTL_OF_CMD(cmd)); + DRIVER_UNLOCK + return(SCSI_ABORT_NOT_RUNNING); + } + +/* + * Hmmm...completeq, QOUTFIFO, QINFIFO, WAITING_SCBH, waitingq all checked. + * OK...the sequencer's paused, interrupts are off, and we haven't found the + * command anyplace where it could be easily aborted. Time for the hard + * work. We also know the command is valid. This essentially means the + * command is disconnected, or connected but not into any phases yet, which + * we know due to the tests we ran earlier on the current active scb phase. + * At this point we can queue the abort tag and go on with life. + */ + if (scb->flags & SCB_WAITINGQ) + { + scbq_remove(p, &p->waiting_scbs, scb); + } + scb->flags &= ~(SCB_WAITINGQ | SCB_ACTIVE); + scb->flags |= SCB_ABORT; + pti_st_done(p, scb); + pti_st_done_cmds_complete(p); +// pti_st_run_waiting_queues(p); + DRIVER_UNLOCK + +/* + * On the return value. If we found the command and aborted it, then we know + * it's already sent back and there is no reason for a further timeout, so + * we use SCSI_ABORT_SUCCESS. On the queued abort side, we aren't so certain + * there hasn't been a bus hang or something that might keep the abort from + * from completing. Therefore, we use SCSI_ABORT_PENDING. The first time +this + * is passed back, the timeout on the command gets extended, the second time + * we pass this back, the mid level SCSI code calls our reset function, which + * would shake loose a hung bus. + */ + return(SCSI_ABORT_SUCCESS); +} + +/* + * Function: pti_st_reset(Scsi_Cmnd *, unsigned int) + * Description: Resetting the bus always succeeds - is has to, otherwise the + * kernel will panic! Try a surgical technique: sending ARRAY + * RESET message frame + */ +int +pti_st_reset(Scsi_Cmnd *cmd, unsigned int flags) +{ + struct pti_st_scb *scb = NULL; + struct pti_st_host *p; + int i; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) + unsigned long cpu_flags = 0; +#endif + Scsi_Cmnd *cmd_prev, *cmd_next; + + + if ( cmd == NULL ) + { + return(SCSI_RESET_SNOOZE); + } + + p = (struct pti_st_host *) cmd->host->hostdata; + for(i = 0; i < MAX_ADAPTORS; i++) + if(p == pti_st_hostp[i]) + break; + + if(!p || i >= MAX_ADAPTORS) + return(SCSI_RESET_NOT_RUNNING); + + scb = (p->scb_data->scb_array[pti_st_position(cmd)]); + + DRIVER_LOCK + + pti_st_isr(p->pci_irq, p, (void *)NULL ); + pti_st_done_cmds_complete(p); + + if (scb == NULL) + { +// if (pti_st_verbose & VERBOSE_RESET_MID) + printk(INFO_LEAD "Reset called with bogus Scsi_Cmnd" + "->SCB mapping, improvising.\n", p->host_no, CTL_OF_CMD(cmd)); + } + else if (scb->cmd != cmd) + { +// if (pti_st_verbose & VERBOSE_RESET_MID) + printk(INFO_LEAD "Reset called with recycled SCB " + "for cmd.\n", p->host_no, CTL_OF_CMD(cmd)); + cmd_prev = NULL; + cmd_next = p->completeq.head; + while ( cmd_next != NULL ) + { + if (cmd_next == cmd) + { +// if (pti_st_verbose & VERBOSE_RESET_RETURN) + printk(INFO_LEAD "Reset, found cmd on completeq" + ", completing.\n", p->host_no, CTL_OF_CMD(cmd)); + DRIVER_UNLOCK + return(SCSI_RESET_NOT_RUNNING); + } + cmd_prev = cmd_next; + cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble; + } + } +/* + * By this point, we want to already know what we are going to do and + * only have the following code implement our course of action. + */ + for (i = 0; i < p->scb_data->maxscbs; i++) + { + scb = p->scb_data->scb_array[i]; + if (scb->flags & SCB_ACTIVE) + { + scb->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE; + scb->flags &= ~(SCB_ACTIVE | SCB_WAITINGQ); + } + } + scbq_init(&p->waiting_scbs); + pti_st_run_done_queue(p, TRUE); + /* We can't rely on run_waiting_queues to unpause the sequencer for + * PCI based controllers since we use AAP */ + DRIVER_UNLOCK + return (SCSI_RESET_SUCCESS); +} + +/* + * Function: pti_st_biosparam(Disk *, kdev_t, int[]) + * Description: Return the disk geometry for the given SCSI device. + */ +int +pti_st_biosparam(Disk *disk, kdev_t dev, int geom[]) +{ + int heads; + int sectors; + int cylinders; + struct pti_st_host *p; + + p = (struct pti_st_host *) disk->device->host->hostdata; + + /* + * XXX - if I could portably find the card's configuration + * information, then this could be autodetected instead + * of left to a boot-time switch. + */ + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return (0); +} + + + + +/*************************************************************************** + Hardware Interface Functions +****************************************************************************/ + +/* + * Function : static int IOP_init(struct pti_st_host *); + * Description: just initialize the hardware, fetch parameters from PCI. + */ +static int IOP_init(struct pti_st_host *hostp) +{ + int index; + int IopStatus; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Inbound; + + // printk("Initializing i960! pBaseAddrReg :%lx\n", pBaseAddrReg); + + // Until the Inbound Queue is available: + pMFA_Inbound = *(U32 *)(pBaseAddrReg+INBOUNDQPORT); + while (((U32) pMFA_Inbound == -1)) + pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + UtilNOPCall(hostp); + + ExecIOPReset(hostp); + + IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); + + OutboundInitCall(hostp); + + UtilNOPCall(hostp); + IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); + + /* Outbound Queue is now available! */ + + SysTabSetCall(hostp, (PI2O_EXEC_SYS_TAB_SET_MESSAGE)hostp->messageBufferp, + (void *)hostp->replyBufferp); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending ExecSysTabSet Message!\n"); + return(FALSE); + } + + IopStatus = GetStatusCall(hostp, (void *)hostp->replyBufferp); + + if (IopStatus == I2O_IOP_STATE_READY) + { + /* + * Send ExecSysEnable message, wait for reply + * + */ + EnableSysCall(hostp); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending ExecSysEnable Message!\n"); + return(FALSE); + } + if (GetStatusCall(hostp, (void *)hostp->replyBufferp) != I2O_IOP_STATE_OPERATIONAL) + return(FALSE); + + } + + + /* IOP is in OPERATIONAL state! */ + + LCTNotifyCall(hostp); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending ExecLctNotify Message!\n"); + return(FALSE); + } + + + /* IOP is now initialized! */ + + GetInfoFromLCT(hostp, + (void *)hostp->replyBufferp, + (PI2ODISK)hostp->I2ODisk, + (unsigned int *)&hostp->TotalDiskCount); + + for (index = 0; index < hostp->TotalDiskCount; index++) + { + ComposeDiskInfo(hostp, + (PI2O_UTIL_PARAMS_GET_MESSAGE)hostp->messageBufferp, + (void *)hostp->replyBufferp, + (PI2ODISK)&hostp->I2ODisk[index] ); + hostp->I2ODisk[index].present = TRUE; + } + + return(TRUE); +} + +/* + * Function: unsigned int GetStatusCall(void *) + * Description: get IOP's state. + * Return : IOP's current state. + */ +static unsigned int GetStatusCall(struct pti_st_host *hostp, void * replyBuffer) +{ + int i; + volatile int state; + U32 timeout; + U32 msgOffset; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + PI2O_EXEC_STATUS_GET_MESSAGE pMsg; + volatile PI2O_EXEC_STATUS_GET_REPLY reply = + (PI2O_EXEC_STATUS_GET_REPLY)replyBuffer; + + msgOffset = hostp->p_atu->InQueue; + pMsg = (PI2O_EXEC_STATUS_GET_MESSAGE)(hostp->LinBaseAddr + msgOffset); + + memset((void *)reply, 0, sizeof(PI2O_EXEC_STATUS_GET_REPLY)); + + pMsg->ReplyBufferLength=0x100; + pMsg->ReplyBufferAddressLow = virt_to_bus(reply); + pMsg->VersionOffset=0x01; + pMsg->MsgFlags=0; /* No flag to set */ + pMsg->MessageSize=(sizeof(I2O_EXEC_STATUS_GET_MESSAGE)>>2); + pMsg->TargetAddress=0; + pMsg->InitiatorAddress=0x1; /* from host */ + pMsg->Function=I2O_EXEC_STATUS_GET; + + *(U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; /* YBM: ... = pMFA_Inbound;*/ + + timeout = 100000; + while(1) + { + for (i=0; i<1000; i++) /* please don't hog the bus! */ + ; + if ((state=reply->IopState) != 0) + break; + if (!timeout--) + { + printk(" Timeout wait for IOP Status Get Ready!\n"); + return -1; + } + } + + memcpy((void *)(&hostp->IopStatus), + (void *)reply, + sizeof(I2O_EXEC_STATUS_GET_REPLY)); + + return (unsigned int) reply->IopState; +} + + +/* +** ========================================================================= +** SendI2OOutboundQInitMsg() +** +** ========================================================================= +*/ +/* +static int +SendI2OOutboundQInitMsg(PPAB pPab) +{ + U32 msgOffset, timeout, phyOutQFrames, i; + volatile PU32 pMsg; + volatile PU32 p32; + + + + msgOffset = pPab->p_atu->InQueue; + + + if (msgOffset == 0xFFFFFFFF) + { +#ifdef DEBUG + kprintf("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n"); +#endif + return RC_RTN_FREE_Q_EMPTY; + } + + + pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); + +#ifdef DEBUG + kprintf("SendI2OOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset); +#endif + + pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6; + pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = 0x106; + pMsg[4] = 4096; + pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; + pMsg[6] = 0xD0000004; + pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); + + p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB)); + p32[0] = 0; + + pPab->p_atu->InQueue = msgOffset; + + timeout = 100000; + while(1) + { + for (i = 0; i < 1000; i++) + ; + + if (p32[0]) + break; + + if (!timeout--) + { +#ifdef DEBUG + kprintf("Timeout wait for InitOutQ InPrgress status from IOP\n"); +#endif + return RC_RTN_NO_I2O_STATUS; + } + } + + timeout = 100000; + while(1) + { + for (i = 0; i < 1000; i++) + ; + + if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE) + break; + + if (!timeout--) + { +#ifdef DEBUG + kprintf("Timeout wait for InitOutQ Complete status from IOP\n"); +#endif + return RC_RTN_NO_I2O_STATUS; + } + } + + phyOutQFrames = pPab->outMsgBlockPhyAddr; + + for (i = 0; i < NMBR_MSG_FRAMES; i++) + { + pPab->p_atu->OutQueue = phyOutQFrames; + phyOutQFrames += MSG_FRAME_SIZE; + } + return RC_RTN_NO_ERROR; +} +*/ + +/* + * + */ +static void OutboundInitCall(struct pti_st_host *hostp) +{ + U32 i; + U32 x; + U32 msgOffset; + U32 timeout; + PI2O_EXEC_OUTBOUND_INIT_MESSAGE pMsg; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Outbound = 0; + + msgOffset = hostp->p_atu->InQueue; + pMsg = (PI2O_EXEC_OUTBOUND_INIT_MESSAGE)(hostp->LinBaseAddr+msgOffset); + + memset((void *)hostp->replyBufferp, 0, 16*1024); + + pMsg->StdMessageFrame.VersionOffset=0x61; // 32 bit frame + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)>>2; + + pMsg->StdMessageFrame.TargetAddress=0; // IXWork + pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host + pMsg->StdMessageFrame.Function = I2O_EXEC_OUTBOUND_INIT; + pMsg->HostPageFrameSize = 4096; + pMsg->InitCode = I2O_MESSAGE_IF_INIT_CODE_NO_OWNER; + pMsg->OutboundMFrameSize = 0x20; //each frame 32 * 4 bytes + // the sgl for OutboundInitStatus Word, only 4 bytes. + pMsg->SGL.u.Simple[0].FlagsCount.Count=4; + pMsg->SGL.u.Simple[0].FlagsCount.Flags=(I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + + pMsg->SGL.u.Simple[0].PhysicalAddress=virt_to_bus(hostp->replyBufferp); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; + + // wait for response: + timeout = 0x100000; + while(1) + { + for (i=0; i<1000; i++) // please don't hog the bus!!! + ; + if (*((U8*)hostp->replyBufferp) != 0) + break; + + if (!timeout--) + { + printk("Timeout wait for I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS status!\n"); + return; + } + } + + timeout = 100000; + while(1) + { + for (i= 0; i<1000; i++) // please don't hog the bus!!! + ; + if (*((U8*)hostp->replyBufferp) == I2O_EXEC_OUTBOUND_INIT_COMPLETE) + break; + + if (!timeout--) + { + printk("Timeout wait for I2O_EXEC_OUTBOUND_INIT_COMPLETE status!\n"); + return; + } + } + + for(x=0; x < 32; x++) + { + pMFA_Outbound = (U32)&(hostp->outboundBufferp->outboundBuff[x]); + *((U32 *)(pBaseAddrReg+OUTBOUNDQPORT))=virt_to_bus((void *)pMFA_Outbound); + for (i=0; i<1000; i++) // just for waitting! + ; + if (DEBUG) + { + printk("Write to Outbound port, MFAs are : \n"); + printk("%lx", pMFA_Outbound); + } + } + // printk(" DONE!\n"); +} + +/* + * + */ +static void SysTabSetCall(struct pti_st_host *hostp, + PI2O_EXEC_SYS_TAB_SET_MESSAGE MF, + void *lsgl) +{ + U8 tempMemPool[0x200]; + int count=0x200; + void *tlsgl = lsgl; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Inbound; + + PI2O_EXEC_STATUS_GET_REPLY ptReplyMemPool = + (PI2O_EXEC_STATUS_GET_REPLY)tempMemPool; + + PI2O_SGE_SIMPLE_ELEMENT ptsgl = + (PI2O_SGE_SIMPLE_ELEMENT)MF->SGL.u.Simple; + + while(count--) + tempMemPool[count] = ((char*)tlsgl)[count]; + + pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + + ZeroMemory((U32*) MF, sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE)+0x10); + ZeroMemory((U32*) lsgl, 0x200); + + MF->StdMessageFrame.VersionOffset=0x61; // 32 bit frame + MF->StdMessageFrame.MsgFlags=0; + MF->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_SYS_TAB_SET_MESSAGE) >> 2; + + MF->StdMessageFrame.TargetAddress=0; // IXWork + MF->StdMessageFrame.InitiatorAddress = 0x01; // from Host + MF->StdMessageFrame.Function = I2O_EXEC_SYS_TAB_SET; + + MF->IOP_ID = MY_IOP_ID; //I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST; + MF->HostUnitID = I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT; + MF->SegmentNumber = I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT; + + MF->SGL.u.Simple[0].FlagsCount.Count= + CreatSysTable(hostp, lsgl, (PI2O_EXEC_STATUS_GET_REPLY)tempMemPool); + + // 1st element: YBM: need I2O_SGL_FLAGS_END_OF_BUFFER ? + ptsgl->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER) ; + + MF->SGL.u.Simple[0].PhysicalAddress = (U32)(virt_to_bus(lsgl)); + + // 2nd element: YBM: need I2O_SGL_FLAGS_END_OF_BUFFER ? + ptsgl++; + ptsgl->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER) ; + ptsgl->FlagsCount.Count = ptReplyMemPool->CurrentPrivateMemSize; + ptsgl->PhysicalAddress = ptReplyMemPool->CurrentPrivateMemBase; + + // 3rd element: +#if defined(MYDEBUG) && 0 + MF->SGL.u.SimpleContext[0].FlagsCount.Count= + ptReplyMemPool->CurrentPrivateIOSize; + + MF->SGL.u.SimpleContext[0].FlagsCount.Flags = + (I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + + MF->SGL.u.SimpleContext[0].PhysicalAddress = ptReplyMemPool->CurrentPrivateIOBase; +#else + ptsgl++; + ptsgl->FlagsCount.Count= + ptReplyMemPool->CurrentPrivateIOSize; + + ptsgl->FlagsCount.Flags = + (I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + + ptsgl->PhysicalAddress = ptReplyMemPool->CurrentPrivateIOBase; +#endif + + memcpy( (void *)(pMFA_Inbound+pBaseAddrReg), (void *)MF, + (sizeof(I2O_EXEC_OUTBOUND_INIT_MESSAGE)+ + (sizeof(I2O_SGE_SIMPLE_ELEMENT) * 2)) ); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = pMFA_Inbound; + +} + +/* + * + */ +static void EnableSysCall(struct pti_st_host *hostp) +{ + U32 msgOffset; + PI2O_EXEC_SYS_ENABLE_MESSAGE pMsg; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_EXEC_SYS_ENABLE_MESSAGE)(hostp->LinBaseAddr + msgOffset); + + pMsg->StdMessageFrame.VersionOffset=0x1; + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_SYS_ENABLE_MESSAGE) >> 2; + + pMsg->StdMessageFrame.TargetAddress=0; // IXWork + pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host + pMsg->StdMessageFrame.Function = I2O_EXEC_SYS_ENABLE; + + *(U32 *)(hostp->LinBaseAddr+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; +} + +/* + * + */ +static void LCTNotifyCall(struct pti_st_host *hostp) +{ + U32 msgOffset; + PI2O_EXEC_LCT_NOTIFY_MESSAGE pMsg; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_EXEC_LCT_NOTIFY_MESSAGE)(hostp->LinBaseAddr + msgOffset); + pMsg->StdMessageFrame.VersionOffset=0x61; + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize=sizeof(I2O_EXEC_LCT_NOTIFY_MESSAGE)>>2; + + pMsg->StdMessageFrame.TargetAddress=0; // IXWork + pMsg->StdMessageFrame.InitiatorAddress = 0x01; // from Host + pMsg->StdMessageFrame.Function = I2O_EXEC_LCT_NOTIFY; + pMsg->ClassIdentifier = 0xffffffff; // all class + // I2O_CLASS_RANDOM_BLOCK_STORAGE; + pMsg->LastReportedChangeIndicator = 0; + pMsg->SGL.u.Simple[0].FlagsCount.Count=0x1000; + pMsg->SGL.u.Simple[0].FlagsCount.Flags=(I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT); + pMsg->SGL.u.Simple[0].PhysicalAddress=virt_to_bus(hostp->replyBufferp); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; // YBM: ... = pMFA_Inbound; +} + +/* + * + */ +static U32 CreatSysTable(struct pti_st_host *hostp, + void *llsgl, + PI2O_EXEC_STATUS_GET_REPLY ltMemPool) +{ + PI2O_SET_SYSTAB_HEADER pPacket = (PI2O_SET_SYSTAB_HEADER) llsgl; + PI2O_IOP_ENTRY pEntry = (PI2O_IOP_ENTRY) ((U8 *) llsgl + sizeof(PI2O_SET_SYSTAB_HEADER)); + + pPacket->NumberEntries=0x1; + pPacket->SysTabVersion=I2O_RESOURCE_MANAGER_VERSION; + pPacket->CurrentChangeIndicator=0; + + // pEntry->OrganizationID = ltMemPool->OrganizationID; + pEntry->OrganizationID = PROMISE_ORG_ID; + pEntry->IOP_ID = MY_IOP_ID; //ltMemPool->IOP_ID; + pEntry->SegmentNumber = ltMemPool->SegmentNumber; + pEntry->I2oVersion = ltMemPool->I2oVersion; + pEntry->IopState = ltMemPool->IopState; + pEntry->MessengerType = ltMemPool->MessengerType; + pEntry->InboundMessageFrameSize = ltMemPool->InboundMFrameSize; + pEntry->LastChanged = 0; + pEntry->IopCapabilities = ltMemPool->IopCapabilities; + pEntry->MessengerInfo.InboundMessagePortAddressLow = (U32)hostp->maddr; + pEntry->MessengerInfo.InboundMessagePortAddressHigh = 0; + + return sizeof(I2O_IOP_ENTRY)+sizeof(I2O_SET_SYSTAB_HEADER); +} + + +/***************************************************************************** + I2O EXECUTIVE CLASS MESSAGE +*****************************************************************************/ + +/* + * + */ +static void ExecIOPReset(struct pti_st_host *hostp) +{ + U32 msgOffset; + U32 timeout; + PI2O_EXEC_IOP_RESET_MESSAGE pMsg; + volatile PU32 p32; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_EXEC_IOP_RESET_MESSAGE)(hostp->LinBaseAddr + msgOffset); + memset((void *)hostp->replyBufferp, 0, 16*1024); + + pMsg->VersionOffset=0x01; + pMsg->MsgFlags=0; + pMsg->MessageSize= sizeof(I2O_EXEC_IOP_RESET_MESSAGE) >> 2; + + pMsg->TargetAddress=0; // IXWork + pMsg->InitiatorAddress = 0x01; // from Host + pMsg->Function = I2O_EXEC_IOP_RESET; + + pMsg->StatusWordHighAddress = 0; + pMsg->StatusWordLowAddress = + (U32)(virt_to_bus((void *)hostp->replyBufferp)); + + p32 = (volatile PU32)hostp->replyBufferp; + + *(U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgOffset; + + /* wait for response: */ + timeout = 1000000; + while(1) + { + int i; + for (i=0; i<1000; i++) /* please don't hog the bus ! */ + ; + if(p32[0] || p32[1]) + break; + if (!timeout--) + { + printk("Timeout while Resetting IOP !\n"); + return; + } + } +} + +static void PTI_StringCutBlank(char * strBuffer, U32 strLength) +{ + U32 i = strLength - 2; + + while (i >= 0 && strBuffer[i] == ' ') + { + strBuffer[i] = '\0'; + i--; + } +} + +/* + * + */ +static void GetInfoFromLCT(struct pti_st_host *hostp, + void *lMemPool, + PI2ODISK pmydisk, + unsigned int *diskcount) +{ + PI2O_LCT pTable = (PI2O_LCT)lMemPool; + PI2O_LCT_ENTRY pLCTEntry; + PI2O_LCT_ENTRY HeadpLCTEntry = pTable->LCTEntry; + U16 ParentID=0xffff; + + int i; + + *diskcount = 0; // initial count + memset((void *)hostp->LctEntryTable, 0, (sizeof(I2O_LCT_ENTRY) * MAX_LCT_ENTRY)); + + while(pTable->TableSize==0) // wait ready + ; + pLCTEntry=HeadpLCTEntry; + + /* get ISM: */ + while (pLCTEntry->TableEntrySize==0x9) + { + if(pLCTEntry->ClassID.Class==I2O_CLASS_DDM && + pLCTEntry->SubClassInfo==I2O_SUBCLASS_ISM) + { + ParentID=(U16) pLCTEntry->LocalTID; + break; + } + pLCTEntry++; + } + + if (ParentID == 0xffff) + { + printk("ISM DDM ID not found!\n"); + return; + } + + /* scan all ISM children first: */ + pLCTEntry=HeadpLCTEntry; + i = 0; + + while(pLCTEntry->TableEntrySize == 0x9) + { + /* + * Insert the LCT Entry to LCT Entry Description + */ + memcpy((void*)&hostp->LctEntryTable[i], + (void *)pLCTEntry, + sizeof(I2O_LCT_ENTRY)); + + if((pLCTEntry->ClassID.Class==I2O_CLASS_RANDOM_BLOCK_STORAGE) && + (pLCTEntry->ParentTID==ParentID)) + { + pmydisk->LocalTID = (unsigned int) pLCTEntry->LocalTID; + pmydisk++; + (*diskcount)++; + } + pLCTEntry++; + i++; + } + +} + +/* + * Starting lMemBuf = 0 + * 0 ~ 3 bytes -- Request Header (0-1) Op Cnt (2-3) Res + * 4 ~ 9 bytes -- first operation list + * a ~10 bytes -- second operation list + * + * Result starts at lMemBuf+4+6+6 + * 0 ~ 3 -- result header (0-1) Result Cnt + * 4 ~ n -- first result (first 4 byte, byte cnt in result+status) + */ +static int ComposeDiskInfo(struct pti_st_host *hostp, + void *MF, + void *lMemBuf, + PI2ODISK pmydisk) +{ + PI2O_UTIL_DEVICE_IDENTITY_SCALAR pResult1; + PI2O_BSA_DEVICE_INFO_SCALAR pResult2; + PI2O_PARAM_READ_OPERATION_RESULT pOpResult; + PI2O_PARAM_RESULTS_LIST_HEADER pResHeader = + (PI2O_PARAM_RESULTS_LIST_HEADER) (((U8 *) lMemBuf)+8+4); + + void * ptMemBuf = lMemBuf; + PI2O_PARAM_OPERATION_ALL_TEMPLATE ptsgl = + (PI2O_PARAM_OPERATION_ALL_TEMPLATE) (((U8*) lMemBuf) + 4); + + U32 wSize; + unsigned int Hd; + unsigned int Sctr = 0x3f; + + /* + * Note:General and Specific parameter get must invoke separately + * General Parameter Get + */ + ZeroMemory(lMemBuf, 0x200); + + *((unsigned int *) ptMemBuf) = 0x1; + ptsgl->Operation = I2O_PARAMS_OPERATION_FIELD_GET; + ptsgl->GroupNumber = I2O_UTIL_DEVICE_IDENTITY_GROUP_NO; + ptsgl->FieldCount = 0xffff; + + PTI_UtilParamGetCall(hostp, + (PI2O_UTIL_PARAMS_GET_MESSAGE) MF, + (void *) ptMemBuf, + (void *) (((U8 *) ptMemBuf)+0x4+0x8), + pmydisk); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending UtilParamsGetMessage!\n"); + return(FALSE); + } + + pOpResult = (PI2O_PARAM_READ_OPERATION_RESULT) (++pResHeader); + if(pOpResult->ErrorInfoSize != 0) + { + return(FALSE); /* Error Action */ + } + pResult1 = (PI2O_UTIL_DEVICE_IDENTITY_SCALAR) (++pOpResult); + + memcpy( &(pmydisk->Vendor), &(pResult1->VendorInfo), + I2O_DEVID_VENDOR_INFO_SZ ); + + pmydisk->Vendor[I2O_DEVID_VENDOR_INFO_SZ] = (char) 0; + + PTI_StringCutBlank(pmydisk->Vendor, I2O_DEVID_VENDOR_INFO_SZ); + + memcpy( &(pmydisk->DiskModel), &(pResult1->ProductInfo), + I2O_DEVID_PRODUCT_INFO_SZ ); + + pmydisk->DiskModel[I2O_DEVID_PRODUCT_INFO_SZ] = (char) 0; + + PTI_StringCutBlank(pmydisk->DiskModel, I2O_DEVID_PRODUCT_INFO_SZ); + + memcpy( &(pmydisk->ProductRevLevel), &(pResult1->ProductRevLevel), + I2O_DEVID_REV_LEVEL_SZ ); + pmydisk->ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ] = '\0'; + + PTI_StringCutBlank(pmydisk->ProductRevLevel, I2O_DEVID_REV_LEVEL_SZ); + + /* + * Device Information (Storage Parameter Get) + */ + ZeroMemory(lMemBuf, 0x200); + + *((unsigned int *) ptMemBuf) = 0x1; + + ptsgl->Operation = I2O_PARAMS_OPERATION_FIELD_GET; + ptsgl->GroupNumber = I2O_BSA_DEVICE_INFO_GROUP_NO; + ptsgl->FieldCount = 0xffff; + + PTI_UtilParamGetCall(hostp, + (PI2O_UTIL_PARAMS_GET_MESSAGE) MF, + (void *) ptMemBuf, + (void *) (((U8 *) ptMemBuf)+0x4+0x8), + pmydisk); + if (pti_st_waitreplymsg(hostp) != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending UtilParamsGetMessage!\n"); + return(FALSE); + } + + pResHeader=(PI2O_PARAM_RESULTS_LIST_HEADER) (((U8 *) lMemBuf)+8+4); + pOpResult = (PI2O_PARAM_READ_OPERATION_RESULT) (++pResHeader); + if(pOpResult->ErrorInfoSize != 0) + { + return(FALSE); // Error Action + } + pResult2 = (PI2O_BSA_DEVICE_INFO_SCALAR) (++pOpResult); + + wSize = (long) ((pResult2->DeviceCapacity.HighPart << (32-9)) | + (pResult2->DeviceCapacity.LowPart >> 9)); + + pmydisk->lastLBA = (U32) wSize - 1; + + // convert LBA to CHS + if(wSize <= (U32) 0x3f*0x10*0x400) + { + Hd = 0x10; + while((wSize/(Hd*Sctr) > 0x400) && (Hd < 0x80)) + Hd <<=1; + } + else if (wSize <= (U32) (0x3fl*0x20l*0x400l)) Hd = 0x20; + else if (wSize <= (U32) (0x3fl*0x40l*0x400l)) Hd = 0x40; + else if (wSize <= (U32) (0x3fl*0x80l*0x400l)) Hd = 0x80; + else Hd = 0xff; + + pmydisk->lastcyl = (unsigned int) ((wSize/ (Hd*Sctr)) - 1);/*starting from 0*/ + pmydisk->lasthead = (U8) (Hd - 1); /*starting from 0*/ + pmydisk->sector = (U8) Sctr; /*starting from 0*/ + + return(TRUE); +} + +/* + * Function: unsigned long pti_st_waitreplymsg(struct pti_st_host *) + * Description: wait reply message from i960. + * Return : Error code (0 represent I2O_REPLY_STATUS_SUCCESS) + */ +unsigned long pti_st_waitreplymsg(struct pti_st_host *hostp) +{ + U8 ReqStatus; + U32 timeout=0; + int i; + PI2O_SINGLE_REPLY_MESSAGE_FRAME replyPointer; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Outbound; + + // wait for response: + timeout = 0x1000000; + while(1) + { + for (i=0; i<1000; i++) // please don't hog the bus!!! + ; + if((pMFA_Outbound=(*(volatile U32 *)(pBaseAddrReg+OUTBOUNDQPORT)))!=-1) + break; + + if (!timeout--) + { + printk("Timeout wait for Reply Message from IOP!\n"); + return -1; + } + } + + replyPointer=(PI2O_SINGLE_REPLY_MESSAGE_FRAME)(bus_to_virt(pMFA_Outbound)); + + ReqStatus = replyPointer->ReqStatus; + + * (U32 *)(pBaseAddrReg+OUTBOUNDQPORT) = pMFA_Outbound; + + return (unsigned long) ReqStatus; +} + + +/***************************************************************************** + I2O UTILITY CLASS MESSAGE +*****************************************************************************/ +/* + * THis is used for ComposeDiskInfo() + */ +static void PTI_UtilParamGetCall(struct pti_st_host *hostp, + PI2O_UTIL_PARAMS_GET_MESSAGE MF, + void *req, + void *buf, + PI2ODISK mydisk) +{ + PI2O_SGE_SIMPLE_ELEMENT sglentry = + (PI2O_SGE_SIMPLE_ELEMENT)MF->SGL.u.Simple; // YBM: )&MF->SGL.u.Simple; + unsigned long pBaseAddrReg = (U32)hostp->maddr; + unsigned long pMFA_Inbound = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + + ZeroMemory((U32*) MF, sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+0x10); + + MF->StdMessageFrame.VersionOffset=0x51; + MF->StdMessageFrame.MsgFlags=0; + MF->StdMessageFrame.MessageSize= + (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+sizeof(I2O_SG_ELEMENT)) >> 2; + + MF->StdMessageFrame.TargetAddress=mydisk->LocalTID; + MF->StdMessageFrame.InitiatorAddress = 0x01; // from Host + MF->StdMessageFrame.Function = I2O_UTIL_PARAMS_GET; + + MF->OperationFlags = 0; // reserved + + // First buffer: + sglentry->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + sglentry->FlagsCount.Count = 0x0c ; + sglentry->PhysicalAddress = (U32)(virt_to_bus(req)); // YBM: *(U32 *)req ; + + // Sencond buffer: + sglentry++; + sglentry->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + sglentry->FlagsCount.Count = 0x100; + //sizeof(I2O_UTIL_DEVICE_IDENTITY_SCALAR); + sglentry->PhysicalAddress = (U32)(virt_to_bus(buf)); // YBM: *(U32 *)buf; + + memcpy( (void *)(pMFA_Inbound+pBaseAddrReg), (void *)MF, + (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+16) ); + + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = pMFA_Inbound; +} + + +/* + * This is used for pti_stdev_ioctl() + * + * Routine Description: + * + * message allows parameter values to be retrieved from + * device parameter groups. + */ +static void PTI_UtilParamsGet( + struct pti_st_host *hostp, + ULONG LocalTID, + ULONG FieldCount, + UCHAR SrbTag, + ULONG SrbID, + UCHAR *Address +) +{ + PI2O_UTIL_PARAMS_GET_MESSAGE MsgPtr; + PI2O_SGE_SIMPLE_ELEMENT SGLPtr; + ULONG msgOffset; + ULONG ParamOffset = 0; + + + msgOffset = hostp->p_atu->InQueue; + MsgPtr = (PI2O_UTIL_PARAMS_GET_MESSAGE)(hostp->LinBaseAddr+msgOffset); + memset((ULONG *)MsgPtr,0,sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+0x10); + SGLPtr = (PI2O_SGE_SIMPLE_ELEMENT)MsgPtr->SGL.u.Simple; + + ParamOffset = sizeof(I2O_PARAM_SCALAR_OPERATION); + if (FieldCount != (USHORT)-1) + ParamOffset = ParamOffset + (FieldCount-1)*sizeof(USHORT); + + /* + * fill the message frame + */ + MsgPtr->StdMessageFrame.VersionOffset = 0x51; + MsgPtr->StdMessageFrame.MsgFlags = 0; + MsgPtr->StdMessageFrame.MessageSize = + (sizeof(I2O_UTIL_PARAMS_GET_MESSAGE)+sizeof(I2O_SG_ELEMENT)) >> 2; + MsgPtr->StdMessageFrame.TargetAddress = LocalTID; + MsgPtr->StdMessageFrame.InitiatorAddress = 0x01; /* from Host */ + MsgPtr->StdMessageFrame.Function = I2O_UTIL_PARAMS_GET; + MsgPtr->StdMessageFrame.InitiatorContext = SrbTag; + + MsgPtr->TransactionContext = SrbID; + MsgPtr->OperationFlags = 0; /* reserved */ + + /* + * fill the SGL frame + * the first buffer contains the operation list that + * identifies which parameters are to be returned + */ + SGLPtr->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + SGLPtr->FlagsCount.Count = ParamOffset; + SGLPtr->PhysicalAddress = cpu_to_le32(VIRT_TO_BUS(Address)); + + /* the second buffer is for target to place the results */ + SGLPtr++; + SGLPtr->FlagsCount.Flags = (I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER ); + SGLPtr->FlagsCount.Count = 0x100; + SGLPtr->PhysicalAddress = cpu_to_le32(VIRT_TO_BUS(Address+ParamOffset)); + + /* + * send the message + */ + hostp->p_atu->InQueue = msgOffset; +} + + +/* + * + */ +static void UtilNOPCall(struct pti_st_host *hostp) +{ + U32 msgOffset; + PI2O_UTIL_NOP_MESSAGE pMsg; + + msgOffset = hostp->p_atu->InQueue; + + pMsg = (PI2O_UTIL_NOP_MESSAGE)(hostp->LinBaseAddr + msgOffset); + pMsg->StdMessageFrame.VersionOffset=0x1; + pMsg->StdMessageFrame.MsgFlags=0; + pMsg->StdMessageFrame.MessageSize= sizeof(I2O_UTIL_NOP_MESSAGE) >> 2; + pMsg->StdMessageFrame.TargetAddress=0; + pMsg->StdMessageFrame.InitiatorAddress = 0x1; // from Host + pMsg->StdMessageFrame.Function = I2O_UTIL_NOP; + + hostp->p_atu->InQueue = msgOffset; + +} + +/******************************************************************** + * + * Private Messages + * + ********************************************************************/ + +static int PTI_PrivateMessageCall( + struct pti_st_host *hostp, + ULONG TargetTID, + U16 XFunctionCode, + U16 OrganizationID, + ULONG InputCount, + UCHAR *InputAddr, + ULONG OutputCount, + UCHAR *OutputAddr, + UCHAR SrbTag, + ULONG SrbID +) +{ + PPTI_ST_PRIVATE_MESSAGE MsgPtr; + unsigned long msgOffset; + int i=0; + + while(i < 10){ + msgOffset = hostp->p_atu->InQueue; + if(msgOffset != -1){ + break; + } + ++i; + } + if( i >= 10) return -1; + MsgPtr = (PPTI_ST_PRIVATE_MESSAGE)(hostp->LinBaseAddr+msgOffset); + memset((UCHAR *)MsgPtr,0,sizeof(PTI_ST_PRIVATE_MESSAGE)+0x10); + + /* + * Fill the message frame + */ + MsgPtr->MyStandMsg.StdMessageFrame.VersionOffset = 0x1; + MsgPtr->MyStandMsg.StdMessageFrame.MsgFlags = 0; + MsgPtr->MyStandMsg.StdMessageFrame.MessageSize = (sizeof(PTI_ST_PRIVATE_MESSAGE) >> 2); + + MsgPtr->MyStandMsg.StdMessageFrame.TargetAddress = TargetTID; /* IXWork */ + MsgPtr->MyStandMsg.StdMessageFrame.InitiatorAddress = 0x01; + MsgPtr->MyStandMsg.StdMessageFrame.Function = I2O_PRIVATE_MESSAGE; + MsgPtr->MyStandMsg.StdMessageFrame.InitiatorContext = SrbTag; + + MsgPtr->MyStandMsg.XFunctionCode = (U16)(((XFunctionCode >> 8) & 0x00ff) | ((XFunctionCode << 8) & 0xff00)); + + MsgPtr->MyStandMsg.OrganizationID = (U16)(((OrganizationID >> 8) & 0x00ff) | ((OrganizationID << 8) & 0xff00)); + + MsgPtr->MyStandMsg.TransactionContext = SrbID; + /* + `a* Fill the private Payload + */ + MsgPtr->InSGL.FlagsCount.Count = InputCount; + MsgPtr->InSGL.FlagsCount.Flags = I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER; + MsgPtr->InSGL.PhysicalAddress[0] = + cpu_to_le32(VIRT_TO_BUS(InputAddr)); + + MsgPtr->OutSGL.FlagsCount.Count = OutputCount; + MsgPtr->OutSGL.FlagsCount.Flags = I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT | I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER; + MsgPtr->OutSGL.PhysicalAddress[0] = + cpu_to_le32(VIRT_TO_BUS(OutputAddr)); + + /* + * send the message + */ + hostp->p_atu->InQueue = msgOffset; + return 0; +} + + +/**************************************************************************** + Misc functions. +****************************************************************************/ +/* + * + */ +static void ZeroMemory(unsigned long *zeroBuffer, unsigned int count) +{ + count = count >> 2; // count/4 + while(count--) + { + * zeroBuffer = 0; + zeroBuffer ++; + } +} + +static void pti_st_flushcache_respond(Scsi_Cmnd *cmd) +{ + cmd->result = DID_OK; + wake_up(&WaitQ); + return; +} + +static void pti_st_wait_flushcache(unsigned long data) +{ + struct pti_st_scb *scb; + Scsi_Cmnd *cmd; + + scb = (struct pti_st_scb *)data; + cmd = scb->cmd; + + cmd->result = DID_ERROR; + + wake_up(&WaitQ); + + return; +} + +static int pti_st_send_flushcache_cmd(struct pti_st_host *p, + struct pti_st_scb *scb, + Scsi_Cmnd *cmd, + int time) +{ + unsigned long pBaseAddrReg; + unsigned long msgoffset; + PI2O_BSA_CACHE_FLUSH_MESSAGE mfp; + unsigned long cpuflags; + + spin_lock_irqsave(&p->spin_lock, cpuflags); + + pBaseAddrReg = (U32)p->maddr; + msgoffset = * (U32 *)(pBaseAddrReg+INBOUNDQPORT); + if (msgoffset == 0xFFFFFFFF) + { + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + scbq_insert_head(p, &p->scb_data->free_scbs, scb); + printk("pti_st_send_flushcache_cmd: Couldn't get a free MF from inboundqport on scsi No. %d.\n", p->host_no); + return(-1); + } + + scb->cmd = cmd; + pti_st_position(cmd) = scb->tag; + p->scb_data->scb_array[scb->tag] = scb; + + /* + * Make sure the Scsi_Cmnd pointer is saved, the struct it points to + * is set up properly, and the parity error flag is reset, then send + * the SCB to the sequencer and watch the fun begin. + */ + cmd->scsi_done = pti_st_flushcache_respond; + cmd->result = DID_OK; + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + cmd->host_scribble = NULL; + + scb->flags |= SCB_ACTIVE; + + mfp = (PI2O_BSA_CACHE_FLUSH_MESSAGE)(pBaseAddrReg + msgoffset); + + memset((unsigned long *)mfp, 0, sizeof(I2O_BSA_CACHE_FLUSH_MESSAGE)+0x10); + + /* Fill the message frame */ + mfp->StdMessageFrame.Function = I2O_BSA_CACHE_FLUSH; + mfp->StdMessageFrame.VersionOffset = 0x01; + mfp->StdMessageFrame.MsgFlags = 0; + mfp->StdMessageFrame.MessageSize = sizeof(I2O_BSA_CACHE_FLUSH_MESSAGE) >> 2; + mfp->StdMessageFrame.TargetAddress = p->I2ODisk[cmd->target].LocalTID; + mfp->StdMessageFrame.InitiatorAddress = 0x01; + mfp->StdMessageFrame.InitiatorContext = scb->tag; + mfp->TransactionContext = cmd->serial_number; + mfp->ControlFlags = 0; + mfp->TimeMultiplier = 0; + + /* Start timer for timeout */ + init_timer(&bufflsh_timer); + bufflsh_timer.expires = (jiffies + time*HZ); + bufflsh_timer.data = (unsigned long)scb; + bufflsh_timer.function=pti_st_wait_flushcache; + + /* modified for shutdown flag */ + mfp->Reserved = cmd->cmnd[2]; + + /* send the message */ + * (U32 *)(pBaseAddrReg+INBOUNDQPORT) = msgoffset; + + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + + add_timer(&bufflsh_timer); + interruptible_sleep_on(&WaitQ); + + del_timer(&bufflsh_timer); + + if(cmd->result != DID_OK) + return(-1); + else + return (0); + +} + +static int pti_st_flushcache(int time) +{ + struct pti_st_host *p; + struct pti_st_scb *scb; + static Scsi_Cmnd scsicmd = {0}; + int err = 0; + int i, ret; + + for(i = 0, err = 0; i < MAX_ADAPTORS; i++) + { + p = (struct pti_st_host *) pti_st_hostp[i]; + if(!p) + continue; + + scb = scbq_remove_head(p, &p->scb_data->free_scbs); + + if (scb == NULL) + { + err++; + continue; + } + + scsicmd.cmnd[0] = 0xfe; + scsicmd.cmnd[2] = 0xfe; + scsicmd.serial_number = 0xfe; + if(p->TotalDiskCount <= 0 || p->I2ODisk[0].present != TRUE) + { + continue; + } else { + /* + * if raid exist, raid 0 should be exist + * because raid is sorted from 0 + */ + scsicmd.target = 0; + } + + ret = pti_st_send_flushcache_cmd(p, scb, &scsicmd, time); + + if(ret) { + err++; + continue; + } + } + + return(err); + + +} + +/************************************************************ + * Device File Function * + ************************************************************/ + +static int pti_stdev_strncmp(char *s, char *d, int n) +{ + /* check null */ + if(!s) { + if(!d) + return(0); + else + return(-1); + } else { + if(!d) + return(1); + } + /* both not null */ + + /* check length 0 */ + if(!s[0]) { + if(!d[0]) + return(0); + else + return(-1); + } else { + if(!d[0]) + return(-1); + } + + /* both length not 0 */ + + return(strncmp(s,d,n)); +} + +/* + * + */ +int pti_stdev_open(struct inode *inodep, struct file *filep) +{ + unsigned long cpuflags; + + int aptno = MINOR(inodep->i_rdev); + struct pti_st_host *p = pti_st_hostp[aptno]; + + if(!pti_st_hostp[aptno] || + pti_st_hostp[aptno]->major <= 0 || + pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) + return(-ENODEV); + + spin_lock_irqsave(&p->spin_lock, cpuflags); + if(pti_st_hostp[aptno]->counter != 0) { + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + return(-EBUSY); + } + pti_st_hostp[aptno]->counter++; + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + MOD_INC_USE_COUNT; + return(0); +} + +int pti_stdev_release(struct inode *inodep, struct file *filep) +{ + int aptno = MINOR(inodep->i_rdev); + struct pti_st_host *p = pti_st_hostp[aptno]; + unsigned long cpuflags; + + if(!pti_st_hostp[aptno] || + pti_st_hostp[aptno]->major <= 0 || + pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) + return(-ENODEV); + + spin_lock_irqsave(&p->spin_lock, cpuflags); + if(pti_st_hostp[aptno]->counter <= 0) { + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + return(-EBADF); + } + pti_st_hostp[aptno]->counter = 0; + spin_unlock_irqrestore(&p->spin_lock, cpuflags); + + MOD_DEC_USE_COUNT; + return(0); +} +//------------------ added by dingo, 2002/8/14 -------------------- +static void pti_st_private_message_code_respond(Scsi_Cmnd *cmd) +{ + cmd->result = DID_OK; + del_timer(&priv_msg_timer); + wake_up(&PrivMsgWaitQ); + return; +} + +static void pti_st_private_message_code_wait(unsigned long data) +{ + Scsi_Cmnd *cmd; + + del_timer(&priv_msg_timer); + cmd = (Scsi_Cmnd *) data; + cmd->result = DID_ERROR; + wake_up(&PrivMsgWaitQ); + return; +} + +static int pti_st_send_private_message_code_cmd(struct pti_st_host *p, + int time, + ULONG TargetTID, + U16 XFunctionCode, + U16 OrganizationID, + ULONG InputCount, + UCHAR *InputAddr, + ULONG OutputCount, + UCHAR *OutputAddr) +{ + unsigned long pBaseAddrReg; + unsigned long msgoffset; + PI2O_BSA_CACHE_FLUSH_MESSAGE mfp; + static Scsi_Cmnd scsicmd = {0}; + Scsi_Cmnd *cmd; + unsigned long cpu_flags; + + cmd = &scsicmd; + scsicmd.cmnd[0] = 0xfd; + scsicmd.cmnd[2] = 0xfd; + scsicmd.serial_number = 0xfd; + + cmd->scsi_done = pti_st_private_message_code_respond; + cmd->result = DID_OK; + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + cmd->host_scribble = NULL; + + spin_lock_irqsave(&p->spin_lock, cpu_flags); + /* Start timer for timeout */ + init_timer(&priv_msg_timer); + priv_msg_timer.expires = (jiffies + time*HZ); + priv_msg_timer.data = (unsigned long)cmd; + priv_msg_timer.function= pti_st_private_message_code_wait; + // we send the cmd variable by a standard message frame directly. + if (PTI_PrivateMessageCall(p, TargetTID, XFunctionCode, OrganizationID, InputCount, + InputAddr, OutputCount, OutputAddr, (U32)scsicmd.cmnd[0], (U32)cmd)) + { + spin_unlock_irqrestore(&p->spin_lock, cpu_flags); + printk("pti_st_send_private_message_code_cmd Couldn't get a free MF from inboundqport on scsi No. %d.\n", p->host_no); + return(-1); + } + add_timer(&priv_msg_timer); + spin_unlock_irqrestore(&p->spin_lock, cpu_flags); + + interruptible_sleep_on(&PrivMsgWaitQ); + + if(cmd->result != DID_OK) + return(-1); + else + return (0); + +} + +int counter =0; +//----------------------------------------------------------------- + +int pti_stdev_ioctl(struct inode *inodep, + struct file *filep, + unsigned int req, + unsigned long arg) +{ + SRB_IO_CONTROL *usr_srbp = (SRB_IO_CONTROL *)arg; + PTI_STDEV_GET_CONFIG_BUFFER *usr_confbufp = + (PTI_STDEV_GET_CONFIG_BUFFER *)arg; + PTI_STDEV_INBUFFER *usr_inbufp = (PTI_STDEV_INBUFFER *)arg; + + SRB_IO_CONTROL *srbp = NULL; + PTI_STDEV_GET_CONFIG_BUFFER *confbufp = NULL; + PTI_STDEV_INBUFFER *inbufp = NULL; + + PI2O_CONFIG_QUERY ConfigQuyPtr = NULL; + PI2O_DEVICE_DESCRIPTOR DevDescriptorPtr = NULL; + PI2O_PARAM_SCALAR_OPERATION ParamScalarPtr = NULL; + USHORT *TargetTIDp = NULL; + USHORT *OrganizationIDp = NULL; + USHORT *XFunctionCodep = NULL; + UCHAR *InputAddr = NULL; + UCHAR *OutputAddr = NULL; + + void *bufferp = NULL; + unsigned long offset; + unsigned long ret; + int i, retval; + int aptno = MINOR(inodep->i_rdev); + struct pti_st_host *p = pti_st_hostp[aptno]; + + if(!pti_st_hostp[aptno] || + pti_st_hostp[aptno]->major <= 0 || + pti_st_hostp[aptno]->major != MAJOR(inodep->i_rdev)) + return(-ENODEV); + + if(pti_st_hostp[aptno]->counter <= 0) { + return(-EIO); + } + + bufferp = pti_st_hostp[aptno]->pti_stdev_bufferp; + memset(bufferp, 0, sizeof(PTI_STDEV_INBUFFER)); + + srbp = (SRB_IO_CONTROL *)bufferp; + + switch (req) { + case IOCTL_SUPERTRAK_GETVERSION: + case IOCTL_FLUSH_CACHE_REQUEST: + ret = copy_from_user(srbp, + usr_srbp, + sizeof(SRB_IO_CONTROL)); + if(ret) + return(-EFAULT); + break; + + case IOCTL_GET_CONFIG_INFO: + confbufp = (PTI_STDEV_GET_CONFIG_BUFFER *)bufferp; + + ret = copy_from_user(confbufp, + usr_confbufp, + sizeof(PTI_STDEV_GET_CONFIG_BUFFER)); + if(ret) + return(-EFAULT); + + break; + + case IOCTL_PRIVATE_MESSAGE_CODE: + case IOCTL_PARAMS_GET_REQUEST: + inbufp = (PTI_STDEV_INBUFFER *)bufferp; + + ret = copy_from_user(inbufp, + usr_inbufp, + sizeof(PTI_STDEV_INBUFFER)); + if(ret) + return(-EFAULT); + + break; + + default: + return(-EINVAL); + } + + if(pti_stdev_strncmp(srbp->Signature, SUPERTRAK_SIGNATURE, SUPERTRAK_SIG_LEN)) + return(-EINVAL); + + switch (req) { + case IOCTL_SUPERTRAK_GETVERSION: + srbp->ControlCode = (VERSIONHI | (VERSIONLO << 16)); + ret = copy_to_user(usr_srbp, + srbp, + sizeof(SRB_IO_CONTROL)); + if(ret) + return(-EINVAL); + else + return(0); + + case IOCTL_GET_CONFIG_INFO: + ConfigQuyPtr = (PI2O_CONFIG_QUERY)((UCHAR *)confbufp+sizeof(SRB_IO_CONTROL)); + DevDescriptorPtr = (PI2O_DEVICE_DESCRIPTOR)((UCHAR *)confbufp+ + + sizeof(SRB_IO_CONTROL) + + sizeof(I2O_CONFIG_QUERY)); + + /* + * fill the I2O_DEVICE_DESCRIPTOR structure + */ + + i = 0; + while(pti_st_hostp[aptno]->LctEntryTable[i].TableEntrySize == 0x09) + { + if (pti_st_hostp[aptno]->LctEntryTable[i].ClassID.Class==ConfigQuyPtr->ClassID.Class && + pti_st_hostp[aptno]->LctEntryTable[i].SubClassInfo==ConfigQuyPtr->SubClassID) + { + /* + * fill the LCT structure + */ + memcpy((void*)&DevDescriptorPtr->LCT, + (void*)&pti_st_hostp[aptno]->LctEntryTable[i], + sizeof(I2O_LCT_ENTRY)); + break; + } + else + i++; + } + + /* + * Get IOP Description + */ + DevDescriptorPtr->IOP.IOPNumber = ConfigQuyPtr->IOPNumber; + DevDescriptorPtr->IOP.IOPCapabilities = pti_st_hostp[aptno]->IopStatus.IopCapabilities; + DevDescriptorPtr->IOP.IOPState = pti_st_hostp[aptno]->IopStatus.IopState; + DevDescriptorPtr->IOP.I2OVersion = pti_st_hostp[aptno]->IopStatus.I2oVersion; + DevDescriptorPtr->IOP.MessengerType = pti_st_hostp[aptno]->IopStatus.MessengerType; + DevDescriptorPtr->IOP.MaxMessageFrameSize = pti_st_hostp[aptno]->IopStatus.InboundMFrameSize; + DevDescriptorPtr->IOP.ExpectedLCTSize = pti_st_hostp[aptno]->IopStatus.ExpectedLCTSize; + DevDescriptorPtr->IOP.MaxInboundMFrames = pti_st_hostp[aptno]->IopStatus.MaxInboundMFrames; + DevDescriptorPtr->IOP.InitialInboundMFrames = pti_st_hostp[aptno]->IopStatus.CurrentInboundMFrames; + DevDescriptorPtr->IOP.Reserved = pti_st_hostp[aptno]->IopStatus.reserved; + + ret = copy_to_user(usr_confbufp, + confbufp, + sizeof(PTI_STDEV_GET_CONFIG_BUFFER)); + if(ret) + return(-EINVAL); + else + return(0); + + case IOCTL_PRIVATE_MESSAGE_CODE: + /* + * read the TargetTID, OrganizationID and XFunctionCode + */ + offset = sizeof(SRB_IO_CONTROL) + sizeof(ULONG); + TargetTIDp = (USHORT *)((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + OrganizationIDp = (USHORT *) ((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + XFunctionCodep = (USHORT *) ((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + InputAddr = (UCHAR *)inbufp + offset; + OutputAddr = InputAddr + 0x800; + + /*** Send Private Message ***/ + retval = pti_st_send_private_message_code_cmd(pti_st_hostp[aptno], 20, *TargetTIDp, + *XFunctionCodep, *OrganizationIDp, + 0x800, InputAddr, 0x800, OutputAddr); + if(retval == 0) { + ret = copy_to_user(usr_inbufp, inbufp,sizeof(PTI_STDEV_INBUFFER)); + if(ret) + return(-EINVAL); + else + return(0); + } else { + return(retval); + } + return (-EIO); + + case IOCTL_PARAMS_GET_REQUEST: + return (-EIO); + offset = sizeof(SRB_IO_CONTROL) + sizeof(ULONG); + TargetTIDp = (USHORT *)((UCHAR *)inbufp + offset); + + offset += sizeof(USHORT); + ParamScalarPtr = (PI2O_PARAM_SCALAR_OPERATION)((UCHAR *)inbufp + offset); + + InputAddr = (UCHAR *)((UCHAR *)inbufp + offset); + + for(ret = 0; ret < 5; ret++) + { + for(i = 0; i < p->scb_data->maxscbs; i++) + if(p->scb_data->scb_array[i]->flags&SCB_ACTIVE) + break; + if(i >= p->scb_data->maxscbs) { /* card is idel */ + DRIVER_LOCK + break; + } + } + + if(ret >= 5) { /* the cards is busy */ + return(-EIO); + } + + DRIVER_LOCK + + /* + * Disable interrupt + */ + pti_st_hostp[aptno]->p_atu->OutIntMask = 0x000000fc; + + PTI_UtilParamsGet(pti_st_hostp[aptno], + *TargetTIDp, + ParamScalarPtr->OpBlock.FieldCount, + -1, + -1, + InputAddr); + if (pti_st_waitreplymsg(pti_st_hostp[aptno]) + != I2O_REPLY_STATUS_SUCCESS) + { + printk("!BAD reply after sending UtilParamsGetMessage!\n"); + retval = -EIO; + } + else + retval = 0; + + /* + * Enable interrupt + */ + pti_st_hostp[aptno]->p_atu->OutIntMask = 0x00000000; + + DRIVER_UNLOCK + + if(retval == 0) { + ret = copy_to_user(usr_inbufp, + inbufp, + sizeof(PTI_STDEV_INBUFFER)); + if(ret) + return(-EINVAL); + else + return(0); + } else { + return(retval); + } + + case IOCTL_FLUSH_CACHE_REQUEST: + if(srbp->TimeOut) { + ret = pti_st_flushcache(srbp->TimeOut); + } else { + ret = pti_st_flushcache(FLUSHCACHE_TIMEOUT_DEFULT); + } + } + return(0); +} + +#ifdef MODULE + +/* + * Support for loading low-level scsi drivers using the linux kernel loadable + * module interface. + * + * To use, the host adapter should first define and initialize the variable + * driver_template (datatype Scsi_Host_Template), and then include this file. + * This should also be wrapped in a #ifdef MODULE/#endif. + * + * The low -level driver must also define a release function which will + * free any irq assignments, release any dma channels, release any I/O + * address space that might be reserved, and otherwise clean up after itself. + * The idea is that the same driver should be able to be reloaded without + * any difficulty. This makes debugging new drivers easier, as you should + * be able to load the driver, test it, unload, modify and reload. + * + * One *very* important caveat. If the driver may need to do DMA on the + * ISA bus, you must have unchecked_isa_dma set in the device template, + * even if this might be changed during the detect routine. This is + * because the shpnt structure will be allocated in a special way so that + * it will be below the appropriate DMA limit - thus if your driver uses + * the hostdata field of shpnt, and the board must be able to access this + * via DMA, the shpnt structure must be in a DMA accessible region of + * memory. This comment would be relevant for something like the buslogic + * driver where there are many boards, only some of which do DMA onto the + * ISA bus. There is no convenient way of specifying whether the host + * needs to be in a ISA DMA accessible region of memory when you call + * scsi_register. + */ + +//------------- Added by dingo, 2002/7/22 ------------- +static int power_off_notifier_func(struct notifier_block *pnb, + unsigned long code, void *unused) +{ + pti_st_flushcache(FLUSHCACHE_TIMEOUT_DEFULT); + return NOTIFY_DONE; +} + +static struct notifier_block pti_power_off_nb={ + power_off_notifier_func, NULL, 0 +}; +//----------------------------------------------------- + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) /* > 2.4.0 */ + +static Scsi_Host_Template pti_st_driver_template = PTI_ST; + +static int __init init_this_scsi_driver(void) +{ + int major, i; + pti_st_driver_template.module = THIS_MODULE; + scsi_register_module(MODULE_SCSI_HA, &pti_st_driver_template); + + pti_st_fops.owner= THIS_MODULE; + if (!pti_st_driver_template.present || + (major = register_chrdev(0, PTCNTL_DEV_NAME, (struct file_operations *)&pti_st_fops)) < 0) + { + if(pti_st_driver_template.present) + scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); + return(-ENODEV); + } + + for(i = 0; i < MAX_ADAPTORS; i++) + { + if(pti_st_hostp[i]) + { + pti_st_hostp[i]->counter = 0; + pti_st_hostp[i]->major = major; + } + } + //------------ added by dingo, 2002/7/22 ------------ + if(register_reboot_notifier(&pti_power_off_nb)){ + printk(KERN_ERR"pti_st: Can not register power notifer notifer!\n"); + return -1; + } + //--------------------------------------------------- + + return (0); + +} + +static void __exit exit_this_scsi_driver(void) +{ + int i; + + unregister_reboot_notifier(&pti_power_off_nb); // added by dingo, 2002/7/22 + + for(i = 0; i < MAX_ADAPTORS; i++) + if(pti_st_hostp[i]) + break; + + if(i < MAX_ADAPTORS) { + if(pti_st_hostp[i]->major > 0) + unregister_chrdev(pti_st_hostp[i]->major,PTCNTL_DEV_NAME); + if(pti_st_hostp[i]) { + scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); + } + } + +} + +module_init(init_this_scsi_driver); +module_exit(exit_this_scsi_driver); + +#else /* > 2.4.0 */ +Scsi_Host_Template pti_st_driver_template = PTI_ST; + +int init_module(void) +{ + int major, i; + pti_st_driver_template.module = &__this_module; + scsi_register_module(MODULE_SCSI_HA, &pti_st_driver_template); + + if (!pti_st_driver_template.present || +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) + (major = register_chrdev(0, PTCNTL_DEV_NAME, (struct file_operations *)&pti_st_fops)) < 0) +#else + (major = register_chrdev(0, PTCNTL_DEV_NAME, (struct file_operations *)&pti_st_fops)) < 0) +#endif + { + if(pti_st_driver_template.present) + scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); + return -1; + } + + for(i = 0; i < MAX_ADAPTORS; i++) + { + if(pti_st_hostp[i]) + { + pti_st_hostp[i]->counter = 0; + pti_st_hostp[i]->major = major; + } + } + //------------ added by dingo, 2002/7/22 ------------ + if(register_reboot_notifier(&pti_power_off_nb)){ + printk(KERN_ERR"pti_st: Can not register power notifer notifer!\n"); + return -1; + } + //--------------------------------------------------- + + return (0); +} + +void cleanup_module(void) +{ + int i; + + unregister_reboot_notifier(&pti_power_off_nb); // added by dingo, 2002/7/22 + + for(i = 0; i < MAX_ADAPTORS; i++) + if(pti_st_hostp[i]) + break; + + if(i < MAX_ADAPTORS) { + if(pti_st_hostp[i]->major > 0) + unregister_chrdev(pti_st_hostp[i]->major,PTCNTL_DEV_NAME); + if(pti_st_hostp[i]) { + scsi_unregister_module(MODULE_SCSI_HA, &pti_st_driver_template); + } + } + +} + +#endif /* > 2.4.0 */ + +#endif diff -Nur linux-2.4.20.org/drivers/scsi/pti_st.h linux-2.4.20/drivers/scsi/pti_st.h --- linux-2.4.20.org/drivers/scsi/pti_st.h Wed Nov 5 08:47:58 2003 +++ linux-2.4.20/drivers/scsi/pti_st.h Wed Oct 16 00:00:00 2002 @@ -1,577 +1,577 @@ -/*+M************************************************************************* - * Promise SuperTrak device driver for Linux. - * - * Copyright (c) 2001 Promise Technology, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * -------------------------------------------------------------------------- - * Copyright (c) 1999-2001 Promise Technology, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Where this Software is combined with software released under the terms of - * the GNU Public License ("GPL") and the terms of the GPL would require the - * combined work to also be released under the terms of the GPL, the terms - * and conditions of this License will apply in addition to those of the - * GPL with the exception of any terms or conditions of this License that - * conflict with, or are expressly prohibited by, the GPL. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - *-M*************************************************************************/ - -/************************************************************************** - * File: pti_st.h Driver Declaraitons for pti_st.c. - **************************************************************************/ - -#if 0 -#include "i2omstor.h" -#include "i2oexec.h" -#else -#include "i2odef.h" -#endif - -#ifndef _pti_st_h -#define _pti_st_h - -#ifndef LINUX_VERSION_CODE -#include -#endif - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -/* INQUIRY data format */ -typedef struct -{ - unchar type_qual; - unchar modif_rmb; - unchar version; - unchar resp_aenc; - unchar add_length; - unchar reserved1; - unchar reserved2; - unchar misc; - unchar vendor[8]; - unchar product[16]; - unchar revision[4]; -}pti_inq_data; - -/* READ_CAPACITY data format */ -typedef struct -{ - u32 last_block_no; - u32 block_length; -}pti_rdcap_data; - -/* REQUEST_SENSE data format */ -typedef struct -{ - unchar errorcode; - unchar segno; - unchar key; - u32 info; - unchar add_length; - u32 cmd_info; - unchar adsc; - unchar adsq; - unchar fruc; - unchar key_spec[3]; -}pti_sense_data; - -/* MODE_SENSE data format */ -typedef struct -{ - struct - { - unchar data_length; - unchar med_type; - unchar dev_par; - unchar bd_length; - }hd; - struct - { - unchar dens_code; - unchar block_count[3]; - unchar reserved; - unchar block_length[3]; - }bd; -}pti_modep_data; - -extern int PTI_procfile_read(char *, char **, off_t, int, int, int); -extern const char *PTI_ST_info(struct Scsi_Host *); -extern int pti_st_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -extern int pti_st_biosparam(Disk *, kdev_t, int[]); -extern int pti_st_detect(Scsi_Host_Template *); -extern int pti_st_reset(Scsi_Cmnd *, unsigned int); -extern int pti_st_abort(Scsi_Cmnd *); - - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65) -#define PTI_ST { \ - next: NULL, \ - module: NULL, \ - proc_dir: NULL, \ - proc_info: PTI_procfile_read, \ - name: NULL, \ - detect: pti_st_detect, \ - release: pti_st_release, \ - info: PTI_ST_info, \ - command: NULL, \ - queuecommand: pti_st_queue, \ - eh_strategy_handler: NULL, \ - eh_abort_handler: NULL, \ - eh_device_reset_handler: NULL, \ - eh_bus_reset_handler: NULL, \ - eh_host_reset_handler: NULL, \ - abort: pti_st_abort, \ - reset: pti_st_reset, \ - slave_attach: NULL, \ - bios_param: pti_st_biosparam, \ - can_queue: 32, \ - this_id: -1, \ - sg_tablesize: 0, \ - cmd_per_lun: 3, \ - present: 0, \ - unchecked_isa_dma: 0, \ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 0 \ -} -#else -#define PTI_ST { \ - next: NULL, \ - usage_count: NULL, \ - proc_dir: NULL, \ - proc_info: PTI_procfile_read, \ - name: NULL, \ - detect: pti_st_detect, \ - release: pti_st_release, \ - info: PTI_ST_info, \ - command: NULL, \ - queuecommand: pti_st_queue, \ - abort: pti_st_abort, \ - reset: pti_st_reset, \ - slave_attach: NULL, \ - bios_param: pti_st_biosparam, \ - can_queue: 32, /* max simultaneous cmds */ \ - this_id: -1, /* scsi id of host adapter */ \ - sg_tablesize: 0, /* max scatter-gather cmds */ \ - cmd_per_lun: 3, /* cmds per lun (linked cmds) */ \ - present: 0, /* number of 7xxx's present */ \ - unchecked_isa_dma: 0, /* no memory DMA restrictions */ \ - use_clustering: ENABLE_CLUSTERING \ -} -#endif - - -#ifdef NULL -#undef NULL -#endif -#define NULL ((void *) 0) - -#define DEBUG (FALSE) - -#define MAX(x,y) (((x) > (y)) ? (x) : (y)) -#define MIN(x,y) (((x) < (y)) ? (x) : (y)) -#define ABSDIFF(x, y) (((x) > (y)) ? ((x) - (y)) : ((y) - (x))) -#define APOGEE(this,max) ((this>max) ? max : this) - -#if !defined(MAX_ADAPTORS) -#define MAX_ADAPTORS 4 -#endif - -#define MAX_DRIVES (8) -#define SECTOR_SIZE (0x200) -// 512 byte sectors - -// Promise Organization ID -#define MY_IOP_ID 0x10 -#define PROMISE_ORG_ID 0x91 - -// ISM String Identity -#define PTI_RAID 'I2O RAID DEVICE' -#define PTI_IDE 'IDE DEVICE' - -#define VERSIONHI (0x0001) -#define VERSIONLO (0x000B) - -typedef struct _DRIVE -{ - char present; // boolean set if drive present - unsigned long sectors; // LBA drive size in sectors -}DRIVE, *ptrDRIVE; - -typedef struct _I2ODISK -{ - int present; /* TRUE / FALSE */ - char DiskModel[I2O_DEVID_PRODUCT_INFO_SZ+4]; - char Vendor[I2O_DEVID_VENDOR_INFO_SZ+4]; - char ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ+4]; - unsigned int LocalTID; - unsigned int lastcyl; // total cyl cnt - 1 = last cyl position - unsigned char lasthead; // total head cnt - 1 = last head position - unsigned char sector; // sector starts at position 1 - unsigned short resvered; // Padding with two bytes - unsigned long lastLBA; // total LBA cnt - 1 = last LBA position - unsigned long DeviceFlag; -}I2ODISK, *PI2ODISK; - -typedef struct _I2OARRAY -{ - unsigned int RaidMode; -}I2OARRAY, *PI2OARRAY; - -/* PTI_ST Private Message Structure */ -typedef struct _PTI_ST_PRIVATE_MESSAGE { - I2O_PRIVATE_MESSAGE_FRAME MyStandMsg; - I2O_SGE_PAGE_ELEMENT InSGL; - I2O_SGE_PAGE_ELEMENT OutSGL; -} PTI_ST_PRIVATE_MESSAGE, *PPTI_ST_PRIVATE_MESSAGE; - -/* - * Maximum number of SG segments these cards can support. - */ -#define PTI_ST_MAX_SG 12 /* 16 */ -#define PTI_ST_MAXSCB 32 - -#define PTI_ST_RESET_DELAY 5 - -typedef PI2O_BSA_READ_MESSAGE PI2O_BSA_RW_MESSAGE; - -typedef enum -{ - SCB_FREE = 0x0000, - SCB_WAITINGQ = 0x0002, - SCB_ACTIVE = 0x0004, - SCB_SENSE = 0x0008, - SCB_ABORT = 0x0010, - SCB_DEVICE_RESET = 0x0020, - SCB_RESET = 0x0040, - SCB_RECOVERY_SCB = 0x0080, - SCB_WAS_BUSY = 0x0100, - SCB_MSGOUT_SENT = 0x0200, - SCB_MSGOUT_SDTR = 0x0400, - SCB_MSGOUT_WDTR = 0x0800, - SCB_MSGOUT_BITS = SCB_MSGOUT_SENT | - SCB_MSGOUT_SDTR | - SCB_MSGOUT_WDTR, - SCB_QUEUED_ABORT = 0x1000, - SCB_QUEUED_FOR_DONE = 0x2000 -} scb_flag_type; - - -struct pti_st_scb -{ - PI2O_MESSAGE_FRAME *mf; /* corresponding hardware scb */ - Scsi_Cmnd *cmd; /* Scsi_Cmnd for this scb */ - struct pti_st_scb *q_next; /* next scb in queue */ - volatile scb_flag_type flags; /* current state of scb */ - unsigned char tag; - unsigned char sg_count; - unsigned char sense_cmd[6]; /* - * Allocate 6 characters for - * sense command. - */ - unsigned int sg_length; /* We init this during buildscb so we - * don't have to calculate anything - * during underflow/overflow/stat - * code - */ - void *kmalloc_ptr; -}; - -typedef struct -{ - struct pti_st_scb *head; - struct pti_st_scb *tail; -} scb_queue_type; - -typedef struct -{ - scb_queue_type free_scbs; /* - * SCBs assigned to free slot on - * card (no paging required) - */ - struct pti_st_scb *scb_array[PTI_ST_MAXSCB]; - unsigned char maxmfs; /* hardware scbs */ - unsigned char maxscbs; /* max scbs including pageable scbs */ -} scb_data_type; - - -/* - * Message Unit CSR definitions for RedCreek PCI45 board - */ -typedef struct tag_atu -{ - volatile unsigned long APICRegSel; /* APIC Register Select */ - volatile unsigned long reserved0; - volatile unsigned long APICWinReg; /* APIC Window Register */ - volatile unsigned long reserved1; - volatile unsigned long InMsgReg0; /* inbound message register 0 */ - volatile unsigned long InMsgReg1; /* inbound message register 1 */ - volatile unsigned long OutMsgReg0; /* outbound message register 0 */ - volatile unsigned long OutMsgReg1; /* outbound message register 1 */ - volatile unsigned long InDoorReg; /* inbound doorbell register */ - volatile unsigned long InIntStat; /* inbound interrupt status register */ - volatile unsigned long InIntMask; /* inbound interrupt mask register */ - volatile unsigned long OutDoorReg; /* outbound doorbell register */ - volatile unsigned long OutIntStat; /* outbound interrupt status register */ - volatile unsigned long OutIntMask; /* outbound interrupt mask register */ - volatile unsigned long reserved2; - volatile unsigned long reserved3; - volatile unsigned long InQueue; /* inbound queue port */ - volatile unsigned long OutQueue; /* outbound queue port */ - volatile unsigned long reserved4; - volatile unsigned long reserver5; - /* RedCreek extension */ - volatile unsigned long EtherMacLow; - volatile unsigned long EtherMacHi; - volatile unsigned long IPaddr; - volatile unsigned long IPmask; -} ATU, *PATU; - -typedef enum -{ - PSTC_FNONE = 0x00000000, - PSTC_PAGESCBS = 0x00000001, - PSTC_CHANNEL_B_PRIMARY = 0x00000002, - PSTC_USEDEFAULTS = 0x00000004, - PSTC_INDIRECT_PAGING = 0x00000008, - PSTC_CHNLB = 0x00000020, - PSTC_CHNLC = 0x00000040, - PSTC_EXTEND_TRANS_A = 0x00000100, - PSTC_EXTEND_TRANS_B = 0x00000200, - PSTC_TERM_ENB_A = 0x00000400, - PSTC_TERM_ENB_SE_LOW = 0x00000400, - PSTC_TERM_ENB_B = 0x00000800, - PSTC_TERM_ENB_SE_HIGH = 0x00000800, - PSTC_HANDLING_REQINITS = 0x00001000, -#define PSTC_IN_IOCTL_BIT PSTC_HANDLING_REQINITS - PSTC_TARGETMODE = 0x00002000, - PSTC_NEWEEPROM_FMT = 0x00004000, - /* - * Here ends the FreeBSD defined flags and here begins the linux defined - * flags. NOTE: I did not preserve the old flag name during this change - * specifically to force me to evaluate what flags were being used properly - * and what flags weren't. This way, I could clean up the flag usage on - * a use by use basis. Doug Ledford - */ - PSTC_RESET_DELAY = 0x00080000, - PSTC_A_SCANNED = 0x00100000, - PSTC_B_SCANNED = 0x00200000, - PSTC_MULTI_CHANNEL = 0x00400000, - PSTC_BIOS_ENABLED = 0x00800000, - PSTC_SEEPROM_FOUND = 0x01000000, - PSTC_TERM_ENB_LVD = 0x02000000, - PSTC_ABORT_PENDING = 0x04000000, - PSTC_RESET_PENDING = 0x08000000, -#define PSTC_IN_ISR_BIT 28 - PSTC_IN_ISR = 0x10000000, - PSTC_IN_ABORT = 0x20000000, - PSTC_IN_RESET = 0x40000000, - PSTC_EXTERNAL_SRAM = 0x80000000 -} pstc_flag_type; - -#define MAX_LCT_ENTRY 32 - -typedef struct _outboundBuff_t { - U8 outboundBuff[32][32*4]; -} outboundBuff_t; - -struct pti_st_host -{ - /* - * This is the first 64 bytes in the host struct - */ - - /* - * We are grouping things here....first, items that get either read or - * written with nearly every interrupt - */ - volatile pstc_flag_type flags; - unsigned int mbase; /* card base address */ - volatile unsigned char *maddr; - PATU p_atu; /* ptr to ATU register block */ - PU8 LinBaseAddr; -#if defined(MYDEBUG) && 0 - U8 replyBuffer[16*1024]; - U8 messageBuffer[256]; - U8 outboundBuffer[32][32*4]; -#else - outboundBuff_t *outboundBufferp; - U8 *replyBufferp; - U8 *messageBufferp; -#endif - PU8 pLinOutMsgBlock; - U32 outMsgBlockPhyAddr; - scb_data_type *scb_data; - struct pti_st_cmd_queue - { - Scsi_Cmnd *head; - Scsi_Cmnd *tail; - } completeq; - - volatile scb_queue_type waiting_scbs; - - /* - * Things read/written on nearly every entry into pti_st_queue() - */ - volatile unsigned char activescbs; /* active scbs */ - volatile unsigned char max_activescbs; - int max_lun; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) - spinlock_t spin_lock; - volatile unsigned char cpu_lock_count[NR_CPUS]; -#endif - - /* - * We put the less frequently used host structure items after the more - * frequently used items to try and ease the burden on the cache subsystem. - * These entries are not *commonly* accessed, whereas the preceding entries - * are accessed very often. The only exceptions are the qinfifo, qoutfifo, - * and untagged_scbs array. But, they are often accessed only once and each - * access into these arrays is likely to blow a cache line, so they are put - * down here so we can minimize the number of cache lines required to hold - * the preceeding entries. - */ - - unsigned char pci_irq; /* IRQ for this adapter */ - int scsi_id; /* host adapter SCSI ID */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) - struct pci_dev *pdev; -#endif - - unsigned char pci_bus; - unsigned char pci_device_fn; - struct Scsi_Host *host; /* pointer to scsi host */ - int host_no; /* SCSI host number */ - - I2O_LCT_ENTRY LctEntryTable[MAX_LCT_ENTRY]; - I2O_EXEC_STATUS_GET_REPLY IopStatus; - - int TotalDiskCount; - I2ODISK I2ODisk[MAX_DRIVES]; - - /* PTI_STCNTL device Variable */ - void *pti_stdev_bufferp; - int major; /* control device's major */ - int counter; /*counter of using control device*/ -}; - -extern struct pti_st_host *pti_st_hostp[MAX_ADAPTORS]; - - -//--------------------------------------------------------------------------- -// I960RP Memory-Mapper Register PCI Addressing Offset -#define ARSR_OFFSET 0 //APICReg -#define AWR_OFFSET 0x08 //APCIWinReg -#define IMR0_OFFSET 0x10 //InboundMsgReg0 -#define IMR1_OFFSET 0x14 //InboundMsgReg1 -#define OMR0_OFFSET 0x18 //OutboundMsgReg0 -#define OMR1_OFFSET 0x1c //OutboundMsgReg1 -#define IDR_OFFSET 0x20 //InboundDBellReg -#define IISR_OFFSET 0x24 //InboundIntStatusReg -#define IIMR_OFFSET 0x28 //InboundIntMaskReg -#define ODR_OFFSET 0x2c //OutboundDBellReg -#define OISR_OFFSET 0x30 //OutboundIntStatusReg -#define OIMR_OFFSET 0x34 //OutboundIntMaskReg -#define INBOUNDQPORT 0x40 -#define OUTBOUNDQPORT 0x44 -#define MUCR_OFFSET 0x50 //MUConfReg -#define QBAR_OFFSET 0x54 //QueueBaseAddReg - -//--------------------------------------------------------------------------- -// Bit Definition for InboundIntStatusReg (IISR) -#define APICW_Status 0x100 //APIC Window Interrupt (R/C) -#define APICR_Status 0x80 //APIC Register Select Interrupt (R/C) -#define IR_Status 0x40 //Index Register Interrupt (R/C) -#define OBFQ_OF_Status 0x20 //Outbound Free Queue OverFlow Interrupt (R/C) -#define IBPQ_Status 0x10 //Inbound Post Queue Interrupt (R/C) -#define NMI_DB_Status 0x08 //NMI Doorbell Interrupt (R/O) -#define IB_DB_Status 0x04 //Inbound Doorbell Interrupt (R/O) -#define IB_MSG1_Status 0x02 //Inbound Message 1 Interrupt (R/C) -#define IB_MSG0_Status 0x01 //Inbound Message 0 Interrupt (R/C) - -// Bit Definition for InboundIntMaskReg (IIMR) -#define APICW_Mask 0x100 //APIC Windows Interrupt Mask (R/W) -#define APICRSI_Mask 0x80 //APIC Register Select Interrupt Mask (R/W) -#define IR_Mask 0x40 //Index Register Interrupt Mask (R/W) -#define OBFQ_OF_Mask 0x20 //Outbound Free Queue Overflow Interrupt Mask (R/W) -#define IBPQ_Mask 0x10 //Inbound Post Queue Interrupt Mask (R/W) -#define NMI_DB_Mask 0x08 //NMI Doorbell Interrupt Mask (R/W) -#define IB_DB_Mask 0x04 //Inbound DoorbellInterrupt Mask (R/W) -#define IB_MSG1_Mask 0x02 //Inbound Message 1 Interrupt Mask (R/W) -#define IB_MSG0_Mask 0x01 //Inbound Message 0 Interrupt Mask (R/W) - -// Bit Definition for Outbound Interrupt Status Register (OISR) -#define PCI_INT_D_Status 0x80 //PCI Interrupt D (RO) -#define PCI_INT_C_Status 0x40 //PCI Interrupt C (RO) -#define PCI_INT_B_Status 0x20 //PCI Interrupt B (RO) -#define PCI_INT_A_Status 0x10 //PCI Interrupt A (RO) -#define OBPQ_INT_Status 0x08 //Outbound Post Queue Interrupt (RO) -#define OBDB_INT_Status 0x04 //Outbound Doorbell Interrupt (RO) -#define OBMSG1_INT_Status 0x02 //Outbound Message 1 Interrupt (PCI R/C) -#define OBMSG0_INT_Status 0x01 //Outbound Message 0 Interrupt (PCI R/C) - -// Bit Definition for Outbound Interrupt Mask Register -#define PCI_INT_D_Mask 0x80 //PCI Interrupt D (RW) -#define PCI_INT_C_Mask 0x40 //PCI Interrupt C (RW) -#define PCI_INT_B_Mask 0x20 //PCI Interrupt B (RW) -#define PCI_INT_A_Mask 0x10 //PCI Interrupt A (RW) -#define OBPQ_INT_Mask 0x08 //Outbound Post Queue Interrupt Mask (RW) -#define OBDB_INT_Mask 0x04 //Outbound Doorbell Interrupt Mask (RW) -#define OBMSG1_INT_Mask 0x02 //Outbound Message 1 Interrupt Mask (RW) -#define OBMSG0_INT_Mask 0x01 //Outbound Message 0 Interrupt Mask (RW) - -//--------------------------------------------------------------------------- -// IOP Status -#define IOPSTATE_INIT 0x01 -#define IOPSTATE_RESET 0x02 -#define IOPSTATE_HOLD 0x04 -#define IOPSTATE_READY 0x05 -#define IOPSTATE_OP 0x08 -#define IOPSTATE_FAILED 0x10 -#define IOPSTATE_FAULTED 0x11 - - - -#endif /* _pti_st_h */ - +/*+M************************************************************************* + * Promise SuperTrak device driver for Linux. + * + * Copyright (c) 2001 Promise Technology, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * Copyright (c) 1999-2001 Promise Technology, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + *-M*************************************************************************/ + +/************************************************************************** + * File: pti_st.h Driver Declaraitons for pti_st.c. + **************************************************************************/ + +#if 0 +#include "i2omstor.h" +#include "i2oexec.h" +#else +#include "i2odef.h" +#endif + +#ifndef _pti_st_h +#define _pti_st_h + +#ifndef LINUX_VERSION_CODE +#include +#endif + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#endif + +/* INQUIRY data format */ +typedef struct +{ + unchar type_qual; + unchar modif_rmb; + unchar version; + unchar resp_aenc; + unchar add_length; + unchar reserved1; + unchar reserved2; + unchar misc; + unchar vendor[8]; + unchar product[16]; + unchar revision[4]; +}pti_inq_data; + +/* READ_CAPACITY data format */ +typedef struct +{ + u32 last_block_no; + u32 block_length; +}pti_rdcap_data; + +/* REQUEST_SENSE data format */ +typedef struct +{ + unchar errorcode; + unchar segno; + unchar key; + u32 info; + unchar add_length; + u32 cmd_info; + unchar adsc; + unchar adsq; + unchar fruc; + unchar key_spec[3]; +}pti_sense_data; + +/* MODE_SENSE data format */ +typedef struct +{ + struct + { + unchar data_length; + unchar med_type; + unchar dev_par; + unchar bd_length; + }hd; + struct + { + unchar dens_code; + unchar block_count[3]; + unchar reserved; + unchar block_length[3]; + }bd; +}pti_modep_data; + +extern int PTI_procfile_read(char *, char **, off_t, int, int, int); +extern const char *PTI_ST_info(struct Scsi_Host *); +extern int pti_st_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); +extern int pti_st_biosparam(Disk *, kdev_t, int[]); +extern int pti_st_detect(Scsi_Host_Template *); +extern int pti_st_reset(Scsi_Cmnd *, unsigned int); +extern int pti_st_abort(Scsi_Cmnd *); + + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65) +#define PTI_ST { \ + next: NULL, \ + module: NULL, \ + proc_dir: NULL, \ + proc_info: PTI_procfile_read, \ + name: NULL, \ + detect: pti_st_detect, \ + release: pti_st_release, \ + info: PTI_ST_info, \ + command: NULL, \ + queuecommand: pti_st_queue, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: NULL, \ + eh_device_reset_handler: NULL, \ + eh_bus_reset_handler: NULL, \ + eh_host_reset_handler: NULL, \ + abort: pti_st_abort, \ + reset: pti_st_reset, \ + slave_attach: NULL, \ + bios_param: pti_st_biosparam, \ + can_queue: 12, \ + this_id: -1, \ + sg_tablesize: 0, \ + cmd_per_lun: 3, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: 0, \ + use_new_eh_code: 0, \ +} +#else +#define PTI_ST { \ + next: NULL, \ + usage_count: NULL, \ + proc_dir: NULL, \ + proc_info: PTI_procfile_read, \ + name: NULL, \ + detect: pti_st_detect, \ + release: pti_st_release, \ + info: PTI_ST_info, \ + command: NULL, \ + queuecommand: pti_st_queue, \ + abort: pti_st_abort, \ + reset: pti_st_reset, \ + slave_attach: NULL, \ + bios_param: pti_st_biosparam, \ + can_queue: 12, /* max simultaneous cmds */ \ + this_id: -1, /* scsi id of host adapter */ \ + sg_tablesize: 0, /* max scatter-gather cmds */ \ + cmd_per_lun: 3, /* cmds per lun (linked cmds) */ \ + present: 0, /* number of 7xxx's present */ \ + unchecked_isa_dma: 0, /* no memory DMA restrictions */ \ + use_clustering: 0 \ +} +#endif + + +#ifdef NULL +#undef NULL +#endif +#define NULL ((void *) 0) + +#define DEBUG (FALSE) + +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define ABSDIFF(x, y) (((x) > (y)) ? ((x) - (y)) : ((y) - (x))) +#define APOGEE(this,max) ((this>max) ? max : this) + +#if !defined(MAX_ADAPTORS) +#define MAX_ADAPTORS 4 +#endif + +#define MAX_DRIVES (8) +#define SECTOR_SIZE (0x200) +// 512 byte sectors + +// Promise Organization ID +#define MY_IOP_ID 0x10 +#define PROMISE_ORG_ID 0x91 + +// ISM String Identity +#define PTI_RAID 'I2O RAID DEVICE' +#define PTI_IDE 'IDE DEVICE' + +#define VERSIONHI (0x0001) +#define VERSIONLO (0x0022) + +typedef struct _DRIVE +{ + char present; // boolean set if drive present + unsigned long sectors; // LBA drive size in sectors +}DRIVE, *ptrDRIVE; + +typedef struct _I2ODISK +{ + int present; /* TRUE / FALSE */ + char DiskModel[I2O_DEVID_PRODUCT_INFO_SZ+4]; + char Vendor[I2O_DEVID_VENDOR_INFO_SZ+4]; + char ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ+4]; + unsigned int LocalTID; + unsigned int lastcyl; // total cyl cnt - 1 = last cyl position + unsigned char lasthead; // total head cnt - 1 = last head position + unsigned char sector; // sector starts at position 1 + unsigned short resvered; // Padding with two bytes + unsigned long lastLBA; // total LBA cnt - 1 = last LBA position + unsigned long DeviceFlag; +}I2ODISK, *PI2ODISK; + +typedef struct _I2OARRAY +{ + unsigned int RaidMode; +}I2OARRAY, *PI2OARRAY; + +/* PTI_ST Private Message Structure */ +typedef struct _PTI_ST_PRIVATE_MESSAGE { + I2O_PRIVATE_MESSAGE_FRAME MyStandMsg; + I2O_SGE_PAGE_ELEMENT InSGL; + I2O_SGE_PAGE_ELEMENT OutSGL; +} PTI_ST_PRIVATE_MESSAGE, *PPTI_ST_PRIVATE_MESSAGE; + +/* + * Maximum number of SG segments these cards can support. + */ +#define PTI_ST_MAX_SG 12 /* 16 */ +#define PTI_ST_MAXSCB 32 + +#define PTI_ST_RESET_DELAY 5 + +typedef PI2O_BSA_READ_MESSAGE PI2O_BSA_RW_MESSAGE; + +typedef enum +{ + SCB_FREE = 0x0000, + SCB_WAITINGQ = 0x0002, + SCB_ACTIVE = 0x0004, + SCB_SENSE = 0x0008, + SCB_ABORT = 0x0010, + SCB_DEVICE_RESET = 0x0020, + SCB_RESET = 0x0040, + SCB_RECOVERY_SCB = 0x0080, + SCB_WAS_BUSY = 0x0100, + SCB_MSGOUT_SENT = 0x0200, + SCB_MSGOUT_SDTR = 0x0400, + SCB_MSGOUT_WDTR = 0x0800, + SCB_MSGOUT_BITS = SCB_MSGOUT_SENT | + SCB_MSGOUT_SDTR | + SCB_MSGOUT_WDTR, + SCB_QUEUED_ABORT = 0x1000, + SCB_QUEUED_FOR_DONE = 0x2000 +} scb_flag_type; + + +struct pti_st_scb +{ + PI2O_MESSAGE_FRAME *mf; /* corresponding hardware scb */ + Scsi_Cmnd *cmd; /* Scsi_Cmnd for this scb */ + struct pti_st_scb *q_next; /* next scb in queue */ + volatile scb_flag_type flags; /* current state of scb */ + unsigned char tag; + unsigned char sg_count; + unsigned char sense_cmd[6]; /* + * Allocate 6 characters for + * sense command. + */ + unsigned int sg_length; /* We init this during buildscb so we + * don't have to calculate anything + * during underflow/overflow/stat + * code + */ + void *kmalloc_ptr; +}; + +typedef struct +{ + struct pti_st_scb *head; + struct pti_st_scb *tail; +} scb_queue_type; + +typedef struct +{ + scb_queue_type free_scbs; /* + * SCBs assigned to free slot on + * card (no paging required) + */ + struct pti_st_scb *scb_array[PTI_ST_MAXSCB]; + unsigned char maxmfs; /* hardware scbs */ + unsigned char maxscbs; /* max scbs including pageable scbs */ +} scb_data_type; + + +/* + * Message Unit CSR definitions for RedCreek PCI45 board + */ +typedef struct tag_atu +{ + volatile unsigned long APICRegSel; /* APIC Register Select */ + volatile unsigned long reserved0; + volatile unsigned long APICWinReg; /* APIC Window Register */ + volatile unsigned long reserved1; + volatile unsigned long InMsgReg0; /* inbound message register 0 */ + volatile unsigned long InMsgReg1; /* inbound message register 1 */ + volatile unsigned long OutMsgReg0; /* outbound message register 0 */ + volatile unsigned long OutMsgReg1; /* outbound message register 1 */ + volatile unsigned long InDoorReg; /* inbound doorbell register */ + volatile unsigned long InIntStat; /* inbound interrupt status register */ + volatile unsigned long InIntMask; /* inbound interrupt mask register */ + volatile unsigned long OutDoorReg; /* outbound doorbell register */ + volatile unsigned long OutIntStat; /* outbound interrupt status register */ + volatile unsigned long OutIntMask; /* outbound interrupt mask register */ + volatile unsigned long reserved2; + volatile unsigned long reserved3; + volatile unsigned long InQueue; /* inbound queue port */ + volatile unsigned long OutQueue; /* outbound queue port */ + volatile unsigned long reserved4; + volatile unsigned long reserver5; + /* RedCreek extension */ + volatile unsigned long EtherMacLow; + volatile unsigned long EtherMacHi; + volatile unsigned long IPaddr; + volatile unsigned long IPmask; +} ATU, *PATU; + +typedef enum +{ + PSTC_FNONE = 0x00000000, + PSTC_PAGESCBS = 0x00000001, + PSTC_CHANNEL_B_PRIMARY = 0x00000002, + PSTC_USEDEFAULTS = 0x00000004, + PSTC_INDIRECT_PAGING = 0x00000008, + PSTC_CHNLB = 0x00000020, + PSTC_CHNLC = 0x00000040, + PSTC_EXTEND_TRANS_A = 0x00000100, + PSTC_EXTEND_TRANS_B = 0x00000200, + PSTC_TERM_ENB_A = 0x00000400, + PSTC_TERM_ENB_SE_LOW = 0x00000400, + PSTC_TERM_ENB_B = 0x00000800, + PSTC_TERM_ENB_SE_HIGH = 0x00000800, + PSTC_HANDLING_REQINITS = 0x00001000, +#define PSTC_IN_IOCTL_BIT PSTC_HANDLING_REQINITS + PSTC_TARGETMODE = 0x00002000, + PSTC_NEWEEPROM_FMT = 0x00004000, + /* + * Here ends the FreeBSD defined flags and here begins the linux defined + * flags. NOTE: I did not preserve the old flag name during this change + * specifically to force me to evaluate what flags were being used properly + * and what flags weren't. This way, I could clean up the flag usage on + * a use by use basis. Doug Ledford + */ + PSTC_RESET_DELAY = 0x00080000, + PSTC_A_SCANNED = 0x00100000, + PSTC_B_SCANNED = 0x00200000, + PSTC_MULTI_CHANNEL = 0x00400000, + PSTC_BIOS_ENABLED = 0x00800000, + PSTC_SEEPROM_FOUND = 0x01000000, + PSTC_TERM_ENB_LVD = 0x02000000, + PSTC_ABORT_PENDING = 0x04000000, + PSTC_RESET_PENDING = 0x08000000, +#define PSTC_IN_ISR_BIT 28 + PSTC_IN_ISR = 0x10000000, + PSTC_IN_ABORT = 0x20000000, + PSTC_IN_RESET = 0x40000000, + PSTC_EXTERNAL_SRAM = 0x80000000 +} pstc_flag_type; + +#define MAX_LCT_ENTRY 32 + +typedef struct _outboundBuff_t { + U8 outboundBuff[32][32*4]; +} outboundBuff_t; + +struct pti_st_host +{ + /* + * This is the first 64 bytes in the host struct + */ + + /* + * We are grouping things here....first, items that get either read or + * written with nearly every interrupt + */ + volatile pstc_flag_type flags; + unsigned int mbase; /* card base address */ + volatile unsigned char *maddr; + PATU p_atu; /* ptr to ATU register block */ + PU8 LinBaseAddr; +#if defined(MYDEBUG) && 0 + U8 replyBuffer[16*1024]; + U8 messageBuffer[256]; + U8 outboundBuffer[32][32*4]; +#else + outboundBuff_t *outboundBufferp; + U8 *replyBufferp; + U8 *messageBufferp; +#endif + PU8 pLinOutMsgBlock; + U32 outMsgBlockPhyAddr; + scb_data_type *scb_data; + struct pti_st_cmd_queue + { + Scsi_Cmnd *head; + Scsi_Cmnd *tail; + } completeq; + + volatile scb_queue_type waiting_scbs; + + /* + * Things read/written on nearly every entry into pti_st_queue() + */ + volatile unsigned char activescbs; /* active scbs */ + volatile unsigned char max_activescbs; + int max_lun; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) + spinlock_t spin_lock; + volatile unsigned char cpu_lock_count[NR_CPUS]; +#endif + + /* + * We put the less frequently used host structure items after the more + * frequently used items to try and ease the burden on the cache subsystem. + * These entries are not *commonly* accessed, whereas the preceding entries + * are accessed very often. The only exceptions are the qinfifo, qoutfifo, + * and untagged_scbs array. But, they are often accessed only once and each + * access into these arrays is likely to blow a cache line, so they are put + * down here so we can minimize the number of cache lines required to hold + * the preceeding entries. + */ + + unsigned char pci_irq; /* IRQ for this adapter */ + int scsi_id; /* host adapter SCSI ID */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) + struct pci_dev *pdev; +#endif + + unsigned char pci_bus; + unsigned char pci_device_fn; + struct Scsi_Host *host; /* pointer to scsi host */ + int host_no; /* SCSI host number */ + + I2O_LCT_ENTRY LctEntryTable[MAX_LCT_ENTRY]; + I2O_EXEC_STATUS_GET_REPLY IopStatus; + + int TotalDiskCount; + I2ODISK I2ODisk[MAX_DRIVES]; + + /* PTI_STCNTL device Variable */ + void *pti_stdev_bufferp; + int major; /* control device's major */ + int counter; /*counter of using control device*/ +}; + +extern struct pti_st_host *pti_st_hostp[MAX_ADAPTORS]; + + +//--------------------------------------------------------------------------- +// I960RP Memory-Mapper Register PCI Addressing Offset +#define ARSR_OFFSET 0 //APICReg +#define AWR_OFFSET 0x08 //APCIWinReg +#define IMR0_OFFSET 0x10 //InboundMsgReg0 +#define IMR1_OFFSET 0x14 //InboundMsgReg1 +#define OMR0_OFFSET 0x18 //OutboundMsgReg0 +#define OMR1_OFFSET 0x1c //OutboundMsgReg1 +#define IDR_OFFSET 0x20 //InboundDBellReg +#define IISR_OFFSET 0x24 //InboundIntStatusReg +#define IIMR_OFFSET 0x28 //InboundIntMaskReg +#define ODR_OFFSET 0x2c //OutboundDBellReg +#define OISR_OFFSET 0x30 //OutboundIntStatusReg +#define OIMR_OFFSET 0x34 //OutboundIntMaskReg +#define INBOUNDQPORT 0x40 +#define OUTBOUNDQPORT 0x44 +#define MUCR_OFFSET 0x50 //MUConfReg +#define QBAR_OFFSET 0x54 //QueueBaseAddReg + +//--------------------------------------------------------------------------- +// Bit Definition for InboundIntStatusReg (IISR) +#define APICW_Status 0x100 //APIC Window Interrupt (R/C) +#define APICR_Status 0x80 //APIC Register Select Interrupt (R/C) +#define IR_Status 0x40 //Index Register Interrupt (R/C) +#define OBFQ_OF_Status 0x20 //Outbound Free Queue OverFlow Interrupt (R/C) +#define IBPQ_Status 0x10 //Inbound Post Queue Interrupt (R/C) +#define NMI_DB_Status 0x08 //NMI Doorbell Interrupt (R/O) +#define IB_DB_Status 0x04 //Inbound Doorbell Interrupt (R/O) +#define IB_MSG1_Status 0x02 //Inbound Message 1 Interrupt (R/C) +#define IB_MSG0_Status 0x01 //Inbound Message 0 Interrupt (R/C) + +// Bit Definition for InboundIntMaskReg (IIMR) +#define APICW_Mask 0x100 //APIC Windows Interrupt Mask (R/W) +#define APICRSI_Mask 0x80 //APIC Register Select Interrupt Mask (R/W) +#define IR_Mask 0x40 //Index Register Interrupt Mask (R/W) +#define OBFQ_OF_Mask 0x20 //Outbound Free Queue Overflow Interrupt Mask (R/W) +#define IBPQ_Mask 0x10 //Inbound Post Queue Interrupt Mask (R/W) +#define NMI_DB_Mask 0x08 //NMI Doorbell Interrupt Mask (R/W) +#define IB_DB_Mask 0x04 //Inbound DoorbellInterrupt Mask (R/W) +#define IB_MSG1_Mask 0x02 //Inbound Message 1 Interrupt Mask (R/W) +#define IB_MSG0_Mask 0x01 //Inbound Message 0 Interrupt Mask (R/W) + +// Bit Definition for Outbound Interrupt Status Register (OISR) +#define PCI_INT_D_Status 0x80 //PCI Interrupt D (RO) +#define PCI_INT_C_Status 0x40 //PCI Interrupt C (RO) +#define PCI_INT_B_Status 0x20 //PCI Interrupt B (RO) +#define PCI_INT_A_Status 0x10 //PCI Interrupt A (RO) +#define OBPQ_INT_Status 0x08 //Outbound Post Queue Interrupt (RO) +#define OBDB_INT_Status 0x04 //Outbound Doorbell Interrupt (RO) +#define OBMSG1_INT_Status 0x02 //Outbound Message 1 Interrupt (PCI R/C) +#define OBMSG0_INT_Status 0x01 //Outbound Message 0 Interrupt (PCI R/C) + +// Bit Definition for Outbound Interrupt Mask Register +#define PCI_INT_D_Mask 0x80 //PCI Interrupt D (RW) +#define PCI_INT_C_Mask 0x40 //PCI Interrupt C (RW) +#define PCI_INT_B_Mask 0x20 //PCI Interrupt B (RW) +#define PCI_INT_A_Mask 0x10 //PCI Interrupt A (RW) +#define OBPQ_INT_Mask 0x08 //Outbound Post Queue Interrupt Mask (RW) +#define OBDB_INT_Mask 0x04 //Outbound Doorbell Interrupt Mask (RW) +#define OBMSG1_INT_Mask 0x02 //Outbound Message 1 Interrupt Mask (RW) +#define OBMSG0_INT_Mask 0x01 //Outbound Message 0 Interrupt Mask (RW) + +//--------------------------------------------------------------------------- +// IOP Status +#define IOPSTATE_INIT 0x01 +#define IOPSTATE_RESET 0x02 +#define IOPSTATE_HOLD 0x04 +#define IOPSTATE_READY 0x05 +#define IOPSTATE_OP 0x08 +#define IOPSTATE_FAILED 0x10 +#define IOPSTATE_FAULTED 0x11 + + + +#endif /* _pti_st_h */ + diff -Nur linux-2.4.20.org/drivers/scsi/pti_stdev.h linux-2.4.20/drivers/scsi/pti_stdev.h --- linux-2.4.20.org/drivers/scsi/pti_stdev.h Wed Nov 5 08:47:58 2003 +++ linux-2.4.20/drivers/scsi/pti_stdev.h Wed Oct 16 00:00:00 2002 @@ -1,255 +1,264 @@ -/*+M************************************************************************* - * Promise SuperTrak device driver for Linux. - * - * Copyright (c) 2001 Promise Technology, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * -------------------------------------------------------------------------- - * Copyright (c) 1999-2001 Promise Technology, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Where this Software is combined with software released under the terms of - * the GNU Public License ("GPL") and the terms of the GPL would require the - * combined work to also be released under the terms of the GPL, the terms - * and conditions of this License will apply in addition to those of the - * GPL with the exception of any terms or conditions of this License that - * conflict with, or are expressly prohibited by, the GPL. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - *-M*************************************************************************/ - -/************************************************************************** - * File: pti_stdev.h Device Declaraitons for pti_st.c. - **************************************************************************/ -#include - -#if !defined(PTI_STDEV_H) -#define PTI_STDEV_H - -#if !defined(__KERNEL__) -#if 0 -#include "i2omsg.h" -#else /* 0 */ -#include "i2odef.h" -#endif /* 0 */ -#endif /* __KERNEL__ */ - -#if !defined(ULOG) -#define ULONG unsigned long -#endif - -#if !defined(USHORT) -#define USHORT unsigned short -#endif - -#if !defined(UCHAR) -#define UCHAR unsigned char -#endif - -/* - * I2O IOP Descriptor - */ - -typedef struct _I2O_IOP_DESCRIPTOR { - ULONG IOPNumber; - ULONG IOPCapabilities; - ULONG IOPState; - ULONG I2OVersion; - ULONG MessengerType; - ULONG MaxMessageFrameSize; - ULONG ExpectedLCTSize; - ULONG MaxInboundMFrames; - ULONG InitialInboundMFrames; - ULONG Reserved; -} I2O_IOP_DESCRIPTOR, *PI2O_IOP_DESCRIPTOR; - -/* - * I2O IOP and LCT Configuration data - */ - -typedef struct _I2O_DEVICE_DESCRIPTOR { - ULONG ChangeIndicator; - I2O_LCT_ENTRY LCT; - I2O_IOP_DESCRIPTOR IOP; -} I2O_DEVICE_DESCRIPTOR, *PI2O_DEVICE_DESCRIPTOR; - -/* - * I2O Query Configuration Record structure - */ - -#define I2O_CLASS_MATCH_ANY_BITS (((1<= KERNEL_VERSION(2,4,0) -struct block_device_operations pti_stdev_fops = { - open: pti_stdev_open, - release: pti_stdev_release, - ioctl: pti_stdev_ioctl, -}; -#else -struct file_operations pti_stdev_fops = { - NULL, NULL, NULL, NULL, NULL, pti_stdev_ioctl, NULL, - pti_stdev_open, NULL, pti_stdev_release, NULL, NULL, NULL, NULL}; -#endif - -#endif /* __KERNEL__ */ - -#endif /* PTI_STDEV_H */ - +/*+M************************************************************************* + * Promise SuperTrak device driver for Linux. + * + * Copyright (c) 2001 Promise Technology, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * -------------------------------------------------------------------------- + * Copyright (c) 1999-2001 Promise Technology, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + *-M*************************************************************************/ + +/************************************************************************** + * File: pti_stdev.h Device Declaraitons for pti_st.c. + **************************************************************************/ +#include + +#if !defined(PTI_STDEV_H) +#define PTI_STDEV_H + +#if !defined(__KERNEL__) +#if 0 +#include "i2omsg.h" +#else /* 0 */ +#include "i2odef.h" +#endif /* 0 */ +#endif /* __KERNEL__ */ + +#if !defined(ULOG) +#define ULONG unsigned long +#endif + +#if !defined(USHORT) +#define USHORT unsigned short +#endif + +#if !defined(UCHAR) +#define UCHAR unsigned char +#endif + +/* + * I2O IOP Descriptor + */ + +typedef struct _I2O_IOP_DESCRIPTOR { + ULONG IOPNumber; + ULONG IOPCapabilities; + ULONG IOPState; + ULONG I2OVersion; + ULONG MessengerType; + ULONG MaxMessageFrameSize; + ULONG ExpectedLCTSize; + ULONG MaxInboundMFrames; + ULONG InitialInboundMFrames; + ULONG Reserved; +} I2O_IOP_DESCRIPTOR, *PI2O_IOP_DESCRIPTOR; + +/* + * I2O IOP and LCT Configuration data + */ + +typedef struct _I2O_DEVICE_DESCRIPTOR { + ULONG ChangeIndicator; + I2O_LCT_ENTRY LCT; + I2O_IOP_DESCRIPTOR IOP; +} I2O_DEVICE_DESCRIPTOR, *PI2O_DEVICE_DESCRIPTOR; + +/* + * I2O Query Configuration Record structure + */ + +#define I2O_CLASS_MATCH_ANY_BITS (((1<= KERNEL_VERSION(2,4,0) +struct block_device_operations pti_stdev_fops = { + open: pti_stdev_open, + release: pti_stdev_release, + ioctl: pti_stdev_ioctl, +}; +#else +struct file_operations pti_stdev_fops = { + NULL, NULL, NULL, NULL, NULL, pti_stdev_ioctl, NULL, + pti_stdev_open, NULL, pti_stdev_release, NULL, NULL, NULL, NULL}; +#endif + +#endif /* __KERNEL__ */ + +#endif /* PTI_STDEV_H */ +