Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/usb/xhci/xhci_abi.rs
5394 views
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
5
use std::fmt;
6
use std::fmt::Display;
7
use std::ops::Deref;
8
9
use bit_field::Error as BitFieldError;
10
use bit_field::*;
11
use remain::sorted;
12
use thiserror::Error;
13
use vm_memory::GuestAddress;
14
use zerocopy::FromBytes;
15
use zerocopy::Immutable;
16
use zerocopy::IntoBytes;
17
use zerocopy::KnownLayout;
18
19
#[sorted]
20
#[derive(Error, Debug)]
21
pub enum Error {
22
#[error("cannot cast trb from raw memory")]
23
CannotCastTrb,
24
#[error("we got an unknown trb type value: {0}")]
25
UnknownTrbType(BitFieldError),
26
}
27
28
type Result<T> = std::result::Result<T, Error>;
29
30
// Fixed size of all TRB types.
31
const TRB_SIZE: usize = 16;
32
33
// Size of segment table.
34
const SEGMENT_TABLE_SIZE: usize = 16;
35
36
/// All kinds of trb.
37
#[bitfield]
38
#[bits = 6]
39
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
40
pub enum TrbType {
41
Reserved = 0,
42
Normal = 1,
43
SetupStage = 2,
44
DataStage = 3,
45
StatusStage = 4,
46
Isoch = 5,
47
Link = 6,
48
EventData = 7,
49
Noop = 8,
50
EnableSlotCommand = 9,
51
DisableSlotCommand = 10,
52
AddressDeviceCommand = 11,
53
ConfigureEndpointCommand = 12,
54
EvaluateContextCommand = 13,
55
ResetEndpointCommand = 14,
56
StopEndpointCommand = 15,
57
SetTRDequeuePointerCommand = 16,
58
ResetDeviceCommand = 17,
59
NoopCommand = 23,
60
TransferEvent = 32,
61
CommandCompletionEvent = 33,
62
PortStatusChangeEvent = 34,
63
}
64
65
/// Completion code of trb types.
66
#[bitfield]
67
#[bits = 8]
68
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
69
pub enum TrbCompletionCode {
70
Success = 1,
71
TransactionError = 4,
72
TrbError = 5,
73
StallError = 6,
74
NoSlotsAvailableError = 9,
75
SlotNotEnabledError = 11,
76
ShortPacket = 13,
77
ContextStateError = 19,
78
}
79
80
/// State of device slot.
81
#[bitfield]
82
#[bits = 5]
83
#[derive(PartialEq, Eq, Debug)]
84
pub 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)]
97
pub 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)]
108
pub struct DequeuePtr(u64);
109
110
impl 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)]
124
pub struct Trb {
125
parameter: B64,
126
status: B32,
127
cycle: bool,
128
flags: B9,
129
trb_type: TrbType,
130
control: B16,
131
}
132
133
impl 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
219
impl 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
228
impl 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)]
301
pub 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)]
321
pub 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)]
342
pub 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)]
362
pub 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)]
379
pub 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)]
401
pub 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)]
417
pub 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)]
434
pub 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)]
450
pub 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)]
463
pub 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)]
476
pub 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)]
489
pub 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)]
501
pub 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)]
516
pub 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)]
531
pub 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)]
548
pub 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)]
561
pub 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)]
577
pub 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)]
590
pub 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.
603
pub trait TypedTrb {
604
const TY: TrbType;
605
}
606
607
impl TypedTrb for Trb {
608
const TY: TrbType = TrbType::Reserved;
609
}
610
611
impl TypedTrb for NormalTrb {
612
const TY: TrbType = TrbType::Normal;
613
}
614
615
impl TypedTrb for SetupStageTrb {
616
const TY: TrbType = TrbType::SetupStage;
617
}
618
619
impl TypedTrb for DataStageTrb {
620
const TY: TrbType = TrbType::DataStage;
621
}
622
623
impl TypedTrb for StatusStageTrb {
624
const TY: TrbType = TrbType::StatusStage;
625
}
626
627
impl TypedTrb for IsochTrb {
628
const TY: TrbType = TrbType::Isoch;
629
}
630
631
impl TypedTrb for LinkTrb {
632
const TY: TrbType = TrbType::Link;
633
}
634
635
impl TypedTrb for EventDataTrb {
636
const TY: TrbType = TrbType::EventData;
637
}
638
639
impl TypedTrb for NoopTrb {
640
const TY: TrbType = TrbType::Noop;
641
}
642
643
impl TypedTrb for DisableSlotCommandTrb {
644
const TY: TrbType = TrbType::DisableSlotCommand;
645
}
646
647
impl TypedTrb for AddressDeviceCommandTrb {
648
const TY: TrbType = TrbType::AddressDeviceCommand;
649
}
650
651
impl TypedTrb for ConfigureEndpointCommandTrb {
652
const TY: TrbType = TrbType::ConfigureEndpointCommand;
653
}
654
655
impl TypedTrb for EvaluateContextCommandTrb {
656
const TY: TrbType = TrbType::EvaluateContextCommand;
657
}
658
659
impl TypedTrb for ResetEndpointCommandTrb {
660
const TY: TrbType = TrbType::ResetEndpointCommand;
661
}
662
663
impl TypedTrb for StopEndpointCommandTrb {
664
const TY: TrbType = TrbType::StopEndpointCommand;
665
}
666
667
impl TypedTrb for SetTRDequeuePointerCommandTrb {
668
const TY: TrbType = TrbType::SetTRDequeuePointerCommand;
669
}
670
671
impl TypedTrb for ResetDeviceCommandTrb {
672
const TY: TrbType = TrbType::ResetDeviceCommand;
673
}
674
675
impl TypedTrb for TransferEventTrb {
676
const TY: TrbType = TrbType::TransferEvent;
677
}
678
679
impl TypedTrb for CommandCompletionEventTrb {
680
const TY: TrbType = TrbType::CommandCompletionEvent;
681
}
682
683
impl 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.
691
pub 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
732
unsafe impl TrbCast for Trb {}
733
// SAFETY: see safety comments for TrbCast
734
unsafe impl TrbCast for NormalTrb {}
735
// SAFETY: see safety comments for TrbCast
736
unsafe impl TrbCast for SetupStageTrb {}
737
// SAFETY: see safety comments for TrbCast
738
unsafe impl TrbCast for DataStageTrb {}
739
// SAFETY: see safety comments for TrbCast
740
unsafe impl TrbCast for StatusStageTrb {}
741
// SAFETY: see safety comments for TrbCast
742
unsafe impl TrbCast for IsochTrb {}
743
// SAFETY: see safety comments for TrbCast
744
unsafe impl TrbCast for LinkTrb {}
745
// SAFETY: see safety comments for TrbCast
746
unsafe impl TrbCast for EventDataTrb {}
747
// SAFETY: see safety comments for TrbCast
748
unsafe impl TrbCast for NoopTrb {}
749
// SAFETY: see safety comments for TrbCast
750
unsafe impl TrbCast for DisableSlotCommandTrb {}
751
// SAFETY: see safety comments for TrbCast
752
unsafe impl TrbCast for AddressDeviceCommandTrb {}
753
// SAFETY: see safety comments for TrbCast
754
unsafe impl TrbCast for ConfigureEndpointCommandTrb {}
755
// SAFETY: see safety comments for TrbCast
756
unsafe impl TrbCast for EvaluateContextCommandTrb {}
757
// SAFETY: see safety comments for TrbCast
758
unsafe impl TrbCast for ResetEndpointCommandTrb {}
759
// SAFETY: see safety comments for TrbCast
760
unsafe impl TrbCast for StopEndpointCommandTrb {}
761
// SAFETY: see safety comments for TrbCast
762
unsafe impl TrbCast for SetTRDequeuePointerCommandTrb {}
763
// SAFETY: see safety comments for TrbCast
764
unsafe impl TrbCast for ResetDeviceCommandTrb {}
765
// SAFETY: see safety comments for TrbCast
766
unsafe impl TrbCast for TransferEventTrb {}
767
// SAFETY: see safety comments for TrbCast
768
unsafe impl TrbCast for CommandCompletionEventTrb {}
769
// SAFETY: see safety comments for TrbCast
770
unsafe impl TrbCast for PortStatusChangeEventTrb {}
771
772
#[bitfield]
773
#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
774
pub 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)]
782
pub 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
797
impl 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).
810
pub const DEVICE_CONTEXT_ENTRY_SIZE: usize = 32usize;
811
812
#[bitfield]
813
#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
814
pub 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)]
840
pub 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)]
867
pub 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)]
878
pub 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)]
885
pub 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)]
894
pub struct AddressedTrb {
895
pub trb: Trb,
896
pub gpa: u64,
897
}
898
899
/// Transfer Descriptor that contains at least one TRB.
900
// To preserve the non-empty invariant, this type does not expose methods
901
// that would move out the contained TRBs.
902
#[derive(Clone, Debug)]
903
pub struct TransferDescriptor(Vec<AddressedTrb>);
904
905
impl TransferDescriptor {
906
/// Create a new `TransferDescriptor` from a non-empty `Vec`.
907
pub fn new(trbs: Vec<AddressedTrb>) -> Option<Self> {
908
if trbs.is_empty() {
909
return None;
910
}
911
Some(TransferDescriptor(trbs))
912
}
913
914
/// Return the first TRB.
915
pub fn first_atrb(&self) -> &AddressedTrb {
916
self.first().expect("TransferDescriptor must be non-empty")
917
}
918
919
/// Return the last TRB.
920
pub fn last_atrb(&self) -> &AddressedTrb {
921
self.last().expect("TransferDescriptor must be non-empty")
922
}
923
}
924
925
impl Deref for TransferDescriptor {
926
type Target = [AddressedTrb];
927
928
fn deref(&self) -> &Self::Target {
929
&self.0
930
}
931
}
932
933
// It should be enough to implement the borrowing iterator, but not the consuming iterator.
934
impl<'a> IntoIterator for &'a TransferDescriptor {
935
type Item = &'a AddressedTrb;
936
type IntoIter = std::slice::Iter<'a, AddressedTrb>;
937
938
fn into_iter(self) -> Self::IntoIter {
939
self.0.iter()
940
}
941
}
942
943
#[cfg(test)]
944
mod tests {
945
use super::*;
946
947
#[test]
948
fn check_struct_sizes() {
949
assert_eq!(std::mem::size_of::<Trb>(), TRB_SIZE);
950
assert_eq!(std::mem::size_of::<NormalTrb>(), TRB_SIZE);
951
assert_eq!(std::mem::size_of::<SetupStageTrb>(), TRB_SIZE);
952
assert_eq!(std::mem::size_of::<DataStageTrb>(), TRB_SIZE);
953
assert_eq!(std::mem::size_of::<StatusStageTrb>(), TRB_SIZE);
954
assert_eq!(std::mem::size_of::<IsochTrb>(), TRB_SIZE);
955
assert_eq!(std::mem::size_of::<LinkTrb>(), TRB_SIZE);
956
assert_eq!(std::mem::size_of::<EventDataTrb>(), TRB_SIZE);
957
assert_eq!(std::mem::size_of::<NoopTrb>(), TRB_SIZE);
958
assert_eq!(std::mem::size_of::<DisableSlotCommandTrb>(), TRB_SIZE);
959
assert_eq!(std::mem::size_of::<AddressDeviceCommandTrb>(), TRB_SIZE);
960
assert_eq!(std::mem::size_of::<ConfigureEndpointCommandTrb>(), TRB_SIZE);
961
assert_eq!(std::mem::size_of::<EvaluateContextCommandTrb>(), TRB_SIZE);
962
assert_eq!(std::mem::size_of::<ResetEndpointCommandTrb>(), TRB_SIZE);
963
assert_eq!(std::mem::size_of::<StopEndpointCommandTrb>(), TRB_SIZE);
964
assert_eq!(
965
std::mem::size_of::<SetTRDequeuePointerCommandTrb>(),
966
TRB_SIZE
967
);
968
assert_eq!(std::mem::size_of::<ResetDeviceCommandTrb>(), TRB_SIZE);
969
assert_eq!(std::mem::size_of::<TransferEventTrb>(), TRB_SIZE);
970
assert_eq!(std::mem::size_of::<CommandCompletionEventTrb>(), TRB_SIZE);
971
assert_eq!(std::mem::size_of::<PortStatusChangeEventTrb>(), TRB_SIZE);
972
973
assert_eq!(
974
std::mem::size_of::<EventRingSegmentTableEntry>(),
975
SEGMENT_TABLE_SIZE
976
);
977
assert_eq!(std::mem::size_of::<InputControlContext>(), 32);
978
assert_eq!(
979
std::mem::size_of::<SlotContext>(),
980
DEVICE_CONTEXT_ENTRY_SIZE
981
);
982
assert_eq!(
983
std::mem::size_of::<EndpointContext>(),
984
DEVICE_CONTEXT_ENTRY_SIZE
985
);
986
assert_eq!(
987
std::mem::size_of::<DeviceContext>(),
988
32 * DEVICE_CONTEXT_ENTRY_SIZE
989
);
990
}
991
}
992
993