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