1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. 14 * Copyright (c) 2017, Joyent, Inc. 15 */ 16 17 #ifndef _SMRT_CISS_H 18 #define _SMRT_CISS_H 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /* 25 * Maximum number of Scatter/Gather List entries. These entries are statically 26 * allocated for all commands. 27 */ 28 #define CISS_MAXSGENTRIES 64 29 30 /* 31 * If the controller advertises a value of 0 for the maximum S/G list length it 32 * supports, the specification states that we should assume a value of 31. 33 */ 34 #define CISS_SGCNT_FALLBACK 31 35 36 /* 37 * The CDB field in the request block is fixed at 16 bytes in length. (See 38 * "3.2. Request Block" in the CISS specification.) 39 */ 40 #define CISS_CDBLEN 16 41 42 /* 43 * Command Status Values. These are listed in "Table 2 Command Status" in "3.3 44 * Error Info" of the CISS specification. 45 */ 46 #define CISS_CMD_SUCCESS 0x00 47 #define CISS_CMD_TARGET_STATUS 0x01 48 #define CISS_CMD_DATA_UNDERRUN 0x02 49 #define CISS_CMD_DATA_OVERRUN 0x03 50 #define CISS_CMD_INVALID 0x04 51 #define CISS_CMD_PROTOCOL_ERR 0x05 52 #define CISS_CMD_HARDWARE_ERR 0x06 53 #define CISS_CMD_CONNECTION_LOST 0x07 54 #define CISS_CMD_ABORTED 0x08 55 #define CISS_CMD_ABORT_FAILED 0x09 56 #define CISS_CMD_UNSOLICITED_ABORT 0x0a 57 #define CISS_CMD_TIMEOUT 0x0b 58 #define CISS_CMD_UNABORTABLE 0x0c 59 60 /* 61 * Request Transfer Directions, used in "RequestBlock.Type.Direction": 62 */ 63 #define CISS_XFER_NONE 0x00 64 #define CISS_XFER_WRITE 0x01 65 #define CISS_XFER_READ 0x02 66 #define CISS_XFER_RSVD 0x03 67 68 /* 69 * Request Attributes, used in "RequestBlock.Type.Attribute": 70 */ 71 #define CISS_ATTR_UNTAGGED 0x00 72 #define CISS_ATTR_SIMPLE 0x04 73 #define CISS_ATTR_HEADOFQUEUE 0x05 74 #define CISS_ATTR_ORDERED 0x06 75 76 /* 77 * Request Type, used in "RequestBlock.Type.Type": 78 */ 79 #define CISS_TYPE_CMD 0x00 80 #define CISS_TYPE_MSG 0x01 81 82 /* 83 * I2O Space Register Offsets 84 * 85 * The name "I2O", and these register offsets, appear to be amongst the last 86 * vestiges of a long-defunct attempt at standardising mainframe-style I/O 87 * channels in the Intel server space: the Intelligent Input/Output (I2O) 88 * Architecture Specification. 89 * 90 * The draft of version 1.5 of this specification, in section "4.2.1.5.1 91 * Extensions for PCI", suggests that the following are memory offsets into 92 * "the memory region specified by the first base address configuration 93 * register indicating memory space (offset 10h, 14h, and so forth)". These 94 * match up with the offsets of the first two BARs in a PCI configuration space 95 * type 0 header. 96 * 97 * The specification also calls out the Inbound Post List FIFO, write-only at 98 * offset 40h; the Outbound Post List FIFO, read-only at offset 44h; the 99 * Interrupt Status Register, at offset 30h; and the Interrupt Mask Register, 100 * at offset 34h. 101 * 102 * This ill-fated attempt to increase the proprietary complexity of (and 103 * presumably, thus, the gross margin on) computer systems is all but extinct. 104 * The transport layer of this storage controller is all that's left of their 105 * religion. 106 */ 107 #define CISS_I2O_INBOUND_DOORBELL 0x20 108 #define CISS_I2O_INTERRUPT_STATUS 0x30 109 #define CISS_I2O_INTERRUPT_MASK 0x34 110 #define CISS_I2O_INBOUND_POST_Q 0x40 111 #define CISS_I2O_OUTBOUND_POST_Q 0x44 112 #define CISS_I2O_OUTBOUND_DOORBELL_STATUS 0x9c 113 #define CISS_I2O_OUTBOUND_DOORBELL_CLEAR 0xa0 114 #define CISS_I2O_SCRATCHPAD 0xb0 115 #define CISS_I2O_CFGTBL_CFG_OFFSET 0xb4 116 #define CISS_I2O_CFGTBL_MEM_OFFSET 0xb8 117 118 /* 119 * Rather than make a lot of small mappings for each part of the address 120 * space we wish to access, we will make one large mapping. If more 121 * offsets are added to the I2O list above, this space should be extended 122 * appropriately. 123 */ 124 #define CISS_I2O_MAP_BASE 0x20 125 #define CISS_I2O_MAP_LIMIT 0x100 126 127 /* 128 * The Scratchpad Register (I2O_SCRATCHPAD) is not mentioned in the CISS 129 * specification. It serves at least two known functions: 130 * - Signalling controller readiness 131 * - Exposing a debugging code when the controller firmware locks up 132 */ 133 #define CISS_SCRATCHPAD_INITIALISED 0xffff0000 134 135 /* 136 * Outbound Doorbell Register Values. 137 * 138 * These are read from the Outbound Doorbell Set/Status Register 139 * (CISS_I2O_OUTBOUND_DOORBELL_STATUS), but cleared by writing to the Clear 140 * Register (CISS_I2O_OUTBOUND_DOORBELL_CLEAR). 141 */ 142 #define CISS_ODR_BIT_INTERRUPT (1UL << 0) 143 #define CISS_ODR_BIT_LOCKUP (1UL << 1) 144 145 /* 146 * Inbound Doorbell Register Values. 147 * 148 * These are written to and read from the Inbound Doorbell Register 149 * (CISS_I2O_INBOUND_DOORBELL). 150 */ 151 #define CISS_IDR_BIT_CFGTBL_CHANGE (1UL << 0) 152 153 /* 154 * Interrupt Mask Register Values. 155 * 156 * These are written to and read from the Interrupt Mask Register 157 * (CISS_I2O_INTERRUPT_MASK). Note that a 1 bit in this register masks or 158 * disables the interrupt in question; to enable the interrupt the bit must be 159 * set to 0. 160 */ 161 #define CISS_IMR_BIT_SIMPLE_INTR_DISABLE (1UL << 3) 162 163 /* 164 * Interrupt Status Register Values. 165 * 166 * These are read from the Interrupt Status Register 167 * (CISS_I2O_INTERRUPT_STATUS). 168 */ 169 #define CISS_ISR_BIT_SIMPLE_INTR (1UL << 3) 170 171 /* 172 * Transport Methods. 173 * 174 * These bit positions are used in the Configuration Table to detect controller 175 * support for a particular method, via "TransportSupport"; to request that the 176 * controller enable a particular method, via "TransportRequest"; and to detect 177 * whether the controller has acknowledged the request and enabled the desired 178 * method, via "TransportActive". 179 * 180 * See: "9.1 Configuration Table" in the CISS Specification. 181 */ 182 #define CISS_CFGTBL_READY_FOR_COMMANDS (1UL << 0) 183 #define CISS_CFGTBL_XPORT_SIMPLE (1UL << 1) 184 #define CISS_CFGTBL_XPORT_PERFORMANT (1UL << 2) 185 #define CISS_CFGTBL_XPORT_MEMQ (1UL << 4) 186 187 /* 188 * In the Simple Transport Method, when the appropriate interrupt status bit is 189 * set (CISS_ISR_BIT_SIMPLE_INTR), the Outbound Post Queue register is 190 * repeatedly read for notifications of the completion of commands previously 191 * submitted to the controller. These macros help break up the read value into 192 * its component fields: the tag number, and whether or not the command 193 * completed in error. 194 */ 195 #define CISS_OPQ_READ_TAG(x) ((x) >> 2) 196 #define CISS_OPQ_READ_ERROR(x) ((x) & (1UL << 1)) 197 198 /* 199 * Physical devices that are reported may be marked as 'masked'. A masked device 200 * is one that the driver can see, but must not perform any I/O to. 201 */ 202 #define SMRT_CISS_MODE_MASKED 3 203 204 /* 205 * The following packed structures are used to ease the manipulation of 206 * requests and responses from the controller. 207 */ 208 #pragma pack(1) 209 210 typedef struct smrt_tag { 211 uint32_t reserved:1; 212 uint32_t error:1; 213 uint32_t tag_value:30; 214 uint32_t unused; 215 } smrt_tag_t; 216 217 typedef union SCSI3Addr { 218 struct { 219 uint8_t Dev; 220 uint8_t Bus:6; 221 uint8_t Mode:2; 222 } PeripDev; 223 struct { 224 uint8_t DevLSB; 225 uint8_t DevMSB:6; 226 uint8_t Mode:2; 227 } LogDev; 228 struct { 229 uint8_t Dev:5; 230 uint8_t Bus:3; 231 uint8_t Targ:6; 232 uint8_t Mode:2; 233 } LogUnit; 234 } SCSI3Addr_t; 235 236 typedef struct PhysDevAddr { 237 uint32_t TargetId:24; 238 uint32_t Bus:6; 239 uint32_t Mode:2; 240 SCSI3Addr_t Target[2]; 241 } PhysDevAddr_t; 242 243 typedef struct LogDevAddr { 244 uint32_t VolId:30; 245 uint32_t Mode:2; 246 uint8_t reserved[4]; 247 } LogDevAddr_t; 248 249 typedef union LUNAddr { 250 uint8_t LunAddrBytes[8]; 251 SCSI3Addr_t SCSI3Lun[4]; 252 PhysDevAddr_t PhysDev; 253 LogDevAddr_t LogDev; 254 } LUNAddr_t; 255 256 typedef struct CommandListHeader { 257 uint8_t ReplyQueue; 258 uint8_t SGList; 259 uint16_t SGTotal; 260 smrt_tag_t Tag; 261 LUNAddr_t LUN; 262 } CommandListHeader_t; 263 264 typedef struct RequestBlock { 265 uint8_t CDBLen; 266 struct { 267 uint8_t Type:3; 268 uint8_t Attribute:3; 269 uint8_t Direction:2; 270 } Type; 271 uint16_t Timeout; 272 uint8_t CDB[CISS_CDBLEN]; 273 } RequestBlock_t; 274 275 typedef struct ErrDescriptor { 276 uint64_t Addr; 277 uint32_t Len; 278 } ErrDescriptor_t; 279 280 typedef struct SGDescriptor { 281 uint64_t Addr; 282 uint32_t Len; 283 uint32_t Ext; 284 } SGDescriptor_t; 285 286 typedef struct CommandList { 287 CommandListHeader_t Header; 288 RequestBlock_t Request; 289 ErrDescriptor_t ErrDesc; 290 SGDescriptor_t SG[CISS_MAXSGENTRIES]; 291 } CommandList_t; 292 293 typedef union MoreErrInfo { 294 struct { 295 uint8_t Reserved[3]; 296 uint8_t Type; 297 uint32_t ErrorInfo; 298 } Common_Info; 299 struct { 300 uint8_t Reserved[2]; 301 uint8_t offense_size; 302 uint8_t offense_num; 303 uint32_t offense_value; 304 } Invalid_Cmd; 305 } MoreErrInfo_t; 306 307 typedef struct ErrorInfo { 308 uint8_t ScsiStatus; 309 uint8_t SenseLen; 310 uint16_t CommandStatus; 311 uint32_t ResidualCnt; 312 MoreErrInfo_t MoreErrInfo; 313 uint8_t SenseInfo[MAX_SENSE_LENGTH]; 314 } ErrorInfo_t; 315 316 typedef struct CfgTable { 317 uint8_t Signature[4]; 318 uint32_t SpecValence; 319 uint32_t TransportSupport; 320 uint32_t TransportActive; 321 uint32_t TransportRequest; 322 uint32_t Upper32Addr; 323 uint32_t CoalIntDelay; 324 uint32_t CoalIntCount; 325 uint32_t CmdsOutMax; 326 uint32_t BusTypes; 327 uint32_t TransportMethodOffset; 328 uint8_t ServerName[16]; 329 uint32_t HeartBeat; 330 uint32_t HostDrvrSupport; 331 uint32_t MaxSGElements; 332 uint32_t MaxLunSupport; 333 uint32_t MaxPhyDevSupport; 334 uint32_t MaxPhyDrvPerLun; 335 uint32_t MaxPerfModeCmdsOutMax; 336 uint32_t MaxBlockFetchCount; 337 } CfgTable_t; 338 339 #pragma pack() 340 341 #ifdef __cplusplus 342 } 343 #endif 344 345 #endif /* _SMRT_CISS_H */ 346