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