summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/scsi/adapters/smrt/smrt_ciss.h
blob: e1f1db68b3ea907174f62de556a4e36842f97b0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
 * Copyright (c) 2017, Joyent, Inc.
 */

#ifndef	_SMRT_CISS_H
#define	_SMRT_CISS_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Maximum number of Scatter/Gather List entries.  These entries are statically
 * allocated for all commands.
 */
#define	CISS_MAXSGENTRIES			64

/*
 * If the controller advertises a value of 0 for the maximum S/G list length it
 * supports, the specification states that we should assume a value of 31.
 */
#define	CISS_SGCNT_FALLBACK			31

/*
 * The CDB field in the request block is fixed at 16 bytes in length.  (See
 * "3.2. Request Block" in the CISS specification.)
 */
#define	CISS_CDBLEN				16

/*
 * Command Status Values.  These are listed in "Table 2 Command Status" in "3.3
 * Error Info" of the CISS specification.
 */
#define	CISS_CMD_SUCCESS			0x00
#define	CISS_CMD_TARGET_STATUS			0x01
#define	CISS_CMD_DATA_UNDERRUN			0x02
#define	CISS_CMD_DATA_OVERRUN			0x03
#define	CISS_CMD_INVALID			0x04
#define	CISS_CMD_PROTOCOL_ERR			0x05
#define	CISS_CMD_HARDWARE_ERR			0x06
#define	CISS_CMD_CONNECTION_LOST		0x07
#define	CISS_CMD_ABORTED			0x08
#define	CISS_CMD_ABORT_FAILED			0x09
#define	CISS_CMD_UNSOLICITED_ABORT		0x0a
#define	CISS_CMD_TIMEOUT			0x0b
#define	CISS_CMD_UNABORTABLE			0x0c

/*
 * Request Transfer Directions, used in "RequestBlock.Type.Direction":
 */
#define	CISS_XFER_NONE				0x00
#define	CISS_XFER_WRITE				0x01
#define	CISS_XFER_READ				0x02
#define	CISS_XFER_RSVD				0x03

/*
 * Request Attributes, used in "RequestBlock.Type.Attribute":
 */
#define	CISS_ATTR_UNTAGGED			0x00
#define	CISS_ATTR_SIMPLE			0x04
#define	CISS_ATTR_HEADOFQUEUE			0x05
#define	CISS_ATTR_ORDERED			0x06

/*
 * Request Type, used in "RequestBlock.Type.Type":
 */
#define	CISS_TYPE_CMD				0x00
#define	CISS_TYPE_MSG				0x01

/*
 * I2O Space Register Offsets
 *
 * The name "I2O", and these register offsets, appear to be amongst the last
 * vestiges of a long-defunct attempt at standardising mainframe-style I/O
 * channels in the Intel server space: the Intelligent Input/Output (I2O)
 * Architecture Specification.
 *
 * The draft of version 1.5 of this specification, in section "4.2.1.5.1
 * Extensions for PCI", suggests that the following are memory offsets into
 * "the memory region specified by the first base address configuration
 * register indicating memory space (offset 10h, 14h, and so forth)".  These
 * match up with the offsets of the first two BARs in a PCI configuration space
 * type 0 header.
 *
 * The specification also calls out the Inbound Post List FIFO, write-only at
 * offset 40h; the Outbound Post List FIFO, read-only at offset 44h; the
 * Interrupt Status Register, at offset 30h; and the Interrupt Mask Register,
 * at offset 34h.
 *
 * This ill-fated attempt to increase the proprietary complexity of (and
 * presumably, thus, the gross margin on) computer systems is all but extinct.
 * The transport layer of this storage controller is all that's left of their
 * religion.
 */
