10d59a3d2SAxel Dörfler/*
293c0a5d7SAxel Dörfler * Copyright 2004-2015, Haiku, Inc. All RightsReserved.
36be1e37dSAxel Dörfler * Copyright 2002/03, Thomas Kurschel. All rights reserved.
46be1e37dSAxel Dörfler *
56be1e37dSAxel Dörfler * Distributed under the terms of the MIT License.
66be1e37dSAxel Dörfler */
76be1e37dSAxel Dörfler#ifndef _SCSI_CMDS_H
86be1e37dSAxel Dörfler#define _SCSI_CMDS_H
90d59a3d2SAxel Dörfler
100a96e186SAxel Dörfler
110a96e186SAxel Dörfler//! SCSI commands and their data structures and constants
120d59a3d2SAxel Dörfler
130d59a3d2SAxel Dörfler
140d59a3d2SAxel Dörfler#include <lendian_bitfield.h>
150d59a3d2SAxel Dörfler
166be1e37dSAxel Dörfler
170a96e186SAxel Dörfler// Always keep in mind that SCSI is big-endian!
180d59a3d2SAxel Dörfler
190d59a3d2SAxel Dörfler#define SCSI_STD_TIMEOUT 10
200d59a3d2SAxel Dörfler
210d59a3d2SAxel Dörfler// SCSI device status (as the result of a command)
220a96e186SAxel Dörfler#define SCSI_STATUS_GOOD					(0 << 1)
230a96e186SAxel Dörfler#define SCSI_STATUS_CHECK_CONDITION			(1 << 1)	// error occured
240a96e186SAxel Dörfler#define SCSI_STATUS_CONDITION_MET			(2 << 1)
250a96e186SAxel Dörfler	// "found" for SEARCH DATA and PREFETCH
260a96e186SAxel Dörfler#define SCSI_STATUS_BUSY					(4 << 1)
270a96e186SAxel Dörfler	// try again later (??? == QUEUE_FULL ???)
280a96e186SAxel Dörfler#define SCSI_STATUS_INTERMEDIATE			(8 << 1)
290a96e186SAxel Dörfler	// used by linked command only
300a96e186SAxel Dörfler#define SCSI_STATUS_INTERMEDIATE_COND_MET	(10 << 1)	// ditto
310a96e186SAxel Dörfler#define SCSI_STATUS_RESERVATION_CONFLICT	(12 << 1)
320a96e186SAxel Dörfler	// only if RESERVE/RELEASE is used
330a96e186SAxel Dörfler#define SCSI_STATUS_COMMAND_TERMINATED		(17 << 1)
340a96e186SAxel Dörfler	// aborted by TERMINATE I/O PROCESS
350a96e186SAxel Dörfler#define SCSI_STATUS_QUEUE_FULL				(20 << 1)	// queue full
360d59a3d2SAxel Dörfler
370d59a3d2SAxel Dörfler#define SCSI_STATUS_MASK 0xfe
380d59a3d2SAxel Dörfler
390d59a3d2SAxel Dörfler// SCSI sense key
400a96e186SAxel Dörfler#define SCSIS_KEY_NO_SENSE					0
410a96e186SAxel Dörfler#define SCSIS_KEY_RECOVERED_ERROR			1
420a96e186SAxel Dörfler#define SCSIS_KEY_NOT_READY					2
430a96e186SAxel Dörfler	// operator intervention may be required
440a96e186SAxel Dörfler#define SCSIS_KEY_MEDIUM_ERROR				3
450a96e186SAxel Dörfler	// can be set if source could be hardware error
460a96e186SAxel Dörfler#define SCSIS_KEY_HARDWARE_ERROR			4
470a96e186SAxel Dörfler#define SCSIS_KEY_ILLEGAL_REQUEST			5	// invalid command
480a96e186SAxel Dörfler#define SCSIS_KEY_UNIT_ATTENTION			6
490a96e186SAxel Dörfler	// medium changed or target reset
500a96e186SAxel Dörfler#define SCSIS_KEY_DATA_PROTECT				7	// data access forbidden
510a96e186SAxel Dörfler#define SCSIS_KEY_BLANK_CHECK				8
520a96e186SAxel Dörfler	// tried to read blank or to write non-blank medium
530a96e186SAxel Dörfler#define SCSIS_KEY_VENDOR_SPECIFIC			9
540a96e186SAxel Dörfler#define SCSIS_KEY_COPY_ABORTED				10
550a96e186SAxel Dörfler	// error in COPY or COMPARE command
560a96e186SAxel Dörfler#define SCSIS_KEY_ABORTED_COMMAND			11
570a96e186SAxel Dörfler	// aborted by target, retry *may* help
580a96e186SAxel Dörfler#define SCSIS_KEY_EQUAL						12	// during SEARCH: data found
590a96e186SAxel Dörfler#define SCSIS_KEY_VOLUME_OVERFLOW			13
600a96e186SAxel Dörfler	// tried to write buffered data beyond end of medium
610a96e186SAxel Dörfler#define SCSIS_KEY_MISCOMPARE				14
620a96e186SAxel Dörfler#define SCSIS_KEY_RESERVED					15
630d59a3d2SAxel Dörfler
640d59a3d2SAxel Dörfler// SCSI ASC and ASCQ data - (ASC << 8) | ASCQ
650d59a3d2SAxel Dörfler// all codes with bit 7 of ASC or ASCQ set are vendor-specific
660a96e186SAxel Dörfler#define SCSIS_ASC_NO_SENSE					0x0000
670a96e186SAxel Dörfler#define SCSIS_ASC_IO_PROC_TERMINATED		0x0006
680a96e186SAxel Dörfler#define SCSIS_ASC_AUDIO_PLAYING				0x0011
690a96e186SAxel Dörfler#define SCSIS_ASC_AUDIO_PAUSED				0x0012
700a96e186SAxel Dörfler#define SCSIS_ASC_AUDIO_COMPLETED			0x0013
710a96e186SAxel Dörfler#define SCSIS_ASC_AUDIO_ERROR				0x0014
720a96e186SAxel Dörfler	// playing has stopped due to error
730a96e186SAxel Dörfler#define SCSIS_ASC_AUDIO_NO_STATUS			0x0015
740a96e186SAxel Dörfler#define SCSIS_ASC_NO_INDEX					0x0100	// no index/sector signal
750a96e186SAxel Dörfler#define SCSIS_ASC_NO_SEEK_CMP				0x0200	// ???
760a96e186SAxel Dörfler#define SCSIS_ASC_WRITE_FAULT				0x0300
770a96e186SAxel Dörfler#define SCSIS_ASC_LUN_NOT_READY				0x0400
780a96e186SAxel Dörfler	// LUN not ready, cause not reportable
790a96e186SAxel Dörfler#define SCSIS_ASC_LUN_BECOMING_READY		0x0401
800a96e186SAxel Dörfler	// LUN in progress of becoming ready
810a96e186SAxel Dörfler#define SCSIS_ASC_LUN_NEED_INIT				0x0402
820a96e186SAxel Dörfler	// LUN need initializing command
830a96e186SAxel Dörfler#define SCSIS_ASC_LUN_NEED_MANUAL_HELP		0x0403
840a96e186SAxel Dörfler	// LUN needs manual intervention
850a96e186SAxel Dörfler#define SCSIS_ASC_LUN_FORMATTING			0x0404
860a96e186SAxel Dörfler	// LUN format in progress
870a96e186SAxel Dörfler#define SCSIS_ASC_LUN_SEL_FAILED			0x0500
880a96e186SAxel Dörfler	// LUN doesn't respond to selection
890a96e186SAxel Dörfler#define SCSIS_ASC_LUN_COM_FAILURE			0x0800	// LUN communication failure
900a96e186SAxel Dörfler#define SCSIS_ASC_LUN_TIMEOUT				0x0801
910a96e186SAxel Dörfler	// LUN communication time-out
920a96e186SAxel Dörfler#define SCSIS_ASC_LUN_COM_PARITY			0x0802
930a96e186SAxel Dörfler	// LUN communication parity failure
940a96e186SAxel Dörfler#define SCSIS_ASC_LUN_COM_CRC				0x0803
950a96e186SAxel Dörfler	// LUN communication CRC failure (SCSI-3)
960a96e186SAxel Dörfler#define SCSIS_ASC_WRITE_ERR_AUTOREALLOC		0x0c01
970a96e186SAxel Dörfler	// recovered by auto-reallocation
980d59a3d2SAxel Dörfler#define SCSIS_ASC_WRITE_ERR_AUTOREALLOC_FAILED 0x0c02
990a96e186SAxel Dörfler#define SCSIS_ASC_ECC_ERROR					0x1000
1000a96e186SAxel Dörfler#define SCSIS_ASC_UNREC_READ_ERR			0x1100	// unrecovered read error
1010a96e186SAxel Dörfler#define SCSIS_ASC_READ_RETRIES_EXH			0x1101	// read retries exhausted
1020a96e186SAxel Dörfler#define SCSIS_ASC_UNREC_READ_ERR_AUTOREALLOC_FAILED 0x1104
1030a96e186SAxel Dörfler	// above + auto-reallocate failed
1040a96e186SAxel Dörfler#define SCSIS_ASC_RECORD_NOT_FOUND			0x1401
1050a96e186SAxel Dörfler#define SCSIS_ASC_RANDOM_POS_ERROR			0x1500	// random positioning error
1060a96e186SAxel Dörfler#define SCSIS_ASC_POSITIONING_ERR			0x1501
1070a96e186SAxel Dörfler	// mechanical positioning error
1080a96e186SAxel Dörfler#define SCSIS_ASC_POS_ERR_ON_READ			0x1502
1090a96e186SAxel Dörfler	// positioning error detected by reading
1100a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_NO_ERR_CORR	0x1700
1110a96e186SAxel Dörfler	// recovered with no error correction applied
1120a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_WITH_RETRIES	0x1701
1130a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_POS_HEAD_OFS	0x1702
1140a96e186SAxel Dörfler	// ?recovered with positive head offset
1150a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_NEG_HEAD_OFS	0x1703
1160a96e186SAxel Dörfler	// ?recovered with negative head offset
1170a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_WITH_RETRIES_CIRC 0x1704
1180a96e186SAxel Dörfler	// recovered with retries/CIRC
1190a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_PREV_SECT_ID	0x1705
1200a96e186SAxel Dörfler	// recovered using previous sector ID
1210d59a3d2SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_NO_ECC_AUTOREALLOC 0x1706
1220d59a3d2SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_NO_ECC_REASSIGN 0x1707 // reassign recommended
1230a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_NO_ECC_REWRITE	0x1708	// rewrite recommended
1240a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_WITH_CORR		0x1800
1250a96e186SAxel Dörfler	// recovered using error correction
1260a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_WITH_CORR_RETRIES 0x1801
1270a96e186SAxel Dörfler	// used error correction and retries
1280a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_AUTOREALLOC	0x1802
1290a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_CIRC			0x1803	// recovered using CIRC
1300a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_LEC			0x1804	// recovered using LEC
1310a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_REASSIGN		0x1805	// reassign recommended
1320a96e186SAxel Dörfler#define SCSIS_ASC_DATA_RECOV_REWRITE		0x1806	// rewrite recommended
1330a96e186SAxel Dörfler#define SCSIS_ASC_PARAM_LIST_LENGTH_ERR		0x1a00	// parameter list too short
1340a96e186SAxel Dörfler#define SCSIS_ASC_ID_RECOV					0x1e00	// recoved ID with ECC
1350a96e186SAxel Dörfler#define SCSIS_ASC_INV_OPCODE				0x2000
1360a96e186SAxel Dörfler#define SCSIS_ASC_LBA_OOR					0x2100	// LBA out of range
1370a96e186SAxel Dörfler#define SCSIS_ASC_ILL_FUNCTION				0x2200
1380a96e186SAxel Dörfler	// better use 0x2000/0x2400/0x2600 instead
1390a96e186SAxel Dörfler#define SCSIS_ASC_INV_CDB_FIELD				0x2400
1400a96e186SAxel Dörfler#define SCSIS_ASC_LUN_NOT_SUPPORTED			0x2500
1410a96e186SAxel Dörfler#define SCSIS_ASC_INV_PARAM_LIST_FIELD		0x2600
1420a96e186SAxel Dörfler#define SCSIS_ASC_PARAM_NOT_SUPPORTED		0x2601
1430a96e186SAxel Dörfler#define SCSIS_ASC_PARAM_VALUE_INV			0x2602
1440a96e186SAxel Dörfler#define SCSIS_ASC_WRITE_PROTECTED			0x2700
1450a96e186SAxel Dörfler#define SCSIS_ASC_MEDIUM_CHANGED			0x2800
1460a96e186SAxel Dörfler#define SCSIS_ASC_WAS_RESET					0x2900
1470a96e186SAxel Dörfler	// reset by power-on/bus reset/device reset
1480a96e186SAxel Dörfler#define SCSIS_ASC_PARAMS_CHANGED			0x2a00
149ea2fa872SJérôme Duval#define SCSIS_ASC_CAPACITY_DATA_HAS_CHANGED	0x2a09
1500a96e186SAxel Dörfler#define SCSIS_ASC_MEDIUM_FORMAT_CORRUPTED	0x3100
1510a96e186SAxel Dörfler#define SCSIS_ASC_ROUNDED_PARAM				0x3700	// parameter got rounded
1520a96e186SAxel Dörfler#define SCSIS_ASC_NO_MEDIUM					0x3a00	// medium not present
1530a96e186SAxel Dörfler#define SCSIS_ASC_INTERNAL_FAILURE			0x4400
1540a96e186SAxel Dörfler#define SCSIS_ASC_SEL_FAILURE				0x4500	// select/reselect failure
1550a96e186SAxel Dörfler#define SCSIS_ASC_UNSUCC_SOFT_RESET			0x4600	// unsuccessful soft reset
1560a96e186SAxel Dörfler#define SCSIS_ASC_SCSI_PARITY_ERR			0x4700	// SCSI parity error
1570a96e186SAxel Dörfler#define SCSIS_ASC_LOAD_EJECT_FAILED			0x5300
1580a96e186SAxel Dörfler	// media load or eject failed
1590a96e186SAxel Dörfler#define SCSIS_ASC_REMOVAL_PREVENTED			0x5302	// medium removal prevented
1600a96e186SAxel Dörfler#define SCSIS_ASC_REMOVAL_REQUESTED			0x5a01
1610a96e186SAxel Dörfler	// operator requests medium removal
1620d59a3d2SAxel Dörfler
1630d59a3d2SAxel Dörfler// some scsi op-codes
1644264efccSJérôme Duval#define SCSI_OP_TEST_UNIT_READY				0x00
1650a96e186SAxel Dörfler#define SCSI_OP_REQUEST_SENSE				0x03
1660a96e186SAxel Dörfler#define SCSI_OP_FORMAT						0x04
1674264efccSJérôme Duval#define SCSI_OP_READ_6						0x08
1680a96e186SAxel Dörfler#define SCSI_OP_WRITE_6						0x0a
1690a96e186SAxel Dörfler#define SCSI_OP_INQUIRY						0x12
170f0588869SJérôme Duval#define SCSI_OP_VERIFY_6					0x13
1710a96e186SAxel Dörfler#define SCSI_OP_MODE_SELECT_6				0x15
1720a96e186SAxel Dörfler#define SCSI_OP_RESERVE						0x16
1730a96e186SAxel Dörfler#define SCSI_OP_RELEASE						0x17
1740a96e186SAxel Dörfler#define SCSI_OP_MODE_SENSE_6				0x1a
1750a96e186SAxel Dörfler#define SCSI_OP_START_STOP					0x1b
1764264efccSJérôme Duval#define SCSI_OP_RECEIVE_DIAGNOSTIC			0x1c
1774264efccSJérôme Duval#define SCSI_OP_SEND_DIAGNOSTIC				0x1d
1780a96e186SAxel Dörfler#define SCSI_OP_PREVENT_ALLOW				0x1e
1794264efccSJérôme Duval#define SCSI_OP_READ_CAPACITY				0x25
1804264efccSJérôme Duval#define SCSI_OP_READ_10						0x28
1810a96e186SAxel Dörfler#define SCSI_OP_WRITE_10					0x2a
1820a96e186SAxel Dörfler#define SCSI_OP_POSITION_TO_ELEMENT			0x2b
183f0588869SJérôme Duval#define SCSI_OP_VERIFY_10					0x2f
1844264efccSJérôme Duval#define SCSI_OP_SYNCHRONIZE_CACHE			0x35
1854264efccSJérôme Duval#define SCSI_OP_WRITE_BUFFER				0x3b
1864264efccSJérôme Duval#define SCSI_OP_READ_BUFFER					0x3c
1874264efccSJérôme Duval#define SCSI_OP_CHANGE_DEFINITION			0x40
18899086aa3SAxel Dörfler#define SCSI_OP_WRITE_SAME_10				0x41
18999086aa3SAxel Dörfler#define SCSI_OP_UNMAP						0x42
1900a96e186SAxel Dörfler#define SCSI_OP_READ_SUB_CHANNEL			0x42
1910a96e186SAxel Dörfler#define SCSI_OP_READ_TOC					0x43
1920a96e186SAxel Dörfler#define SCSI_OP_PLAY_MSF					0x47
1930a96e186SAxel Dörfler#define SCSI_OP_PLAY_AUDIO_TRACK_INDEX		0x48	// obsolete, spec missing
1940a96e186SAxel Dörfler#define SCSI_OP_PAUSE_RESUME				0x4b
1950a96e186SAxel Dörfler#define SCSI_OP_STOP_PLAY					0x4e
1964264efccSJérôme Duval#define SCSI_OP_MODE_SELECT_10				0x55
1974264efccSJérôme Duval#define SCSI_OP_MODE_SENSE_10				0x5a
1984264efccSJérôme Duval#define SCSI_OP_VARIABLE_LENGTH_CDB			0x7f
1990a96e186SAxel Dörfler#define SCSI_OP_READ_16						0x88
2000a96e186SAxel Dörfler#define SCSI_OP_WRITE_16					0x8a
201f0588869SJérôme Duval#define SCSI_OP_VERIFY_16					0x8f
20237286363SAlexander von Gluck IV#define SCSI_OP_WRITE_SAME_16				0x93
2030a96e186SAxel Dörfler#define SCSI_OP_SERVICE_ACTION_IN			0x9e
2040a96e186SAxel Dörfler#define SCSI_OP_SERVICE_ACTION_OUT			0x9f
2050a96e186SAxel Dörfler#define SCSI_OP_MOVE_MEDIUM					0xa5
2060a96e186SAxel Dörfler#define SCSI_OP_READ_12						0xa8
2070a96e186SAxel Dörfler#define SCSI_OP_WRITE_12					0xaa
208f0588869SJérôme Duval#define SCSI_OP_VERIFY_12					0xaf
2090a96e186SAxel Dörfler#define SCSI_OP_READ_ELEMENT_STATUS			0xb8
2100a96e186SAxel Dörfler#define SCSI_OP_SCAN						0xba
2110a96e186SAxel Dörfler#define SCSI_OP_READ_CD						0xbe
2120a96e186SAxel Dörfler
2130a96e186SAxel Dörfler// Service-Action-In defines
2140a96e186SAxel Dörfler#define SCSI_SAI_READ_CAPACITY_16			0x10
2154264efccSJérôme Duval#define SCSI_SAI_READ_LONG					0x11
2164264efccSJérôme Duval
2174264efccSJérôme Duval// Service-Action-Out defines
2184264efccSJérôme Duval#define SCSI_SAO_WRITE_LONG					0x11
2190a96e186SAxel Dörfler
2200d59a3d2SAxel Dörfler
2210d59a3d2SAxel Dörfler// INQUIRY
2220d59a3d2SAxel Dörfler
2230d59a3d2SAxel Dörflertypedef struct scsi_cmd_inquiry {
2246be1e37dSAxel Dörfler	uint8	opcode;
22593c0a5d7SAxel Dörfler	B_LBITFIELD8_3(
2266be1e37dSAxel Dörfler		evpd : 1,						// enhanced vital product data
2276be1e37dSAxel Dörfler		_res1_1 : 4,
2286be1e37dSAxel Dörfler		lun : 3
2290d59a3d2SAxel Dörfler	);
2306be1e37dSAxel Dörfler	uint8	page_code;
2316be1e37dSAxel Dörfler	uint8	_res3;
2326be1e37dSAxel Dörfler	uint8	allocation_length;
2336be1e37dSAxel Dörfler	uint8	control;
2346be1e37dSAxel Dörfler} _PACKED scsi_cmd_inquiry;
2350d59a3d2SAxel Dörfler
2360d59a3d2SAxel Dörflertypedef struct scsi_res_inquiry {
23793c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
2380d59a3d2SAxel Dörfler		device_type : 5,
2390d59a3d2SAxel Dörfler		device_qualifier : 3
2400d59a3d2SAxel Dörfler	);
24193c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
2426be1e37dSAxel Dörfler		device_type_modifier : 7,		// obsolete, normally set to zero
2436be1e37dSAxel Dörfler		removable_medium : 1
2440d59a3d2SAxel Dörfler	);
24593c0a5d7SAxel Dörfler	B_LBITFIELD8_3(						// 0 always means "not conforming"
2466be1e37dSAxel Dörfler		ansi_version : 3,				// 1 for SCSI-1, 2 for SCSI-2 etc.
2476be1e37dSAxel Dörfler		ecma_version : 3,
2486be1e37dSAxel Dörfler		iso_version : 2
2490d59a3d2SAxel Dörfler	);
25093c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
2516be1e37dSAxel Dörfler		response_data_format : 4,		// 2 = SCSI/2 compliant
2526be1e37dSAxel Dörfler		_res3_4 : 2,
2536be1e37dSAxel Dörfler		term_iop : 1,					// 1 = supports TERMINATE I/O PROCESS
2540a96e186SAxel Dörfler		async_enc : 1					// processor devices only :
2556be1e37dSAxel Dörfler										// Asynchronous Event Notification Capable
2566be1e37dSAxel Dörfler	);
2576be1e37dSAxel Dörfler	uint8	additional_length;			// total (whished) length = this + 4
2586be1e37dSAxel Dörfler	uint8	_res5;
2596be1e37dSAxel Dörfler	uint8	_res6;
26093c0a5d7SAxel Dörfler	B_LBITFIELD8_8(
2616be1e37dSAxel Dörfler		soft_reset : 1,					// 0 = soft reset leads to hard reset
2626be1e37dSAxel Dörfler		cmd_queue : 1,					// 1 = supports tagged command queuing
2636be1e37dSAxel Dörfler		_res7_2 : 1,
2646be1e37dSAxel Dörfler		linked : 1,						// 1 = supports linked commands
2656be1e37dSAxel Dörfler		sync : 1,						// 1 = supports synchronous transfers
2666be1e37dSAxel Dörfler		write_bus16 : 1,				// 1 = supports 16 bit transfers
2676be1e37dSAxel Dörfler		write_bus32 : 1,				// 1 = supports 32 bit transfers
2686be1e37dSAxel Dörfler		relative_address : 1			// 1 = supports relative addr. for linking
2696be1e37dSAxel Dörfler	);
2706be1e37dSAxel Dörfler	char	vendor_ident[8];
2716be1e37dSAxel Dörfler	char	product_ident[16];
2726be1e37dSAxel Dörfler	char	product_rev[4];
2736be1e37dSAxel Dörfler
2740d59a3d2SAxel Dörfler	// XPT doesn't return following data on XPT_GDEV_TYPE
2756be1e37dSAxel Dörfler	uint8	vendor_spec[20];
2766be1e37dSAxel Dörfler	uint8	_res56[2];
2776be1e37dSAxel Dörfler
2786be1e37dSAxel Dörfler	uint16	version_descriptor[8];		// array of supported standards, big endian
2796be1e37dSAxel Dörfler
2806be1e37dSAxel Dörfler	uint8	_res74[22];
2816be1e37dSAxel Dörfler	/* additional vendor specific data */
2826be1e37dSAxel Dörfler} _PACKED scsi_res_inquiry;
2830d59a3d2SAxel Dörfler
2846be1e37dSAxel Dörflerenum scsi_peripheral_qualifier {
2850d59a3d2SAxel Dörfler	scsi_periph_qual_connected = 0,
2860d59a3d2SAxel Dörfler	scsi_periph_qual_not_connected = 2,
2870d59a3d2SAxel Dörfler	scsi_periph_qual_not_connectable = 3
2880d59a3d2SAxel Dörfler	// value 1 is reserved, values of 4 and above are vendor-specific
2896be1e37dSAxel Dörfler};
2900d59a3d2SAxel Dörfler
2916be1e37dSAxel Dörflerenum scsi_device_type {
2920d59a3d2SAxel Dörfler	scsi_dev_direct_access = 0,
2930d59a3d2SAxel Dörfler	scsi_dev_sequential_access = 1,
2940d59a3d2SAxel Dörfler	scsi_dev_printer = 2,
2950d59a3d2SAxel Dörfler	scsi_dev_processor = 3,
2960d59a3d2SAxel Dörfler	scsi_dev_WORM = 4,
2970d59a3d2SAxel Dörfler	scsi_dev_CDROM = 5,
2980d59a3d2SAxel Dörfler	scsi_dev_scanner = 6,
2990d59a3d2SAxel Dörfler	scsi_dev_optical = 7,
3000d59a3d2SAxel Dörfler	scsi_dev_medium_changer = 8,
3010d59a3d2SAxel Dörfler	scsi_dev_communication = 9,
3020d59a3d2SAxel Dörfler	// 0xa - 0xb are graphics arts pre-press devices
3030d59a3d2SAxel Dörfler	// 0xc - 0x1e reserved
3040d59a3d2SAxel Dörfler	scsi_dev_storage_array = 0xc,
3050d59a3d2SAxel Dörfler	scsi_dev_enclosure_services = 0xd,
3060d59a3d2SAxel Dörfler	scsi_dev_simplified_direct_access = 0xe,
3070d59a3d2SAxel Dörfler	scsi_dev_optical_card = 0xf,
3080d59a3d2SAxel Dörfler	scsi_dev_unknown = 0x1f 	// used for scsi_periph_qual_not_connectable
3096be1e37dSAxel Dörfler};
3100d59a3d2SAxel Dörfler
3110d59a3d2SAxel Dörfler
3126fd00f80SJérôme Duval// vital product data: pages
3136fd00f80SJérôme Duval#define SCSI_PAGE_SUPPORTED_VPD 0x00	/* Supported VPD Pages */
3146fd00f80SJérôme Duval#define SCSI_PAGE_USN 0x80				/* Unit serial number */
3156fd00f80SJérôme Duval#define SCSI_PAGE_BLOCK_LIMITS 0xb0		/* Block limits */
3166fd00f80SJérôme Duval#define SCSI_PAGE_BLOCK_DEVICE_CHARS 0xb1	/* Block device characteristics */
3176fd00f80SJérôme Duval#define SCSI_PAGE_LB_PROVISIONING 0xb2	/* Logical block provisioning */
3186fd00f80SJérôme Duval#define SCSI_PAGE_REFERRALS 0xb3		/* Referrals */
3196fd00f80SJérôme Duval
3206fd00f80SJérôme Duval// vital product data: supported pages
3216fd00f80SJérôme Duvaltypedef struct scsi_page_list {
32293c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
3236fd00f80SJérôme Duval		device_type : 5,
3246fd00f80SJérôme Duval		device_qualifier : 3
3256fd00f80SJérôme Duval	);
3266fd00f80SJérôme Duval	uint8	page_code;
3276fd00f80SJérôme Duval	uint8	_res2;
3280d59a3d2SAxel Dörfler
3296fd00f80SJérôme Duval	uint8	page_length;
3306fd00f80SJérôme Duval	uint8	pages[1]; 			// size according to page_length
3316fd00f80SJérôme Duval} _PACKED scsi_page_list;
3320d59a3d2SAxel Dörfler
3336fd00f80SJérôme Duval// vital product data: unit serial number page
3346be1e37dSAxel Dörflertypedef struct scsi_page_usn {
33593c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
3360d59a3d2SAxel Dörfler		device_type : 5,
3370d59a3d2SAxel Dörfler		device_qualifier : 3
3380d59a3d2SAxel Dörfler	);
3396be1e37dSAxel Dörfler	uint8	page_code;
3406be1e37dSAxel Dörfler	uint8	_res2;
3416be1e37dSAxel Dörfler
3426be1e37dSAxel Dörfler	uint8	_page_length;		// total size = this + 3
3436be1e37dSAxel Dörfler	char	psn[1];			// size according to page_length
3446be1e37dSAxel Dörfler} _PACKED scsi_page_usn;
3450d59a3d2SAxel Dörfler
3466fd00f80SJérôme Duvaltypedef struct scsi_page_block_limits {
34793c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
3486fd00f80SJérôme Duval		device_type : 5,
3496fd00f80SJérôme Duval		device_qualifier : 3
3506fd00f80SJérôme Duval	);
3516fd00f80SJérôme Duval	uint8	page_code;
3526fd00f80SJérôme Duval
3536fd00f80SJérôme Duval	uint16	_page_length;
35493c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
3556fd00f80SJérôme Duval		wsnz : 1,
3566fd00f80SJérôme Duval		_res4_1 : 7
3576fd00f80SJérôme Duval	);
3586fd00f80SJérôme Duval	uint8	max_cmp_write_length;
3596fd00f80SJérôme Duval	uint16	opt_transfer_length_grain;
3606fd00f80SJérôme Duval	uint32	max_transfer_length;
3616fd00f80SJérôme Duval	uint32	opt_transfer_length;
3626fd00f80SJérôme Duval	uint32	max_prefetch_length;
3636fd00f80SJérôme Duval	uint32	max_unmap_lba_count;
3646fd00f80SJérôme Duval	uint32	max_unmap_blk_count;
3656fd00f80SJérôme Duval	uint32	opt_unmap_grain;
3666fd00f80SJérôme Duval	uint32	unmap_grain_align;
3676fd00f80SJérôme Duval	uint64	max_write_same_length;
3686fd00f80SJérôme Duval	uint8	_res44[20];
3696fd00f80SJérôme Duval} _PACKED scsi_page_block_limits;
3706fd00f80SJérôme Duval
3716fd00f80SJérôme Duvaltypedef struct scsi_page_lb_provisioning {
37293c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
3736fd00f80SJérôme Duval		device_type : 5,
3746fd00f80SJérôme Duval		device_qualifier : 3
3756fd00f80SJérôme Duval	);
3766fd00f80SJérôme Duval	uint8	page_code;
3776fd00f80SJérôme Duval
3786fd00f80SJérôme Duval	uint16	page_length;
3796fd00f80SJérôme Duval	uint8	threshold_exponent;
38093c0a5d7SAxel Dörfler	B_LBITFIELD8_7(
3816fd00f80SJérôme Duval		dp : 1,
3826fd00f80SJérôme Duval		anc_sup : 1,
3836fd00f80SJérôme Duval		lbprz : 1,
3846fd00f80SJérôme Duval		_res5_3 : 2,
3856fd00f80SJérôme Duval		lbpws10 : 1,
3866fd00f80SJérôme Duval		lbpws : 1,
3876fd00f80SJérôme Duval		lbpu : 1
3886fd00f80SJérôme Duval	);
38993c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
3906fd00f80SJérôme Duval		provisioning_type : 3,
3916fd00f80SJérôme Duval		_res6_3 : 5
3926fd00f80SJérôme Duval	);
3936fd00f80SJérôme Duval	uint8 _res7;
3946fd00f80SJérôme Duval} _PACKED scsi_page_lb_provisioning;
3956fd00f80SJérôme Duval
3966fd00f80SJérôme Duval
397f10a55a6SJérôme Duval// READ CAPACITY (10)
3980d59a3d2SAxel Dörfler
3990d59a3d2SAxel Dörflertypedef struct scsi_cmd_read_capacity {
4006be1e37dSAxel Dörfler	uint8	opcode;
40193c0a5d7SAxel Dörfler	B_LBITFIELD8_3(
4026be1e37dSAxel Dörfler		relative_address : 1,		// relative address
4036be1e37dSAxel Dörfler		_res1_1 : 4,
4046be1e37dSAxel Dörfler		lun : 3
4050d59a3d2SAxel Dörfler	);
4066be1e37dSAxel Dörfler	uint32	lba;
4076be1e37dSAxel Dörfler	uint8	_res6[2];
40893c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
4096be1e37dSAxel Dörfler		pmi : 1,							// partial medium indicator
4106be1e37dSAxel Dörfler		_res8_1 : 7
4110d59a3d2SAxel Dörfler	);
4126be1e37dSAxel Dörfler	uint8	control;
4136be1e37dSAxel Dörfler} _PACKED scsi_cmd_read_capacity;
4140d59a3d2SAxel Dörfler
4150d59a3d2SAxel Dörflertypedef struct scsi_res_read_capacity {
4166be1e37dSAxel Dörfler	uint32	lba;					// big endian
4176be1e37dSAxel Dörfler	uint32	block_size;				// in bytes
4186be1e37dSAxel Dörfler} _PACKED scsi_res_read_capacity;
4190d59a3d2SAxel Dörfler
420f10a55a6SJérôme Duval// READ CAPACITY (16)
421f10a55a6SJérôme Duval
422f10a55a6SJérôme Duvaltypedef struct scsi_cmd_read_capacity_long {
423f10a55a6SJérôme Duval	uint8	opcode;
424f10a55a6SJérôme Duval	uint8	service_action;
425f10a55a6SJérôme Duval	uint64	lba;
426f10a55a6SJérôme Duval	uint32	alloc_length;
427f10a55a6SJérôme Duval	uint8	relative_address;
428f10a55a6SJérôme Duval	uint8	control;
429f10a55a6SJérôme Duval} _PACKED scsi_cmd_read_capacity_long;
430f10a55a6SJérôme Duval
431f10a55a6SJérôme Duvaltypedef struct scsi_res_read_capacity_long {
432f10a55a6SJérôme Duval	uint64	lba;					// big endian
433f10a55a6SJérôme Duval	uint32	block_size;				// in bytes
434f10a55a6SJérôme Duval} _PACKED scsi_res_read_capacity_long;
435f10a55a6SJérôme Duval
4360d59a3d2SAxel Dörfler
4370d59a3d2SAxel Dörfler// READ (6), WRITE (6)
4380d59a3d2SAxel Dörfler
4390d59a3d2SAxel Dörflertypedef struct scsi_cmd_rw_6 {
4406be1e37dSAxel Dörfler	uint8	opcode;
44193c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
4426be1e37dSAxel Dörfler		high_lba : 5,
4436be1e37dSAxel Dörfler		lun : 3
4440d59a3d2SAxel Dörfler	);
4456be1e37dSAxel Dörfler	uint8	mid_lba;
4466be1e37dSAxel Dörfler	uint8	low_lba;
4476be1e37dSAxel Dörfler	uint8	length;					// 0 = 256 blocks
4486be1e37dSAxel Dörfler	uint8	control;
4496be1e37dSAxel Dörfler} _PACKED scsi_cmd_rw_6;
4500d59a3d2SAxel Dörfler
4510d59a3d2SAxel Dörfler
4520d59a3d2SAxel Dörfler// READ (10), WRITE (10)
4530d59a3d2SAxel Dörfler
4540d59a3d2SAxel Dörflertypedef struct scsi_cmd_rw_10 {
4556be1e37dSAxel Dörfler	uint8	opcode;
45693c0a5d7SAxel Dörfler	B_LBITFIELD8_5(
4576be1e37dSAxel Dörfler		relative_address : 1,		// relative address
4586be1e37dSAxel Dörfler		_res1_1 : 2,
4596be1e37dSAxel Dörfler		force_unit_access : 1,		// force unit access (1 = safe, cacheless access)
4606be1e37dSAxel Dörfler		disable_page_out : 1,		// disable page out (1 = not worth caching)
4616be1e37dSAxel Dörfler		lun : 3
4620d59a3d2SAxel Dörfler	);
4636be1e37dSAxel Dörfler	uint32	lba;					// big endian
4646be1e37dSAxel Dörfler	uint8	_res6;
4656be1e37dSAxel Dörfler	uint16	length;					// 0 = no block
4666be1e37dSAxel Dörfler	uint8	control;
4676be1e37dSAxel Dörfler} _PACKED scsi_cmd_rw_10;
4680d59a3d2SAxel Dörfler
4690d59a3d2SAxel Dörfler
4700d59a3d2SAxel Dörfler// READ (12), WRITE (12)
4710d59a3d2SAxel Dörfler
4720d59a3d2SAxel Dörflertypedef struct scsi_cmd_rw_12 {
4736be1e37dSAxel Dörfler	uint8	opcode;
47493c0a5d7SAxel Dörfler	B_LBITFIELD8_5(
4756be1e37dSAxel Dörfler		relative_address : 1,		// relative address
4766be1e37dSAxel Dörfler		_res1_1 : 2,
4776be1e37dSAxel Dörfler		force_unit_access : 1,		// force unit access (1 = safe, cacheless access)
4786be1e37dSAxel Dörfler		disable_page_out : 1,		// disable page out (1 = not worth caching)
4796be1e37dSAxel Dörfler		lun : 3
4800d59a3d2SAxel Dörfler	);
4816be1e37dSAxel Dörfler	uint32	lba;					// big endian
4826be1e37dSAxel Dörfler	uint32	length;					// 0 = no block
4836be1e37dSAxel Dörfler	uint8	_res10;
4846be1e37dSAxel Dörfler	uint8	control;
4856be1e37dSAxel Dörfler} _PACKED scsi_cmd_rw_12;
4860d59a3d2SAxel Dörfler
4870d59a3d2SAxel Dörfler
4883e9b601dSAndreas Färber// READ (16), WRITE (16)
4893e9b601dSAndreas Färber
4903e9b601dSAndreas Färbertypedef struct scsi_cmd_rw_16 {
4913e9b601dSAndreas Färber	uint8	opcode;
49293c0a5d7SAxel Dörfler	B_LBITFIELD8_6(
4933e9b601dSAndreas Färber		_res1_0 : 1,
4943e9b601dSAndreas Färber		force_unit_access_non_volatile : 1,
4953e9b601dSAndreas Färber		_res1_2 : 1,
4963e9b601dSAndreas Färber		force_unit_access : 1,
4973e9b601dSAndreas Färber		disable_page_out : 1,
4983e9b601dSAndreas Färber		read_protect : 3
4993e9b601dSAndreas Färber	);
5003e9b601dSAndreas Färber	uint64	lba;					// big endian
5013e9b601dSAndreas Färber	uint32	length;
50293c0a5d7SAxel Dörfler	B_LBITFIELD8_3(
5033e9b601dSAndreas Färber		group_number : 5,
5043e9b601dSAndreas Färber		_res_14_5 : 2,
5053e9b601dSAndreas Färber		_res_14_7 : 1
5063e9b601dSAndreas Färber	);
5073e9b601dSAndreas Färber	uint8	control;
5083e9b601dSAndreas Färber} _PACKED scsi_cmd_rw_16;
5093e9b601dSAndreas Färber
5103e9b601dSAndreas Färber
51137286363SAlexander von Gluck IV// WRITE SAME (16)
51237286363SAlexander von Gluck IV
51337286363SAlexander von Gluck IVtypedef struct scsi_cmd_wsame_16 {
51437286363SAlexander von Gluck IV	uint8	opcode;
51593c0a5d7SAxel Dörfler	B_LBITFIELD8_6(
51637286363SAlexander von Gluck IV		_res1_0 : 1,
51737286363SAlexander von Gluck IV		lb_data : 1,
51837286363SAlexander von Gluck IV		pb_data : 1,
51937286363SAlexander von Gluck IV		unmap : 1,
52037286363SAlexander von Gluck IV		_res1_4 : 1,
52137286363SAlexander von Gluck IV		write_protect : 3
52237286363SAlexander von Gluck IV	);
52337286363SAlexander von Gluck IV	uint64	lba;
52437286363SAlexander von Gluck IV	uint32	length;
52593c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
52637286363SAlexander von Gluck IV		group_number : 5,
52737286363SAlexander von Gluck IV		_res14_5 : 3
52837286363SAlexander von Gluck IV	);
52937286363SAlexander von Gluck IV	uint8	control;
53037286363SAlexander von Gluck IV} _PACKED scsi_cmd_wsame_16;
53199086aa3SAxel Dörfler
53299086aa3SAxel Dörfler
53399086aa3SAxel Dörfler// UNMAP
53499086aa3SAxel Dörfler
53599086aa3SAxel Dörflertypedef struct scsi_cmd_unmap {
53699086aa3SAxel Dörfler	uint8	opcode;
53793c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
53899086aa3SAxel Dörfler		anchor : 1,
53999086aa3SAxel Dörfler		_reserved1_7 : 7
54099086aa3SAxel Dörfler	);
54199086aa3SAxel Dörfler	uint32	_reserved1;
54293c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
54399086aa3SAxel Dörfler		group_number : 5,
54499086aa3SAxel Dörfler		_reserved5_7 : 3
54599086aa3SAxel Dörfler	);
54699086aa3SAxel Dörfler	uint16	length;
54799086aa3SAxel Dörfler	uint8	control;
54899086aa3SAxel Dörfler} _PACKED scsi_cmd_unmap;
54999086aa3SAxel Dörfler
55099086aa3SAxel Dörflerstruct scsi_unmap_block_descriptor {
55199086aa3SAxel Dörfler	uint64	lba;
55299086aa3SAxel Dörfler	uint32	block_count;
55399086aa3SAxel Dörfler	uint32	_reserved1;
55499086aa3SAxel Dörfler} _PACKED;
55599086aa3SAxel Dörfler
55699086aa3SAxel Dörflerstruct scsi_unmap_parameter_list {
55799086aa3SAxel Dörfler	uint16	data_length;
55899086aa3SAxel Dörfler	uint16	block_data_length;
55999086aa3SAxel Dörfler	uint32	_reserved1;
56099086aa3SAxel Dörfler	struct scsi_unmap_block_descriptor blocks[1];
56199086aa3SAxel Dörfler} _PACKED;
56299086aa3SAxel Dörfler
56337286363SAlexander von Gluck IV
5640d59a3d2SAxel Dörfler// REQUEST SENSE
5650d59a3d2SAxel Dörfler
5660d59a3d2SAxel Dörflertypedef struct scsi_cmd_request_sense {
5676be1e37dSAxel Dörfler	uint8	opcode;
56893c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
5696be1e37dSAxel Dörfler		_res1_0 : 5,
5706be1e37dSAxel Dörfler		lun : 3
5710d59a3d2SAxel Dörfler	);
5726be1e37dSAxel Dörfler	uint8	_res2[2];
5736be1e37dSAxel Dörfler	uint8	allocation_length;
5746be1e37dSAxel Dörfler	uint8	control;
5756be1e37dSAxel Dörfler} _PACKED scsi_cmd_request_sense;
5760d59a3d2SAxel Dörfler
5770d59a3d2SAxel Dörfler
5780d59a3d2SAxel Dörfler// sense data structures
5790d59a3d2SAxel Dörfler
5800d59a3d2SAxel Dörfler#define SCSIS_CURR_ERROR 0x70
5810d59a3d2SAxel Dörfler#define SCSIS_DEFERRED_ERROR 0x71
5820d59a3d2SAxel Dörfler
5830d59a3d2SAxel Dörflertypedef struct scsi_sense {
58493c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
5850d59a3d2SAxel Dörfler		error_code : 7,
5860d59a3d2SAxel Dörfler		valid : 1							// 0 = not conforming to standard
5870d59a3d2SAxel Dörfler	);
5880d59a3d2SAxel Dörfler	uint8 segment_number;					// for COPY/COPY AND VERIFY/COMPARE
58993c0a5d7SAxel Dörfler	B_LBITFIELD8_5(
5900d59a3d2SAxel Dörfler		sense_key : 4,
5910d59a3d2SAxel Dörfler		res2_4 : 1,
5920a96e186SAxel Dörfler		ILI : 1,							// incorrect length indicator - req. block
5930d59a3d2SAxel Dörfler											// length doesn't match physical block length
5940d59a3d2SAxel Dörfler		EOM : 1,							// serial devices only
5950d59a3d2SAxel Dörfler		Filemark : 1						// optional for random access
5960d59a3d2SAxel Dörfler	);
5970a96e186SAxel Dörfler
5980d59a3d2SAxel Dörfler	uint8 highest_inf;						// device-type or command specific
5990d59a3d2SAxel Dörfler	uint8 high_inf;							// device-type 0, 4, 5, 7: block address
6000d59a3d2SAxel Dörfler	uint8 mid_inf;							// device-type 1, 2, 3: req length - act. length
6010d59a3d2SAxel Dörfler	uint8 low_inf;							// (and others for sequential dev. and COPY cmds
6020a96e186SAxel Dörfler
6030d59a3d2SAxel Dörfler	uint8 add_sense_length; 				// total length = this + 7
6040a96e186SAxel Dörfler
6050d59a3d2SAxel Dörfler	uint8 highest_cmd_inf;
6060d59a3d2SAxel Dörfler	uint8 high_cmd_inf;
6070d59a3d2SAxel Dörfler	uint8 mid_cmd_inf;
6080d59a3d2SAxel Dörfler	uint8 low_cmd_inf;
6090d59a3d2SAxel Dörfler	uint8 asc;
6100d59a3d2SAxel Dörfler	uint8 ascq;								// this can be zero if unsupported
6110d59a3d2SAxel Dörfler	uint8 unit_code;						// != 0 to specify internal device unit
6120a96e186SAxel Dörfler
6130d59a3d2SAxel Dörfler	union {
6140d59a3d2SAxel Dörfler		struct {
61593c0a5d7SAxel Dörfler		B_LBITFIELD8_2(
6160d59a3d2SAxel Dörfler			high_key_spec : 7,
6170d59a3d2SAxel Dörfler			SKSV : 1						// 1 = sense key specific (byte 15-17) valid
6180d59a3d2SAxel Dörfler		);
6190d59a3d2SAxel Dörfler		uint8 mid_key_spec;
6200d59a3d2SAxel Dörfler		uint8 low_key_spec;
6210d59a3d2SAxel Dörfler		} raw;
6220a96e186SAxel Dörfler
6230d59a3d2SAxel Dörfler		// ILLEGAL REQUEST
6240d59a3d2SAxel Dörfler		struct {
62593c0a5d7SAxel Dörfler		B_LBITFIELD8_5(
6260d59a3d2SAxel Dörfler			bit_pointer : 3,				// points to (highest) invalid bit of parameter
6270d59a3d2SAxel Dörfler			BPV : 1,						// 1 = bit_pointer is valid
6280d59a3d2SAxel Dörfler			res15_4 : 2,
6290d59a3d2SAxel Dörfler			c_d : 2,						// 1 = error command, 0 = error in data
6300d59a3d2SAxel Dörfler			SKSV : 1						// s.a.
6310d59a3d2SAxel Dörfler		);
6320d59a3d2SAxel Dörfler		uint8 high_field_pointer;			// points to (highest) invalid byte of parameter
6330d59a3d2SAxel Dörfler		uint8 low_field_pointer;			// (!using big endian, this means the first byte!)
6340d59a3d2SAxel Dörfler		} ill_request;
6350d59a3d2SAxel Dörfler
6360d59a3d2SAxel Dörfler		// access error (RECOVERED, HARDWARE or MEDIUM ERROR)
6370d59a3d2SAxel Dörfler		struct {
63893c0a5d7SAxel Dörfler		B_LBITFIELD8_2(
6390d59a3d2SAxel Dörfler			res15_0 : 7,
6400a96e186SAxel Dörfler			SKSV : 1
6410d59a3d2SAxel Dörfler		);
6420d59a3d2SAxel Dörfler		uint8 high_retry_cnt;
6430d59a3d2SAxel Dörfler		uint8 low_retry_cnt;
6440d59a3d2SAxel Dörfler		} acc_error;
6450a96e186SAxel Dörfler
6460d59a3d2SAxel Dörfler		// format progress (if sense key = NOT READY)
6470d59a3d2SAxel Dörfler		struct {
64893c0a5d7SAxel Dörfler		B_LBITFIELD8_2(
6490d59a3d2SAxel Dörfler			res15_0 : 7,
6500a96e186SAxel Dörfler			SKSV : 1
6510d59a3d2SAxel Dörfler		);
6526be1e37dSAxel Dörfler		uint16	progress;				// 0 = start, 0xffff = almost finished
6530d59a3d2SAxel Dörfler		} format_progress;
6540d59a3d2SAxel Dörfler	} sense_key_spec;
6550a96e186SAxel Dörfler
6560d59a3d2SAxel Dörfler	// starting with offset 18 there are additional sense byte
6576be1e37dSAxel Dörfler} _PACKED scsi_sense;
6580d59a3d2SAxel Dörfler
6590d59a3d2SAxel Dörfler
6600d59a3d2SAxel Dörfler// PREVENT ALLOW
6610d59a3d2SAxel Dörfler
6620d59a3d2SAxel Dörflertypedef struct scsi_cmd_prevent_allow {
6636be1e37dSAxel Dörfler	uint8	opcode;
66493c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
6656be1e37dSAxel Dörfler		_res1_0 : 5,
6666be1e37dSAxel Dörfler		lun : 3
6670d59a3d2SAxel Dörfler	);
6686be1e37dSAxel Dörfler	uint8	_res2[2];
66993c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
6700d59a3d2SAxel Dörfler		prevent : 1,		// 1 - prevent medium removal, 0 - allow removal
6716be1e37dSAxel Dörfler		_res4_1 : 7
6720d59a3d2SAxel Dörfler	);
6736be1e37dSAxel Dörfler	uint8	control;
6746be1e37dSAxel Dörfler} _PACKED scsi_cmd_prevent_allow;
6750d59a3d2SAxel Dörfler
6760d59a3d2SAxel Dörfler// START STOP UNIT
6770d59a3d2SAxel Dörfler
6780d59a3d2SAxel Dörflertypedef struct scsi_cmd_ssu {
6796be1e37dSAxel Dörfler	uint8	opcode;
68093c0a5d7SAxel Dörfler	B_LBITFIELD8_3(
6816be1e37dSAxel Dörfler		immediately : 1,			// 1 - return immediately, 0 - return on completion
6826be1e37dSAxel Dörfler		_res1_1 : 4,
6836be1e37dSAxel Dörfler		lun : 3
6840d59a3d2SAxel Dörfler	);
6850d59a3d2SAxel Dörfler	uint8 res2[2];
68693c0a5d7SAxel Dörfler	B_LBITFIELD8_3(
6870d59a3d2SAxel Dörfler		start : 1,			// 1 - load+start, i.e. allow, 0 - eject+stop, i.e. deny
6886be1e37dSAxel Dörfler		load_eject : 1,			// 1 - include loading/ejecting, 0 - only to allow/deny
6896be1e37dSAxel Dörfler		_res4_2 : 6
6900d59a3d2SAxel Dörfler	);
6916be1e37dSAxel Dörfler	uint8	control;
6926be1e37dSAxel Dörfler} _PACKED scsi_cmd_ssu;
6930d59a3d2SAxel Dörfler
6940d59a3d2SAxel Dörfler
6950d59a3d2SAxel Dörfler// MODE SELECT (6)
6960d59a3d2SAxel Dörfler
6970d59a3d2SAxel Dörflertypedef struct scsi_cmd_mode_select_6 {
6986be1e37dSAxel Dörfler	uint8	opcode;
69993c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
7006be1e37dSAxel Dörfler		save_pages : 1,		// 1 = save pages to non-volatile memory
7016be1e37dSAxel Dörfler		_res1_1 : 3,
7026be1e37dSAxel Dörfler		pf : 1,				// 0 = old SCSI-1; 1 = new SCSI-2 format
7036be1e37dSAxel Dörfler		lun : 3
7040d59a3d2SAxel Dörfler	);
7056be1e37dSAxel Dörfler	uint8	_res2[2];
7066be1e37dSAxel Dörfler	uint8	param_list_length;	// data size
7076be1e37dSAxel Dörfler	uint8	control;
7086be1e37dSAxel Dörfler} _PACKED scsi_cmd_mode_select_6;
7090d59a3d2SAxel Dörfler
7100d59a3d2SAxel Dörfler
7110d59a3d2SAxel Dörfler// MODE SENSE (6)
7120d59a3d2SAxel Dörfler
7130d59a3d2SAxel Dörflertypedef struct scsi_cmd_mode_sense_6 {
7146be1e37dSAxel Dörfler	uint8	opcode;
71593c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
7166be1e37dSAxel Dörfler		_res1_0 : 3,
7176be1e37dSAxel Dörfler		disable_block_desc : 1,		// disable block descriptors
7186be1e37dSAxel Dörfler		_res1_4 : 1,
7196be1e37dSAxel Dörfler		lun : 3
7200d59a3d2SAxel Dörfler	);
72193c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
7220d59a3d2SAxel Dörfler		page_code : 6,
7236be1e37dSAxel Dörfler		page_control : 2			// page control field
7240d59a3d2SAxel Dörfler	);
7256be1e37dSAxel Dörfler	uint8	_res3;
7266be1e37dSAxel Dörfler	uint8	allocation_length;		// maximum amount of data
7276be1e37dSAxel Dörfler	uint8	control;
7286be1e37dSAxel Dörfler} _PACKED scsi_cmd_mode_sense_6;
7290d59a3d2SAxel Dörfler
7300d59a3d2SAxel Dörfler
7310d59a3d2SAxel Dörfler// MODE SELECT (10)
7320d59a3d2SAxel Dörfler
7330d59a3d2SAxel Dörflertypedef struct scsi_cmd_mode_select_10 {
7346be1e37dSAxel Dörfler	uint8	opcode;
73593c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
7366be1e37dSAxel Dörfler		save_pages : 1,				// 1 = save pages to non-volatile memory
7376be1e37dSAxel Dörfler		_res1_1 : 3,
7386be1e37dSAxel Dörfler		pf : 1,						// 0 = old SCSI-1; 1 = new SCSI-2 format
7396be1e37dSAxel Dörfler		lun : 3
7400d59a3d2SAxel Dörfler	);
7416be1e37dSAxel Dörfler	uint8	_res2[5];
7426be1e37dSAxel Dörfler	uint16	param_list_length;		// data size, big endian
7436be1e37dSAxel Dörfler	uint8	control;
7446be1e37dSAxel Dörfler} _PACKED scsi_cmd_mode_select_10;
7450d59a3d2SAxel Dörfler
7460d59a3d2SAxel Dörfler
7470d59a3d2SAxel Dörfler// MODE SENSE (10)
7480d59a3d2SAxel Dörfler
7490d59a3d2SAxel Dörflertypedef struct scsi_cmd_mode_sense_10 {
7506be1e37dSAxel Dörfler	uint8	opcode;
75193c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
7526be1e37dSAxel Dörfler		_res1_0 : 3,
7536be1e37dSAxel Dörfler		disable_block_desc : 1,		// disable block descriptors
7546be1e37dSAxel Dörfler		_res1_4 : 1,
7556be1e37dSAxel Dörfler		lun : 3
7560d59a3d2SAxel Dörfler	);
75793c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
7580d59a3d2SAxel Dörfler		page_code : 6,
7596be1e37dSAxel Dörfler		page_control : 2			// page control field
7600d59a3d2SAxel Dörfler	);
7616be1e37dSAxel Dörfler	uint8	_res3[4];
7626be1e37dSAxel Dörfler	uint16	allocation_length;		// maximum amount of data, big endian
7636be1e37dSAxel Dörfler	uint8	control;
7646be1e37dSAxel Dörfler} _PACKED scsi_cmd_mode_sense_10;
7650d59a3d2SAxel Dörfler
7666be1e37dSAxel Dörfler// possible contents of page control (PC)
7670d59a3d2SAxel Dörfler#define SCSI_MODE_SENSE_PC_CURRENT 0
7686be1e37dSAxel Dörfler#define SCSI_MODE_SENSE_PC_CHANGABLE 1
7696be1e37dSAxel Dörfler	// changable field are filled with "1"
7700d59a3d2SAxel Dörfler#define SCSI_MODE_SENSE_PC_DEFAULT 2
7710d59a3d2SAxel Dörfler#define SCSI_MODE_SENSE_PC_SAVED 3
7720d59a3d2SAxel Dörfler
7730d59a3d2SAxel Dörfler// special mode page indicating to return all mode pages
7740d59a3d2SAxel Dörfler#define SCSI_MODEPAGE_ALL 0x3f
7750d59a3d2SAxel Dörfler
7760d59a3d2SAxel Dörfler// header of mode data; followed by block descriptors and mode pages
7770d59a3d2SAxel Dörflertypedef struct scsi_mode_param_header_6 {
7786be1e37dSAxel Dörfler	uint8	mode_data_length;		// total length excluding this byte
7796be1e37dSAxel Dörfler	uint8	medium_type;
7806be1e37dSAxel Dörfler	uint8	dev_spec_parameter;
7816be1e37dSAxel Dörfler	uint8	block_desc_length;		// total length of all transmitted block descriptors
7826be1e37dSAxel Dörfler} _PACKED scsi_mode_param_header_6;
7830d59a3d2SAxel Dörfler
7840d59a3d2SAxel Dörflertypedef struct scsi_mode_param_header_10 {
7856be1e37dSAxel Dörfler	uint16	mode_data_length;		// total length excluding these two bytes
7866be1e37dSAxel Dörfler	uint8	medium_type;
7876be1e37dSAxel Dörfler	uint8	dev_spec_parameter;
7886be1e37dSAxel Dörfler	uint8	_res4[2];
7896be1e37dSAxel Dörfler	uint16	block_desc_length;		// total length of all transmitted block descriptors
7906be1e37dSAxel Dörfler} _PACKED scsi_mode_param_header_10;
7910d59a3d2SAxel Dörfler
7920d59a3d2SAxel Dörfler
7930d59a3d2SAxel Dörfler// content of dev_spec_parameter for direct access devices
7940d59a3d2SAxel Dörflertypedef struct scsi_mode_param_dev_spec_da {
79593c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
7966be1e37dSAxel Dörfler		_res0_0 : 4,
7976be1e37dSAxel Dörfler		dpo_fua : 1,			// 1 = supports DPO and FUA, see READ (10) (sense only)
7986be1e37dSAxel Dörfler		_res0_6 : 1,
7996be1e37dSAxel Dörfler		write_protected : 1		// write protected (sense only)
8000d59a3d2SAxel Dörfler	);
8016be1e37dSAxel Dörfler} _PACKED scsi_mode_param_dev_spec_da;
8020d59a3d2SAxel Dörfler
8030d59a3d2SAxel Dörflertypedef struct scsi_mode_param_block_desc {
8046be1e37dSAxel Dörfler	uint8	density;			// density code of area
8056be1e37dSAxel Dörfler	uint8	high_numblocks;		// size of this area in blocks
8066be1e37dSAxel Dörfler	uint8	med_numblocks;		// 0 = all remaining blocks
8076be1e37dSAxel Dörfler	uint8	low_numblocks;
8086be1e37dSAxel Dörfler	uint8	_res4;
8096be1e37dSAxel Dörfler	uint8	high_blocklen;		// block size
8106be1e37dSAxel Dörfler	uint8	med_blocklen;
8116be1e37dSAxel Dörfler	uint8	low_blocklen;
8126be1e37dSAxel Dörfler} _PACKED scsi_mode_param_block_desc;
8130d59a3d2SAxel Dörfler
8140d59a3d2SAxel Dörfler
8150d59a3d2SAxel Dörfler// header of a mode pages
8160d59a3d2SAxel Dörflertypedef struct scsi_modepage_header {
81793c0a5d7SAxel Dörfler	B_LBITFIELD8_3(
8180d59a3d2SAxel Dörfler		page_code : 6,
8196be1e37dSAxel Dörfler		_res0_6 : 1,
8200d59a3d2SAxel Dörfler		PS : 1				// 1 = page can be saved (only valid for MODE SENSE)
8210d59a3d2SAxel Dörfler	);
8226be1e37dSAxel Dörfler	uint8	page_length;	// size of page excluding this common header
8236be1e37dSAxel Dörfler} _PACKED scsi_modepage_header;
8240d59a3d2SAxel Dörfler
8250d59a3d2SAxel Dörfler
8260d59a3d2SAxel Dörfler// control mode page
8270d59a3d2SAxel Dörfler#define SCSI_MODEPAGE_CONTROL 0xa
8280d59a3d2SAxel Dörfler
8296be1e37dSAxel Dörflertypedef struct scsi_modepage_control {
8300d59a3d2SAxel Dörfler	scsi_modepage_header header;
83193c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
8320d59a3d2SAxel Dörfler		RLEC : 1,			// Report Log Exception Condition
8330d59a3d2SAxel Dörfler		res2_1 : 7
8340d59a3d2SAxel Dörfler	);
83593c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
8360d59a3d2SAxel Dörfler		DQue : 1,			// disable Queuing
8370d59a3d2SAxel Dörfler		QErr : 1,			// abort queued commands on contingent allegiance condition
8380d59a3d2SAxel Dörfler		res3_2 : 2,
8390d59a3d2SAxel Dörfler		QAM : 4				// Queue Algorithm Modifier
8400d59a3d2SAxel Dörfler	);
84193c0a5d7SAxel Dörfler	B_LBITFIELD8_5(
8420d59a3d2SAxel Dörfler		EAENP : 1,			// error AEN permission; true = send AEN on deferred error
8430d59a3d2SAxel Dörfler							// false = generate UA condition after deferred error
8440d59a3d2SAxel Dörfler		UAAENP : 1,			// unit attention AEN permission; true = send AEN,
8450d59a3d2SAxel Dörfler							// false = generate UA condition (for everything but init.)
8460d59a3d2SAxel Dörfler		RAENP : 1,			// ready AEN permission; true = send async event notification
8470a96e186SAxel Dörfler							// (AEN) instead of generating an Unit Attention (UA) Condition
8480d59a3d2SAxel Dörfler							// after initialization
8490d59a3d2SAxel Dörfler		res4_3 : 4,
8500d59a3d2SAxel Dörfler		EECA : 1			// enable Extended Contingent Allegiance
8510d59a3d2SAxel Dörfler	);
8520d59a3d2SAxel Dörfler	uint8 res5;
8530a96e186SAxel Dörfler	uint8 high_AEN_holdoff;	// ready AEN hold off period - delay in ms between
8540d59a3d2SAxel Dörfler	uint8 low_AEN_holdoff;	// initialization and AEN
8556be1e37dSAxel Dörfler} scsi_modepage_control;
8560d59a3d2SAxel Dörfler
8570d59a3d2SAxel Dörfler// values for QAM
8580d59a3d2SAxel Dörfler#define SCSI_QAM_RESTRICTED 0
8590d59a3d2SAxel Dörfler#define SCSI_QAM_UNRESTRICTED 1
8600d59a3d2SAxel Dörfler// 2 - 7 reserved, 8 - 0xf vendor-specific
8610d59a3d2SAxel Dörfler
8620d59a3d2SAxel Dörfler
8630d59a3d2SAxel Dörfler// CD audio control page
8640d59a3d2SAxel Dörfler#define SCSI_MODEPAGE_AUDIO 0xe
8650d59a3d2SAxel Dörfler
8660d59a3d2SAxel Dörflertypedef struct scsi_modepage_audio {
8670d59a3d2SAxel Dörfler	scsi_modepage_header header;
86893c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
8696be1e37dSAxel Dörfler		_res2_0 : 1,
8706be1e37dSAxel Dörfler		stop_on_track_crossing : 1,		// Stop On Track Crossing
8716be1e37dSAxel Dörfler			// 0 - stop according transfer length, 1 - stop at end of track
8726be1e37dSAxel Dörfler		immediately : 1,					// must be one
8736be1e37dSAxel Dörfler		_res2_3 : 5
8746be1e37dSAxel Dörfler	);
8756be1e37dSAxel Dörfler	uint8 _res3[3];
8766be1e37dSAxel Dörfler	uint8 _obsolete6[2];
8770d59a3d2SAxel Dörfler	struct {
87893c0a5d7SAxel Dörfler		B_LBITFIELD8_2(
8790d59a3d2SAxel Dörfler			channel : 4,	// select channel to connect to this port
8806be1e37dSAxel Dörfler			_res0_4 : 4
8810d59a3d2SAxel Dörfler		);
8820d59a3d2SAxel Dörfler		uint8 volume;
8830d59a3d2SAxel Dörfler	} ports[4];
8846be1e37dSAxel Dörfler} _PACKED scsi_modepage_audio;
8850d59a3d2SAxel Dörfler
8860d59a3d2SAxel Dörfler// connection between output port and audio channel
8870d59a3d2SAxel Dörfler#define SCSI_CHANNEL_SEL_MUTED		0	// mute port
8880d59a3d2SAxel Dörfler#define SCSI_CHANNEL_SEL_CHANNEL0	1	// connect to channel 0
8890d59a3d2SAxel Dörfler#define SCSI_CHANNEL_SEL_CHANNEL1	2	// connect to channel 1
8900d59a3d2SAxel Dörfler#define SCSI_CHANNEL_SEL_CHANNEL0_1	3	// connect to channel 0 and channel 1
8910d59a3d2SAxel Dörfler#define SCSI_CHANNEL_SEL_CHANNEL2	4	// connect to channel 2
8920d59a3d2SAxel Dörfler#define SCSI_CHANNEL_SEL_CHANNEL3	8	// connect to channel 3
8930d59a3d2SAxel Dörfler
8940d59a3d2SAxel Dörfler// TUR
8950d59a3d2SAxel Dörfler
8960d59a3d2SAxel Dörflertypedef struct scsi_cmd_tur {
8976be1e37dSAxel Dörfler	uint8	opcode;
89893c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
8996be1e37dSAxel Dörfler		_res1_0 : 5,
9006be1e37dSAxel Dörfler		lun : 3
9010d59a3d2SAxel Dörfler	);
9026be1e37dSAxel Dörfler	uint8	_res3[3];
9036be1e37dSAxel Dörfler	uint8	control;
9046be1e37dSAxel Dörfler} _PACKED scsi_cmd_tur;
9050d59a3d2SAxel Dörfler
9060d59a3d2SAxel Dörfler
9070d59a3d2SAxel Dörfler// READ_TOC
9080d59a3d2SAxel Dörfler
9090d59a3d2SAxel Dörflertypedef struct scsi_cmd_read_toc {
9106be1e37dSAxel Dörfler	uint8	opcode;
91193c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
9126be1e37dSAxel Dörfler		_res1_0 : 1,
9136be1e37dSAxel Dörfler		time : 1,					// true, to use MSF format, false for LBA format
9146be1e37dSAxel Dörfler		_res1_2 : 3,
9156be1e37dSAxel Dörfler		lun : 3
9160d59a3d2SAxel Dörfler	);
91793c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
9180d59a3d2SAxel Dörfler		format : 4,					// see below
9196be1e37dSAxel Dörfler		_res2_4 : 4
9200d59a3d2SAxel Dörfler	);
9216be1e37dSAxel Dörfler	uint8	_res3[3];
9226be1e37dSAxel Dörfler	uint8	track;					// (starting) track
9236be1e37dSAxel Dörfler	uint16	allocation_length;		// maximum amount of data (big endian)
9246be1e37dSAxel Dörfler	uint8	control;
9256be1e37dSAxel Dörfler} _PACKED scsi_cmd_read_toc;
9260d59a3d2SAxel Dörfler
9270d59a3d2SAxel Dörfler// values of <format> in TOC command
9280d59a3d2SAxel Dörfler#define SCSI_TOC_FORMAT_TOC 0			// all TOCs starting with <track> (0xaa for lead-out)
9290d59a3d2SAxel Dörfler#define SCSI_TOC_FORMAT_SESSION_INFO 1	// Session info
9300d59a3d2SAxel Dörfler#define SCSI_TOC_FORMAT_FULL_TOC 2		// all Q-channel data in TOC
9310d59a3d2SAxel Dörfler#define SCSI_TOC_FORMAT_PMA 3			// Q-channel data in PMA area
9320d59a3d2SAxel Dörfler#define SCSI_TOC_FORMAT_ATIP 4			// get ATIP data
9330d59a3d2SAxel Dörfler#define SCSI_TOC_FORMAT_CD_TEXT 5		// get CD-Text from R/W-channel in lead-in
9340d59a3d2SAxel Dörfler
9350d59a3d2SAxel Dörfler// general structure of response
9360d59a3d2SAxel Dörflertypedef struct scsi_toc_general {
9376be1e37dSAxel Dörfler	uint16	data_length;				// big endian, total length - 2
9386be1e37dSAxel Dörfler	uint8	first;						// first track/session/reserved
9396be1e37dSAxel Dörfler	uint8	last;							// last one
9400d59a3d2SAxel Dörfler	// remainder are parameter list descriptors
9416be1e37dSAxel Dörfler} _PACKED scsi_toc_general;
9420d59a3d2SAxel Dörfler
9430d59a3d2SAxel Dörfler// definition of CD-ROM LBA
9446be1e37dSAxel Dörflertypedef uint32 scsi_cd_lba;				// big endian
9450d59a3d2SAxel Dörfler
9460d59a3d2SAxel Dörfler// definition of CD-ROM MSF time
9470d59a3d2SAxel Dörflertypedef struct scsi_cd_msf {
9486be1e37dSAxel Dörfler	uint8	_reserved;
9496be1e37dSAxel Dörfler	uint8	minute;
9506be1e37dSAxel Dörfler	uint8	second;
9516be1e37dSAxel Dörfler	uint8	frame;
9526be1e37dSAxel Dörfler} _PACKED scsi_cd_msf;
9530d59a3d2SAxel Dörfler
9540d59a3d2SAxel Dörfler// definition of Track Number address format
9556be1e37dSAxel Dörflertypedef struct scsi_cd_track_number {
9566be1e37dSAxel Dörfler	uint8	_res0[3];
9576be1e37dSAxel Dörfler	uint8	track;
9586be1e37dSAxel Dörfler} _PACKED scsi_cd_track_number;
9590d59a3d2SAxel Dörfler
9600d59a3d2SAxel Dörfler// one track for SCSI_TOC_FORMAT_TOC
9610d59a3d2SAxel Dörflertypedef struct scsi_toc_track {
9626be1e37dSAxel Dörfler	uint8	_res0;
96393c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
9646be1e37dSAxel Dörfler		control : 4,
9656be1e37dSAxel Dörfler		adr : 4
9660d59a3d2SAxel Dörfler	);
9676be1e37dSAxel Dörfler	uint8	track_number;		// track number (hex)
9686be1e37dSAxel Dörfler	uint8	_res3;
9690d59a3d2SAxel Dörfler	union {					// start of track (time or LBA, see TIME of command)
9700d59a3d2SAxel Dörfler		scsi_cd_lba lba;
9710d59a3d2SAxel Dörfler		scsi_cd_msf time;
9720d59a3d2SAxel Dörfler	} start;
9736be1e37dSAxel Dörfler} _PACKED scsi_toc_track;
9740d59a3d2SAxel Dörfler
9750d59a3d2SAxel Dörfler// possible value of ADR-field (described Q-channel content)
9766be1e37dSAxel Dörflerenum scsi_adr {
9770d59a3d2SAxel Dörfler	scsi_adr_none = 0,				// no Q-channel mode info
9780d59a3d2SAxel Dörfler	scsi_adr_position = 1,			// Q-channel encodes current position data
9790d59a3d2SAxel Dörfler	scsi_adr_mcn = 2,				// Q-channel encodes Media Catalog Number
9800d59a3d2SAxel Dörfler	scsi_adr_isrc = 3				// Q-channel encodes ISRC
9816be1e37dSAxel Dörfler};
9820d59a3d2SAxel Dörfler
9830d59a3d2SAxel Dörfler// value of Q-channel control field (CONTROL)
9846be1e37dSAxel Dörflerenum scsi_q_control {
9850d59a3d2SAxel Dörfler	scsi_q_control_2audio 			= 0,	// stereo audio
9860d59a3d2SAxel Dörfler	scsi_q_control_2audio_preemp	= 1,	// stereo audio with 50/15��s pre-emphasis
9870d59a3d2SAxel Dörfler	scsi_q_control_1audio			= 8,	// audio (reserved in CD-R/W)
9880d59a3d2SAxel Dörfler	scsi_q_control_1audio_preemp	= 9,	// audio with pre-emphasis (reserved in CD-R/W)
9890d59a3d2SAxel Dörfler	scsi_q_control_data_un_intr 	= 4,	// data, recorded un-interrupted
9900d59a3d2SAxel Dörfler	scsi_q_control_data_incr		= 5,	// data, recorded incremental
9910d59a3d2SAxel Dörfler	scsi_q_control_ddcd				= 4,	// DDCD data
9920d59a3d2SAxel Dörfler	scsi_q_control_copy_perm		= 2		// copy permitted (or-ed with value above)
9936be1e37dSAxel Dörfler};
9940d59a3d2SAxel Dörfler
9950d59a3d2SAxel Dörfler// format SCSI_TOC_FORMAT_TOC
9960d59a3d2SAxel Dörflertypedef struct scsi_toc_toc {
9976be1e37dSAxel Dörfler	uint16	data_length;			// big endian, total length - 2
9986be1e37dSAxel Dörfler	uint8	first_track;			// first track
9996be1e37dSAxel Dörfler	uint8	last_track;				// last track
10006be1e37dSAxel Dörfler
10010d59a3d2SAxel Dörfler	scsi_toc_track tracks[1];		// one entry per track
10026be1e37dSAxel Dörfler} _PACKED scsi_toc_toc;
10030d59a3d2SAxel Dörfler
10040d59a3d2SAxel Dörfler
10050d59a3d2SAxel Dörfler// READ SUB-CHANNEL
10060d59a3d2SAxel Dörfler
10070d59a3d2SAxel Dörflertypedef struct scsi_cmd_read_subchannel {
10086be1e37dSAxel Dörfler	uint8	opcode;
100993c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
10106be1e37dSAxel Dörfler		_res1_0 : 1,
10116be1e37dSAxel Dörfler		time : 1,					// true, to use MSF format, false for LBA format
10126be1e37dSAxel Dörfler		_res1_2 : 3,
10136be1e37dSAxel Dörfler		lun : 3
10140d59a3d2SAxel Dörfler	);
101593c0a5d7SAxel Dörfler	B_LBITFIELD8_3(
10166be1e37dSAxel Dörfler		_res2_0 : 6,
10176be1e37dSAxel Dörfler		subq : 1,					// 1 - return Q sub-channel data
10186be1e37dSAxel Dörfler		_res2_7 : 1
10190d59a3d2SAxel Dörfler	);
10206be1e37dSAxel Dörfler	uint8	parameter_list;			// see below
10216be1e37dSAxel Dörfler	uint8	_res4[2];
10226be1e37dSAxel Dörfler	uint8	track;					// track number (hex)
10236be1e37dSAxel Dörfler	uint16	allocation_length;		// maximum amount of data, big endian
10246be1e37dSAxel Dörfler	uint8	control;
10256be1e37dSAxel Dörfler} _PACKED scsi_cmd_read_subchannel;
10260d59a3d2SAxel Dörfler
10270d59a3d2SAxel Dörfler// values of parameter_list
10286be1e37dSAxel Dörflerenum scsi_sub_channel_parameter_list {
10290d59a3d2SAxel Dörfler	scsi_sub_channel_parameter_list_cd_pos 	= 1,	// CD current position
10300d59a3d2SAxel Dörfler	scsi_sub_channel_parameter_list_mcn		= 2,	// Media Catalog Number
10310d59a3d2SAxel Dörfler	scsi_sub_channel_parameter_list_isrc	= 3		// Track International Standard Recording Code
10326be1e37dSAxel Dörfler};
10330d59a3d2SAxel Dörfler
10340d59a3d2SAxel Dörfler// header of response
10350d59a3d2SAxel Dörflertypedef struct scsi_subchannel_data_header {
10366be1e37dSAxel Dörfler	uint8	_res0;
10376be1e37dSAxel Dörfler	uint8	audio_status;			// see below
10386be1e37dSAxel Dörfler	uint16	data_length;			// total length - 4, big endian
10396be1e37dSAxel Dörfler} _PACKED scsi_subchannel_data_header;
10400d59a3d2SAxel Dörfler
10410d59a3d2SAxel Dörfler// possible audio_status
10426be1e37dSAxel Dörflerenum scsi_audio_status {
10430d59a3d2SAxel Dörfler	scsi_audio_status_not_supported		= 0,
10440d59a3d2SAxel Dörfler	scsi_audio_status_playing			= 0x11,
10450d59a3d2SAxel Dörfler	scsi_audio_status_paused			= 0x12,
10460d59a3d2SAxel Dörfler	scsi_audio_status_completed			= 0x13,
10470d59a3d2SAxel Dörfler	scsi_audio_status_error_stop		= 0x14,
10480d59a3d2SAxel Dörfler	scsi_audio_status_no_status			= 0x15
10496be1e37dSAxel Dörfler};
10500d59a3d2SAxel Dörfler
10510d59a3d2SAxel Dörflertypedef struct scsi_cd_current_position {
10526be1e37dSAxel Dörfler	uint8	format_code;			// always 1
105393c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
10546be1e37dSAxel Dörfler		control : 4,				// see scsi_q_control
10556be1e37dSAxel Dörfler		adr : 4						// see scsi_adr
10560d59a3d2SAxel Dörfler	);
10576be1e37dSAxel Dörfler	uint8	track;
10586be1e37dSAxel Dörfler	uint8	index;
10590d59a3d2SAxel Dörfler	union {							// current position, relative to logical beginning
10600d59a3d2SAxel Dörfler		scsi_cd_lba lba;
10610d59a3d2SAxel Dörfler		scsi_cd_msf time;
10620d59a3d2SAxel Dörfler	} absolute_address;
10630d59a3d2SAxel Dörfler	union {							// current position, relative to track
10640d59a3d2SAxel Dörfler		scsi_cd_lba lba;
10650d59a3d2SAxel Dörfler		scsi_cd_msf time;
10660d59a3d2SAxel Dörfler	} track_relative_address;
10676be1e37dSAxel Dörfler} _PACKED scsi_cd_current_position;
10680d59a3d2SAxel Dörfler
10690d59a3d2SAxel Dörfler
10700d59a3d2SAxel Dörfler// PLAY AUDIO MSF
10710d59a3d2SAxel Dörfler
10720d59a3d2SAxel Dörflertypedef struct scsi_cmd_play_msf {
10736be1e37dSAxel Dörfler	uint8	opcode;
107493c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
10756be1e37dSAxel Dörfler		_res1_0 : 5,
10766be1e37dSAxel Dörfler		lun : 3
10770d59a3d2SAxel Dörfler	);
10786be1e37dSAxel Dörfler	uint8	_res2;
10796be1e37dSAxel Dörfler	uint8	start_minute;			// start time
10806be1e37dSAxel Dörfler	uint8	start_second;
10816be1e37dSAxel Dörfler	uint8	start_frame;
10826be1e37dSAxel Dörfler	uint8	end_minute;				// end time (excluding)
10836be1e37dSAxel Dörfler	uint8	end_second;
10846be1e37dSAxel Dörfler	uint8	end_frame;
10856be1e37dSAxel Dörfler	uint8	control;
10866be1e37dSAxel Dörfler} _PACKED scsi_cmd_play_msf;
10870d59a3d2SAxel Dörfler
10880d59a3d2SAxel Dörfler
10890d59a3d2SAxel Dörfler// STOP AUDIO
10900d59a3d2SAxel Dörfler
10910d59a3d2SAxel Dörflertypedef struct scsi_cmd_stop_play {
10926be1e37dSAxel Dörfler	uint8	opcode;
109393c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
10946be1e37dSAxel Dörfler		_res1_0 : 5,
10956be1e37dSAxel Dörfler		lun : 3
10960d59a3d2SAxel Dörfler	);
10976be1e37dSAxel Dörfler	uint8	_res2[7];
10986be1e37dSAxel Dörfler	uint8	control;
10996be1e37dSAxel Dörfler} _PACKED scsi_cmd_stop_play;
11000d59a3d2SAxel Dörfler
11010d59a3d2SAxel Dörfler
11020d59a3d2SAxel Dörfler// PAUSE/RESUME
11030d59a3d2SAxel Dörfler
11040d59a3d2SAxel Dörflertypedef struct scsi_cmd_pause_resume {
11056be1e37dSAxel Dörfler	uint8	opcode;
110693c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
11076be1e37dSAxel Dörfler		_res1_0 : 5,
11086be1e37dSAxel Dörfler		lun : 3
11090d59a3d2SAxel Dörfler	);
11106be1e37dSAxel Dörfler	uint8	_res2[6];
111193c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
11120d59a3d2SAxel Dörfler		resume : 1,				// 1 for resume, 0 for pause
11136be1e37dSAxel Dörfler		_res8_2 : 7
11140d59a3d2SAxel Dörfler	);
11156be1e37dSAxel Dörfler	uint8	control;
11166be1e37dSAxel Dörfler} _PACKED scsi_cmd_pause_resume;
11170d59a3d2SAxel Dörfler
11180d59a3d2SAxel Dörfler
11190a96e186SAxel Dörfler// SCAN
11200d59a3d2SAxel Dörfler
11210d59a3d2SAxel Dörflertypedef struct scsi_cmd_scan {
11226be1e37dSAxel Dörfler	uint8	opcode;
112393c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
11246be1e37dSAxel Dörfler		relative_address : 1,	// must be zero
11256be1e37dSAxel Dörfler		_res1_1 : 3,
11266be1e37dSAxel Dörfler		direct : 1,				// direction: 0 forward, 1 backward
11276be1e37dSAxel Dörfler		lun : 3
11280d59a3d2SAxel Dörfler	);
11290d59a3d2SAxel Dörfler	union {						// start of track (depends on <type>)
11300d59a3d2SAxel Dörfler		scsi_cd_lba lba;
11310d59a3d2SAxel Dörfler		scsi_cd_msf time;
11326be1e37dSAxel Dörfler		scsi_cd_track_number track_number;
11330d59a3d2SAxel Dörfler	} start;
11346be1e37dSAxel Dörfler	uint8	_res6[3];
113593c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
11360d59a3d2SAxel Dörfler		res9_0 : 6,
11370d59a3d2SAxel Dörfler		type : 2				// actual type of <start> (see below)
11380d59a3d2SAxel Dörfler	);
11396be1e37dSAxel Dörfler	uint8	_res10;
11406be1e37dSAxel Dörfler	uint8	control;
11416be1e37dSAxel Dörfler} _PACKED scsi_cmd_scan;
11420d59a3d2SAxel Dörfler
11430d59a3d2SAxel Dörfler// possible values for type
11446be1e37dSAxel Dörflerenum scsi_scan_type {
11450d59a3d2SAxel Dörfler	scsi_scan_lba = 0,
11460d59a3d2SAxel Dörfler	scsi_scan_msf = 1,
11470d59a3d2SAxel Dörfler	scsi_scan_tno = 2
11486be1e37dSAxel Dörfler};
11490d59a3d2SAxel Dörfler
11500d59a3d2SAxel Dörfler
11510d59a3d2SAxel Dörfler// READ_CD
11520d59a3d2SAxel Dörfler
11530d59a3d2SAxel Dörflertypedef struct scsi_cmd_read_cd {
11546be1e37dSAxel Dörfler	uint8	opcode;
115593c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
11566be1e37dSAxel Dörfler		relative_address : 1,	// must be zero
11576be1e37dSAxel Dörfler		_res1_1 : 1,
11580d59a3d2SAxel Dörfler		sector_type : 3,		// required sector type (1=CDDA)
11596be1e37dSAxel Dörfler		lun : 3
11600d59a3d2SAxel Dörfler	);
11610d59a3d2SAxel Dörfler	scsi_cd_lba lba;
11626be1e37dSAxel Dörfler	uint8	high_length;
11636be1e37dSAxel Dörfler	uint8	mid_length;
11646be1e37dSAxel Dörfler	uint8	low_length;
116593c0a5d7SAxel Dörfler	B_LBITFIELD8_6(
11666be1e37dSAxel Dörfler		_res9_0 : 1,
11670d59a3d2SAxel Dörfler		error_field : 2,
11686be1e37dSAxel Dörfler		edc_ecc : 1,			// include EDC/ECC; includes 8 byte padding for Mode 1 format
11690a96e186SAxel Dörfler		user_data : 1,			// if 1, include user data
11700d59a3d2SAxel Dörfler								// (mode select block size is ignored)
11710d59a3d2SAxel Dörfler		header_code : 2,
11726be1e37dSAxel Dörfler		sync : 1				// if 1, include sync field from sector
11730d59a3d2SAxel Dörfler	);
117493c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
11750d59a3d2SAxel Dörfler		sub_channel_selection : 4,
11766be1e37dSAxel Dörfler		_res10_4 : 4
11770d59a3d2SAxel Dörfler	);
11786be1e37dSAxel Dörfler	uint8	control;
11796be1e37dSAxel Dörfler} _PACKED scsi_cmd_read_cd;
11800d59a3d2SAxel Dörfler
11810d59a3d2SAxel Dörfler// possible values for header_code
11826be1e37dSAxel Dörflerenum scsi_read_cd_header_code {
11830d59a3d2SAxel Dörfler	scsi_read_cd_header_none			= 0,
11840a96e186SAxel Dörfler	scsi_read_cd_header_hdr_only		= 1,
11850d59a3d2SAxel Dörfler	scsi_read_cd_header_sub_header_only	= 2,
11860d59a3d2SAxel Dörfler	scsi_read_cd_header_all_headers		= 3,
11876be1e37dSAxel Dörfler};
11880d59a3d2SAxel Dörfler
11890d59a3d2SAxel Dörfler// possible values for error_field
11906be1e37dSAxel Dörflerenum scsi_read_cd_error_field {
11910d59a3d2SAxel Dörfler	scsi_read_cd_error_none					= 0,
11920d59a3d2SAxel Dörfler	scsi_read_cd_error_c2_error				= 1, // include 2352 bits indicating error in byte
11930d59a3d2SAxel Dörfler	scsi_read_cd_error_c2_and_block_error	= 2, // include or of C2 data plus pad byte
11946be1e37dSAxel Dörfler};
11950d59a3d2SAxel Dörfler
11960d59a3d2SAxel Dörfler// possible values for sub_channel_selection
11976be1e37dSAxel Dörflerenum scsi_read_cd_sub_channel_selection {
11980d59a3d2SAxel Dörfler	scsi_read_cd_sub_channel_none			= 0,
11990d59a3d2SAxel Dörfler	scsi_read_cd_sub_channel_RAW			= 1,
12000d59a3d2SAxel Dörfler	scsi_read_cd_sub_channel_Q				= 2,
12010d59a3d2SAxel Dörfler	scsi_read_cd_sub_channel_P_W			= 4	// R/W data, depending on CD capabilities
12020d59a3d2SAxel Dörfler												// and Mechanism status page
12036be1e37dSAxel Dörfler};
12040d59a3d2SAxel Dörfler
1205e62e6bd5SBruno G. Albuquerque// SYNCHRONIZE CACHE (10)
1206e62e6bd5SBruno G. Albuquerque
1207e62e6bd5SBruno G. Albuquerquetypedef struct scsi_cmd_sync_cache {
12086be1e37dSAxel Dörfler	uint8	opcode;
120993c0a5d7SAxel Dörfler	B_LBITFIELD8_4(
12106be1e37dSAxel Dörfler		relative_address : 1,	// must be zero
12116be1e37dSAxel Dörfler		immediately : 1,		// 1 - return immediately, 0 - return on completion
12126be1e37dSAxel Dörfler		_res1_1 : 3,
12136be1e37dSAxel Dörfler		lun : 3
1214e62e6bd5SBruno G. Albuquerque	);
1215e62e6bd5SBruno G. Albuquerque	scsi_cd_lba lba;
12160a96e186SAxel Dörfler	uint8	_res2;
12176be1e37dSAxel Dörfler	uint16	block_count;		// big endian
12186be1e37dSAxel Dörfler	uint8	control;
12196be1e37dSAxel Dörfler} _PACKED scsi_cmd_sync_cache;
1220e62e6bd5SBruno G. Albuquerque
12210a96e186SAxel Dörfler
12226be1e37dSAxel Dörfler#endif	/* _SCSI_CMDS_H */