1use 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
29const TRB_SIZE: usize = 16;
31
32const SEGMENT_TABLE_SIZE: usize = 16;
34
35#[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#[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#[bitfield]
82#[bits = 5]
83#[derive(PartialEq, Eq, Debug)]
84pub enum DeviceSlotState {
85 DisabledOrEnabled = 0,
88 Default = 1,
89 Addressed = 2,
90 Configured = 3,
91}
92
93#[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 pub fn get_gpa(&self) -> GuestAddress {
117 GuestAddress(self.0 << 4)
118 }
119}
120
121#[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 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 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 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 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 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 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 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
602pub 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
687pub 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
731unsafe impl TrbCast for Trb {}
733unsafe impl TrbCast for NormalTrb {}
735unsafe impl TrbCast for SetupStageTrb {}
737unsafe impl TrbCast for DataStageTrb {}
739unsafe impl TrbCast for StatusStageTrb {}
741unsafe impl TrbCast for IsochTrb {}
743unsafe impl TrbCast for LinkTrb {}
745unsafe impl TrbCast for EventDataTrb {}
747unsafe impl TrbCast for NoopTrb {}
749unsafe impl TrbCast for DisableSlotCommandTrb {}
751unsafe impl TrbCast for AddressDeviceCommandTrb {}
753unsafe impl TrbCast for ConfigureEndpointCommandTrb {}
755unsafe impl TrbCast for EvaluateContextCommandTrb {}
757unsafe impl TrbCast for ResetEndpointCommandTrb {}
759unsafe impl TrbCast for StopEndpointCommandTrb {}
761unsafe impl TrbCast for SetTRDequeuePointerCommandTrb {}
763unsafe impl TrbCast for ResetDeviceCommandTrb {}
765unsafe impl TrbCast for TransferEventTrb {}
767unsafe impl TrbCast for CommandCompletionEventTrb {}
769unsafe 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 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 pub fn drop_context_flag(&self, idx: u8) -> bool {
800 (self.get_drop_context_flags() & (1 << idx)) != 0
801 }
802
803 pub fn add_context_flag(&self, idx: u8) -> bool {
805 (self.get_add_context_flags() & (1 << idx)) != 0
806 }
807}
808
809pub 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#[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#[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}