#define	CISS_I2O_INBOUND_DOORBELL		0x20
#define	CISS_I2O_INTERRUPT_STATUS		0x30
#define	CISS_I2O_INTERRUPT_MASK			0x34
#define	CISS_I2O_INBOUND_POST_Q			0x40
#define	CISS_I2O_OUTBOUND_POST_Q		0x44
#define	CISS_I2O_OUTBOUND_DOORBELL_STATUS	0x9c
#define	CISS_I2O_OUTBOUND_DOORBELL_CLEAR	0xa0
#define	CISS_I2O_SCRATCHPAD			0xb0
#define	CISS_I2O_CFGTBL_CFG_OFFSET		0xb4
#define	CISS_I2O_CFGTBL_MEM_OFFSET		0xb8

/*
 * Rather than make a lot of small mappings for each part of the address
 * space we wish to access, we will make one large mapping.  If more
 * offsets are added to the I2O list above, this space should be extended
 * appropriately.
 */
#define	CISS_I2O_MAP_BASE			0x20
#define	CISS_I2O_MAP_LIMIT			0x100

/*
 * The Scratchpad Register (I2O_SCRATCHPAD) is not mentioned in the CISS
 * specification.  It serves at least two known functions:
 *	- Signalling controller readiness
 *	- Exposing a debugging code when the controller firmware locks up
 */
#define	CISS_SCRATCHPAD_INITIALISED		0xffff0000

/*
 * Outbound Doorbell Register Values.
 *
 * These are read from the Outbound Doorbell Set/Status Register
 * (CISS_I2O_OUTBOUND_DOORBELL_STATUS), but cleared by writing to the Clear
 * Register (CISS_I2O_OUTBOUND_DOORBELL_CLEAR).
 */
#define	CISS_ODR_BIT_INTERRUPT			(1UL << 0)
#define	CISS_ODR_BIT_LOCKUP			(1UL << 1)

/*
 * Inbound Doorbell Register Values.
 *
 * These are written to and read from the Inbound Doorbell Register
 * (CISS_I2O_INBOUND_DOORBELL).
 */
#define	CISS_IDR_BIT_CFGTBL_CHANGE		(1UL << 0)

/*
 * Interrupt Mask Register Values.
 *
 * These are written to and read from the Interrupt Mask Register
 * (CISS_I2O_INTERRUPT_MASK).  Note that a 1 bit in this register masks or
 * disables the interrupt in question; to enable the interrupt the bit must be
 * set to 0.
 */
#define	CISS_IMR_BIT_SIMPLE_INTR_DISABLE	(1UL << 3)

/*
 * Interrupt Status Register Values.
 *
 * These are read from the Interrupt Status Register
 * (CISS_I2O_INTERRUPT_STATUS).
 */
#define	CISS_ISR_BIT_SIMPLE_INTR		(1UL << 3)

/*
 * Transport Methods.
 *
 * These bit positions are used in the Configuration Table to detect controller
 * support for a particular method, via "TransportSupport"; to request that the
 * controller enable a particular method, via "TransportRequest"; and to detect
 * whether the controller has acknowledged the request and enabled the desired
 * method, via "TransportActive".
 *
 * See: "9.1 Configuration Table" in the CISS Specification.
 */
#define	CISS_CFGTBL_READY_FOR_COMMANDS		(1UL << 0)
#define	CISS_CFGTBL_XPORT_SIMPLE		(1UL << 1)
#define	CISS_CFGTBL_XPORT_PERFORMANT		(1UL << 2)
#define	CISS_CFGTBL_XPORT_MEMQ			(1UL << 4)

/*
 * In the Simple Transport Method, when the appropriate interrupt status bit is
 * set (CISS_ISR_BIT_SIMPLE_INTR), the Outbound Post Queue register is
 * repeatedly read for notifications of the completion of commands previously
 * submitted to the controller.  These macros help break up the read value into
 * its component fields: the tag number, and whether or not the command
 * completed in error.
 */
#define	CISS_OPQ_READ_TAG(x)			((x) >> 2)
#define	CISS_OPQ_READ_ERROR(x)			((x) & (1UL << 1))

/*
 * Physical devices that are reported may be marked as 'masked'. A masked device
 * is one that the driver can see, but must not perform any I/O to.
 */
#define	SMRT_CISS_MODE_MASKED			3

/*
 * The following packed structures are used to ease the manipulation of
 * requests and responses from the controller.
 */
