scsi_defs/
lib.rs

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