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_SCSI_H
18 #define	_SMRT_SCSI_H
19 
20 #include <sys/types.h>
21 
22 #include <sys/scsi/adapters/smrt/smrt_ciss.h>
23 
24 #ifdef	__cplusplus
25 extern "C" {
26 #endif
27 
28 /* CISS LUN Addressing MODEs */
29 #define	PERIPHERIAL_DEV_ADDR			0x0
30 #define	LOGICAL_VOL_ADDR			0x1
31 #define	MASK_PERIPHERIAL_DEV_ADDR		0x3
32 #define	CISS_PHYS_MODE				0x0
33 
34 /*
35  * Vendor-specific SCSI Commands
36  *
37  * These command opcodes are for use in the opcode byte of the CDB in a request
38  * of type CISS_TYPE_CMD.  They are custom SCSI commands, using the
39  * vendor-specific part of the opcode space; i.e., 0xC0 through 0xFF.
40  */
41 #define	CISS_SCMD_READ				0xC0
42 #define	CISS_SCMD_WRITE				0xC1
43 #define	CISS_SCMD_REPORT_LOGICAL_LUNS		0xC2
44 #define	CISS_SCMD_REPORT_PHYSICAL_LUNS		0xC3
45 
46 /*
47  * These command opcodes are _not_ in the usual vendor-specific space, but are
48  * nonetheless vendor-specific.  They allow BMIC commands to be written to and
49  * read from the controller.  If a command transfers no data, the specification
50  * suggests that BMIC_WRITE (0x27) is appropriate.
51  */
52 #define	CISS_SCMD_BMIC_READ			0x26
53 #define	CISS_SCMD_BMIC_WRITE			0x27
54 
55 /*
56  * CISS Messages
57  *
58  * The CISS specification describes several directives that do not behave like
59  * SCSI commands.  They are sent in requests of type CISS_TYPE_MSG.
60  *
61  * The Abort, Reset, and Nop, messages are defined in "8. Messages" in the CISS
62  * Specification.
63  */
64 #define	CISS_MSG_ABORT				0x0
65 #define	CISS_ABORT_TASK				0x0
66 #define	CISS_ABORT_TASKSET			0x1
67 
68 #define	CISS_MSG_RESET				0x1
69 #define	CISS_RESET_CTLR				0x0
70 #define	CISS_RESET_BUS				0x1
71 #define	CISS_RESET_TGT				0x3
72 #define	CISS_RESET_LUN				0x4
73 
74 #define	CISS_MSG_NOP				0x3
75 
76 /*
77  * BMIC Commands
78  *
79  * These commands allow for the use of non-standard facilities specific to the
80  * Smart Array firmware.  They are sent to the controller through a specially
81  * constructed CDB with the CISS_SCMD_BMIC_READ or CISS_SCMD_BMIC_WRITE opcode.
82  */
83 #define	CISS_BMIC_IDENTIFY_CONTROLLER		0x11
84 #define	CISS_BMIC_IDENTIFY_PHYSICAL_DEVICE	0x15
85 #define	CISS_BMIC_NOTIFY_ON_EVENT		0xD0
86 #define	CISS_BMIC_NOTIFY_ON_EVENT_CANCEL	0xD1
87 
88 /*
89  * Device and Phy type codes.  These are used across many commands, including
90  * IDENTIFY PHYSICAL DEVICE and the REPORT PHYSICAL LUN extended reporting.
91  */
92 #define	SMRT_DTYPE_PSCSI			0x00
93 #define	SMRT_DTYPE_SATA				0x01
94 #define	SMRT_DTYPE_SAS				0x02
95 #define	SMRT_DTYPE_SATA_BW			0x03
96 #define	SMRT_DTYPE_SAS_BW			0x04
97 #define	SMRT_DTYPE_EXPANDER			0x05
98 #define	SMRT_DTYPE_SES				0x06
99 #define	SMRT_DTYPE_CONTROLLER			0x07
100 #define	SMRT_DTYPE_SGPIO			0x08
101 #define	SMRT_DTYPE_NVME				0x09
102 #define	SMRT_DTYPE_NOPHY			0xFF
103 
104 /*
105  * The following packed structures are used to ease the manipulation of SCSI
106  * and BMIC commands sent to, and status information returned from, the
107  * controller.
108  */
109 #pragma pack(1)
110 
111 typedef struct smrt_report_logical_lun_ent {
112 	LogDevAddr_t smrle_addr;
113 } smrt_report_logical_lun_ent_t;
114 
115 typedef struct smrt_report_logical_lun_extent {
116 	LogDevAddr_t smrle_addr;
117 	uint8_t smrle_wwn[16];
118 } smrt_report_logical_lun_extent_t;
119 
120 typedef struct smrt_report_logical_lun {
121 	uint32_t smrll_datasize; /* Big Endian */
122 	uint8_t smrll_extflag;
123 	uint8_t smrll_reserved1[3];
124 	union {
125 		smrt_report_logical_lun_ent_t ents[SMRT_MAX_LOGDRV];
126 		smrt_report_logical_lun_extent_t extents[SMRT_MAX_LOGDRV];
127 	} smrll_data;
128 } smrt_report_logical_lun_t;
129 
130 typedef struct smrt_report_logical_lun_req {
131 	uint8_t smrllr_opcode;
132 	uint8_t smrllr_extflag;
133 	uint8_t smrllr_reserved1[4];
134 	uint32_t smrllr_datasize; /* Big Endian */
135 	uint8_t smrllr_reserved2;
136 	uint8_t smrllr_control;
137 } smrt_report_logical_lun_req_t;
138 
139 typedef struct smrt_report_physical_lun_ent {
140 	PhysDevAddr_t srple_addr;
141 } smrt_report_physical_lun_ent_t;
142 
143 /*
144  * This structure represents the 'physical node identifier' extended option for
145  * REPORT PHYSICAL LUNS.  This is triggered when the extended flags is set to
146  * 0x1.  Note that for SAS the other structure should always be used.
147  */
148 typedef struct smrt_report_physical_pnid {
149 	uint8_t srpp_node[8];
150 	uint8_t srpp_port[8];
151 } smrt_report_physical_pnid_t;
152 
153 /*
154  * This structure represents the 'other physical device info' extended option
155  * for report physical luns.  This is triggered when the extended flags is set
156  * to 0x2.
157  */
158 typedef struct smrt_report_physical_opdi {
159 	uint8_t srpo_wwid[8];
160 	uint8_t srpo_dtype;
161 	uint8_t srpo_flags;
162 	uint8_t srpo_multilun;
163 	uint8_t srpo_paths;
164 	uint32_t srpo_iohdl;
165 } smrt_report_physical_opdi_t;
166 
167 typedef struct smrt_report_physical_lun_extent {
168 	PhysDevAddr_t srple_addr;
169 	union {
170 		smrt_report_physical_pnid_t srple_pnid;
171 		smrt_report_physical_opdi_t srple_opdi;
172 	} srple_extdata;
173 } smrt_report_physical_lun_extent_t;
174 
175 /*
176  * Values that can be ORed together into smrllr_extflag. smprl_extflag indicates
177  * if any extended processing was done or not.
178  */
179 #define	SMRT_REPORT_PHYSICAL_LUN_EXT_NONE	0x00
180 #define	SMRT_REPORT_PHYSICAL_LUN_EXT_PNID	0x01
181 #define	SMRT_REPORT_PHYSICAL_LUN_EXT_OPDI	0x02
182 #define	SMRT_REPORT_PHYSICAL_LUN_EXT_MASK	0x0f
183 #define	SMRT_REPORT_PHYSICAL_LUN_CTRL_ONLY	(1 << 6)
184 #define	SMRT_REPORT_PHYSICAL_LUN_ALL_PATHS	(1 << 7)
185 
186 typedef struct smrt_report_physical_lun {
187 	uint32_t smrpl_datasize; /* Big Endian */
188 	uint8_t smrpl_extflag;
189 	uint8_t smrpl_reserved1[3];
190 	union {
191 		smrt_report_physical_lun_ent_t ents[SMRT_MAX_PHYSDEV];
192 		smrt_report_physical_lun_extent_t extents[SMRT_MAX_PHYSDEV];
193 	} smrpl_data;
194 } smrt_report_physical_lun_t;
195 
196 
197 typedef struct smrt_report_physical_lun_req {
198 	uint8_t smrplr_opcode;
199 	uint8_t smrplr_extflag;
200 	uint8_t smrplr_reserved[1];
201 	uint32_t smrplr_datasize; /* Big Endian */
202 	uint8_t smrplr_reserved2;
203 	uint8_t smrplr_control;
204 } smrt_report_physical_lun_req_t;
205 
206 /*
207  * Request structure for the BMIC command IDENTIFY CONTROLLER.  This structure
208  * is written into the CDB with the CISS_SCMD_BMIC_READ SCSI opcode.  Reserved
209  * fields should be filled with zeroes.
210  */
211 typedef struct smrt_identify_controller_req {
212 	uint8_t smicr_opcode;
213 	uint8_t smicr_lun;
214 	uint8_t smicr_reserved1[4];
215 	uint8_t smicr_command;
216 	uint8_t smicr_reserved2[2];
217 	uint8_t smicr_reserved3[1];
218 	uint8_t smicr_reserved4[6];
219 } smrt_identify_controller_req_t;
220 
221 /*
222  * Response structure for IDENTIFY CONTROLLER.  This structure is used to
223  * interpret the response the controller will write into the data buffer.
224  */
225 typedef struct smrt_identify_controller {
226 	uint8_t smic_logical_drive_count;
227 	uint32_t smic_config_signature;
228 	uint8_t smic_firmware_rev[4];
229 	uint8_t smic_recovery_rev[4];
230 	uint8_t smic_hardware_version;
231 	uint8_t smic_bootblock_rev[4];
232 
233 	/*
234 	 * These are obsolete for SAS controllers:
235 	 */
236 	uint32_t smic_drive_present_map;
237 	uint32_t smic_external_drive_map;
238 
239 	uint32_t smic_board_id;
240 } smrt_identify_controller_t;
241 
242 /*
243  * Request structure for IDENTIFY PHYSICAL DEVICE.  This structure is written
244  * into the CDB with the CISS_SCMD_BMIC_READ SCSI opcode.  Reserved fields
245  * should be filled with zeroes.  Note, the lower 8 bits of the BMIC ID are in
246  * index1, whereas the upper 8 bites are in index2; however, the controller may
247  * only support 8 bits worth of devices (and this driver does not support that
248  * many devices).
249  */
250 typedef struct smrt_identify_physical_drive_req {
251 	uint8_t sipdr_opcode;
252 	uint8_t sipdr_lun;
253 	uint8_t	sipdr_bmic_index1;
254 	uint8_t sipdr_reserved1[3];
255 	uint8_t sipdr_command;
256 	uint8_t sipdr_reserved2[2];
257 	uint8_t sipdr_bmic_index2;
258 	uint8_t sipdr_reserved4[6];
259 } smrt_identify_physical_drive_req_t;
260 
261 /*
262  * Relevant values for the sipd_more_flags member.
263  */
264 #define	SMRT_MORE_FLAGS_LOGVOL	(1 << 5)
265 #define	SMRT_MORE_FLAGS_SPARE	(1 << 6)
266 
267 /*
268  * Response structure for IDENTIFY PHYSICAL DEVICE.  This structure is used to
269  * describe aspects of a physical drive. Note, not all fields are valid in all
270  * firmware revisions.
271  */
272 typedef struct smrt_identify_physical_drive {
273 	uint8_t		sipd_scsi_bus;	/* Invalid for SAS */
274 	uint8_t		sipd_scsi_id;	/* Invalid for SAS */
275 	uint16_t	sipd_lblk_size;
276 	uint32_t	sipd_nblocks;
277 	uint32_t	sipd_rsrvd_blocsk;
278 	uint8_t		sipd_model[40];
279 	uint8_t		sipd_serial[40];
280 	uint8_t		sipd_firmware[8];
281 	uint8_t		sipd_scsi_inquiry;
282 	uint8_t		sipd_compaq_stamp;
283 	uint8_t		sipd_last_failure;
284 	uint8_t		sipd_flags;
285 	uint8_t		sipd_more_flags;
286 	uint8_t		sipd_scsi_lun;	/* Invalid for SAS */
287 	uint8_t		sipd_yet_more_flags;
288 	uint8_t		sipd_even_more_flags;
289 	uint32_t	sipd_spi_speed_rules;
290 	uint8_t		sipd_phys_connector[2];
291 	uint8_t		sipd_phys_box_on_bus;
292 	uint8_t		sipd_phys_bay_in_box;
293 	uint32_t	sipd_rpm;
294 	uint8_t		sipd_device_type;
295 	uint8_t		sipd_sata_version;
296 	uint64_t	sipd_big_nblocks;
297 	uint64_t	sipd_ris_slba;
298 	uint32_t	sipd_ris_size;
299 	uint8_t		sipd_wwid[20];
300 	uint8_t		sipd_controller_phy_map[32];
301 	uint16_t	sipd_phy_count;
302 	uint8_t		sipd_phy_connected_dev_type[256];
303 	uint8_t		sipd_phy_to_drive_bay[256];
304 	uint16_t	sipd_phy_to_attached_dev[256];
305 	uint8_t		sipd_box_index;
306 	uint8_t		sipd_drive_support;
307 	uint16_t	sipd_extra_flags;
308 	uint8_t		sipd_neogiated_link_rate[256];
309 	uint8_t		sipd_phy_to_phy_map[256];
310 	uint8_t		sipd_pad[312];
311 } smrt_identify_physical_drive_t;
312 
313 /*
314  * Note that this structure describes the CISS version of the command. There
315  * also exists a BMIC version, but it has a slightly different structure.  This
316  * structure is also used for the cancellation request; however, in that case,
317  * the senr_flags field is reserved.
318  */
319 typedef struct smrt_event_notify_req {
320 	uint8_t		senr_opcode;
321 	uint8_t		senr_subcode;
322 	uint8_t		senr_reserved1[2];
323 	uint32_t	senr_flags;	/* Big Endian */
324 	uint32_t	senr_size;	/* Big Endian */
325 	uint8_t		senr_control;
326 } smrt_event_notify_req_t;
327 
328 /*
329  * When receiving event notifications, the buffer size must be 512 bytes large.
330  * We make sure that we always allocate a buffer of this size, even though we
331  * define a structure that is much shorter and only uses the fields that we end
332  * up caring about.  This size requirement comes from the specification.
333  */
334 #define	SMRT_EVENT_NOTIFY_BUFLEN	512
335 
336 #define	SMRT_EVENT_CLASS_PROTOCOL		0
337 #define	SMRT_EVENT_PROTOCOL_SUBCLASS_ERROR	1
338 
339 #define	SMRT_EVENT_CLASS_HOTPLUG		1
340 #define	SMRT_EVENT_HOTPLUG_SUBCLASS_DRIVE	0
341 
342 #define	SMRT_EVENT_CLASS_HWERROR		2
343 #define	SMRT_EVENT_CLASS_ENVIRONMENT		3
344 
345 #define	SMRT_EVENT_CLASS_PHYS			4
346 #define	SMRT_EVENT_PHYS_SUBCLASS_STATE		0
347 
348 #define	SMRT_EVENT_CLASS_LOGVOL			5
349 
350 typedef struct smrt_event_notify {
351 	uint32_t	sen_timestamp;
352 	uint16_t	sen_class;
353 	uint16_t	sen_subclass;
354 	uint16_t	sen_detail;
355 	uint8_t		sen_data[64];
356 	char		sen_message[80];
357 	uint32_t	sen_tag;
358 	uint16_t	sen_date;
359 	uint16_t	sen_year;
360 	uint32_t	sen_time;
361 	uint16_t	sen_pre_power_time;
362 	LUNAddr_t	sen_addr;
363 } smrt_event_notify_t;
364 
365 #pragma pack()
366 
367 #ifdef	__cplusplus
368 }
369 #endif
370 
371 #endif	/* _SMRT_SCSI_H */
372