#pragma pack(1)

typedef struct smrt_tag {
	uint32_t reserved:1;
	uint32_t error:1;
	uint32_t tag_value:30;
	uint32_t unused;
} smrt_tag_t;

typedef union SCSI3Addr {
	struct {
		uint8_t Dev;
		uint8_t Bus:6;
		uint8_t Mode:2;
	} PeripDev;
	struct {
		uint8_t DevLSB;
		uint8_t DevMSB:6;
		uint8_t Mode:2;
	} LogDev;
	struct {
		uint8_t Dev:5;
		uint8_t Bus:3;
		uint8_t Targ:6;
		uint8_t Mode:2;
	} LogUnit;
} SCSI3Addr_t;

typedef struct PhysDevAddr {
	uint32_t TargetId:24;
	uint32_t Bus:6;
	uint32_t Mode:2;
	SCSI3Addr_t Target[2];
} PhysDevAddr_t;

typedef struct LogDevAddr {
	uint32_t VolId:30;
	uint32_t Mode:2;
	uint8_t reserved[4];
} LogDevAddr_t;

typedef union LUNAddr {
	uint8_t LunAddrBytes[8];
	SCSI3Addr_t SCSI3Lun[4];
	PhysDevAddr_t PhysDev;
	LogDevAddr_t LogDev;
} LUNAddr_t;

typedef struct CommandListHeader {
	uint8_t ReplyQueue;
	uint8_t SGList;
	uint16_t SGTotal;
	smrt_tag_t Tag;
	LUNAddr_t LUN;
} CommandListHeader_t;

typedef struct RequestBlock {
	uint8_t CDBLen;
	struct {
		uint8_t Type:3;
		uint8_t Attribute:3;
		uint8_t Direction:2;
	} Type;
	uint16_t Timeout;
	uint8_t CDB[CISS_CDBLEN];
} RequestBlock_t;

typedef struct ErrDescriptor {
	uint64_t Addr;
	uint32_t Len;
} ErrDescriptor_t;

typedef struct SGDescriptor {
	uint64_t Addr;
	uint32_t Len;
	uint32_t Ext;
} SGDescriptor_t;

typedef struct CommandList {
	CommandListHeader_t Header;
	RequestBlock_t Request;
	ErrDescriptor_t ErrDesc;
	SGDescriptor_t SG[CISS_MAXSGENTRIES];
} CommandList_t;

typedef union MoreErrInfo {
	struct {
		uint8_t Reserved[3];
		uint8_t Type;
		uint32_t ErrorInfo;
	} Common_Info;
	struct {
		uint8_t Reserved[2];
		uint8_t offense_size;
		uint8_t offense_num;
		uint32_t offense_value;
	} Invalid_Cmd;
} MoreErrInfo_t;

typedef struct ErrorInfo {
	uint8_t ScsiStatus;
	uint8_t SenseLen;
	uint16_t CommandStatus;
	uint32_t ResidualCnt;
	MoreErrInfo_t MoreErrInfo;
	uint8_t SenseInfo[MAX_SENSE_LENGTH];
} ErrorInfo_t;

typedef struct CfgTable {
	uint8_t Signature[4];
	uint32_t SpecValence;
	uint32_t TransportSupport;
	uint32_t TransportActive;
	uint32_t TransportRequest;
	uint32_t Upper32Addr;
	uint32_t CoalIntDelay;
	uint32_t CoalIntCount;
	uint32_t CmdsOutMax;
	uint32_t BusTypes;
	uint32_t TransportMethodOffset;
	uint8_t ServerName[16];
	uint32_t HeartBeat;
	uint32_t HostDrvrSupport;
	uint32_t MaxSGElements;
	uint32_t MaxLunSupport;
	uint32_t MaxPhyDevSupport;
	uint32_t MaxPhyDrvPerLun;
	uint32_t MaxPerfModeCmdsOutMax;
	uint32_t MaxBlockFetchCount;
} CfgTable_t;

#pragma pack()

#ifdef	__cplusplus
}
#endif

#endif /* _SMRT_CISS_H */