devices/usb/xhci/
xhci_abi.rs

1// Copyright 2018 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::fmt;
6use std::fmt::Display;
7
8use bit_field::Error as BitFieldError;
9use bit_field::*;
10use remain::sorted;
11use thiserror::Error;
12use vm_memory::GuestAddress;
13use zerocopy::FromBytes;
14use zerocopy::Immutable;
15use zerocopy::IntoBytes;
16use zerocopy::KnownLayout;
17
18#[sorted]
19#[derive(Error, Debug)]
20pub enum Error {
21    #[error("cannot cast trb from raw memory")]
22    CannotCastTrb,
23    #[error("we got an unknown trb type value: {0}")]
24    UnknownTrbType(BitFieldError),
25}
26
27type Result<T> = std::result::Result<T, Error>;
28
29// Fixed size of all TRB types.
30const TRB_SIZE: usize = 16;
31
32// Size of segment table.
33const SEGMENT_TABLE_SIZE: usize = 16;
34
35/// All kinds of trb.
36#[bitfield]
37#[bits = 6]
38#[derive(PartialEq, Eq, Debug, Clone, Copy)]
39pub enum TrbType {
40    Reserved = 0,
41    Normal = 1,
42    SetupStage = 2,
43    DataStage = 3,
44    StatusStage = 4,
45    Isoch = 5,
46    Link = 6,
47    EventData = 7,
48    Noop = 8,
49    EnableSlotCommand = 9,
50    DisableSlotCommand = 10,
51    AddressDeviceCommand = 11,
52    ConfigureEndpointCommand = 12,
53    EvaluateContextCommand = 13,
54    ResetEndpointCommand = 14,
55    StopEndpointCommand = 15,
56    SetTRDequeuePointerCommand = 16,
57    ResetDeviceCommand = 17,
58    NoopCommand = 23,
59    TransferEvent = 32,
60    CommandCompletionEvent = 33,
61    PortStatusChangeEvent = 34,
62}
63
64/// Completion code of trb types.
65#[bitfield]
66#[bits = 8]
67#[derive(PartialEq, Eq, Debug)]
68pub enum TrbCompletionCode {
69    Success = 1,
70    TransactionError = 4,
71    TrbError = 5,
72    StallError = 6,
73    NoSlotsAvailableError = 9,
74    SlotNotEnabledError = 11,
75    ShortPacket = 13,
76    ContextStateError = 19,
77}
78
79/// State of device slot.
80#[bitfield]
81#[bits = 5]
82#[derive(PartialEq, Eq, Debug)]
83pub enum DeviceSlotState {
84    // The same value (0) is used for both the enabled and disabled states. See
85    // xhci spec table 60.
86    DisabledOrEnabled = 0,
87    Default = 1,
88    Addressed = 2,
89    Configured = 3,
90}
91
92/// State of endpoint.
93#[bitfield]
94#[bits = 3]
95#[derive(PartialEq, Eq, Debug)]
96pub enum EndpointState {
97    Disabled = 0,
98    Running = 1,
99    Halted = 2,
100    Stopped = 3,
101    Error = 4,
102}
103
104#[bitfield]
105#[bits = 60]
106#[derive(PartialEq, Eq, Debug)]
107pub struct DequeuePtr(u64);
108
109impl DequeuePtr {
110    pub fn new(addr: GuestAddress) -> Self {
111        DequeuePtr(addr.0 >> 4)
112    }
113
114    // Get the guest physical address.
115    pub fn get_gpa(&self) -> GuestAddress {
116        GuestAddress(self.0 << 4)
117    }
118}
119
120// Generic TRB struct containing only fields common to all types.
121#[bitfield]
122#[derive(Clone, Copy, PartialEq, Eq, FromBytes, Immutable, IntoBytes, KnownLayout)]
123pub struct Trb {
124    parameter: B64,
125    status: B32,
126    cycle: bool,
127    flags: B9,
128    trb_type: TrbType,
129    control: B16,
130}
131
132impl Trb {
133    fn fmt_helper(&self, f: &mut fmt::Formatter) -> Result<fmt::Result> {
134        match self.get_trb_type().map_err(Error::UnknownTrbType)? {
135            TrbType::Reserved => Ok(write!(f, "reserved trb type")),
136            TrbType::Normal => {
137                let t = self.cast::<NormalTrb>()?;
138                Ok(write!(f, "trb: {t:?}"))
139            }
140            TrbType::SetupStage => {
141                let t = self.cast::<SetupStageTrb>()?;
142                Ok(write!(f, "trb: {t:?}"))
143            }
144            TrbType::DataStage => {
145                let t = self.cast::<DataStageTrb>()?;
146                Ok(write!(f, "trb: {t:?}"))
147            }
148            TrbType::StatusStage => {
149                let t = self.cast::<StatusStageTrb>()?;
150                Ok(write!(f, "trb: {t:?}"))
151            }
152            TrbType::Isoch => {
153                let t = self.cast::<IsochTrb>()?;
154                Ok(write!(f, "trb: {t:?}"))
155            }
156            TrbType::Link => {
157                let t = self.cast::<LinkTrb>()?;
158                Ok(write!(f, "trb: {t:?}"))
159            }
160            TrbType::EventData => {
161                let t = self.cast::<EventDataTrb>()?;
162                Ok(write!(f, "trb: {t:?}"))
163            }
164            TrbType::Noop => {
165                let t = self.cast::<NoopTrb>()?;
166                Ok(write!(f, "trb: {t:?}"))
167            }
168            TrbType::EnableSlotCommand => Ok(write!(f, "trb: enable slot command {self:?}")),
169            TrbType::DisableSlotCommand => {
170                let t = self.cast::<DisableSlotCommandTrb>()?;
171                Ok(write!(f, "trb: {t:?}"))
172            }
173            TrbType::AddressDeviceCommand => {
174                let t = self.cast::<AddressDeviceCommandTrb>()?;
175                Ok(write!(f, "trb: {t:?}"))
176            }
177            TrbType::ConfigureEndpointCommand => {
178                let t = self.cast::<ConfigureEndpointCommandTrb>()?;
179                Ok(write!(f, "trb: {t:?}"))
180            }
181            TrbType::EvaluateContextCommand => {
182                let t = self.cast::<EvaluateContextCommandTrb>()?;
183                Ok(write!(f, "trb: {t:?}"))
184            }
185            TrbType::ResetEndpointCommand => {
186                let t = self.cast::<ResetEndpointCommandTrb>()?;
187                Ok(write!(f, "trb: {t:?}"))
188            }
189            TrbType::StopEndpointCommand => {
190                let t = self.cast::<StopEndpointCommandTrb>()?;
191                Ok(write!(f, "trb: {t:?}"))
192            }
193            TrbType::SetTRDequeuePointerCommand => {
194                let t = self.cast::<SetTRDequeuePointerCommandTrb>()?;
195                Ok(write!(f, "trb: {t:?}"))
196            }
197            TrbType::ResetDeviceCommand => {
198                let t = self.cast::<ResetDeviceCommandTrb>()?;
199                Ok(write!(f, "trb: {t:?}"))
200            }
201            TrbType::NoopCommand => Ok(write!(f, "trb: noop command {self:?}")),
202            TrbType::TransferEvent => {
203                let t = self.cast::<TransferEventTrb>()?;
204                Ok(write!(f, "trb: {t:?}"))
205            }
206            TrbType::CommandCompletionEvent => {
207                let t = self.cast::<CommandCompletionEventTrb>()?;
208                Ok(write!(f, "trb: {t:?}"))
209            }
210            TrbType::PortStatusChangeEvent => {
211                let t = self.cast::<PortStatusChangeEventTrb>()?;
212                Ok(write!(f, "trb: {t:?}"))
213            }
214        }
215    }
216}
217
218impl Display for Trb {
219    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
220        match self.fmt_helper(f) {
221            Ok(f) => f,
222            Err(e) => write!(f, "fail to format trb {e}"),
223        }
224    }
225}
226
227impl Trb {
228    /// Get chain bit.
229    pub fn get_chain_bit(&self) -> Result<bool> {
230        Ok(match self.get_trb_type() {
231            Ok(TrbType::Normal) => self.cast::<NormalTrb>()?.get_chain(),
232            Ok(TrbType::DataStage) => self.cast::<DataStageTrb>()?.get_chain(),
233            Ok(TrbType::StatusStage) => self.cast::<StatusStageTrb>()?.get_chain(),
234            Ok(TrbType::Isoch) => self.cast::<IsochTrb>()?.get_chain(),
235            Ok(TrbType::Noop) => self.cast::<NoopTrb>()?.get_chain(),
236            Ok(TrbType::Link) => self.cast::<LinkTrb>()?.get_chain(),
237            Ok(TrbType::EventData) => self.cast::<EventDataTrb>()?.get_chain(),
238            _ => false,
239        })
240    }
241
242    /// Get interrupt target.
243    pub fn interrupter_target(&self) -> u8 {
244        const STATUS_INTERRUPTER_TARGET_OFFSET: u8 = 22;
245        (self.get_status() >> STATUS_INTERRUPTER_TARGET_OFFSET) as u8
246    }
247
248    /// Only some of trb types could appear in transfer ring.
249    pub fn can_be_in_transfer_ring(&self) -> Result<bool> {
250        match self.get_trb_type().map_err(Error::UnknownTrbType)? {
251            TrbType::Normal
252            | TrbType::SetupStage
253            | TrbType::DataStage
254            | TrbType::StatusStage
255            | TrbType::Isoch
256            | TrbType::Link
257            | TrbType::EventData
258            | TrbType::Noop => Ok(true),
259            _ => Ok(false),
260        }
261    }
262
263    /// Length of this transfer.
264    pub fn transfer_length(&self) -> Result<u32> {
265        const STATUS_TRANSFER_LENGTH_MASK: u32 = 0x1ffff;
266        match self.get_trb_type().map_err(Error::UnknownTrbType)? {
267            TrbType::Normal | TrbType::SetupStage | TrbType::DataStage | TrbType::Isoch => {
268                Ok(self.get_status() & STATUS_TRANSFER_LENGTH_MASK)
269            }
270            _ => Ok(0),
271        }
272    }
273
274    /// Returns true if interrupt is required on completion.
275    pub fn interrupt_on_completion(&self) -> bool {
276        const FLAGS_INTERRUPT_ON_COMPLETION_MASK: u16 = 0x10;
277        (self.get_flags() & FLAGS_INTERRUPT_ON_COMPLETION_MASK) > 0
278    }
279
280    /// Returns true if interrupt is required on transfer of short packet.
281    pub fn interrupt_on_short_packet(&self) -> bool {
282        const FLAGS_INTERRUPT_ON_SHORT_PACKET: u16 = 0x2;
283        (self.get_flags() & FLAGS_INTERRUPT_ON_SHORT_PACKET) > 0
284    }
285
286    /// Returns true if this trb is immediate data.
287    pub fn immediate_data(&self) -> Result<bool> {
288        const FLAGS_IMMEDIATE_DATA_MASK: u16 = 0x20;
289        match self.get_trb_type().map_err(Error::UnknownTrbType)? {
290            TrbType::Normal | TrbType::SetupStage | TrbType::DataStage | TrbType::Isoch => {
291                Ok((self.get_flags() & FLAGS_IMMEDIATE_DATA_MASK) != 0)
292            }
293            _ => Ok(false),
294        }
295    }
296}
297
298#[bitfield]
299#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
300pub struct NormalTrb {
301    data_buffer_pointer: B64,
302    trb_transfer_length: B17,
303    td_size: B5,
304    interrupter_target: B10,
305    cycle: bool,
306    evaluate_next_trb: B1,
307    interrupt_on_short_packet: B1,
308    no_snoop: B1,
309    chain: bool,
310    interrupt_on_completion: B1,
311    immediate_data: B1,
312    reserved: B2,
313    block_event_interrupt: B1,
314    trb_type: TrbType,
315    reserved1: B16,
316}
317
318#[bitfield]
319#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
320pub struct SetupStageTrb {
321    request_type: B8,
322    request: B8,
323    value: B16,
324    index: B16,
325    length: B16,
326    trb_transfer_length: B17,
327    reserved0: B5,
328    interrupter_target: B10,
329    cycle: bool,
330    reserved1: B4,
331    interrupt_on_completion: B1,
332    immediate_data: B1,
333    reserved2: B3,
334    trb_type: TrbType,
335    transfer_type: B2,
336    reserved3: B14,
337}
338
339#[bitfield]
340#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
341pub struct DataStageTrb {
342    data_buffer_pointer: B64,
343    trb_transfer_length: B17,
344    td_size: B5,
345    interrupter_target: B10,
346    cycle: bool,
347    evaluate_next_trb: B1,
348    interrupt_on_short_packet: B1,
349    no_snoop: B1,
350    chain: bool,
351    interrupt_on_completion: B1,
352    immediate_data: B1,
353    reserved0: B3,
354    trb_type: TrbType,
355    direction: B1,
356    reserved1: B15,
357}
358
359#[bitfield]
360#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
361pub struct StatusStageTrb {
362    reserved0: B64,
363    reserved1: B22,
364    interrupter_target: B10,
365    cycle: bool,
366    evaluate_next_trb: B1,
367    reserved2: B2,
368    chain: bool,
369    interrupt_on_completion: B1,
370    reserved3: B4,
371    trb_type: TrbType,
372    direction: B1,
373    reserved4: B15,
374}
375
376#[bitfield]
377#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
378pub struct IsochTrb {
379    data_buffer_pointer: B64,
380    trb_transfer_length: B17,
381    td_size: B5,
382    interrupter_target: B10,
383    cycle: bool,
384    evaulate_next_trb: B1,
385    interrupt_on_short_packet: B1,
386    no_snoop: B1,
387    chain: bool,
388    interrupt_on_completion: B1,
389    immediate_data: B1,
390    transfer_burst_count: B2,
391    block_event_interrupt: B1,
392    trb_type: TrbType,
393    tlbpc: B4,
394    frame_id: B11,
395    sia: B1,
396}
397
398#[bitfield]
399#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
400pub struct LinkTrb {
401    ring_segment_pointer: B64,
402    reserved0: B22,
403    interrupter_target: B10,
404    cycle: bool,
405    toggle_cycle: bool,
406    reserved1: B2,
407    chain: bool,
408    interrupt_on_completion: bool,
409    reserved2: B4,
410    trb_type: TrbType,
411    reserved3: B16,
412}
413
414#[bitfield]
415#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
416pub struct EventDataTrb {
417    event_data: B64,
418    reserved0: B22,
419    interrupter_target: B10,
420    cycle: bool,
421    evaluate_next_trb: B1,
422    reserved1: B2,
423    chain: bool,
424    interrupt_on_completion: B1,
425    reserved2: B3,
426    block_event_interrupt: B1,
427    trb_type: TrbType,
428    reserved3: B16,
429}
430
431#[bitfield]
432#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
433pub struct NoopTrb {
434    reserved0: B64,
435    reserved1: B22,
436    interrupter_target: B10,
437    cycle: bool,
438    evaluate_next_trb: B1,
439    reserved2: B2,
440    chain: bool,
441    interrupt_on_completion: B1,
442    reserved3: B4,
443    trb_type: TrbType,
444    reserved4: B16,
445}
446
447#[bitfield]
448#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
449pub struct DisableSlotCommandTrb {
450    reserved0: B32,
451    reserved1: B32,
452    reserved2: B32,
453    cycle: bool,
454    reserved3: B9,
455    trb_type: TrbType,
456    reserved4: B8,
457    slot_id: B8,
458}
459
460#[bitfield]
461#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
462pub struct AddressDeviceCommandTrb {
463    input_context_pointer: B64,
464    reserved: B32,
465    cycle: bool,
466    reserved2: B8,
467    block_set_address_request: bool,
468    trb_type: TrbType,
469    reserved3: B8,
470    slot_id: B8,
471}
472
473#[bitfield]
474#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
475pub struct ConfigureEndpointCommandTrb {
476    input_context_pointer: B64,
477    reserved0: B32,
478    cycle: bool,
479    reserved1: B8,
480    deconfigure: bool,
481    trb_type: TrbType,
482    reserved2: B8,
483    slot_id: B8,
484}
485
486#[bitfield]
487#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
488pub struct EvaluateContextCommandTrb {
489    input_context_pointer: B64,
490    reserved0: B32,
491    cycle: bool,
492    reserved1: B9,
493    trb_type: TrbType,
494    reserved2: B8,
495    slot_id: B8,
496}
497
498#[bitfield]
499#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
500pub struct ResetEndpointCommandTrb {
501    reserved0: B32,
502    reserved1: B32,
503    reserved2: B32,
504    cycle: bool,
505    reserved3: B8,
506    transfer_state_preserve: B1,
507    trb_type: TrbType,
508    endpoint_id: B5,
509    reserved4: B3,
510    slot_id: B8,
511}
512
513#[bitfield]
514#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
515pub struct StopEndpointCommandTrb {
516    reserved0: B32,
517    reserved1: B32,
518    reserved2: B32,
519    cycle: bool,
520    reserved3: B9,
521    trb_type: TrbType,
522    endpoint_id: B5,
523    reserved4: B2,
524    suspend: B1,
525    slot_id: B8,
526}
527
528#[bitfield]
529#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
530pub struct SetTRDequeuePointerCommandTrb {
531    dequeue_cycle_state: bool,
532    stream_context_type: B3,
533    dequeue_ptr: DequeuePtr,
534    reserved0: B16,
535    stream_id: B16,
536    cycle: bool,
537    reserved1: B9,
538    trb_type: TrbType,
539    endpoint_id: B5,
540    reserved3: B2,
541    suspend: B1,
542    slot_id: B8,
543}
544
545#[bitfield]
546#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
547pub struct ResetDeviceCommandTrb {
548    reserved0: B32,
549    reserved1: B32,
550    reserved2: B32,
551    cycle: bool,
552    reserved3: B9,
553    trb_type: TrbType,
554    reserved4: B8,
555    slot_id: B8,
556}
557
558#[bitfield]
559#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
560pub struct TransferEventTrb {
561    trb_pointer: B64,
562    trb_transfer_length: B24,
563    completion_code: TrbCompletionCode,
564    cycle: bool,
565    reserved0: B1,
566    event_data: B1,
567    reserved1: B7,
568    trb_type: TrbType,
569    endpoint_id: B5,
570    reserved2: B3,
571    slot_id: B8,
572}
573
574#[bitfield]
575#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
576pub struct CommandCompletionEventTrb {
577    trb_pointer: B64,
578    command_completion_parameter: B24,
579    completion_code: TrbCompletionCode,
580    cycle: bool,
581    reserved: B9,
582    trb_type: TrbType,
583    vf_id: B8,
584    slot_id: B8,
585}
586
587#[bitfield]
588#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
589pub struct PortStatusChangeEventTrb {
590    reserved0: B24,
591    port_id: B8,
592    reserved1: B32,
593    reserved2: B24,
594    completion_code: TrbCompletionCode,
595    cycle: bool,
596    reserved3: B9,
597    trb_type: TrbType,
598    reserved4: B16,
599}
600
601/// Associate real type of trb.
602pub trait TypedTrb {
603    const TY: TrbType;
604}
605
606impl TypedTrb for Trb {
607    const TY: TrbType = TrbType::Reserved;
608}
609
610impl TypedTrb for NormalTrb {
611    const TY: TrbType = TrbType::Normal;
612}
613
614impl TypedTrb for SetupStageTrb {
615    const TY: TrbType = TrbType::SetupStage;
616}
617
618impl TypedTrb for DataStageTrb {
619    const TY: TrbType = TrbType::DataStage;
620}
621
622impl TypedTrb for StatusStageTrb {
623    const TY: TrbType = TrbType::StatusStage;
624}
625
626impl TypedTrb for IsochTrb {
627    const TY: TrbType = TrbType::Isoch;
628}
629
630impl TypedTrb for LinkTrb {
631    const TY: TrbType = TrbType::Link;
632}
633
634impl TypedTrb for EventDataTrb {
635    const TY: TrbType = TrbType::EventData;
636}
637
638impl TypedTrb for NoopTrb {
639    const TY: TrbType = TrbType::Noop;
640}
641
642impl TypedTrb for DisableSlotCommandTrb {
643    const TY: TrbType = TrbType::DisableSlotCommand;
644}
645
646impl TypedTrb for AddressDeviceCommandTrb {
647    const TY: TrbType = TrbType::AddressDeviceCommand;
648}
649
650impl TypedTrb for ConfigureEndpointCommandTrb {
651    const TY: TrbType = TrbType::ConfigureEndpointCommand;
652}
653
654impl TypedTrb for EvaluateContextCommandTrb {
655    const TY: TrbType = TrbType::EvaluateContextCommand;
656}
657
658impl TypedTrb for ResetEndpointCommandTrb {
659    const TY: TrbType = TrbType::ResetEndpointCommand;
660}
661
662impl TypedTrb for StopEndpointCommandTrb {
663    const TY: TrbType = TrbType::StopEndpointCommand;
664}
665
666impl TypedTrb for SetTRDequeuePointerCommandTrb {
667    const TY: TrbType = TrbType::SetTRDequeuePointerCommand;
668}
669
670impl TypedTrb for ResetDeviceCommandTrb {
671    const TY: TrbType = TrbType::ResetDeviceCommand;
672}
673
674impl TypedTrb for TransferEventTrb {
675    const TY: TrbType = TrbType::TransferEvent;
676}
677
678impl TypedTrb for CommandCompletionEventTrb {
679    const TY: TrbType = TrbType::CommandCompletionEvent;
680}
681
682impl TypedTrb for PortStatusChangeEventTrb {
683    const TY: TrbType = TrbType::PortStatusChangeEvent;
684}
685
686/// # Safety
687///
688/// All trb structs have the same size. One trb could be safely casted to another, though the
689/// values might be invalid.
690pub unsafe trait TrbCast:
691    FromBytes + Immutable + IntoBytes + KnownLayout + TypedTrb
692{
693    fn cast<T: TrbCast>(&self) -> Result<&T> {
694        zerocopy::Ref::<_, T>::from_bytes(self.as_bytes())
695            .map_err(|_| Error::CannotCastTrb)
696            .map(zerocopy::Ref::into_ref)
697    }
698
699    fn cast_mut<T: TrbCast>(&mut self) -> Result<&mut T> {
700        zerocopy::Ref::<_, T>::from_bytes(self.as_mut_bytes())
701            .map_err(|_| Error::CannotCastTrb)
702            .map(zerocopy::Ref::into_mut)
703    }
704
705    fn checked_cast<T: TrbCast>(&self) -> Result<&T> {
706        if self
707            .cast::<Trb>()?
708            .get_trb_type()
709            .map_err(Error::UnknownTrbType)?
710            != T::TY
711        {
712            return Err(Error::CannotCastTrb);
713        }
714        self.cast::<T>()
715    }
716
717    fn checked_mut_cast<T: TrbCast>(&mut self) -> Result<&mut T> {
718        if self
719            .cast::<Trb>()?
720            .get_trb_type()
721            .map_err(Error::UnknownTrbType)?
722            != T::TY
723        {
724            return Err(Error::CannotCastTrb);
725        }
726        self.cast_mut::<T>()
727    }
728}
729
730// SAFETY: see safety comments for TrbCast
731unsafe impl TrbCast for Trb {}
732// SAFETY: see safety comments for TrbCast
733unsafe impl TrbCast for NormalTrb {}
734// SAFETY: see safety comments for TrbCast
735unsafe impl TrbCast for SetupStageTrb {}
736// SAFETY: see safety comments for TrbCast
737unsafe impl TrbCast for DataStageTrb {}
738// SAFETY: see safety comments for TrbCast
739unsafe impl TrbCast for StatusStageTrb {}
740// SAFETY: see safety comments for TrbCast
741unsafe impl TrbCast for IsochTrb {}
742// SAFETY: see safety comments for TrbCast
743unsafe impl TrbCast for LinkTrb {}
744// SAFETY: see safety comments for TrbCast
745unsafe impl TrbCast for EventDataTrb {}
746// SAFETY: see safety comments for TrbCast
747unsafe impl TrbCast for NoopTrb {}
748// SAFETY: see safety comments for TrbCast
749unsafe impl TrbCast for DisableSlotCommandTrb {}
750// SAFETY: see safety comments for TrbCast
751unsafe impl TrbCast for AddressDeviceCommandTrb {}
752// SAFETY: see safety comments for TrbCast
753unsafe impl TrbCast for ConfigureEndpointCommandTrb {}
754// SAFETY: see safety comments for TrbCast
755unsafe impl TrbCast for EvaluateContextCommandTrb {}
756// SAFETY: see safety comments for TrbCast
757unsafe impl TrbCast for ResetEndpointCommandTrb {}
758// SAFETY: see safety comments for TrbCast
759unsafe impl TrbCast for StopEndpointCommandTrb {}
760// SAFETY: see safety comments for TrbCast
761unsafe impl TrbCast for SetTRDequeuePointerCommandTrb {}
762// SAFETY: see safety comments for TrbCast
763unsafe impl TrbCast for ResetDeviceCommandTrb {}
764// SAFETY: see safety comments for TrbCast
765unsafe impl TrbCast for TransferEventTrb {}
766// SAFETY: see safety comments for TrbCast
767unsafe impl TrbCast for CommandCompletionEventTrb {}
768// SAFETY: see safety comments for TrbCast
769unsafe impl TrbCast for PortStatusChangeEventTrb {}
770
771#[bitfield]
772#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
773pub struct EventRingSegmentTableEntry {
774    ring_segment_base_address: B64,
775    ring_segment_size: B16,
776    reserved2: B48,
777}
778
779#[bitfield]
780#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
781pub struct InputControlContext {
782    // Xhci spec 6.2.5.1.
783    drop_context_flags: B32,
784    add_context_flags: B32,
785    reserved0: B32,
786    reserved1: B32,
787    reserved2: B32,
788    reserved3: B32,
789    reserved4: B32,
790    configuration_value: B8,
791    interface_number: B8,
792    alternate_setting: B8,
793    reserved5: B8,
794}
795
796impl InputControlContext {
797    /// Get drop context flag.
798    pub fn drop_context_flag(&self, idx: u8) -> bool {
799        (self.get_drop_context_flags() & (1 << idx)) != 0
800    }
801
802    /// Get add context flag.
803    pub fn add_context_flag(&self, idx: u8) -> bool {
804        (self.get_add_context_flags() & (1 << idx)) != 0
805    }
806}
807
808// Size of device context entries (SlotContext and EndpointContext).
809pub const DEVICE_CONTEXT_ENTRY_SIZE: usize = 32usize;
810
811#[bitfield]
812#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
813pub struct SlotContext {
814    route_string: B20,
815    speed: B4,
816    reserved1: B1,
817    mtt: B1,
818    hub: B1,
819    context_entries: B5,
820    max_exit_latency: B16,
821    root_hub_port_number: B8,
822    num_ports: B8,
823    tt_hub_slot_id: B8,
824    tt_port_number: B8,
825    tt_think_time: B2,
826    reserved2: B4,
827    interrupter_target: B10,
828    usb_device_address: B8,
829    reserved3: B19,
830    slot_state: DeviceSlotState,
831    reserved4: B32,
832    reserved5: B32,
833    reserved6: B32,
834    reserved7: B32,
835}
836
837#[bitfield]
838#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
839pub struct EndpointContext {
840    endpoint_state: EndpointState,
841    reserved1: B5,
842    mult: B2,
843    max_primary_streams: B5,
844    linear_stream_array: B1,
845    interval: B8,
846    max_esit_payload_hi: B8,
847    reserved2: B1,
848    error_count: B2,
849    endpoint_type: B3,
850    reserved3: B1,
851    host_initiate_disable: B1,
852    max_burst_size: B8,
853    max_packet_size: B16,
854    dequeue_cycle_state: bool,
855    reserved4: B3,
856    tr_dequeue_pointer: DequeuePtr,
857    average_trb_length: B16,
858    max_esit_payload_lo: B16,
859    reserved5: B32,
860    reserved6: B32,
861    reserved7: B32,
862}
863
864#[bitfield]
865#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
866pub struct StreamContext {
867    dequeue_cycle_state: bool,
868    stream_context_type: B3,
869    tr_dequeue_pointer: DequeuePtr,
870    stopped_edtla: B24,
871    reserved1: B8,
872    reserved2: B32,
873}
874
875#[repr(C)]
876#[derive(Clone, Copy, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)]
877pub struct StreamContextArray {
878    pub stream_contexts: [StreamContext; 16],
879}
880
881/// Device context.
882#[repr(C)]
883#[derive(Clone, Copy, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)]
884pub struct DeviceContext {
885    pub slot_context: SlotContext,
886    pub endpoint_context: [EndpointContext; 31],
887}
888
889/// POD struct associates a TRB with its address in guest memory.  This is
890/// useful because transfer and command completion event TRBs must contain
891/// pointers to the original TRB that generated the event.
892#[derive(Clone, Copy, Debug, PartialEq, Eq)]
893pub struct AddressedTrb {
894    pub trb: Trb,
895    pub gpa: u64,
896}
897
898pub type TransferDescriptor = Vec<AddressedTrb>;
899
900#[cfg(test)]
901mod tests {
902    use super::*;
903
904    #[test]
905    fn check_struct_sizes() {
906        assert_eq!(std::mem::size_of::<Trb>(), TRB_SIZE);
907        assert_eq!(std::mem::size_of::<NormalTrb>(), TRB_SIZE);
908        assert_eq!(std::mem::size_of::<SetupStageTrb>(), TRB_SIZE);
909        assert_eq!(std::mem::size_of::<DataStageTrb>(), TRB_SIZE);
910        assert_eq!(std::mem::size_of::<StatusStageTrb>(), TRB_SIZE);
911        assert_eq!(std::mem::size_of::<IsochTrb>(), TRB_SIZE);
912        assert_eq!(std::mem::size_of::<LinkTrb>(), TRB_SIZE);
913        assert_eq!(std::mem::size_of::<EventDataTrb>(), TRB_SIZE);
914        assert_eq!(std::mem::size_of::<NoopTrb>(), TRB_SIZE);
915        assert_eq!(std::mem::size_of::<DisableSlotCommandTrb>(), TRB_SIZE);
916        assert_eq!(std::mem::size_of::<AddressDeviceCommandTrb>(), TRB_SIZE);
917        assert_eq!(std::mem::size_of::<ConfigureEndpointCommandTrb>(), TRB_SIZE);
918        assert_eq!(std::mem::size_of::<EvaluateContextCommandTrb>(), TRB_SIZE);
919        assert_eq!(std::mem::size_of::<ResetEndpointCommandTrb>(), TRB_SIZE);
920        assert_eq!(std::mem::size_of::<StopEndpointCommandTrb>(), TRB_SIZE);
921        assert_eq!(
922            std::mem::size_of::<SetTRDequeuePointerCommandTrb>(),
923            TRB_SIZE
924        );
925        assert_eq!(std::mem::size_of::<ResetDeviceCommandTrb>(), TRB_SIZE);
926        assert_eq!(std::mem::size_of::<TransferEventTrb>(), TRB_SIZE);
927        assert_eq!(std::mem::size_of::<CommandCompletionEventTrb>(), TRB_SIZE);
928        assert_eq!(std::mem::size_of::<PortStatusChangeEventTrb>(), TRB_SIZE);
929
930        assert_eq!(
931            std::mem::size_of::<EventRingSegmentTableEntry>(),
932            SEGMENT_TABLE_SIZE
933        );
934        assert_eq!(std::mem::size_of::<InputControlContext>(), 32);
935        assert_eq!(
936            std::mem::size_of::<SlotContext>(),
937            DEVICE_CONTEXT_ENTRY_SIZE
938        );
939        assert_eq!(
940            std::mem::size_of::<EndpointContext>(),
941            DEVICE_CONTEXT_ENTRY_SIZE
942        );
943        assert_eq!(
944            std::mem::size_of::<DeviceContext>(),
945            32 * DEVICE_CONTEXT_ENTRY_SIZE
946        );
947    }
948}