xref: /openbsd/sys/scsi/scsi_disk.h (revision e471ee1c)
1 /*	$OpenBSD: scsi_disk.h,v 1.43 2022/01/11 23:10:11 jsg Exp $	*/
2 /*	$NetBSD: scsi_disk.h,v 1.10 1996/07/05 16:19:05 christos Exp $	*/
3 
4 /*
5  * SCSI interface description
6  */
7 
8 /*
9  * Some lines of this file come from a file of the name "scsi.h"
10  * distributed by OSF as part of mach2.5,
11  *  so the following disclaimer has been kept.
12  *
13  * Copyright 1990 by Open Software Foundation,
14  * Grenoble, FRANCE
15  *
16  *		All Rights Reserved
17  *
18  *   Permission to use, copy, modify, and distribute this software and
19  * its documentation for any purpose and without fee is hereby granted,
20  * provided that the above copyright notice appears in all copies and
21  * that both the copyright notice and this permission notice appear in
22  * supporting documentation, and that the name of OSF or Open Software
23  * Foundation not be used in advertising or publicity pertaining to
24  * distribution of the software without specific, written prior
25  * permission.
26  *
27  *   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
28  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
29  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
30  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
31  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
32  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
33  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34  */
35 
36 /*
37  * Largely written by Julian Elischer (julian@tfs.com)
38  * for TRW Financial Systems.
39  *
40  * TRW Financial Systems, in accordance with their agreement with Carnegie
41  * Mellon University, makes this software available to CMU to distribute
42  * or use in any manner that they see fit as long as this message is kept with
43  * the software. For this reason TFS also grants any other persons or
44  * organisations permission to use or modify this software.
45  *
46  * TFS supplies this software to be publicly redistributed
47  * on the understanding that TFS is not responsible for the correct
48  * functioning of this software in any circumstances.
49  *
50  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
51  */
52 
53 /*
54  * SCSI command format
55  */
56 
57 #ifndef	_SCSI_SCSI_DISK_H
58 #define _SCSI_SCSI_DISK_H
59 
60 /*
61  * XXX Is this also used by ATAPI?
62  */
63 #define	FORMAT_UNIT		0x04
64 struct scsi_format_unit {
65 	u_int8_t opcode;
66 	u_int8_t flags;
67 #define	SFU_DLF_MASK	0x07
68 #define	SFU_CMPLST	0x08
69 #define	SFU_FMTDATA	0x10
70 	u_int8_t vendor_specific;
71 	u_int8_t interleave[2];
72 	u_int8_t control;
73 };
74 
75 /*
76  * If the FmtData bit is set, a FORMAT UNIT parameter list is transferred
77  * to the target during the DATA OUT phase.  The parameter list includes
78  *
79  *	Defect list header
80  *	Initialization pattern descriptor (if any)
81  *	Defect descriptor(s) (if any)
82  */
83 
84 struct scsi_format_unit_defect_list_header {
85 	u_int8_t reserved;
86 	u_int8_t flags;
87 #define	DLH_VS		0x01		/* vendor specific */
88 #define	DLH_IMMED	0x02		/* immediate return */
89 #define	DLH_DSP		0x04		/* disable saving parameters */
90 #define	DLH_IP		0x08		/* initialization pattern */
91 #define	DLH_STPF	0x10		/* stop format */
92 #define	DLH_DCRT	0x20		/* disable certification */
93 #define	DLH_DPRY	0x40		/* disable primary */
94 #define	DLH_FOV		0x80		/* format options valid */
95 	u_int8_t defect_lst_len[2];
96 };
97 
98 /*
99  * See Table 117 of the SCSI-2 specification for a description of
100  * the IP modifier.
101  */
102 struct scsi_initialization_pattern_descriptor {
103 	u_int8_t ip_modifier;
104 	u_int8_t pattern_type;
105 #define	IP_TYPE_DEFAULT		0x01
106 #define	IP_TYPE_REPEAT		0x01
107 				/* 0x02 -> 0x7f: reserved */
108 				/* 0x80 -> 0xff: vendor-specific */
109 	u_int8_t pattern_length[2];
110 #if 0
111 	u_int8_t pattern[...];
112 #endif /* 0 */
113 };
114 
115 /*
116  * Defect descriptors.  These are used as the defect lists in the FORMAT UNIT
117  * and READ DEFECT DATA commands, and as the translate page of the
118  * SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS commands.
119  */
120 
121 /* Block format */
122 struct scsi_defect_descriptor_bf {
123 	u_int8_t block_address[4];
124 };
125 
126 /* Bytes from index format */
127 struct scsi_defect_descriptor_bfif {
128 	u_int8_t cylinder[2];
129 	u_int8_t head;
130 	u_int8_t bytes_from_index[2];
131 };
132 
133 /* Physical sector format */
134 struct scsi_defect_descriptor_psf {
135 	u_int8_t cylinder[2];
136 	u_int8_t head;
137 	u_int8_t sector[2];
138 };
139 
140 
141 struct scsi_reassign_blocks {
142 	u_int8_t opcode;
143 	u_int8_t byte2;
144 	u_int8_t unused[3];
145 	u_int8_t control;
146 };
147 
148 /*
149  * XXX Is this also used by ATAPI?
150  */
151 #define	REZERO_UNIT		0x01
152 struct scsi_rezero_unit {
153 	u_int8_t opcode;
154 	u_int8_t byte2;
155 	u_int8_t reserved[3];
156 	u_int8_t control;
157 };
158 
159 struct scsi_rw {
160 	u_int8_t opcode;
161 	u_int8_t addr[3];
162 #define	SRW_TOPADDR	0x1F	/* only 5 bits here */
163 	u_int8_t length;
164 	u_int8_t control;
165 };
166 
167 struct scsi_rw_10 {
168 	u_int8_t opcode;
169 	u_int8_t byte2;
170 #define	SRWB_RELADDR	0x01
171 	u_int8_t addr[4];
172 	u_int8_t reserved;
173 	u_int8_t length[2];
174 	u_int8_t control;
175 };
176 
177 struct scsi_rw_12 {
178 	u_int8_t opcode;
179 	u_int8_t byte2;
180 	u_int8_t addr[4];
181 	u_int8_t length[4];
182 	u_int8_t reserved;
183 	u_int8_t control;
184 };
185 
186 struct scsi_rw_16 {
187 	u_int8_t opcode;
188 	u_int8_t byte2;
189 	u_int8_t addr[8];
190 	u_int8_t length[4];
191 	u_int8_t reserved;
192 	u_int8_t control;
193 };
194 
195 struct scsi_write_same_10 {
196 	u_int8_t opcode;
197 	u_int8_t flags;
198 #define WRITE_SAME_F_LBDATA	(1 << 1)
199 #define WRITE_SAME_F_PBDATA	(1 << 2)
200 	u_int8_t lba[4];
201 	u_int8_t group_number;
202 	u_int8_t length[2];
203 	u_int8_t control;
204 };
205 
206 struct scsi_write_same_16 {
207 	u_int8_t opcode;
208 	u_int8_t flags;
209 /* includes WRITE SAME 10 flags */
210 #define WRITE_SAME_F_UNMAP	(1 << 3)
211 #define WRITE_SAME_F_ANCHOR	(1 << 4)
212 	u_int8_t lba[8];
213 	u_int8_t length[4];
214 	u_int8_t group_number;
215 	u_int8_t control;
216 };
217 
218 struct scsi_unmap {
219 	u_int8_t opcode;
220 	u_int8_t anchor;
221 	u_int8_t _reserved[4];
222 	u_int8_t group_number;
223 	u_int8_t list_len[2];
224 	u_int8_t control;
225 };
226 
227 struct scsi_unmap_data {
228 	u_int8_t data_length[2];
229 	u_int8_t desc_length[2];
230 	u_int8_t _reserved[4];
231 
232 	/* followed by struct scsi_unmap_desc */
233 };
234 
235 struct scsi_unmap_desc {
236 	u_int8_t logical_addr[8];
237 	u_int8_t logical_blocks[4];
238 	u_int8_t _reserved[4];
239 };
240 
241 struct scsi_read_capacity {
242 	u_int8_t opcode;
243 	u_int8_t byte2;
244 	u_int8_t addr[4];
245 	u_int8_t unused[3];
246 	u_int8_t control;
247 };
248 
249 struct scsi_read_capacity_16 {
250 	u_int8_t opcode;
251 	u_int8_t byte2;
252 #define	SRC16_SERVICE_ACTION	0x10
253 	u_int8_t addr[8];
254 	u_int8_t length[4];
255 	u_int8_t reserved;
256 	u_int8_t control;
257 };
258 
259 struct scsi_start_stop {
260 	u_int8_t opcode;
261 	u_int8_t byte2;
262 	u_int8_t unused[2];
263 	u_int8_t how;
264 #define	SSS_STOP		0x00
265 #define	SSS_START		0x01
266 #define	SSS_LOEJ		0x02
267 	u_int8_t control;
268 };
269 
270 
271 /*
272  * XXX Does ATAPI have an equivalent?
273  */
274 struct scsi_synchronize_cache {
275 	u_int8_t opcode;
276 	u_int8_t flags;
277 #define	SSC_RELADR	0x01
278 #define	SSC_IMMED	0x02
279 	u_int8_t addr[4];
280 	u_int8_t reserved;
281 	u_int8_t length[2];
282 	u_int8_t control;
283 };
284 
285 
286 
287 /*
288  * Disk specific opcodes
289  */
290 #define REASSIGN_BLOCKS		0x07
291 #define READ_COMMAND		0x08
292 #define WRITE_COMMAND		0x0a
293 #define READ_CAPACITY		0x25
294 #define READ_CAPACITY_16	0x9e
295 #define READ_10			0x28
296 #define WRITE_10		0x2a
297 #define READ_12			0xa8
298 #define WRITE_12		0xaa
299 #define READ_16			0x88
300 #define WRITE_16		0x8a
301 #define SYNCHRONIZE_CACHE	0x35
302 #define WRITE_SAME_10		0x41
303 #define WRITE_SAME_16		0x93
304 #define UNMAP			0x42
305 
306 
307 struct scsi_reassign_blocks_data {
308 	u_int8_t reserved[2];
309 	u_int8_t length[2];
310 	struct {
311 		u_int8_t dlbaddr[4];
312 	} defect_descriptor[1];
313 };
314 
315 /* Only the lower 6 bits of the pg_code field are used for page #. */
316 #define PAGE_DISK_FORMAT	3
317 #define PAGE_RIGID_GEOMETRY	4
318 #define PAGE_FLEX_GEOMETRY	5
319 #define PAGE_REDUCED_GEOMETRY	6
320 #define PAGE_CACHING_MODE	8
321 
322 struct page_disk_format {
323 	u_int8_t pg_code;	/* page code (should be 3) */
324 	u_int8_t pg_length;	/* page length (should be 0x16) */
325 	u_int8_t trk_z[2];	/* tracks per zone */
326 	u_int8_t alt_sec[2];	/* alternate sectors per zone */
327 	u_int8_t alt_trk_z[2];	/* alternate tracks per zone */
328 	u_int8_t alt_trk_v[2];	/* alternate tracks per volume */
329 	u_int8_t ph_sec_t[2];	/* physical sectors per track */
330 	u_int8_t bytes_s[2];	/* bytes per sector */
331 	u_int8_t interleave[2];	/* interleave */
332 	u_int8_t trk_skew[2];	/* track skew factor */
333 	u_int8_t cyl_skew[2];	/* cylinder skew */
334 	u_int8_t flags;		/* various */
335 #define	DISK_FMT_SURF	0x10
336 #define	DISK_FMT_RMB	0x20
337 #define	DISK_FMT_HSEC	0x40
338 #define	DISK_FMT_SSEC	0x80
339 	u_int8_t reserved1;
340 	u_int8_t reserved2;
341 	u_int8_t reserved3;
342 };
343 
344 struct page_rigid_geometry {
345 	u_int8_t pg_code;	/* page code (should be 4) */
346 	u_int8_t pg_length;	/* page length (should be 0x12 or 0x16)	*/
347 	u_int8_t ncyl[3];	/* number of cylinders */
348 	u_int8_t nheads;	/* number of heads */
349 	u_int8_t st_cyl_wp[3];	/* starting cyl., write precomp */
350 	u_int8_t st_cyl_rwc[3];	/* starting cyl., red. write cur */
351 	u_int8_t driv_step[2];	/* drive step rate */
352 	u_int8_t land_zone[3];	/* landing zone cylinder */
353 	u_int8_t sp_sync_ctl;	/* spindle synch control */
354 #define SPINDLE_SYNCH_MASK	0x03	/* mask of valid bits */
355 #define SPINDLE_SYNCH_NONE	0x00	/* synch disabled or not supported */
356 #define SPINDLE_SYNCH_SLAVE	0x01	/* disk is a slave */
357 #define SPINDLE_SYNCH_MASTER	0x02	/* disk is a master */
358 #define SPINDLE_SYNCH_MCONTROL	0x03	/* disk is a master control */
359 	u_int8_t rot_offset;	/* rotational offset (for spindle synch) */
360 	u_int8_t reserved1;
361 	u_int8_t rpm[2];	/* media rotation speed */
362 	u_int8_t reserved2;
363 	u_int8_t reserved3;
364 };
365 
366 struct page_flex_geometry {
367 	u_int8_t pg_code;	/* page code (should be 5) */
368 	u_int8_t pg_length;	/* page length (should be 0x1a or 0x1e) */
369 	u_int8_t xfr_rate[2];
370 	u_int8_t nheads;	/* number of heads */
371 	u_int8_t ph_sec_tr;	/* physical sectors per track */
372 	u_int8_t bytes_s[2];	/* bytes per sector */
373 	u_int8_t ncyl[2];	/* number of cylinders */
374 	u_int8_t st_cyl_wp[2];	/* start cyl., write precomp */
375 	u_int8_t st_cyl_rwc[2];	/* start cyl., red. write cur */
376 	u_int8_t driv_step[2];	/* drive step rate */
377 	u_int8_t driv_step_w;	/* drive step pulse width */
378 	u_int8_t head_settle[2];/* head settle delay */
379 	u_int8_t motor_on;	/* motor on delay */
380 	u_int8_t motor_off;	/* motor off delay */
381 	u_int8_t flags;		/* various flags */
382 #define MOTOR_ON		0x20	/* motor on (pin 16)? */
383 #define START_AT_SECTOR_1	0x40	/* start at sector 1  */
384 #define READY_VALID		0x20	/* RDY (pin 34) valid */
385 	u_int8_t step_p_cyl;	/* step pulses per cylinder */
386 	u_int8_t write_pre;	/* write precompensation */
387 	u_int8_t head_load;	/* head load delay */
388 	u_int8_t head_unload;	/* head unload delay */
389 	u_int8_t pin_34_2;	/* pin 34 (6) pin 2 (7/11) definition */
390 	u_int8_t pin_4_1;	/* pin 4 (8/9) pin 1 (13) definition */
391 	u_int8_t rpm[2];	/* media rotation speed */
392 	u_int8_t reserved1;
393 	u_int8_t reserved2;
394 };
395 
396 struct page_reduced_geometry {
397 	u_int8_t pg_code;	/* page code (should be 6) */
398 	u_int8_t pg_length;	/* page length (should be 0x0B) */
399 	u_int8_t wcd;		/* bit 0 = write cache disable */
400 	u_int8_t bytes_s[2];	/* bytes per sector */
401 	u_int8_t sectors[5];	/* total number of sectors */
402 	u_int8_t pow_perf;	/* power/performance level */
403 	u_int8_t flags;		/* various */
404 #define	LOCK_DISABLED	0x1
405 #define	FORMAT_DISABLED	0x2
406 #define	WRITE_DISABLED	0x4
407 #define	READ_DISABLED	0x8
408 	u_int8_t reserved;
409 };
410 
411 struct page_caching_mode {
412 	u_int8_t pg_code;	/* page code (should be 8) */
413 	u_int8_t pg_length;	/* page length (should be 0x12) */
414 	u_int8_t flags;
415 #define PG_CACHE_FL_RCD		(1<<0)
416 #define PG_CACHE_FL_MF		(1<<1)
417 #define PG_CACHE_FL_WCE		(1<<2)
418 #define PG_CACHE_FL_SIZE	(1<<3)
419 #define PG_CACHE_FL_DISC	(1<<4)
420 #define PG_CACHE_FL_CAP		(1<<5)
421 #define PG_CACHE_FL_ABPF	(1<<6)
422 #define PG_CACHE_FL_IC		(1<<7)
423 	u_int8_t priority;
424 #define PG_CACHE_PRI_DEMAND(_f)		((_f) & 0x0f)
425 #define PG_CACHE_PRI_WRITE(_f)		(((_f) >> 4) & 0x0f)
426 	u_int8_t dis_prefetch_tl[2];
427 	u_int8_t min_prefetch[2];
428 	u_int8_t max_prefetch[2];
429 	u_int8_t max_prefetch_ceil[2];
430 };
431 
432 #define SI_PG_DISK_LIMITS	0xb0 /* block limits */
433 #define SI_PG_DISK_INFO		0xb1 /* device characteristics */
434 #define SI_PG_DISK_THIN		0xb2 /* thin provisioning */
435 
436 struct scsi_vpd_disk_limits {
437 	struct scsi_vpd_hdr hdr;
438 #define SI_PG_DISK_LIMITS_LEN		0x10
439 #define SI_PG_DISK_LIMITS_LEN_THIN	0x3c
440 
441 	u_int8_t		_reserved1[1];
442 	u_int8_t		max_comp_wr_len;
443 	u_int8_t		optimal_xfer_granularity[2];
444 
445 	u_int8_t		max_xfer_len[4];
446 
447 	u_int8_t		optimal_xfer[4];
448 
449 	u_int8_t		max_xd_prefetch_len[4];
450 
451 	u_int8_t		max_unmap_lba_count[4];
452 
453 	u_int8_t		max_unmap_desc_count[4];
454 
455 	u_int8_t		optimal_unmap_granularity[4];
456 
457 	u_int8_t		unmap_granularity_align[4];
458 #define SI_PG_DISK_LIMITS_UGAVALID	(1U << 31)
459 
460 	u_int8_t		_reserved2[28];
461 };
462 
463 struct scsi_vpd_disk_info {
464 	struct scsi_vpd_hdr	hdr;
465 	u_int8_t		rpm[2];
466 #define VPD_DISK_INFO_RPM_UNDEF		0x0000
467 #define VPD_DISK_INFO_RPM_NONE		0x0001
468 	u_int8_t		_reserved1[1];
469 	u_int8_t		form_factor;
470 #define VPD_DISK_INFO_FORM_MASK		0xf
471 #define VPD_DISK_INFO_FORM_UNDEF	0x0
472 #define VPD_DISK_INFO_FORM_5_25		0x1
473 #define VPD_DISK_INFO_FORM_3_5		0x2
474 #define VPD_DISK_INFO_FORM_2_5		0x3
475 #define VPD_DISK_INFO_FORM_1_8		0x4
476 #define VPD_DISK_INFO_FORM_LT_1_8	0x5
477 	u_int8_t		_reserved2[56];
478 };
479 
480 struct scsi_vpd_disk_thin {
481 	struct scsi_vpd_hdr	hdr;
482 
483 	u_int8_t		threshold_exponent;
484 	u_int8_t		flags;
485 #define VPD_DISK_THIN_DP		(1 << 0) /* descriptor present */
486 #define VPD_DISK_THIN_ANC_SUP		(0x7 << 1)
487 #define VPD_DISK_THIN_ANC_SUP_NO	(0x0 << 1)
488 #define VPD_DISK_THIN_ANC_SUP_YES	(0x1 << 1)
489 #define VPD_DISK_THIN_TPWS		(1 << 6) /* WRITE SAME 16 */
490 #define VPD_DISK_THIN_TPU		(1 << 7) /* UNMAP */
491 	u_int8_t		_reserved1[2];
492 
493 	/* followed by a designation descriptor if DP is set */
494 };
495 
496 #endif /* _SCSI_SCSI_DISK_H */
497