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