scsi_defs/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![expect(missing_docs)]
5#![forbid(unsafe_code)]
6
7pub mod srb;
8
9use bitfield_struct::bitfield;
10use core::fmt::Debug;
11use open_enum::open_enum;
12use zerocopy::FromBytes;
13use zerocopy::Immutable;
14use zerocopy::IntoBytes;
15use zerocopy::KnownLayout;
16
17type U16BE = zerocopy::byteorder::U16<zerocopy::byteorder::BigEndian>;
18type U32BE = zerocopy::byteorder::U32<zerocopy::byteorder::BigEndian>;
19type U64BE = zerocopy::byteorder::U64<zerocopy::byteorder::BigEndian>;
20
21open_enum! {
22    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
23    pub enum ScsiOp: u8 {
24        TEST_UNIT_READY = 0x00,
25        REZERO_UNIT = 0x01,
26        REWIND = 0x01,
27        REQUEST_BLOCK_ADDR = 0x02,
28        REQUEST_SENSE = 0x03,
29        FORMAT_UNIT = 0x04,
30        READ_BLOCK_LIMITS = 0x05,
31        REASSIGN_BLOCKS = 0x07,
32        INIT_ELEMENT_STATUS = 0x07,
33        READ6 = 0x08,
34        RECEIVE = 0x08,
35        WRITE6 = 0x0A,
36        PRINT = 0x0A,
37        SEND = 0x0A,
38        SEEK6 = 0x0B,
39        TRACK_SELECT = 0x0B,
40        SLEW_PRINT = 0x0B,
41        SET_CAPACITY = 0x0B, // tape
42        SEEK_BLOCK = 0x0C,
43        PARTITION = 0x0D,
44        READ_REVERSE = 0x0F,
45        WRITE_FILEMARKS = 0x10,
46        FLUSH_BUFFER = 0x10,
47        SPACE = 0x11,
48        INQUIRY = 0x12,
49        VERIFY6 = 0x13,
50        RECOVER_BUF_DATA = 0x14,
51        MODE_SELECT = 0x15,
52        RESERVE_UNIT = 0x16,
53        RELEASE_UNIT = 0x17,
54        COPY = 0x18,
55        ERASE = 0x19,
56        MODE_SENSE = 0x1A,
57        START_STOP_UNIT = 0x1B,
58        STOP_PRINT = 0x1B,
59        LOAD_UNLOAD = 0x1B,
60        RECEIVE_DIAGNOSTIC = 0x1C,
61        SEND_DIAGNOSTIC = 0x1D,
62        MEDIUM_REMOVAL = 0x1E,
63        READ_FORMATTED_CAPACITY = 0x23,
64        READ_CAPACITY = 0x25,
65        READ = 0x28,
66        WRITE = 0x2A,
67        SEEK = 0x2B,
68        LOCATE = 0x2B,
69        POSITION_TO_ELEMENT = 0x2B,
70        WRITE_VERIFY = 0x2E,
71        VERIFY = 0x2F,
72        SEARCH_DATA_HIGH = 0x30,
73        SEARCH_DATA_EQUAL = 0x31,
74        SEARCH_DATA_LOW = 0x32,
75        SET_LIMITS = 0x33,
76        READ_POSITION = 0x34,
77        SYNCHRONIZE_CACHE = 0x35,
78        COMPARE = 0x39,
79        COPY_COMPARE = 0x3A,
80        WRITE_DATA_BUFF = 0x3B,
81        READ_DATA_BUFF = 0x3C,
82        WRITE_LONG = 0x3F,
83        CHANGE_DEFINITION = 0x40,
84        WRITE_SAME = 0x41,
85        READ_SUB_CHANNEL = 0x42,
86        UNMAP = 0x42, // block device
87        READ_TOC = 0x43,
88        READ_HEADER = 0x44,
89        REPORT_DENSITY_SUPPORT = 0x44, // tape
90        PLAY_AUDIO = 0x45,
91        GET_CONFIGURATION = 0x46,
92        PLAY_AUDIO_MSF = 0x47,
93        PLAY_TRACK_INDEX = 0x48,
94        SANITIZE = 0x48, // block device
95        PLAY_TRACK_RELATIVE = 0x49,
96        GET_EVENT_STATUS = 0x4A,
97        PAUSE_RESUME = 0x4B,
98        LOG_SELECT = 0x4C,
99        LOG_SENSE = 0x4D,
100        STOP_PLAY_SCAN = 0x4E,
101        XDWRITE = 0x50,
102        XPWRITE = 0x51,
103        READ_DISC_INFORMATION = 0x51,
104        READ_TRACK_INFORMATION = 0x52,
105        XDWRITE_READ = 0x53,
106        RESERVE_TRACK_RZONE = 0x53,
107        SEND_OPC_INFORMATION = 0x54, // optimum power calibration
108        MODE_SELECT10 = 0x55,
109        RESERVE_UNIT10 = 0x56,
110        RESERVE_ELEMENT = 0x56,
111        RELEASE_UNIT10 = 0x57,
112        RELEASE_ELEMENT = 0x57,
113        REPAIR_TRACK = 0x58,
114        MODE_SENSE10 = 0x5A,
115        CLOSE_TRACK_SESSION = 0x5B,
116        READ_BUFFER_CAPACITY = 0x5C,
117        SEND_CUE_SHEET = 0x5D,
118        PERSISTENT_RESERVE_IN = 0x5E,
119        PERSISTENT_RESERVE_OUT = 0x5F,
120        REPORT_LUNS = 0xA0,
121        BLANK = 0xA1,
122        ATA_PASSTHROUGH12 = 0xA1,
123        SEND_EVENT = 0xA2,
124        SECURITY_PROTOCOL_IN = 0xA2,
125        SEND_KEY = 0xA3,
126        MAINTENANCE_IN = 0xA3,
127        REPORT_KEY = 0xA4,
128        MAINTENANCE_OUT = 0xA4,
129        MOVE_MEDIUM = 0xA5,
130        LOAD_UNLOAD_SLOT = 0xA6,
131        EXCHANGE_MEDIUM = 0xA6,
132        SET_READ_AHEAD = 0xA7,
133        MOVE_MEDIUM_ATTACHED = 0xA7,
134        READ12 = 0xA8,
135        GET_MESSAGE = 0xA8,
136        SERVICE_ACTION_OUT12 = 0xA9,
137        WRITE12 = 0xAA,
138        SEND_MESSAGE = 0xAB,
139        SERVICE_ACTION_IN12 = 0xAB,
140        GET_PERFORMANCE = 0xAC,
141        READ_DVD_STRUCTURE = 0xAD,
142        WRITE_VERIFY12 = 0xAE,
143        VERIFY12 = 0xAF,
144        SEARCH_DATA_HIGH12 = 0xB0,
145        SEARCH_DATA_EQUAL12 = 0xB1,
146        SEARCH_DATA_LOW12 = 0xB2,
147        SET_LIMITS12 = 0xB3,
148        READ_ELEMENT_STATUS_ATTACHED = 0xB4,
149        REQUEST_VOL_ELEMENT = 0xB5,
150        SECURITY_PROTOCOL_OUT = 0xB5,
151        SEND_VOLUME_TAG = 0xB6,
152        SET_STREAMING = 0xB6, // CD/DVD
153        READ_DEFECT_DATA = 0xB7,
154        READ_ELEMENT_STATUS = 0xB8,
155        READ_CD_MSF = 0xB9,
156        SCAN_CD = 0xBA,
157        REDUNDANCY_GROUP_IN = 0xBA,
158        SET_CD_SPEED = 0xBB,
159        REDUNDANCY_GROUP_OUT = 0xBB,
160        PLAY_CD = 0xBC,
161        SPARE_IN = 0xBC,
162        MECHANISM_STATUS = 0xBD,
163        SPARE_OUT = 0xBD,
164        READ_CD = 0xBE,
165        VOLUME_SET_IN = 0xBE,
166        SEND_DVD_STRUCTURE = 0xBF,
167        VOLUME_SET_OUT = 0xBF,
168        INIT_ELEMENT_RANGE = 0xE7,
169        XDWRITE_EXTENDED16 = 0x80, // disk
170        WRITE_FILEMARKS16 = 0x80, // tape
171        REBUILD16 = 0x81, // disk
172        READ_REVERSE16 = 0x81, // tape
173        REGENERATE16 = 0x82, // disk
174        EXTENDED_COPY = 0x83,
175        POPULATE_TOKEN = 0x83, // disk
176        WRITE_USING_TOKEN = 0x83, // disk
177        RECEIVE_COPY_RESULTS = 0x84,
178        RECEIVE_ROD_TOKEN_INFORMATION = 0x84, //disk
179        ATA_PASSTHROUGH16 = 0x85,
180        ACCESS_CONTROL_IN = 0x86,
181        ACCESS_CONTROL_OUT = 0x87,
182        READ16 = 0x88,
183        COMPARE_AND_WRITE = 0x89,
184        WRITE16 = 0x8A,
185        READ_ATTRIBUTES = 0x8C,
186        WRITE_ATTRIBUTES = 0x8D,
187        WRITE_VERIFY16 = 0x8E,
188        VERIFY16 = 0x8F,
189        PREFETCH16 = 0x90,
190        SYNCHRONIZE_CACHE16 = 0x91,
191        SPACE16 = 0x91, // tape
192        LOCK_UNLOCK_CACHE16 = 0x92,
193        LOCATE16 = 0x92, // tape
194        WRITE_SAME16 = 0x93,
195        ERASE16 = 0x93, // tape
196        ZBC_OUT = 0x94, // Close Zone, Finish Zone, Open Zone, Reset Write Pointer, etc.
197        ZBC_IN = 0x95, // Report Zones, etc.
198        READ_DATA_BUFF16 = 0x9B,
199        READ_CAPACITY16 = 0x9E,
200        GET_LBA_STATUS = 0x9E,
201        GET_PHYSICAL_ELEMENT_STATUS = 0x9E,
202        REMOVE_ELEMENT_AND_TRUNCATE = 0x9E,
203        SERVICE_ACTION_IN16 = 0x9E,
204        SERVICE_ACTION_OUT16 = 0x9F,
205    }
206}
207
208pub const VPD_SUPPORTED_PAGES: u8 = 0x00;
209pub const VPD_SERIAL_NUMBER: u8 = 0x80;
210pub const VPD_DEVICE_IDENTIFIERS: u8 = 0x83;
211pub const VPD_THIRD_PARTY_COPY: u8 = 0x8F;
212pub const VPD_BLOCK_LIMITS: u8 = 0xB0;
213pub const VPD_BLOCK_DEVICE_CHARACTERISTICS: u8 = 0xB1;
214pub const VPD_LOGICAL_BLOCK_PROVISIONING: u8 = 0xB2;
215pub const VPD_MSFT_VIRTUAL_DEVICE_PROPERTIES: u8 = 0xCF;
216pub const VPD_MSFT_PAGING_EXTENT_PROPERTIES: u8 = 0xCE;
217pub const DIRECT_ACCESS_DEVICE: u8 = 0x00;
218pub const READ_ONLY_DIRECT_ACCESS_DEVICE: u8 = 0x05;
219pub const ISO_INQUIRY_VPD_SUPPORTED_PAGE_COUNT: u8 = 0x02;
220
221pub const VPD_CODE_SET_RESERVED: u8 = 0;
222pub const VPD_CODE_SET_BINARY: u8 = 1;
223pub const VPD_CODE_SET_ASCII: u8 = 2;
224pub const VPD_CODE_SET_UTF8: u8 = 3;
225
226pub const VPD_IDENTIFIER_TYPE_VENDOR_ID: u8 = 1;
227pub const VPD_IDENTIFIER_TYPE_FCPH_NAME: u8 = 3;
228
229pub const INQUIRY_DATA_BUFFER_SIZE: u8 = 36;
230
231// readiness errors
232pub const MEDIUM_NOT_PRESENT_TRAY_CLOSED: u8 = 0x01;
233pub const MEDIUM_NOT_PRESENT_TRAY_OPEN: u8 = 0x02;
234
235#[repr(C)]
236#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
237pub struct CdbInquiry {
238    pub operation_code: u8, // 0x12 - SCSIOP_INQUIRY
239    pub flags: InquiryFlags,
240    pub page_code: u8,
241    pub allocation_length: U16BE,
242    pub control: u8,
243}
244
245#[bitfield(u8)]
246#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
247pub struct InquiryFlags {
248    #[bits(1)]
249    pub vpd: bool,
250    #[bits(1)]
251    pub csd: bool,
252    #[bits(6)]
253    pub reserved: u8,
254}
255
256pub const INQUIRY_ENABLE_VPD: u8 = 0x1;
257pub const INQUIRY_COMMAND_SUPPORT_DATA: u8 = 0x2;
258pub const T10_VERSION_SPC3: u8 = 0x05;
259pub const T10_RESPONSE_DATA_SPC3: u8 = 0x02;
260
261/*
262struct InquiryData {
263    UCHAR DeviceType : 5;
264    UCHAR DeviceTypeQualifier : 3;
265
266    UCHAR DeviceTypeModifier : 7;
267    UCHAR RemovableMedia : 1;
268
269    union {
270        UCHAR Versions;
271        struct {
272            UCHAR ANSIVersion : 3;
273            UCHAR ECMAVersion : 3;
274            UCHAR ISOVersion : 2;
275        };
276    };
277
278    UCHAR ResponseDataFormat : 4;
279    UCHAR HiSupport : 1;
280    UCHAR NormACA : 1;
281    UCHAR TerminateTask : 1;
282    UCHAR AERC : 1;
283
284    UCHAR AdditionalLength;
285
286    //5
287    union {
288        UCHAR Reserved;
289        struct {
290            UCHAR PROTECT : 1;
291            UCHAR Reserved_1 : 2;
292            UCHAR ThirdPartyCopy : 1;
293            UCHAR TPGS : 2;
294            UCHAR ACC : 1;
295            UCHAR SCCS : 1;
296       };
297    };
298
299    UCHAR Addr16 : 1;               // defined only for SIP devices.
300    UCHAR Addr32 : 1;               // defined only for SIP devices.
301    UCHAR AckReqQ: 1;               // defined only for SIP devices.
302    UCHAR MediumChanger : 1;
303    UCHAR MultiPort : 1;
304    UCHAR ReservedBit2 : 1;
305    UCHAR EnclosureServices : 1;
306    UCHAR ReservedBit3 : 1;
307
308    // 7
309    UCHAR SoftReset : 1;
310    UCHAR CommandQueue : 1;
311    UCHAR TransferDisable : 1;      // defined only for SIP devices.
312    UCHAR LinkedCommands : 1;
313    UCHAR Synchronous : 1;          // defined only for SIP devices.
314    UCHAR Wide16Bit : 1;            // defined only for SIP devices.
315    UCHAR Wide32Bit : 1;            // defined only for SIP devices.
316    UCHAR RelativeAddressing : 1;
317
318    // 8
319    UCHAR VendorId[8];
320    //16
321    UCHAR ProductId[16];
322    //32
323    UCHAR ProductRevisionLevel[4];
324    //36
325    UCHAR VendorSpecific[20];
326    //56
327    UCHAR Reserved3[2];
328    //58
329    VERSION_DESCRIPTOR VersionDescriptors[8];
330    //74
331    UCHAR Reserved4[30];
332    //104
333} INQUIRYDATA, *PINQUIRYDATA;
334*/
335
336#[repr(C)]
337#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
338pub struct InquiryDataHeader {
339    /*
340    UCHAR DeviceType : 5;
341    UCHAR DeviceTypeQualifier : 3;
342    */
343    pub device_type: u8,
344    pub flags2: InquiryDataFlag2,
345    pub versions: u8,
346    pub flags3: InquiryDataFlag3,
347    pub additional_length: u8,
348}
349
350#[bitfield(u8)]
351#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
352pub struct InquiryDataFlag2 {
353    #[bits(7)]
354    pub device_type_modifier: u8,
355    #[bits(1)]
356    pub removable_media: bool,
357}
358
359#[bitfield(u8)]
360#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
361pub struct InquiryDataFlag3 {
362    #[bits(4)]
363    pub response_data_format: u8,
364    #[bits(1)]
365    pub hi_support: bool,
366    #[bits(1)]
367    pub norm_aca: bool,
368    #[bits(1)]
369    pub reserved_bit: bool,
370    #[bits(1)]
371    pub aerc: bool,
372}
373
374#[repr(C)]
375#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
376pub struct InquiryData {
377    pub header: InquiryDataHeader,
378    pub reserved: [u8; 2],
379    /*
380    UCHAR SoftReset : 1;
381    UCHAR CommandQueue : 1;
382    UCHAR TransferDisable : 1;      // defined only for SIP devices.
383    UCHAR LinkedCommands : 1;
384    UCHAR Synchronous : 1;          // defined only for SIP devices.
385    UCHAR Wide16Bit : 1;            // defined only for SIP devices.
386    UCHAR Wide32Bit : 1;            // defined only for SIP devices.
387    UCHAR RelativeAddressing : 1;
388     */
389    pub misc: u8,
390    pub vendor_id: [u8; 8],
391    pub product_id: [u8; 16],
392    pub product_revision_level: [u8; 4],
393    pub vendor_specific: [u8; 20],
394    pub reserved3: [u8; 2],
395    pub version_descriptors: [u16; 8],
396    pub reserved4: [u8; 30],
397}
398
399#[repr(C)]
400#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
401pub struct VpdPageHeader {
402    /*
403    UCHAR DeviceType : 5;
404    UCHAR DeviceTypeQualifier : 3;
405     */
406    pub device_type: u8,
407    pub page_code: u8,
408    pub reserved: u8,
409    pub page_length: u8,
410}
411
412#[repr(C)]
413#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
414pub struct VpdT10Id {
415    pub header: VpdIdentificationDescriptor,
416    pub vendor_id: [u8; 8],
417    pub context_guid: [u8; 16],
418}
419
420/// NAA IEEE Registered Extended designator format.
421/// => NAA = 6.
422///
423#[repr(C)]
424#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
425pub struct VpdNaaId {
426    pub header: VpdIdentificationDescriptor,
427    /*
428    UCHAR OuidMSB : 4;
429    UCHAR Naa : 4;
430     */
431    pub ouid_msb: u8,
432    pub ouid_middle: [u8; 2],
433    /*
434    UCHAR Reserved4 : 4; // part of vendor specific id, always set to 0.
435    UCHAR OuidLSB : 4;
436     */
437    pub ouid_lsb: u8,
438    pub vendor_specific_id: [u8; 12],
439}
440
441#[repr(C)]
442#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
443pub struct VpdIdentificationDescriptor {
444    pub code_set: u8,
445    pub identifiertype: u8,
446    pub reserved3: u8,
447    pub identifier_length: u8,
448}
449
450#[repr(C)]
451#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
452pub struct VpdBlockLimitsDescriptor {
453    pub reserved0: u8,
454    pub max_compare_and_write_length: u8,
455    pub optimal_transfer_length_granularity: U16BE,
456    pub max_transfer_length: U32BE,
457    pub optimal_transfer_length: U32BE,
458    pub max_prefetch_xd_read_xd_write_transfer_length: U32BE,
459    pub max_unmap_lba_count: U32BE,
460    pub max_unmap_block_descriptor_count: U32BE,
461    pub optimal_unmap_granularity: U32BE,
462    pub unmap_granularity_alignment: [u8; 4],
463    pub max_write_same_length: U64BE,
464    pub max_atomic_transfer_length: U32BE,
465    pub atomic_alignment: U32BE,
466    pub atomic_transfer_length_granularity: U32BE,
467    pub reserved1: [u8; 8],
468}
469
470/// VPD Page 0xB1, Block Device Characteristics
471#[repr(C)]
472#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
473pub struct VpdBlockDeviceCharacteristicsPage {
474    pub medium_rotation_rate: U16BE,
475    pub data: [u8; 58], // Needn't know the details
476}
477
478#[repr(C)]
479#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
480pub struct VpdMsftVirtualDevicePropertiesPage {
481    pub version: u8,
482    /*
483    UCHAR LBPRZ     : 1;
484    UCHAR DisableIoRetries : 1; // Added in v2, indicates Classpnp should not perform any retries (any relevant retries would have been performed at a lower, physical stack).
485    UCHAR Spaces : 1; // Added in v2, indicates this is a storage space
486    UCHAR Reserved1 : 5;
487    */
488    pub flags: u8,
489    pub reserved: [u8; 2],
490    pub signature: [u8; 16],
491}
492
493#[repr(C)]
494#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
495pub struct VpdMsftPagingExtentPropertiesPage {
496    pub version: u8,
497    /*
498    UCHAR ModeSelectExtension : 1;
499    UCHAR Reserved1 : 7;
500     */
501    pub mode_select_extension: u8,
502    pub reserved: [u8; 2],
503}
504
505// VPD Page 0xB2, Logical Block Provisioning
506
507pub const PROVISIONING_TYPE_UNKNOWN: u8 = 0x0;
508pub const PROVISIONING_TYPE_RESOURCE: u8 = 0x1;
509pub const PROVISIONING_TYPE_THIN: u8 = 0x2;
510
511#[repr(C)]
512#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
513pub struct VpdLogicalBlockProvisioningPage {
514    pub threshold_exponent: u8,
515    /*
516    UCHAR DP                : 1;
517    UCHAR ANC_SUP           : 1;
518    UCHAR LBPRZ             : 1;
519    UCHAR Reserved0         : 2;
520    UCHAR LBPWS10           : 1;
521    UCHAR LBPWS             : 1;
522    UCHAR LBPU              : 1;
523    */
524    pub flags: u8,
525    /*
526    UCHAR ProvisioningType  : 3;
527    UCHAR Reserved1         : 5;
528    */
529    pub provisioning_type: u8,
530    pub reserved2: u8,
531}
532
533#[repr(C)]
534#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
535pub struct SenseDataHeader {
536    /*
537    UCHAR ErrorCode:7;
538    UCHAR Valid:1;
539     */
540    pub error_code: SenseDataErrorCode,
541    pub segment_number: u8,
542    /*
543    UCHAR SenseKey:4;
544    UCHAR Reserved:1;
545    UCHAR IncorrectLength:1;
546    UCHAR EndOfMedia:1;
547    UCHAR FileMark:1;
548     */
549    pub sense_key: SenseKey,
550    /*
551    reserved:1 : u8,
552    incorrect_length:1 : u8,
553    end_of_media:1 : u8,
554    file_mark:1 : u8,
555    */
556    pub information: [u8; 4],
557    pub additional_sense_length: u8,
558}
559
560#[repr(C)]
561#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
562pub struct SenseData {
563    pub header: SenseDataHeader,
564    pub command_specific_information: [u8; 4],
565    pub additional_sense_code: AdditionalSenseCode,
566    pub additional_sense_code_qualifier: u8,
567    pub field_replaceable_unit_code: u8,
568    pub sense_key_specific: [u8; 3],
569}
570
571impl SenseData {
572    pub const fn new(
573        sense_key: SenseKey,
574        additional_sense_code: AdditionalSenseCode,
575        additional_sense_code_qualifier: u8,
576    ) -> Self {
577        // Fill in sense info
578        // Since MM Drives support only a 32-bit LBA format, MM Drives ignore the setting of the
579        // Desc bit in the REQUEST SENSE command CDB and return only fixed format sense data.
580        SenseData {
581            header: SenseDataHeader {
582                error_code: SenseDataErrorCode::FIXED_CURRENT,
583                segment_number: 0,
584                sense_key,
585                information: [0; 4],
586                additional_sense_length: (size_of::<SenseData>() - size_of::<SenseDataHeader>())
587                    as u8,
588            },
589            command_specific_information: [0; 4],
590            additional_sense_code,
591            additional_sense_code_qualifier,
592            field_replaceable_unit_code: 0,
593            sense_key_specific: [0; 3],
594        }
595    }
596}
597
598open_enum! {
599    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
600    pub enum SenseKey: u8 {
601        NO_SENSE = 0x00,
602        RECOVERED_ERROR = 0x01,
603        NOT_READY = 0x02,
604        MEDIUM_ERROR = 0x03,
605        HARDWARE_ERROR = 0x04,
606        ILLEGAL_REQUEST = 0x05,
607        UNIT_ATTENTION = 0x06,
608        DATA_PROTECT = 0x07,
609        BLANK_CHECK = 0x08,
610        UNIQUE = 0x09,
611        COPY_ABORTED = 0x0A,
612        ABORTED_COMMAND = 0x0B,
613        EQUAL = 0x0C,
614        VOL_OVERFLOW = 0x0D,
615        MISCOMPARE = 0x0E,
616        RESERVED = 0x0F,
617    }
618}
619
620open_enum! {
621    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
622    pub enum SenseDataErrorCode: u8 {
623        FIXED_CURRENT = 0x70,
624        FIXED_DEFERRED = 0x71,
625        DESCRIPTOR_CURRENT = 0x72,
626        DESCRIPTOR_DEFERRED = 0x73,
627    }
628}
629
630open_enum! {
631    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
632    pub enum AdditionalSenseCode: u8 {
633        NO_SENSE = 0x00,
634        NO_SEEK_COMPLETE = 0x02,
635        WRITE = 0x03,
636        LUN_NOT_READY = 0x04,
637        LUN_COMMUNICATION = 0x08,
638        SERVO_ERROR = 0x09,
639        WARNING = 0x0B,
640        WRITE_ERROR = 0x0C,
641        COPY_TARGET_DEVICE_ERROR = 0x0D,
642        CRC_OR_ECC_ERROR = 0x10,
643        UNRECOVERED_ERROR = 0x11,
644        TRACK_ERROR = 0x14,
645        SEEK_ERROR = 0x15,
646        REC_DATA_NOECC = 0x17,
647        REC_DATA_ECC = 0x18,
648        DEFECT_LIST_ERROR = 0x19,
649        PARAMETER_LIST_LENGTH = 0x1A,
650        MISCOMPARE_DURING_VERIFY_OPERATION = 0x1D,
651        ILLEGAL_COMMAND = 0x20,
652        ACCESS_DENIED = 0x20,
653        ILLEGAL_BLOCK = 0x21,
654        INVALID_TOKEN = 0x23,
655        INVALID_CDB = 0x24,
656        INVALID_LUN = 0x25,
657        INVALID_FIELD_PARAMETER_LIST = 0x26,
658        WRITE_PROTECT = 0x27,
659        MEDIUM_CHANGED = 0x28,
660        BUS_RESET = 0x29,
661        PARAMETERS_CHANGED = 0x2A,
662        COMMAND_SEQUENCE_ERROR = 0x2C,
663        INSUFFICIENT_TIME_FOR_OPERATION = 0x2E,
664        INVALID_MEDIA = 0x30,
665        MEDIUM_FORMAT_CORRUPTED = 0x31,
666        DEFECT_LIST = 0x32,
667        LB_PROVISIONING = 0x38,
668        SAVING_PARAMETER_NOT_SUPPORTED = 0x39,
669        NO_MEDIA_IN_DEVICE = 0x3a,
670        POSITION_ERROR = 0x3b,
671        LOGICAL_UNIT_ERROR = 0x3e,
672        OPERATING_CONDITIONS_CHANGED = 0x3f,
673        DATA_PATH_FAILURE = 0x41,
674        POWER_ON_SELF_TEST_FAILURE = 0x42,
675        INTERNAL_TARGET_FAILURE = 0x44,
676        DATA_TRANSFER_ERROR = 0x4b,
677        LUN_FAILED_SELF_CONFIGURATION = 0x4c,
678        MEDIUM_REMOVAL_PREVENTED = 0x53,
679        RESOURCE_FAILURE = 0x55,
680        OPERATOR_REQUEST = 0x5a, // see below
681        FAILURE_PREDICTION_THRESHOLD_EXCEEDED = 0x5d,
682        ILLEGAL_MODE_FOR_THIS_TRACK = 0x64,
683        COPY_PROTECTION_FAILURE = 0x6f,
684        POWER_CALIBRATION_ERROR = 0x73,
685        VENDOR_UNIQUE = 0x80, // and higher
686        MUSIC_AREA = 0xA0,
687        DATA_AREA = 0xA1,
688        VOLUME_OVERFLOW = 0xA7,
689    }
690}
691
692// SCSI_ADSENSE_LUN_NOT_READY (0x04) qualifiers
693pub const SCSI_SENSEQ_FORMAT_IN_PROGRESS: u8 = 0x04;
694
695// SCSI_ADSENSE_WARNING (0x0B) qualifiers
696pub const SCSI_SENSEQ_POWER_LOSS_EXPECTED: u8 = 0x08;
697
698// SCSI_ADSENSE_CRC_OR_ECC_ERROR (0x10) qualifiers
699pub const SCSI_SENSEQ_LOGICAL_BLOCK_GUARD_CHECK_FAILED: u8 = 0x01;
700pub const SCSI_SENSEQ_LOGICAL_BLOCK_TAG_CHECK_FAILED: u8 = 0x02;
701pub const SCSI_SENSEQ_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: u8 = 0x03;
702
703// SCSI_ADSENSE_ACCESS_DENIED (0x20) qualifiers
704pub const SCSI_SENSEQ_NO_ACCESS_RIGHTS: u8 = 0x02;
705pub const SCSI_SENSEQ_INVALID_LU_ID: u8 = 0x09;
706
707// SCSI_ADSENSE_PARAMETERS_CHANGED (0x2A) qualifiers
708pub const SCSI_SENSEQ_CAPACITY_DATA_CHANGED: u8 = 0x09;
709
710// SCSI_ADSENSE_INVALID_MEDIA (0x30) qualifiers
711pub const SCSI_SENSEQ_INCOMPATIBLE_FORMAT: u8 = 0x02;
712
713// SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED (0x3f) qualifiers
714pub const SCSI_SENSEQ_OPERATING_DEFINITION_CHANGED: u8 = 0x02;
715
716open_enum! {
717    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
718    #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
719    pub enum ScsiStatus: u8 {
720        GOOD = 0x00,
721        CHECK_CONDITION = 0x02,
722        CONDITION_MET = 0x04,
723        BUSY = 0x08,
724        INTERMEDIATE = 0x10,
725        INTERMEDIATE_COND_MET = 0x14,
726        RESERVATION_CONFLICT = 0x18,
727        COMMAND_TERMINATED = 0x22,
728        QUEUE_FULL = 0x28,
729        TASK_ABORTED = 0x40,
730    }
731}
732
733#[repr(C)]
734#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
735pub struct ReadCapacityData {
736    pub logical_block_address: U32BE,
737    pub bytes_per_block: U32BE,
738}
739
740#[repr(C)]
741#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
742pub struct ModeSense {
743    pub operation_code: ScsiOp,
744    pub flags1: u8,
745    pub flags2: ModeSenseFlags,
746    pub sub_page_code: u8,
747    pub allocation_length: u8,
748    pub control: u8,
749}
750
751#[repr(C)]
752#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
753pub struct ModeSense10 {
754    pub operation_code: ScsiOp,
755    pub flags1: u8,
756    pub flags2: ModeSenseFlags,
757    pub sub_page_code: u8,
758    pub reserved2: [u8; 3],
759    pub allocation_length: U16BE,
760    pub control: u8,
761}
762
763#[bitfield(u8)]
764#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
765pub struct ModeSenseFlags {
766    #[bits(6)]
767    pub page_code: u8,
768    #[bits(2)]
769    pub pc: u8,
770}
771
772#[repr(C)]
773#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
774pub struct ModeReadWriteRecoveryPage {
775    /*
776        UCHAR PageCode : 6;
777        UCHAR Reserved1 : 1;
778        UCHAR PSBit : 1;
779    */
780    pub page_code: u8,
781    pub page_length: u8,
782    /*
783       UCHAR DCRBit : 1;
784       UCHAR DTEBit : 1;
785       UCHAR PERBit : 1;
786       UCHAR EERBit : 1;
787       UCHAR RCBit : 1;
788       UCHAR TBBit : 1;
789       UCHAR ARRE : 1;
790       UCHAR AWRE : 1;
791    */
792    pub bit_info: u8,
793    pub read_retry_count: u8,
794    pub reserved: [u8; 4],
795    pub write_retry_count: u8,
796    pub reserved2: [u8; 3],
797}
798
799#[repr(C)]
800#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
801pub struct ModeSenseModePageTimeoutProtect {
802    /*
803       UCHAR PageCode : 6;
804       UCHAR Reserved1 : 1;
805       UCHAR PSBit : 1;
806    */
807    pub page_code: u8,
808    pub page_length: u8,
809    pub reserved: [u8; 2],
810    /*
811       UCHAR SWPP : 1;
812       UCHAR DISP : 1;
813       UCHAR TMOE : 1;
814       UCHAR G3Enable : 1;
815       UCHAR Reserved3 : 4;
816    */
817    pub bit_info: u8,
818    pub reserved2: u8,
819    pub group_one_minimum_timeout: [u8; 2],
820    pub group_two_minimum_timeout: [u8; 2],
821    pub group_three_timeout: [u8; 2],
822}
823
824#[repr(C)]
825#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
826pub struct PowerConditionPage {
827    /*
828       UCHAR PageCode : 6;
829       UCHAR Reserved1 : 1;
830       UCHAR PSBit : 1;
831    */
832    pub page_code: u8,
833    pub page_length: u8,
834    pub reserved: u8,
835    /*
836       UCHAR Standby : 1;
837       UCHAR Idle : 1;
838       UCHAR Reserved3 : 6;
839    */
840    pub flags: u8,
841    pub idle_timer: U32BE,
842    pub standby_timer: U32BE,
843}
844
845pub const LIST_OF_MODE_PAGES: [u8; 3] = [
846    MODE_PAGE_ERROR_RECOVERY,
847    MODE_PAGE_POWER_CONDITION,
848    MODE_PAGE_CDVD_INACTIVITY,
849];
850
851#[repr(C)]
852#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
853pub struct ModeSelect {
854    pub operation_code: ScsiOp,
855    pub flags: ModeSelectFlags,
856    pub reserved2: [u8; 2],
857    pub parameter_list_length: u8,
858    pub control: u8,
859}
860
861#[repr(C)]
862#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
863pub struct ModeSelect10 {
864    pub operation_code: ScsiOp,
865    pub flags: ModeSelectFlags,
866    pub reserved2: [u8; 5],
867    pub parameter_list_length: U16BE,
868    pub control: u8,
869}
870
871#[bitfield(u8)]
872#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
873pub struct ModeSelectFlags {
874    #[bits(1)]
875    pub spbit: bool,
876    #[bits(7)]
877    pub other_flags: u8,
878}
879
880pub const MODE_CONTROL_CURRENT_VALUES: u8 = 0x00;
881pub const MODE_CONTROL_CHANGEABLE_VALUES: u8 = 0x40;
882pub const MODE_CONTROL_DEFAULT_VALUES: u8 = 0x80;
883pub const MODE_CONTROL_SAVED_VALUES: u8 = 0xc0;
884
885pub const MODE_PAGE_VENDOR_SPECIFIC: u8 = 0x00;
886pub const MODE_PAGE_ERROR_RECOVERY: u8 = 0x01;
887pub const MODE_PAGE_DISCONNECT: u8 = 0x02;
888pub const MODE_PAGE_FORMAT_DEVICE: u8 = 0x03; // disk
889pub const MODE_PAGE_MRW: u8 = 0x03; // cdrom
890pub const MODE_PAGE_RIGID_GEOMETRY: u8 = 0x04;
891pub const MODE_PAGE_FLEXIBLE: u8 = 0x05; // disk
892pub const MODE_PAGE_WRITE_PARAMETERS: u8 = 0x05; // cdrom
893pub const MODE_PAGE_VERIFY_ERROR: u8 = 0x07;
894pub const MODE_PAGE_CACHING: u8 = 0x08;
895pub const MODE_PAGE_PERIPHERAL: u8 = 0x09;
896pub const MODE_PAGE_CONTROL: u8 = 0x0A;
897pub const MODE_PAGE_MEDIUM_TYPES: u8 = 0x0B;
898pub const MODE_PAGE_NOTCH_PARTITION: u8 = 0x0C;
899pub const MODE_PAGE_CD_AUDIO_CONTROL: u8 = 0x0E;
900pub const MODE_PAGE_DATA_COMPRESS: u8 = 0x0F;
901pub const MODE_PAGE_DEVICE_CONFIG: u8 = 0x10;
902pub const MODE_PAGE_XOR_CONTROL: u8 = 0x10; // disk
903pub const MODE_PAGE_MEDIUM_PARTITION: u8 = 0x11;
904pub const MODE_PAGE_ENCLOSURE_SERVICES_MANAGEMENT: u8 = 0x14;
905pub const MODE_PAGE_EXTENDED: u8 = 0x15;
906pub const MODE_PAGE_EXTENDED_DEVICE_SPECIFIC: u8 = 0x16;
907pub const MODE_PAGE_CDVD_FEATURE_SET: u8 = 0x18;
908pub const MODE_PAGE_PROTOCOL_SPECIFIC_LUN: u8 = 0x18;
909pub const MODE_PAGE_PROTOCOL_SPECIFIC_PORT: u8 = 0x19;
910pub const MODE_PAGE_POWER_CONDITION: u8 = 0x1A;
911pub const MODE_PAGE_LUN_MAPPING: u8 = 0x1B;
912pub const MODE_PAGE_FAULT_REPORTING: u8 = 0x1C;
913pub const MODE_PAGE_CDVD_INACTIVITY: u8 = 0x1D; // cdrom
914pub const MODE_PAGE_ELEMENT_ADDRESS: u8 = 0x1D;
915pub const MODE_PAGE_TRANSPORT_GEOMETRY: u8 = 0x1E;
916pub const MODE_PAGE_DEVICE_CAPABILITIES: u8 = 0x1F;
917pub const MODE_PAGE_CAPABILITIES: u8 = 0x2A; // cdrom
918pub const MODE_PAGE_ALL: u8 = 0x3f;
919pub const MODE_SENSE_SAVED_VALUES: u8 = 0xc0;
920pub const MODE_SENSE_RETURN_ALL: u8 = 0x3f;
921
922#[repr(C)]
923#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
924pub struct ModeParameterHeader {
925    pub mode_data_length: u8,
926    pub medium_type: u8,
927    pub device_specific_parameter: u8,
928    pub block_descriptor_length: u8,
929}
930
931#[repr(C)]
932#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
933pub struct ModeParameterHeader10 {
934    pub mode_data_length: U16BE,
935    pub medium_type: u8,
936    pub device_specific_parameter: u8,
937    pub reserved: [u8; 2],
938    pub block_descriptor_length: U16BE,
939}
940
941#[repr(C)]
942#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
943pub struct ModeCachingPage {
944    /*
945    UCHAR PageCode : 6;
946    UCHAR Reserved : 1;
947    UCHAR PageSavable : 1;
948     */
949    pub page_code: u8,
950    pub page_length: u8,
951    /*
952    UCHAR ReadDisableCache : 1;
953    UCHAR MultiplicationFactor : 1;
954    UCHAR WriteCacheEnable : 1;
955    UCHAR Reserved2 : 5;
956     */
957    pub flags: u8,
958    /*
959    UCHAR WriteRetensionPriority : 4;
960    UCHAR ReadRetensionPriority : 4;
961     */
962    pub retension_priority: u8,
963    pub disable_prefetch_transfer: [u8; 2],
964    pub minimum_prefetch: [u8; 2],
965    pub maximum_prefetch: [u8; 2],
966    pub maximum_prefetch_ceiling: [u8; 2],
967}
968
969pub const MODE_CACHING_WRITE_CACHE_ENABLE: u8 = 0x4;
970pub const WRITE_CACHE_ENABLE_BYTE_OFFSET: usize = 3;
971
972pub const MODE_DSP_FUA_SUPPORTED: u8 = 0x10;
973pub const MODE_DSP_WRITE_PROTECT: u8 = 0x80;
974
975#[repr(C)]
976#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
977pub struct LunList {
978    pub length: U32BE,
979    pub reserved: [u8; 4],
980}
981
982#[repr(C)]
983#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
984pub struct LunListEntry(pub [u8; 8]);
985
986#[repr(C)]
987#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
988pub struct Cdb10 {
989    pub operation_code: ScsiOp,
990    pub flags: CdbFlags,
991    pub logical_block: U32BE,
992    pub reserved2: u8,
993    pub transfer_blocks: U16BE,
994    pub control: u8,
995}
996
997#[repr(C)]
998#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
999pub struct Cdb6ReadWrite {
1000    pub operation_code: u8, // 0x08, 0x0A - SCSIOP_READ, SCSIOP_WRITE
1001    pub logical_block: [u8; 3],
1002    pub transfer_blocks: u8,
1003    pub control: u8,
1004}
1005
1006#[repr(C)]
1007#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1008pub struct Cdb12 {
1009    pub operation_code: ScsiOp,
1010    pub flags: CdbFlags,
1011    pub logical_block: U32BE,
1012    pub transfer_blocks: U32BE,
1013    pub reserved2: u8,
1014    pub control: u8,
1015}
1016
1017#[repr(C)]
1018#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1019pub struct Cdb16 {
1020    pub operation_code: ScsiOp,
1021    pub flags: Cdb16Flags,
1022    pub logical_block: U64BE,
1023    pub transfer_blocks: U32BE,
1024    pub reserved2: u8,
1025    pub control: u8,
1026}
1027
1028#[bitfield(u8)]
1029#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1030pub struct CdbFlags {
1031    pub relative_address: bool,
1032    #[bits(2)]
1033    pub reserved1: u8,
1034    pub fua: bool,
1035    pub disable_page_out: bool,
1036    #[bits(3)]
1037    pub protection: u8,
1038}
1039
1040#[bitfield(u8)]
1041#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1042pub struct Cdb16Flags {
1043    #[bits(3)]
1044    pub reserved1: u8,
1045    pub fua: bool,
1046    pub disable_page_out: bool,
1047    #[bits(3)]
1048    pub protection: u8,
1049}
1050
1051#[repr(C)]
1052#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1053pub struct ServiceActionIn16 {
1054    pub operation_code: ScsiOp,
1055    pub service_action: u8,
1056    pub logical_block: [u8; 8],
1057    pub allocation_length: [u8; 4],
1058    pub flags: u8,
1059    pub control: u8,
1060}
1061
1062pub const SERVICE_ACTION_READ_CAPACITY16: u8 = 0x10;
1063pub const SERVICE_ACTION_GET_LBA_STATUS: u8 = 0x12;
1064pub const SERVICE_ACTION_GET_PHYSICAL_ELEMENT_STATUS: u8 = 0x17;
1065pub const SERVICE_ACTION_REMOVE_ELEMENT_AND_TRUNCATE: u8 = 0x18;
1066
1067#[repr(C)]
1068#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1069pub struct ReadCapacityDataEx {
1070    pub logical_block_address: U64BE,
1071    pub bytes_per_block: U32BE,
1072}
1073
1074#[repr(C)]
1075#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1076pub struct ReadCapacity16Data {
1077    pub ex: ReadCapacityDataEx,
1078    /*
1079    UCHAR ProtectionEnable : 1;
1080    UCHAR ProtectionType : 3;
1081    UCHAR RcBasis  : 2;
1082    UCHAR Reserved : 2;
1083    */
1084    pub flags: u8,
1085    /*
1086    UCHAR LogicalPerPhysicalExponent : 4;
1087    UCHAR ProtectionInfoExponent : 4;
1088     */
1089    pub exponents: u8, // low: logical per physical, high: protection info
1090    /*
1091    UCHAR LowestAlignedBlock_MSB : 6;
1092    UCHAR LBPRZ : 1;
1093    UCHAR LBPME : 1;
1094    UCHAR LowestAlignedBlock_LSB;
1095    */
1096    pub lowest_aligned_block_msb: u8,
1097    pub lowest_aligned_block_lsb: u8,
1098    pub reserved: [u8; 16],
1099}
1100
1101pub const READ_CAPACITY16_LBPRZ: u8 = 1 << 6;
1102pub const READ_CAPACITY16_LBPME: u8 = 1 << 7;
1103
1104// This flag indicates that there is some special behavior required for the
1105// request.  The precise meaning of the flag depends on the type/context of the
1106// request.
1107pub const SRB_FLAGS_MS_SPECIAL_BEHAVIOR: u32 = 0x00008000;
1108// For SCSI GET LBA STATUS, the special behavior flag indicates that the device
1109// should only return blocks that are consolidateable as "mapped".  Blocks that
1110// shouldn't be consolidated should be returned as "unmapped".
1111pub const SRB_FLAGS_CONSOLIDATEABLE_BLOCKS_ONLY: u32 = SRB_FLAGS_MS_SPECIAL_BEHAVIOR;
1112// For SCSI UNMAP, the special behavior flag indicates that the request is a
1113// block-level request. If this flag is not set, it does NOT imply the request
1114// is a file-level request.
1115pub const SRB_FLAGS_BLOCK_LEVEL_ONLY: u32 = SRB_FLAGS_MS_SPECIAL_BEHAVIOR;
1116
1117#[repr(C)]
1118#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1119pub struct GetLbaStatus {
1120    pub operation_code: ScsiOp,
1121    /*
1122    UCHAR ServiceAction : 5;
1123    UCHAR Reserved1     : 3;
1124    */
1125    pub service_action: u8,
1126    pub start_lba: U64BE,
1127    pub allocation_length: U32BE,
1128    pub reserved: u8,
1129    pub control: u8,
1130}
1131
1132#[repr(C)]
1133#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1134pub struct LbaStatusDescriptor {
1135    pub start_lba: U64BE,
1136    pub logical_block_count: U32BE,
1137    /*
1138    UCHAR ProvisioningStatus : 4;
1139    UCHAR Reserved1 : 4;
1140    */
1141    pub provisioning_status: u8,
1142    pub reserved2: [u8; 3],
1143}
1144
1145#[repr(C)]
1146#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1147pub struct LbaStatusListHeader {
1148    pub parameter_length: U32BE,
1149    pub reserved: u32,
1150}
1151
1152pub const LBA_STATUS_MAPPED: u8 = 0x0;
1153pub const LBA_STATUS_DEALLOCATED: u8 = 0x1;
1154pub const LBA_STATUS_ANCHORED: u8 = 0x2;
1155
1156#[repr(C)]
1157#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1158pub struct Unmap {
1159    pub operation_code: ScsiOp,
1160    /*
1161    UCHAR Anchor        : 1;
1162    UCHAR Reserved1     : 7;
1163    */
1164    pub anchor: u8,
1165    pub reserved2: [u8; 4],
1166    /*
1167    UCHAR GroupNumber   : 5;
1168    UCHAR Reserved3     : 3;
1169    */
1170    pub group_number: u8,
1171    pub allocation_length: U16BE,
1172    pub control: u8,
1173}
1174
1175#[repr(C)]
1176#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1177pub struct UnmapBlockDescriptor {
1178    pub start_lba: U64BE,
1179    pub lba_count: U32BE,
1180    pub reserved: [u8; 4],
1181}
1182
1183#[repr(C)]
1184#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1185pub struct UnmapListHeader {
1186    pub data_length: U16BE,
1187    pub block_descriptor_data_length: U16BE,
1188    pub reserved: [u8; 4],
1189}
1190#[repr(C)]
1191#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1192pub struct StartStop {
1193    pub operation_code: ScsiOp,
1194    /*
1195    UCHAR Immediate: 1;
1196    UCHAR Reserved1 : 4;
1197    UCHAR LogicalUnitNumber : 3;
1198     */
1199    pub immediate: u8,
1200    pub reserved2: [u8; 2],
1201    pub flag: StartStopFlags,
1202    pub control: u8,
1203}
1204
1205#[bitfield(u8)]
1206#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1207pub struct StartStopFlags {
1208    #[bits(1)]
1209    pub start: bool,
1210    #[bits(1)]
1211    pub load_eject: bool,
1212    #[bits(6)]
1213    pub reserved: u8,
1214}
1215
1216pub const IMMEDIATE_BIT: u8 = 1;
1217pub const START_BIT: u8 = 1;
1218
1219#[repr(C)]
1220#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1221pub struct PersistentReserveIn {
1222    pub operation_code: ScsiOp,
1223    pub service_action: PersistentReserveServiceActionIn,
1224    pub reserved2: [u8; 5],
1225    pub allocation_length: U16BE,
1226    pub control: u8,
1227}
1228
1229#[repr(C)]
1230#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1231pub struct PersistentReserveOut {
1232    pub operation_code: ScsiOp,
1233    pub service_action: PersistentReserveServiceActionOut,
1234    pub type_scope: PersistentReserveTypeScope,
1235    pub reserved2: [u8; 4],
1236    pub parameter_list_length: U16BE,
1237    pub control: u8,
1238}
1239
1240#[bitfield(u8)]
1241#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1242pub struct PersistentReserveTypeScope {
1243    #[bits(4)]
1244    reserve_type_bits: u8,
1245    #[bits(4)]
1246    pub scope: u8,
1247}
1248
1249impl PersistentReserveTypeScope {
1250    pub fn reserve_type(&self) -> ReservationType {
1251        ReservationType(self.reserve_type_bits())
1252    }
1253
1254    pub fn set_reserve_type(&mut self, ty: ReservationType) {
1255        self.set_reserve_type_bits(ty.0)
1256    }
1257
1258    pub fn with_reserve_type(self, ty: ReservationType) -> Self {
1259        self.with_reserve_type_bits(ty.0)
1260    }
1261}
1262
1263pub const RESERVATION_SCOPE_LU: u8 = 0x00;
1264pub const RESERVATION_SCOPE_ELEMENT: u8 = 0x02;
1265
1266#[bitfield(u8)]
1267#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1268pub struct PersistentReserveServiceActionIn {
1269    #[bits(5)]
1270    service_action_bits: u8,
1271    #[bits(3)]
1272    pub reserved1: u8,
1273}
1274
1275impl PersistentReserveServiceActionIn {
1276    pub fn service_action(&self) -> ServiceActionIn {
1277        ServiceActionIn(self.service_action_bits())
1278    }
1279
1280    pub fn set_service_action(&mut self, act: ServiceActionIn) {
1281        self.set_service_action_bits(act.0)
1282    }
1283
1284    pub fn with_service_action(self, act: ServiceActionIn) -> Self {
1285        self.with_service_action_bits(act.0)
1286    }
1287}
1288
1289#[bitfield(u8)]
1290#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1291pub struct PersistentReserveServiceActionOut {
1292    #[bits(5)]
1293    service_action_bits: u8,
1294    #[bits(3)]
1295    pub reserved1: u8,
1296}
1297
1298impl PersistentReserveServiceActionOut {
1299    pub fn service_action(&self) -> ServiceActionOut {
1300        ServiceActionOut(self.service_action_bits())
1301    }
1302
1303    pub fn set_service_action(&mut self, act: ServiceActionOut) {
1304        self.set_service_action_bits(act.0)
1305    }
1306
1307    pub fn with_service_action(self, act: ServiceActionOut) -> Self {
1308        self.with_service_action_bits(act.0)
1309    }
1310}
1311
1312//
1313// PERSISTENT_RESERVE_* definitions
1314//
1315open_enum! {
1316    pub enum ServiceActionIn: u8 {
1317        READ_KEYS = 0x00,
1318        READ_RESERVATIONS = 0x01,
1319        REPORT_CAPABILITIES = 0x02,
1320        READ_FULL_STATUS = 0x03,
1321    }
1322}
1323
1324open_enum! {
1325    pub enum ServiceActionOut: u8 {
1326        REGISTER = 0x00,
1327        RESERVE = 0x01,
1328        RELEASE = 0x02,
1329        CLEAR = 0x03,
1330        PREEMPT = 0x04,
1331        PREEMPT_ABORT = 0x05,
1332        REGISTER_IGNORE_EXISTING = 0x06,
1333        REGISTER_AND_MOVE = 0x07,
1334        REPLACE_LOST_RESERVATION = 0x08,
1335    }
1336}
1337
1338open_enum! {
1339    pub enum ReservationType: u8 {
1340        WRITE_EXCLUSIVE = 0x01,
1341        EXCLUSIVE = 0x03,
1342        WRITE_EXCLUSIVE_REGISTRANTS = 0x05,
1343        EXCLUSIVE_REGISTRANTS = 0x06,
1344        WRITE_EXCLUSIVE_ALL_REGISTRANTS = 0x07,
1345        EXCLUSIVE_ALL_REGISTRANTS = 0x08,
1346    }
1347}
1348
1349#[repr(C)]
1350#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1351pub struct ProParameterList {
1352    pub reservation_key: U64BE,
1353    pub service_action_reservation_key: U64BE,
1354    pub obsolete: [u8; 4],
1355    pub flags: ProParameterListFlags,
1356    pub reserved3: u8,
1357    pub obsolete2: [u8; 2],
1358}
1359
1360#[bitfield(u8)]
1361#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1362pub struct ProParameterListFlags {
1363    pub aptpl: bool,
1364    pub reserved1: bool,
1365    pub all_target_ports: bool,
1366    pub specify_initiator_ports: bool,
1367    #[bits(4)]
1368    pub reserved2: u8,
1369}
1370
1371#[bitfield(u8)]
1372#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1373pub struct SendDiagnosticFlags {
1374    pub unit_offline: bool,
1375    pub device_offline: bool,
1376    pub self_test: bool,
1377    pub reserved1: bool,
1378    pub page_format: bool,
1379    #[bits(3)]
1380    pub self_test_code: u8,
1381}
1382
1383#[repr(C)]
1384#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1385pub struct SendDiagnostic {
1386    pub op_code: u8, // 0x1D - SCSIOP_SEND_DIAGNOSTIC
1387    pub flags: SendDiagnosticFlags,
1388    pub reserved2: u8,
1389    pub parameter_list_length: U16BE,
1390    pub control: u8,
1391}
1392
1393#[repr(C)]
1394#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1395pub struct PriReportCapabilities {
1396    pub length: U16BE,
1397    pub flags: PriReportCapabilitiesFlags,
1398    pub type_mask: PriReportCapabilitiesTypeMask,
1399    pub reserved7: [u8; 2],
1400}
1401
1402#[bitfield(u16)]
1403#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1404pub struct PriReportCapabilitiesFlags {
1405    pub persist_through_power_loss_capable: bool,
1406    _reserved: bool,
1407    pub all_target_ports_capable: bool,
1408    pub specify_initiator_ports_capable: bool,
1409    pub compatible_reservation_handling: bool,
1410    #[bits(2)]
1411    _reserved1: u8,
1412    pub replace_lost_reservation_capable: bool,
1413    pub persist_through_power_loss_activated: bool,
1414    #[bits(3)]
1415    _reserved2: u8,
1416    #[bits(3)]
1417    pub allow_commands: u8,
1418    pub type_mask_valid: bool,
1419}
1420
1421#[bitfield(u16)]
1422#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1423pub struct PriReportCapabilitiesTypeMask {
1424    _reserved: bool,
1425    pub write_exclusive: bool,
1426    _reserved2: bool,
1427    pub exclusive_access: bool,
1428    _reserved3: bool,
1429    pub write_exclusive_registrants_only: bool,
1430    pub exclusive_access_registrants_only: bool,
1431    pub write_exclusive_all_registrants: bool,
1432    pub exclusive_access_all_registrants: bool,
1433    #[bits(7)]
1434    _reserved4: u8,
1435}
1436
1437#[repr(C)]
1438#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1439pub struct PriRegistrationListHeader {
1440    pub generation: U32BE,
1441    pub additional_length: U32BE,
1442}
1443
1444#[repr(C)]
1445#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1446pub struct PriFullStatusListHeader {
1447    pub generation: U32BE,
1448    pub additional_length: U32BE,
1449}
1450
1451#[repr(C)]
1452#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1453pub struct PriReservationListHeader {
1454    pub generation: U32BE,
1455    pub additional_length: U32BE,
1456}
1457
1458#[repr(C)]
1459#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1460pub struct PriReservationDescriptor {
1461    pub reservation_key: U64BE,
1462    pub obsolete: [u8; 4],
1463    pub reserved: u8,
1464    pub type_scope: PersistentReserveTypeScope,
1465    pub obsolete2: [u8; 2],
1466}
1467
1468#[repr(C)]
1469#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1470pub struct PriFullStatusDescriptorHeader {
1471    pub reservation_key: U64BE,
1472    pub reserved: [u8; 4],
1473    pub flags: PriFullStatusDescriptorHeaderFlags,
1474    pub type_scope: PersistentReserveTypeScope,
1475    pub reserved2: [u8; 4],
1476    pub relative_target_port_identifier: U16BE,
1477    pub additional_descriptor_length: U32BE,
1478}
1479
1480#[bitfield(u8)]
1481#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1482pub struct PriFullStatusDescriptorHeaderFlags {
1483    pub reservation_holder: bool,
1484    pub all_target_ports: bool,
1485    #[bits(6)]
1486    pub _reserved1: u8,
1487}
1488
1489#[repr(C)]
1490#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1491pub struct IsoVpdIdentifiers {
1492    pub id_page: VpdIdentificationDescriptor,
1493    pub vendor_id: [u8; 8],
1494    pub context_guid: [u8; 16],
1495}
1496
1497#[repr(C)]
1498#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1499pub struct CdbGetEventStatusNotification {
1500    pub operation_code: ScsiOp,
1501    pub flags: GetEventStatusFlags,
1502    pub reserved: [u8; 2],
1503    pub notification_class_request: u8,
1504    pub reserved2: [u8; 2],
1505    pub event_list_length: U16BE,
1506    pub control: u8,
1507}
1508
1509#[bitfield(u8)]
1510#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1511pub struct GetEventStatusFlags {
1512    #[bits(1)]
1513    pub immediate: bool,
1514    #[bits(4)]
1515    pub reserved: u8,
1516    #[bits(3)]
1517    pub lun: u8,
1518}
1519
1520// GET_EVENT_STATUS_NOTIFICATION
1521pub const NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK: u8 = 0x02;
1522pub const NOTIFICATION_POWER_MANAGEMENT_CLASS_MASK: u8 = 0x04;
1523pub const NOTIFICATION_EXTERNAL_REQUEST_CLASS_MASK: u8 = 0x08;
1524pub const NOTIFICATION_MEDIA_STATUS_CLASS_MASK: u8 = 0x10;
1525pub const NOTIFICATION_MULTI_HOST_CLASS_MASK: u8 = 0x20;
1526pub const NOTIFICATION_DEVICE_BUSY_CLASS_MASK: u8 = 0x40;
1527pub const NOTIFICATION_NO_CLASS_EVENTS: u8 = 0x0;
1528pub const NOTIFICATION_OPERATIONAL_CHANGE_CLASS_EVENTS: u8 = 0x1;
1529pub const NOTIFICATION_POWER_MANAGEMENT_CLASS_EVENTS: u8 = 0x2;
1530pub const NOTIFICATION_EXTERNAL_REQUEST_CLASS_EVENTS: u8 = 0x3;
1531pub const NOTIFICATION_MEDIA_STATUS_CLASS_EVENTS: u8 = 0x4;
1532pub const NOTIFICATION_MULTI_HOST_CLASS_EVENTS: u8 = 0x5;
1533pub const NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS: u8 = 0x6;
1534
1535pub const NOTIFICATION_MEDIA_EVENT_NO_CHANGE: u8 = 0x0;
1536pub const NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST: u8 = 0x1;
1537pub const NOTIFICATION_MEDIA_EVENT_NEW_MEDIA: u8 = 0x2;
1538pub const NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL: u8 = 0x3;
1539pub const NOTIFICATION_MEDIA_EVENT_MEDIA_CHANGE: u8 = 0x4;
1540
1541pub const NOTIFICATION_OPERATIONAL_EVENT_NO_CHANGE: u8 = 0x0;
1542pub const NOTIFICATION_OPERATIONAL_STATUS_AVAILABLE: u8 = 0x0;
1543pub const NOTIFICATION_OPERATIONAL_OPCODE_NONE: u8 = 0x0;
1544
1545pub const NOTIFICATION_POWER_EVENT_NO_CHANGE: u8 = 0x0;
1546pub const NOTIFICATION_POWER_STATUS_ACTIVE: u8 = 0x1;
1547
1548pub const NOTIFICATION_EXTERNAL_EVENT_NO_CHANGE: u8 = 0x0;
1549pub const NOTIFICATION_EXTERNAL_STATUS_READY: u8 = 0x0;
1550
1551pub const NOTIFICATION_MULTI_HOST_EVENT_NO_CHANGE: u8 = 0x0;
1552pub const NOTIFICATION_MULTI_HOST_STATUS_READY: u8 = 0x0;
1553
1554pub const NOTIFICATION_BUSY_EVENT_NO_EVENT: u8 = 0x0;
1555pub const NOTIFICATION_BUSY_STATUS_NO_EVENT: u8 = 0x0;
1556
1557#[repr(C)]
1558#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1559pub struct NotificationMediaStatus {
1560    /*
1561        UCHAR MediaEvent : 4;
1562        UCHAR Reserved : 4;
1563    */
1564    pub media_event: u8,
1565    pub status_info: MediaFlags,
1566    pub start_slot: u8,
1567    pub end_slot: u8,
1568}
1569
1570#[bitfield(u8)]
1571#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1572pub struct MediaFlags {
1573    #[bits(1)]
1574    pub door_tray_open: bool,
1575    #[bits(1)]
1576    pub media_present: bool,
1577    #[bits(6)]
1578    pub reserved: u8,
1579}
1580
1581#[repr(C)]
1582#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1583pub struct NotificationEventStatusHeader {
1584    pub event_data_length: U16BE,
1585    pub flags: EventStatusFlags,
1586    pub supported_event_classes: u8,
1587}
1588
1589#[bitfield(u8)]
1590#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1591pub struct EventStatusFlags {
1592    #[bits(3)]
1593    pub notification_class: u8,
1594    #[bits(4)]
1595    pub reserved: u8,
1596    #[bits(1)]
1597    pub nea: bool,
1598}
1599
1600#[repr(C)]
1601#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1602pub struct NotificationOperationalStatus {
1603    /*
1604        UCHAR OperationalEvent : 4;
1605        UCHAR Reserved1 : 4;
1606    */
1607    pub operation_event: u8,
1608    pub flags: OperationalStatusFlags,
1609    pub operation: U16BE,
1610}
1611
1612#[bitfield(u8)]
1613#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1614pub struct OperationalStatusFlags {
1615    #[bits(4)]
1616    pub operational_status: u8,
1617    #[bits(3)]
1618    pub reserved2: u8,
1619    #[bits(1)]
1620    pub persistent_prevented: bool,
1621}
1622
1623#[repr(C)]
1624#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1625pub struct NotificationPowerStatus {
1626    /*
1627       UCHAR PowerEvent : 4;
1628       UCHAR Reserved : 4;
1629    */
1630    pub power_event: u8,
1631    pub power_status: u8,
1632    pub reserved: [u8; 2],
1633}
1634
1635#[repr(C)]
1636#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1637pub struct NotificationExternalStatus {
1638    /*
1639        UCHAR ExternalEvent : 4;
1640        UCHAR Reserved1 : 4;
1641    */
1642    pub external_event: u8,
1643    pub flags: ExternalStatusFlags,
1644    pub reserved: [u8; 2],
1645}
1646
1647#[bitfield(u8)]
1648#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1649pub struct ExternalStatusFlags {
1650    #[bits(4)]
1651    pub external_status: u8,
1652    #[bits(3)]
1653    pub reserved2: u8,
1654    #[bits(1)]
1655    pub persistent_prevented: bool,
1656}
1657
1658#[repr(C)]
1659#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1660pub struct NotificationMultiHostStatus {
1661    /*
1662        UCHAR MultiHostEvent : 4;
1663        UCHAR Reserved1 : 4;
1664    */
1665    pub multi_host_event: u8,
1666    pub flags: MultiHostStatusFlags,
1667    pub priority: U16BE,
1668}
1669
1670#[bitfield(u8)]
1671#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1672pub struct MultiHostStatusFlags {
1673    #[bits(4)]
1674    pub multi_host_status: u8,
1675    #[bits(3)]
1676    pub reserved2: u8,
1677    #[bits(1)]
1678    pub persistent_prevented: bool,
1679}
1680
1681#[repr(C)]
1682#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1683pub struct NotificationBusyStatus {
1684    /*
1685        UCHAR DeviceBusyEvent : 4;
1686        UCHAR Reserved : 4;
1687    */
1688    pub device_busy_event: u8,
1689    pub device_busy_status: u8,
1690    pub time: U16BE,
1691}
1692
1693open_enum! {
1694    pub enum RequestType: u8 {
1695        ALL = 0,
1696        CURRENT = 1,
1697        ONE = 2,
1698    }
1699}
1700
1701/// CD-Rom feature list
1702#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1703pub enum FeatureNumber {
1704    FeatureProfileList = 0x0000,
1705    FeatureCore = 0x0001,
1706    FeatureMorphing = 0x0002,
1707    FeatureRemovableMedium = 0x0003,
1708    FeatureWriteProtect = 0x0004,
1709    // Reserved                  0x0005 - 0x000f
1710    FeatureRandomReadable = 0x0010,
1711    // Reserved                  0x0011 - 0x001c
1712    FeatureMultiRead = 0x001D,
1713    FeatureCdRead = 0x001E,
1714    FeatureDvdRead = 0x001F,
1715    FeatureRandomWritable = 0x0020,
1716    FeatureIncrementalStreamingWritable = 0x0021,
1717    FeatureSectorErasable = 0x0022,
1718    FeatureFormattable = 0x0023,
1719    FeatureDefectManagement = 0x0024,
1720    FeatureWriteOnce = 0x0025,
1721    FeatureRestrictedOverwrite = 0x0026,
1722    FeatureCdrwCAVWrite = 0x0027,
1723    FeatureMrw = 0x0028,
1724    // Reserved                  0x0029
1725    FeatureDvdPlusRW = 0x002A,
1726    FeatureDvdPlusR = 0x002B,
1727    FeatureRigidRestrictedOverwrite = 0x002C,
1728    FeatureCdTrackAtOnce = 0x002D,
1729    FeatureCdMastering = 0x002E,
1730    FeatureDvdRecordableWrite = 0x002F, // both -R and -RW
1731    FeatureDDCDRead = 0x0030,
1732    FeatureDDCDRWrite = 0x0031,
1733    FeatureDDCDRWWrite = 0x0032,
1734    // Reserved                  0x0033 - 0x00ff
1735    FeaturePowerManagement = 0x0100,
1736    FeatureSMART = 0x0101,
1737    FeatureEmbeddedChanger = 0x0102,
1738    FeatureCDAudioAnalogPlay = 0x0103,
1739    FeatureMicrocodeUpgrade = 0x0104,
1740    FeatureTimeout = 0x0105,
1741    FeatureDvdCSS = 0x0106,
1742    FeatureRealTimeStreaming = 0x0107,
1743    FeatureLogicalUnitSerialNumber = 0x0108,
1744    // Reserved                      0x0109
1745    FeatureDiscControlBlocks = 0x010A,
1746    FeatureDvdCPRM = 0x010B,
1747    FeatureFirmwareDate = 0x010C,
1748    // Reserved                  0x010D - 0xfeff
1749    // Vendor Unique             0xff00 - 0xffff
1750    FeatureUnknown,
1751}
1752
1753pub const FEATURE_SIZE: u8 = 39;
1754pub const PROFILE_DVD_ROM: u16 = 0x0010;
1755pub const PROFILE_CD_ROM: u16 = 0x0008;
1756pub const ISO_SECTOR_SIZE: u32 = 0x00000800_u32;
1757
1758pub const LIST_OF_FEATURES: [FeatureNumber; 10] = [
1759    FeatureNumber::FeatureProfileList,
1760    FeatureNumber::FeatureCore,
1761    FeatureNumber::FeatureMorphing,
1762    FeatureNumber::FeatureRemovableMedium,
1763    FeatureNumber::FeatureRandomReadable,
1764    FeatureNumber::FeatureCdRead,
1765    FeatureNumber::FeatureDvdRead,
1766    FeatureNumber::FeaturePowerManagement,
1767    FeatureNumber::FeatureTimeout,
1768    FeatureNumber::FeatureRealTimeStreaming,
1769];
1770
1771impl TryFrom<usize> for FeatureNumber {
1772    type Error = std::io::Error;
1773
1774    fn try_from(v: usize) -> Result<Self, Self::Error> {
1775        Ok(match v {
1776            0x00 => Self::FeatureProfileList,
1777            0x01 => Self::FeatureCore,
1778            0x02 => Self::FeatureMorphing,
1779            0x03 => Self::FeatureRemovableMedium,
1780            0x10 => Self::FeatureRandomReadable,
1781            0x1E => Self::FeatureCdRead,
1782            0x1F => Self::FeatureDvdRead,
1783            0x100 => Self::FeaturePowerManagement,
1784            0x105 => Self::FeatureTimeout,
1785            0x107 => Self::FeatureRealTimeStreaming,
1786            _ => Self::FeatureUnknown,
1787        })
1788    }
1789}
1790#[repr(C)]
1791#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1792pub struct GetConfigurationHeader {
1793    pub data_length: U32BE,
1794    pub reserved: [u8; 2],
1795    pub current_profile: U16BE,
1796}
1797
1798#[repr(C)]
1799#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1800pub struct CdbGetConfiguration {
1801    pub operation_code: ScsiOp,
1802    pub flags: GetConfigurationFlags,
1803    pub starting_feature: U16BE,
1804    pub reserved2: [u8; 3],
1805    pub allocation_length: U16BE,
1806    pub control: u8,
1807}
1808
1809#[bitfield(u8)]
1810#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1811pub struct GetConfigurationFlags {
1812    #[bits(2)]
1813    request_type_bits: u8,
1814    #[bits(6)]
1815    pub reserved: u8,
1816}
1817
1818impl GetConfigurationFlags {
1819    pub fn request_type(&self) -> RequestType {
1820        RequestType(self.request_type_bits())
1821    }
1822
1823    pub fn set_request_type(&mut self, ty: RequestType) {
1824        self.set_request_type_bits(ty.0)
1825    }
1826
1827    pub fn with_request_type(self, ty: RequestType) -> Self {
1828        self.with_request_type_bits(ty.0)
1829    }
1830}
1831
1832#[repr(C)]
1833#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1834pub struct GetConfigurationFeatureDataProfileList {
1835    pub header: FeatureHeader,
1836    pub profile: [FeatureDataProfileList; 2],
1837}
1838
1839#[repr(C)]
1840#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1841pub struct FeatureDataProfileList {
1842    pub profile_number: U16BE,
1843    /*
1844        UCHAR Current                   : 1;
1845        UCHAR Reserved1                 : 7;
1846    */
1847    pub current: u8,
1848    pub reserved: u8,
1849}
1850
1851#[repr(C)]
1852#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1853pub struct FeatureHeader {
1854    pub feature_code: U16BE,
1855    pub flags: FeatureHeaderFlags,
1856    pub additional_length: u8,
1857}
1858
1859#[bitfield(u8)]
1860#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1861pub struct FeatureHeaderFlags {
1862    #[bits(1)]
1863    pub current: bool,
1864    #[bits(1)]
1865    pub persistent: bool,
1866    #[bits(4)]
1867    pub version: u8,
1868    #[bits(2)]
1869    pub reserved: u8,
1870}
1871
1872#[repr(C)]
1873#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1874pub struct FeatureDataRandomReadable {
1875    pub header: FeatureHeader,
1876    pub logical_block_size: U32BE,
1877    pub blocking: U16BE,
1878    /*
1879       UCHAR ErrorRecoveryPagePresent : 1;
1880       UCHAR Reserved1                : 7;
1881    */
1882    pub error_recovery_page_present: u8,
1883    pub reserved: u8,
1884}
1885
1886#[repr(C)]
1887#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1888pub struct FeatureDataDvdRead {
1889    pub header: FeatureHeader,
1890    /*
1891       UCHAR Multi110                 : 1;
1892       UCHAR Reserved1                : 7;
1893    */
1894    pub multi_110: u8,
1895    pub reserved: u8,
1896    /*
1897        UCHAR DualDashR                : 1;
1898        UCHAR Reserved3                : 7;
1899    */
1900    pub dual_dash_r: u8,
1901    pub reserved2: u8,
1902}
1903
1904#[bitfield(u8)]
1905#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1906pub struct RealTimeStreamingFlags {
1907    #[bits(1)]
1908    pub stream_recording: bool,
1909    #[bits(1)]
1910    pub write_speed_in_get_perf: bool,
1911    #[bits(1)]
1912    pub write_speed_in_mp2_a: bool,
1913    #[bits(1)]
1914    pub set_cdspeed: bool,
1915    #[bits(1)]
1916    pub read_buffer_capacity_block: bool,
1917    #[bits(3)]
1918    pub reserved1: u8,
1919}
1920
1921#[repr(C)]
1922#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1923pub struct FeatureDataRealTimeStreaming {
1924    pub header: FeatureHeader,
1925    pub flags: RealTimeStreamingFlags,
1926    pub reserved: [u8; 3],
1927}
1928
1929#[repr(C)]
1930#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1931pub struct FeatureDataCore {
1932    pub header: FeatureHeader,
1933    pub physical_interface: U32BE,
1934    /*
1935        UCHAR DeviceBusyEvent           : 1;
1936        UCHAR INQUIRY2                  : 1;
1937        UCHAR Reserved1                 : 6;
1938    */
1939    pub device_busy_event: u8,
1940    pub reserved2: [u8; 3],
1941}
1942
1943#[bitfield(u8)]
1944#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1945pub struct FeatureMorphingFlags {
1946    #[bits(1)]
1947    pub asynchronous: bool,
1948    #[bits(1)]
1949    pub ocevent: bool,
1950    #[bits(6)]
1951    pub reserved1: u8,
1952}
1953
1954#[repr(C)]
1955#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1956pub struct FeatureDataMorphing {
1957    pub header: FeatureHeader,
1958    pub flags: FeatureMorphingFlags,
1959    pub reserved2: [u8; 3],
1960}
1961
1962#[bitfield(u8)]
1963#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1964pub struct RemovableMediumFlags {
1965    #[bits(1)]
1966    pub lockable: bool,
1967    #[bits(1)]
1968    pub dbml: bool,
1969    #[bits(1)]
1970    pub default_to_prevent: bool,
1971    #[bits(1)]
1972    pub eject: bool,
1973    #[bits(1)]
1974    pub load: bool,
1975    #[bits(3)]
1976    pub loading_mechanism: u8,
1977}
1978
1979#[repr(C)]
1980#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1981pub struct FeatureDataRemovableMedium {
1982    pub header: FeatureHeader,
1983    pub flags: RemovableMediumFlags,
1984    pub reserved2: [u8; 3],
1985}
1986
1987#[bitfield(u8)]
1988#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1989pub struct CDReadFlags {
1990    #[bits(1)]
1991    pub cd_text: bool,
1992    #[bits(1)]
1993    pub c2_error_data: bool,
1994    #[bits(5)]
1995    pub reserved: u8,
1996    #[bits(1)]
1997    pub digital_audio_play: bool,
1998}
1999
2000#[repr(C)]
2001#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2002pub struct FeatureDataCdRead {
2003    pub header: FeatureHeader,
2004    pub flags: CDReadFlags,
2005    pub reserved2: [u8; 3],
2006}
2007
2008#[repr(C)]
2009#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2010pub struct FeatureDataPowerManagement {
2011    pub header: FeatureHeader,
2012}
2013
2014#[repr(C)]
2015#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2016pub struct FeatureDataTimeout {
2017    pub header: FeatureHeader,
2018    /*
2019       UCHAR Group3    : 1;
2020       UCHAR Reserved1 : 7;
2021    */
2022    pub group: u8,
2023    pub reserved: u8,
2024    pub unit_length: U16BE,
2025}
2026
2027pub const CDROM_READ_TOC_EX_FORMAT_TOC: u8 = 0x00;
2028pub const CDROM_READ_TOC_EX_FORMAT_SESSION: u8 = 0x01;
2029pub const CDROM_READ_TOC_EX_FORMAT_FULL_TOC: u8 = 0x02;
2030pub const CDROM_READ_TOC_EX_FORMAT_PMA: u8 = 0x03;
2031pub const CDROM_READ_TOC_EX_FORMAT_ATIP: u8 = 0x04;
2032pub const CDROM_READ_TOC_EX_FORMAT_CDTEXT: u8 = 0x05;
2033#[repr(C)]
2034#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2035pub struct CdbReadToc {
2036    pub operation_code: ScsiOp,
2037    /*
2038        UCHAR Reserved0 : 1;
2039        UCHAR Msf : 1;
2040        UCHAR Reserved1 : 3;
2041        UCHAR LogicalUnitNumber : 3;
2042    */
2043    pub flag1: ReadTocFlag,
2044    /*
2045        UCHAR Format2 : 4;
2046        UCHAR Reserved2 : 4;
2047    */
2048    pub format2: u8,
2049    pub reserved: [u8; 3],
2050    pub starting_track: u8,
2051    pub allocation_length: U16BE,
2052    /*
2053        UCHAR Control : 6;
2054        UCHAR Format : 2;
2055    */
2056    pub reserved1: u8,
2057}
2058#[bitfield(u8)]
2059#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2060pub struct ReadTocFlag {
2061    #[bits(1)]
2062    pub reserved0: bool,
2063    #[bits(1)]
2064    pub msf: bool,
2065    #[bits(3)]
2066    pub reserved1: u8,
2067    #[bits(3)]
2068    pub location_unit_number: u8,
2069}
2070#[repr(C)]
2071#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2072pub struct ReadTocFormattedToc {
2073    pub length: U16BE,
2074    pub first_complete_session: u8,
2075    pub last_complete_session: u8,
2076    pub track1: TrackData,
2077    pub trackaa: TrackData,
2078}
2079#[repr(C)]
2080#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2081pub struct TrackData {
2082    pub reserved: u8,
2083    pub flag: TrackDataFlag,
2084    pub track_number: u8,
2085    pub reserved1: u8,
2086    pub address: [u8; 4],
2087}
2088#[bitfield(u8)]
2089#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2090pub struct TrackDataFlag {
2091    #[bits(4)]
2092    pub control: u8,
2093    #[bits(4)]
2094    pub adr: u8,
2095}
2096#[repr(C)]
2097#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2098pub struct CdromTocSessionData {
2099    // Header
2100    pub length: U16BE, // add two bytes for this field
2101    pub first_complete_session: u8,
2102    pub last_complete_session: u8,
2103    // One track, representing the first track
2104    // of the last finished session
2105    pub track_data: TrackData,
2106}
2107
2108#[repr(C)]
2109#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2110pub struct CdbRequestSense {
2111    pub operation_code: ScsiOp,
2112    pub desc: u8,
2113    pub reserved: [u8; 2],
2114    pub allocation_length: u8,
2115    pub control: u8,
2116}
2117
2118#[repr(C)]
2119#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2120pub struct CdbMediaRemoval {
2121    pub operation_code: ScsiOp,
2122    /*
2123        UCHAR Reserved1 : 5;
2124        UCHAR LogicalUnitNumber : 3;
2125    */
2126    pub lun: u8,
2127    pub reserved: [u8; 2],
2128    pub flags: MediaRemovalFlags,
2129}
2130
2131#[bitfield(u8)]
2132#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2133pub struct MediaRemovalFlags {
2134    #[bits(1)]
2135    pub prevent: bool,
2136    #[bits(1)]
2137    pub persistent: bool,
2138    #[bits(6)]
2139    pub reserved: u8,
2140}
2141
2142#[bitfield(u8)]
2143#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2144pub struct ReadTrackInfoFlag {
2145    #[bits(2)]
2146    pub number_type: u8,
2147    #[bits(1)]
2148    pub open: bool,
2149    #[bits(5)]
2150    pub reserved: u8,
2151}
2152
2153#[repr(C)]
2154#[derive(Copy, Clone, FromBytes)]
2155pub struct CdbReadTrackInformation {
2156    pub operation_code: ScsiOp,
2157    /*
2158        UCHAR NumberType : 2;
2159        UCHAR Open: 1;
2160        UCHAR Reserved1 : 5;
2161    */
2162    pub flag: ReadTrackInfoFlag,
2163    pub logical_track_number: U32BE,
2164    pub reserved: u8,
2165    pub allocation_length: U16BE,
2166    pub control: u8,
2167}
2168
2169#[repr(C)]
2170#[derive(Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
2171pub struct TrackInformation3 {
2172    pub length: U16BE,
2173    pub track_number_lsb: u8,
2174    pub session_number_lsb: u8,
2175    pub reserved: u8,
2176    /*
2177       UCHAR TrackMode : 4;
2178       UCHAR Copy      : 1;
2179       UCHAR Damage    : 1;
2180       UCHAR Reserved5 : 2;
2181    */
2182    pub track_mode: u8,
2183    /*
2184       UCHAR DataMode      : 4;
2185       UCHAR FixedPacket   : 1;
2186       UCHAR Packet        : 1;
2187       UCHAR Blank         : 1;
2188       UCHAR ReservedTrack : 1;
2189    */
2190    pub data_mode: u8,
2191    /*
2192       UCHAR NWA_V     : 1;
2193       UCHAR LRA_V     : 1;
2194       UCHAR Reserved6 : 6;
2195    */
2196    pub nwa_v: u8,
2197    pub track_start_address: U32BE,
2198    pub next_writable_address: U32BE,
2199    pub free_blocks: U32BE,
2200    pub fixed_packet_size: U32BE, // blocking factor
2201    pub track_size: U32BE,
2202    pub last_recorded_address: U32BE,
2203    pub track_number_msb: u8,
2204    pub session_number_msb: u8,
2205    pub reserved2: [u8; 2],
2206    pub read_compatibility_lba: U32BE,
2207}
2208
2209// Read DVD Structure Definitions and Constants
2210pub const DVD_FORMAT_LEAD_IN: u8 = 0x00;
2211pub const DVD_FORMAT_COPYRIGHT: u8 = 0x01;
2212pub const DVD_FORMAT_DISK_KEY: u8 = 0x02;
2213pub const DVD_FORMAT_BCA: u8 = 0x03;
2214pub const DVD_FORMAT_MANUFACTURING: u8 = 0x04;
2215
2216#[repr(C)]
2217#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2218pub struct CdbReadDVDStructure {
2219    pub op: u8,
2220    /*
2221       UCHAR MediaType : 4;
2222       UCHAR Reserved1 : 4;
2223    */
2224    pub media_type: u8,
2225    // RMDBlockNumber[4]
2226    pub reserved: [u8; 4],
2227    pub layer: u8,
2228    pub format: u8,
2229    pub allocation_length: U16BE,
2230    /*
2231       UCHAR Reserved3 : 6;
2232       UCHAR AGID : 2;
2233    */
2234    pub reserved3: u8,
2235    pub control: u8,
2236}
2237
2238#[repr(C)]
2239#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2240pub struct ReadDVDStructurePhysicalFormatInformation {
2241    pub length: U16BE,
2242    pub reserved: [u8; 2],
2243    /*
2244        UCHAR PartVersion : 4;
2245        UCHAR DiskCategory : 4;
2246    */
2247    pub reserved2: u8,
2248    /*
2249        UCHAR MaximumRate : 4;
2250        UCHAR DiscSize : 4;
2251    */
2252    pub maximum_rate: u8,
2253    /*
2254        UCHAR LayerType : 4;
2255        UCHAR Track : 1;
2256        UCHAR NumberOfLayers : 2;
2257        UCHAR Reserved1: 1;
2258    */
2259    pub layer: u8,
2260    /*
2261        UCHAR TrackDensity : 4;
2262        UCHAR LinearDensity : 4;
2263    */
2264    pub reserved3: u8,
2265    pub reserved4: u8,
2266    pub starting_physical_sector: [u8; 3],
2267    pub reserved5: u8,
2268    pub end_physical_sector: [u8; 3],
2269    pub reserved6: u8,
2270    pub end_physical_sector_in_layer0: [u8; 3],
2271    /*
2272        UCHAR Reserved5 : 7;
2273        UCHAR BCA : 1;
2274    */
2275    pub bca: u8,
2276}
2277
2278#[repr(C)]
2279#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2280pub struct ReadDVDStructureCopyrightInformation {
2281    pub data_length: U16BE,
2282    pub reserved: u8,
2283    pub copyright_protection_system: u8,
2284    pub region_management_information: u8,
2285    pub reserved2: [u8; 2],
2286}
2287
2288#[repr(C)]
2289#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2290pub struct ReadDVDStructureManufacturingStructure {
2291    pub data_length: U16BE,
2292    pub reserved: [u8; 2],
2293}
2294
2295pub const PERFORMANCE_TYPE_PERFORMANCE_DATA: u8 = 0x00;
2296pub const PERFORMANCE_TYPE_UNUSABLE_AREA_DATA: u8 = 0x01;
2297pub const PERFORMANCE_TYPE_DEFECT_STATUS_DATA: u8 = 0x02;
2298pub const PERFORMANCE_TYPE_WRITE_SPEED_DESCRIPTOR: u8 = 0x03;
2299pub const PERFORMANCE_TYPE_DBI: u8 = 0x04;
2300pub const PERFORMANCE_TYPE_DBI_CACHE_ZONE: u8 = 0x05;
2301pub const PERFORMANCE_EXCEPT_NOMINAL_PERFORMANCE: u8 = 0x0;
2302pub const PERFORMANCE_EXCEPT_ENTIRE_PERFORMANCE_LIST: u8 = 0x1;
2303pub const PERFORMANCE_EXCEPT_PERFORMANCE_EXCEPTIONS_ONLY: u8 = 0x2;
2304pub const PERFORMANCE_1000_BYTES_PER_SECOND: u32 = 1350 * 24;
2305
2306#[repr(C)]
2307#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2308pub struct CdbGetPerformance {
2309    pub op: u8,
2310    pub flags: GetPerformanceFlags,
2311    pub starting_lba: U32BE,
2312    pub reserved: [u8; 2],
2313    pub maximum_number_of_descriptors: U16BE,
2314    pub data_type: u8,
2315    pub control: u8,
2316}
2317
2318#[bitfield(u8)]
2319#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2320pub struct GetPerformanceFlags {
2321    #[bits(2)]
2322    pub except: u8,
2323    #[bits(1)]
2324    pub write: bool,
2325    #[bits(2)]
2326    pub tolerance: u8,
2327    #[bits(3)]
2328    pub reserved: u8,
2329}
2330
2331#[repr(C)]
2332#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2333pub struct GetPerformanceNominalPerformanceDescriptor {
2334    pub start_lba: U32BE,
2335    pub start_performance: U32BE,
2336    pub end_lba: U32BE,
2337    pub end_performance: U32BE,
2338}
2339
2340#[repr(C)]
2341#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2342pub struct GetPerformanceHeader {
2343    pub total_data_length: U32BE,
2344    /*
2345        UCHAR Except : 1;
2346        UCHAR Write  : 1;
2347        UCHAR Reserved0 : 6;
2348    */
2349    pub except: u8,
2350    pub reserved: [u8; 3],
2351}
2352
2353#[repr(C)]
2354#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2355pub struct CdbMechStatus {
2356    pub op: u8,
2357    /*
2358        UCHAR Reserved : 5;
2359        UCHAR Lun : 3;
2360        UCHAR Reserved1[6];
2361    */
2362    pub reserved1: [u8; 7],
2363    pub allocation_length: U16BE,
2364    pub reserved2: u8,
2365    pub control: u8,
2366}
2367
2368#[repr(C)]
2369#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2370pub struct MechanismStatusHeader {
2371    /*
2372        UCHAR CurrentSlotLow5 : 5;
2373        UCHAR ChangerState : 2;
2374        UCHAR Fault : 1;
2375    */
2376    pub reserved: u8,
2377    pub flags: MechanismStatusHeaderFlags,
2378    pub current_logical_block_address: [u8; 3],
2379    pub number_available_slots: u8,
2380    pub slot_table_length: U16BE,
2381}
2382
2383#[bitfield(u8)]
2384#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2385pub struct MechanismStatusHeaderFlags {
2386    #[bits(3)]
2387    pub current_slot_high3: u8,
2388    #[bits(1)]
2389    pub reserved: bool,
2390    #[bits(1)]
2391    pub door_open: bool,
2392    #[bits(3)]
2393    pub mechanism_state: u8,
2394}
2395
2396#[repr(C)]
2397#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2398pub struct CdbReadBufferCapacity {
2399    pub op: u8,
2400    pub flags: ReadBufferCapacityFlags,
2401    pub reserved: [u8; 5],
2402    pub allocation_length: U16BE,
2403    pub control: u8,
2404}
2405
2406#[bitfield(u8)]
2407#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2408pub struct ReadBufferCapacityFlags {
2409    #[bits(1)]
2410    pub block_info: bool,
2411    #[bits(7)]
2412    pub reserved: u8,
2413}
2414
2415#[repr(C)]
2416#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2417pub struct ReadBufferCapacityData {
2418    pub data_length: U16BE,
2419    pub reserved1: u8,
2420    /*
2421        UCHAR BlockDataReturned : 1;
2422        UCHAR Reserved4         : 7;
2423    */
2424    pub block_data_returned: u8,
2425    pub total_buffer_size: U32BE,
2426    pub available_buffer_size: U32BE,
2427}
2428
2429#[repr(C)]
2430#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2431pub struct CdbReadDiscInformation {
2432    pub operation_code: ScsiOp,
2433    pub flags: ReadDiscFlags,
2434    pub reserved1: [u8; 5],
2435    pub allocation_length: U16BE,
2436    pub control: u8,
2437}
2438
2439#[bitfield(u8)]
2440#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2441pub struct ReadDiscFlags {
2442    #[bits(3)]
2443    pub data_type: u8,
2444    #[bits(5)]
2445    pub reserved: u8,
2446}
2447
2448#[repr(C)]
2449#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2450pub struct DiscInformation {
2451    pub length: U16BE,
2452    pub flags1: DiscInfoFlags1,
2453    pub first_track_number: u8,
2454
2455    pub number_of_sessions_lsb: u8,
2456    pub last_session_first_track_lsb: u8,
2457    pub last_session_last_track_lsb: u8,
2458
2459    pub flags2: DiscInfoFlags2,
2460    pub disc_type: u8,
2461    pub number_of_sessions_msb: u8,
2462    pub last_session_first_track_msb: u8,
2463    pub last_session_last_track_msb: u8,
2464
2465    pub disk_identification: U32BE,
2466    pub last_session_lead_in: U32BE,
2467    pub last_possible_lead_out_start_time: U32BE,
2468    pub disk_bar_code: [u8; 8],
2469
2470    pub reserved4: u8,
2471    pub number_opcentries: u8,
2472
2473    pub speed: U16BE,
2474    pub opcvalue: [u8; 6],
2475}
2476
2477#[bitfield(u8)]
2478#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2479pub struct DiscInfoFlags1 {
2480    #[bits(2)]
2481    pub disc_status: u8,
2482    #[bits(2)]
2483    pub last_session_status: u8,
2484    #[bits(1)]
2485    pub erasable: bool,
2486    #[bits(3)]
2487    pub reserved1: u8,
2488}
2489
2490#[bitfield(u8)]
2491#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2492pub struct DiscInfoFlags2 {
2493    #[bits(2)]
2494    pub mrw_status: u8,
2495    #[bits(1)]
2496    pub mrw_dirty_bit: bool,
2497    #[bits(2)]
2498    pub reserved2: u8,
2499    #[bits(1)]
2500    pub uru: bool,
2501    #[bits(1)]
2502    pub dbc_v: bool,
2503    #[bits(1)]
2504    pub did_v: bool,
2505}
2506
2507#[repr(C)]
2508#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2509pub struct CdbSetStreaming {
2510    pub operation_code: ScsiOp,
2511    pub reserved: [u8; 8],
2512    pub parameter_list_length: U16BE,
2513    pub control: u8,
2514}
2515
2516#[repr(C)]
2517#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2518pub struct SetStreamingPerformanceDescriptor {
2519    pub flags: SetStreamingFlags,
2520    pub reserved2: [u8; 3],
2521    pub start_lba: U32BE,
2522    pub end_lba: U32BE,
2523    pub read_size: U32BE,
2524    pub read_time: U32BE,
2525    pub write_size: U32BE,
2526    pub write_time: U32BE,
2527}
2528
2529#[bitfield(u8)]
2530#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2531pub struct SetStreamingFlags {
2532    #[bits(1)]
2533    pub mrw: bool,
2534    #[bits(1)]
2535    pub exact: bool,
2536    #[bits(1)]
2537    pub rdd: bool,
2538    #[bits(2)]
2539    pub wrc: u8,
2540    #[bits(1)]
2541    pub hie: bool,
2542    #[bits(2)]
2543    pub reserved: u8,
2544}
2545
2546#[repr(C)]
2547#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2548pub struct ReportLuns {
2549    pub operation_code: ScsiOp,
2550    pub reserved1: [u8; 5],
2551    pub allocation_length: U32BE,
2552    pub reserved2: u8,
2553    pub control: u8,
2554}