From 4fd60b94b9a77e1983300f9fadd46f677bee567f Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Fri, 1 Dec 2023 14:27:51 +0000 Subject: [PATCH 01/17] Clarify the exact behavior of RW1C setters --- src/macros.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 9fd12d6..c3dea31 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -113,18 +113,18 @@ macro_rules! rw1c_bit { ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { bit_getter!([$offset]($bit), $method, $name); paste::paste! { - #[doc = "Clears the"] + #[doc = "Assigns 1 to the"] #[doc = $name] - #[doc = "bit."] + #[doc = "bit. On register write, this results in clearing the bit."] pub fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0[$offset].set_bit($bit,true); self } - #[doc = "Set the "] + #[doc = "Assigns 0 to the"] #[doc = $name] - #[doc = " bit to 0, preventing the bit from being cleared on write."] + #[doc = "bit, preventing the bit from being cleared on write."] pub fn [](&mut self) -> &mut Self { use bit_field::BitField; self.0[$offset].set_bit($bit,false); @@ -135,18 +135,18 @@ macro_rules! rw1c_bit { ($bit:literal,$method:ident,$name:literal) => { bit_getter!($bit, $method, $name); paste::paste! { - #[doc = "Clears the"] + #[doc = "Assigns 1 to the"] #[doc = $name] - #[doc = "bit."] + #[doc = "bit. On register write, this results in clearing the bit."] pub fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0.set_bit($bit,true); self } - #[doc = "Set the "] + #[doc = "Assigns 0 to the"] #[doc = $name] - #[doc = " bit to 0, preventing the bit from being cleared on write."] + #[doc = "bit, preventing the bit from being cleared on write."] pub fn [](&mut self) -> &mut Self { use bit_field::BitField; self.0.set_bit($bit,false); From f2e067e6877549285c9d22a8d4e31a93fb5b406f Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Mon, 4 Dec 2023 06:14:25 +0000 Subject: [PATCH 02/17] rename doorbell::Register to Doorbell --- src/registers/doorbell.rs | 11 ++++++++--- src/registers/mod.rs | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/registers/doorbell.rs b/src/registers/doorbell.rs index 989f3e1..8a6db5b 100644 --- a/src/registers/doorbell.rs +++ b/src/registers/doorbell.rs @@ -5,11 +5,15 @@ use accessor::array; use accessor::Mapper; use core::{convert::TryFrom, fmt}; +/// A type alias to [`Doorbell`] register for backward compability. +#[deprecated = "Use `Doorbell` instead of `Register`."] +pub type Register = Doorbell; + /// The element of the Doorbell Array. #[repr(transparent)] #[derive(Copy, Clone, Default)] -pub struct Register(u32); -impl Register { +pub struct Doorbell(u32); +impl Doorbell { /// Creates a new accessor to the Doorbell Array. /// /// # Safety @@ -44,7 +48,8 @@ impl Register { rw_field!(0..=7, doorbell_target, "Doorbell Target", u8); rw_field!(16..=31, doorbell_stream_id, "Doorbell Stream ID", u16); } -impl fmt::Debug for Register { + +impl fmt::Debug for Doorbell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("doorbell::Register") .field("doorbell_target", &self.doorbell_target()) diff --git a/src/registers/mod.rs b/src/registers/mod.rs index d98507b..a34472c 100644 --- a/src/registers/mod.rs +++ b/src/registers/mod.rs @@ -22,7 +22,7 @@ where /// Host Controller Capability Register pub capability: Capability, /// Doorbell Array - pub doorbell: array::ReadWrite, + pub doorbell: array::ReadWrite, /// Host Controller Operational Register pub operational: Operational, /// Port Register Set Array @@ -75,7 +75,7 @@ where /// ``` pub unsafe fn new(mmio_base: usize, mapper: M) -> Self { let capability = Capability::new(mmio_base, &mapper); - let doorbell = doorbell::Register::new(mmio_base, &capability, mapper.clone()); + let doorbell = doorbell::Doorbell::new(mmio_base, &capability, mapper.clone()); let operational = Operational::new(mmio_base, capability.caplength.read_volatile(), &mapper); let port_register_set = PortRegisterSet::new(mmio_base, &capability, mapper.clone()); From b89a5d47d9aca60658ed8bfb8f9db12b3ee77e44 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Mon, 4 Dec 2023 06:31:26 +0000 Subject: [PATCH 03/17] mark cap registers as read-only. --- src/registers/capability.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/registers/capability.rs b/src/registers/capability.rs index 8b5cc72..323863c 100644 --- a/src/registers/capability.rs +++ b/src/registers/capability.rs @@ -11,25 +11,25 @@ where M: Mapper + Clone, { /// Capability Registers Length - pub caplength: single::ReadWrite, + pub caplength: single::ReadOnly, /// Host Controller Interface Version Number - pub hciversion: single::ReadWrite, + pub hciversion: single::ReadOnly, /// Structural Parameters 1 - pub hcsparams1: single::ReadWrite, + pub hcsparams1: single::ReadOnly, /// Structural Parameters 2 - pub hcsparams2: single::ReadWrite, + pub hcsparams2: single::ReadOnly, /// Structural Parameters 3 - pub hcsparams3: single::ReadWrite, + pub hcsparams3: single::ReadOnly, /// Capability Parameters 1 - pub hccparams1: single::ReadWrite, + pub hccparams1: single::ReadOnly, /// Doorbell Offset - pub dboff: single::ReadWrite, + pub dboff: single::ReadOnly, /// Runtime Register Space Offset - pub rtsoff: single::ReadWrite, + pub rtsoff: single::ReadOnly, /// Capability Parameters 2 - pub hccparams2: single::ReadWrite, + pub hccparams2: single::ReadOnly, /// Virtualization Based Trusted IO Register Space Offset - pub vtiosoff: single::ReadWrite, + pub vtiosoff: single::ReadOnly, } impl Capability where @@ -51,7 +51,7 @@ where { macro_rules! m { ($offset:expr) => { - single::ReadWrite::new(mmio_base + $offset, mapper.clone()) + single::ReadOnly::new(mmio_base + $offset, mapper.clone()) }; } From 3e05ecaa9916b3559b461842ea3c31d0484bb5dc Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Tue, 5 Dec 2023 08:33:52 +0900 Subject: [PATCH 04/17] convention fix Co-authored-by: Hiroki Tokunaga --- src/registers/doorbell.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/registers/doorbell.rs b/src/registers/doorbell.rs index 8a6db5b..0406013 100644 --- a/src/registers/doorbell.rs +++ b/src/registers/doorbell.rs @@ -48,7 +48,6 @@ impl Doorbell { rw_field!(0..=7, doorbell_target, "Doorbell Target", u8); rw_field!(16..=31, doorbell_stream_id, "Doorbell Stream ID", u16); } - impl fmt::Debug for Doorbell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("doorbell::Register") From 7303e5df67fbe28e4bcd741bcc5de074a2659102 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Tue, 5 Dec 2023 00:59:12 +0000 Subject: [PATCH 05/17] add visibility qualifier to macros --- src/extended_capabilities/debug.rs | 30 ++-- .../hci_extended_power_management.rs | 28 ++-- .../usb_legacy_support_capability.rs | 24 ++-- .../xhci_extended_message_interrupt.rs | 2 +- .../xhci_message_interrupt.rs | 6 +- src/macros.rs | 120 ++++++++-------- src/registers/capability.rs | 62 ++++----- src/registers/doorbell.rs | 4 +- src/registers/operational.rs | 128 +++++++++--------- src/registers/runtime.rs | 14 +- src/ring/trb/command.rs | 72 +++++----- src/ring/trb/event.rs | 28 ++-- src/ring/trb/mod.rs | 10 +- src/ring/trb/transfer.rs | 96 ++++++------- 14 files changed, 312 insertions(+), 312 deletions(-) diff --git a/src/extended_capabilities/debug.rs b/src/extended_capabilities/debug.rs index 8d8f030..d02e588 100644 --- a/src/extended_capabilities/debug.rs +++ b/src/extended_capabilities/debug.rs @@ -209,11 +209,11 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct Control(u32); impl Control { - ro_bit!(0, dbc_run, "DbC Run"); - rw_bit!(1, link_status_event_enable, "Link Status Event Enable"); - rw1s_bit!(2, halt_out_tr, "Halt OUT TR"); - rw1s_bit!(3, halt_in_tr, "Halt IN TR"); - rw1c_bit!(4, dbc_run_change, "DbC Run Change"); + ro_bit!(pub, 0, dbc_run, "DbC Run"); + rw_bit!(pub, 1, link_status_event_enable, "Link Status Event Enable"); + rw1s_bit!(pub, 2, halt_out_tr, "Halt OUT TR"); + rw1s_bit!(pub, 3, halt_in_tr, "Halt IN TR"); + rw1c_bit!(pub, 4, dbc_run_change, "DbC Run Change"); /// Returns the value of the Debug Max Burst Size field. #[must_use] @@ -227,7 +227,7 @@ impl Control { self.0.get_bits(24..=30).try_into().unwrap() } - rw_bit!(31, debug_capability_enable, "Debug Capability Enable"); + rw_bit!(pub, 31, debug_capability_enable, "Debug Capability Enable"); } impl_debug_from_methods! { Control { @@ -247,8 +247,8 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct Status(u32); impl Status { - ro_bit!(0, event_ring_not_empty, "Event Ring Not Empty"); - ro_bit!(1, dbc_system_bus_reset, "DbC System Bus Reset"); + ro_bit!(pub, 0, event_ring_not_empty, "Event Ring Not Empty"); + ro_bit!(pub, 1, dbc_system_bus_reset, "DbC System Bus Reset"); /// Returns the value of the Debug Port Number field. #[must_use] @@ -269,9 +269,9 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PortStatusAndControl(u32); impl PortStatusAndControl { - ro_bit!(0, current_connect_status, "Current Connect Status"); - rw_bit!(1, port_enabled_disabled, "Port Enabled/Disabled"); - ro_bit!(4, port_reset, "Port Reset"); + ro_bit!(pub, 0, current_connect_status, "Current Connect Status"); + rw_bit!(pub, 1, port_enabled_disabled, "Port Enabled/Disabled"); + ro_bit!(pub, 4, port_reset, "Port Reset"); /// Returns the value of the Port Link State field. #[must_use] @@ -285,10 +285,10 @@ impl PortStatusAndControl { self.0.get_bits(10..=13).try_into().unwrap() } - rw1c_bit!(17, connect_status_change, "Connect Status Change"); - rw1c_bit!(21, port_reset_change, "Port Reset Change"); - rw1c_bit!(22, port_link_status_change, "Port Link Status Change"); - rw1c_bit!(23, port_config_error_change, "Port Config Error Change"); + rw1c_bit!(pub, 17, connect_status_change, "Connect Status Change"); + rw1c_bit!(pub, 21, port_reset_change, "Port Reset Change"); + rw1c_bit!(pub, 22, port_link_status_change, "Port Link Status Change"); + rw1c_bit!(pub, 23, port_config_error_change, "Port Config Error Change"); } impl_debug_from_methods! { PortStatusAndControl { diff --git a/src/extended_capabilities/hci_extended_power_management.rs b/src/extended_capabilities/hci_extended_power_management.rs index b3e9d70..4bc2535 100644 --- a/src/extended_capabilities/hci_extended_power_management.rs +++ b/src/extended_capabilities/hci_extended_power_management.rs @@ -32,13 +32,13 @@ where #[derive(Copy, Clone)] pub struct PowerManagementCapabilities(u16); impl PowerManagementCapabilities { - ro_field!(11..=15, pme_support, "PME_Support", u8); - ro_bit!(10, d2_support, "D2_Support"); - ro_bit!(9, d1_support, "D1_Support"); - ro_field!(6..=8, aux_current, "Aux_Current", u8); - ro_bit!(5, dsi, "DSI"); - ro_bit!(3, pme_clock, "PME Clock"); - ro_field!(0..=2, version, "Version", u8); + ro_field!(pub, 11..=15, pme_support, "PME_Support", u8); + ro_bit!(pub, 10, d2_support, "D2_Support"); + ro_bit!(pub, 9, d1_support, "D1_Support"); + ro_field!(pub, 6..=8, aux_current, "Aux_Current", u8); + ro_bit!(pub, 5, dsi, "DSI"); + ro_bit!(pub, 3, pme_clock, "PME Clock"); + ro_field!(pub, 0..=2, version, "Version", u8); } impl_debug_from_methods! { PowerManagementCapabilities { @@ -57,11 +57,11 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PowerManagementControlStatusRegister(u16); impl PowerManagementControlStatusRegister { - rw1c_bit!(15, pme_status, "PME_Status"); - ro_field!(13..=14, data_scale, "Data_Scale", u8); - rw_field!(9..=12, data_select, "Data_Select", u8); - rw_bit!(8, pme_en, "PME_En"); - rw_field!(0..=1, power_state, "PowerState", u8); + rw1c_bit!(pub, 15, pme_status, "PME_Status"); + ro_field!(pub, 13..=14, data_scale, "Data_Scale", u8); + rw_field!(pub, 9..=12, data_select, "Data_Select", u8); + rw_bit!(pub, 8, pme_en, "PME_En"); + rw_field!(pub, 0..=1, power_state, "PowerState", u8); } impl_debug_from_methods! { PowerManagementControlStatusRegister { @@ -78,8 +78,8 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PmesrBse(u8); impl PmesrBse { - ro_bit!(7, bpcc_en, "BPCC_En"); - ro_bit!(6, b2_b3, "B2_B3"); + ro_bit!(pub, 7, bpcc_en, "BPCC_En"); + ro_bit!(pub, 6, b2_b3, "B2_B3"); } impl_debug_from_methods! { PmesrBse { diff --git a/src/extended_capabilities/usb_legacy_support_capability.rs b/src/extended_capabilities/usb_legacy_support_capability.rs index a55db0b..38363e2 100644 --- a/src/extended_capabilities/usb_legacy_support_capability.rs +++ b/src/extended_capabilities/usb_legacy_support_capability.rs @@ -53,8 +53,8 @@ where #[derive(Copy, Clone)] pub struct LegSup(u32); impl LegSup { - rw_bit!(16, hc_bios_owned_semaphore, "HC BIOS Owned Semaphore"); - rw_bit!(24, hc_os_owned_semaphore, "HC OS Owned Semaphore"); + rw_bit!(pub, 16, hc_bios_owned_semaphore, "HC BIOS Owned Semaphore"); + rw_bit!(pub, 24, hc_os_owned_semaphore, "HC OS Owned Semaphore"); } impl_debug_from_methods! { LegSup { @@ -68,20 +68,20 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct UsbLegacySupportControlStatus(u32); impl UsbLegacySupportControlStatus { - rw_bit!(0, usb_smi_enable, "USB SMI Enable"); - rw_bit!( + rw_bit!(pub, 0, usb_smi_enable, "USB SMI Enable"); + rw_bit!(pub, 4, smi_on_host_system_error_enable, "SMI on Host System Error Enable" ); - rw_bit!(13, smi_on_os_ownership_enable, "SMI on OS Ownership Enable"); - rw_bit!(14, smi_on_pci_command_enable, "SMI on PCI Command Enable"); - rw_bit!(15, smi_on_bar_enable, "SMI on BAR Enable"); - ro_bit!(16, smi_on_event_interrupt, "SMI on Event Interrupt"); - ro_bit!(20, smi_on_host_system_error, "SMI on Host System Error"); - rw1c_bit!(29, smi_on_os_ownership_change, "SMI on OS Ownership Change"); - rw1c_bit!(30, smi_on_pci_command, "SMI on PCI Command"); - rw1c_bit!(31, smi_on_bar, "SMI on BAR"); + rw_bit!(pub, 13, smi_on_os_ownership_enable, "SMI on OS Ownership Enable"); + rw_bit!(pub, 14, smi_on_pci_command_enable, "SMI on PCI Command Enable"); + rw_bit!(pub, 15, smi_on_bar_enable, "SMI on BAR Enable"); + ro_bit!(pub, 16, smi_on_event_interrupt, "SMI on Event Interrupt"); + ro_bit!(pub, 20, smi_on_host_system_error, "SMI on Host System Error"); + rw1c_bit!(pub, 29, smi_on_os_ownership_change, "SMI on OS Ownership Change"); + rw1c_bit!(pub, 30, smi_on_pci_command, "SMI on PCI Command"); + rw1c_bit!(pub, 31, smi_on_bar, "SMI on BAR"); } impl_debug_from_methods! { UsbLegacySupportControlStatus { diff --git a/src/extended_capabilities/xhci_extended_message_interrupt.rs b/src/extended_capabilities/xhci_extended_message_interrupt.rs index bb2af1c..9544b57 100644 --- a/src/extended_capabilities/xhci_extended_message_interrupt.rs +++ b/src/extended_capabilities/xhci_extended_message_interrupt.rs @@ -33,7 +33,7 @@ where #[derive(Copy, Clone)] pub struct MessageControl(u16); impl MessageControl { - rw_bit!(15, msi_x_enable, "MSI-X Enable"); + rw_bit!(pub, 15, msi_x_enable, "MSI-X Enable"); /// Returns the value of the Table Size field. #[must_use] diff --git a/src/extended_capabilities/xhci_message_interrupt.rs b/src/extended_capabilities/xhci_message_interrupt.rs index 1bbc91c..0a3f17a 100644 --- a/src/extended_capabilities/xhci_message_interrupt.rs +++ b/src/extended_capabilities/xhci_message_interrupt.rs @@ -113,8 +113,8 @@ impl MessageAddress for u64 {} #[derive(Copy, Clone)] pub struct MessageControl(u16); impl MessageControl { - ro_bit!(8, per_vector_masking_capable, "Per-vector masking capable"); - ro_bit!(7, bit64_address_capable, "64 bit address capable"); + ro_bit!(pub, 8, per_vector_masking_capable, "Per-vector masking capable"); + ro_bit!(pub, 7, bit64_address_capable, "64 bit address capable"); /// Returns the value of the Multiple Message Enable field. #[must_use] @@ -133,7 +133,7 @@ impl MessageControl { self.0.get_bits(1..=3).try_into().unwrap() } - rw_bit!(0, msi_enable, "MSI Enable"); + rw_bit!(pub, 0, msi_enable, "MSI Enable"); } impl_debug_from_methods! { MessageControl { diff --git a/src/macros.rs b/src/macros.rs index c3dea31..376724f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,22 +13,22 @@ macro_rules! impl_debug_from_methods { } macro_rules! bit_getter { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { #[doc = "Returns the"] #[doc = $name] #[doc = "bit."] #[must_use] - pub fn $method(self) -> bool { + $vis fn $method(self) -> bool { use bit_field::BitField; self.0[$offset].get_bit($bit) } }; - ($bit:literal,$method:ident,$name:literal) => { + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { #[doc = "Returns the"] #[doc = $name] #[doc = "bit."] #[must_use] - pub fn $method(self) -> bool { + $vis fn $method(self) -> bool { use bit_field::BitField; self.0.get_bit($bit) } @@ -36,12 +36,12 @@ macro_rules! bit_getter { } macro_rules! bit_modifier { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { paste::paste! { #[doc = "Sets the"] #[doc = $name] #[doc = "bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0[$offset].set_bit($bit,true); self @@ -50,19 +50,19 @@ macro_rules! bit_modifier { #[doc = "Clears the"] #[doc = $name] #[doc = "bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0[$offset].set_bit($bit,false); self } } }; - ($bit:literal,$method:ident,$name:literal) => { + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { paste::paste! { #[doc = "Sets the"] #[doc = $name] #[doc = "bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0.set_bit($bit,true); self @@ -71,7 +71,7 @@ macro_rules! bit_modifier { #[doc = "Clears the"] #[doc = $name] #[doc = "bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0.set_bit($bit,false); self @@ -81,42 +81,42 @@ macro_rules! bit_modifier { } macro_rules! ro_bit { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!([$offset]($bit), $method, $name); + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_getter!($vis, [$offset]($bit), $method, $name); }; - ($bit:literal,$method:ident,$name:literal) => { - bit_getter!($bit, $method, $name); + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $bit, $method, $name); }; } macro_rules! wo_bit { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_modifier!([$offset]($bit), $method, $name); + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_modifier!($vis, [$offset]($bit), $method, $name); }; - ($bit:literal,$method:ident,$name:literal) => { - bit_modifier!($bit, $method, $name); + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_modifier!($vis, $bit, $method, $name); }; } macro_rules! rw_bit { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!([$offset]($bit), $method, $name); - bit_modifier!([$offset]($bit), $method, $name); + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_getter!($vis, [$offset]($bit), $method, $name); + bit_modifier!($vis, [$offset]($bit), $method, $name); }; - ($bit:literal,$method:ident,$name:literal) => { - bit_getter!($bit, $method, $name); - bit_modifier!($bit, $method, $name); + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $bit, $method, $name); + bit_modifier!($vis, $bit, $method, $name); }; } macro_rules! rw1c_bit { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!([$offset]($bit), $method, $name); + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_getter!($vis, [$offset]($bit), $method, $name); paste::paste! { #[doc = "Assigns 1 to the"] #[doc = $name] #[doc = "bit. On register write, this results in clearing the bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0[$offset].set_bit($bit,true); self @@ -125,20 +125,20 @@ macro_rules! rw1c_bit { #[doc = "Assigns 0 to the"] #[doc = $name] #[doc = "bit, preventing the bit from being cleared on write."] - pub fn [](&mut self) -> &mut Self { + $vis fn [](&mut self) -> &mut Self { use bit_field::BitField; self.0[$offset].set_bit($bit,false); self } } }; - ($bit:literal,$method:ident,$name:literal) => { - bit_getter!($bit, $method, $name); + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $bit, $method, $name); paste::paste! { #[doc = "Assigns 1 to the"] #[doc = $name] #[doc = "bit. On register write, this results in clearing the bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0.set_bit($bit,true); self @@ -147,7 +147,7 @@ macro_rules! rw1c_bit { #[doc = "Assigns 0 to the"] #[doc = $name] #[doc = "bit, preventing the bit from being cleared on write."] - pub fn [](&mut self) -> &mut Self { + $vis fn [](&mut self) -> &mut Self { use bit_field::BitField; self.0.set_bit($bit,false); self @@ -157,24 +157,24 @@ macro_rules! rw1c_bit { } macro_rules! w1s_bit { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { paste::paste! { #[doc = "Sets the"] #[doc = $name] #[doc = "bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0[$offset].set_bit($bit,true); self } } }; - ($bit:literal,$method:ident,$name:literal) => { + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { paste::paste! { #[doc = "Sets the"] #[doc = $name] #[doc = "bit."] - pub fn [](&mut self)->&mut Self{ + $vis fn [](&mut self)->&mut Self{ use bit_field::BitField; self.0.set_bit($bit,true); self @@ -184,34 +184,34 @@ macro_rules! w1s_bit { } macro_rules! rw1s_bit { - ([$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!([$offset]($bit), $method, $name); - w1s_bit!([$offset]($bit), $method, $name); + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_getter!($vis, [$offset]($bit), $method, $name); + w1s_bit!($vis, [$offset]($bit), $method, $name); }; - ($bit:literal,$method:ident,$name:literal) => { - bit_getter!($bit, $method, $name); - w1s_bit!($bit, $method, $name); + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $bit, $method, $name); + w1s_bit!($vis, $bit, $method, $name); }; } macro_rules! field_getter { - ([$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { + ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { #[doc = "Returns the value of the"] #[doc = $name] #[doc = "field."] #[must_use] - pub fn $method(self) -> $ty { + $vis fn $method(self) -> $ty { use bit_field::BitField; use core::convert::TryInto; self.0[$offset].get_bits($range).try_into().unwrap() } }; - ($range:expr,$method:ident,$name:literal,$ty:ty) => { + ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { #[doc = "Returns the value of the"] #[doc = $name] #[doc = "field."] #[must_use] - pub fn $method(self) -> $ty { + $vis fn $method(self) -> $ty { use bit_field::BitField; use core::convert::TryInto; self.0.get_bits($range).try_into().unwrap() @@ -220,12 +220,12 @@ macro_rules! field_getter { } macro_rules! field_setter { - ([$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { + ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { paste::paste! { #[doc = "Sets the value of the"] #[doc = $name] #[doc = "field."] - pub fn [](&mut self,value:$ty) -> &mut Self { + $vis fn [](&mut self,value:$ty) -> &mut Self { use bit_field::BitField; use core::convert::TryInto; self.0[$offset].set_bits($range,value.try_into().unwrap()); @@ -233,12 +233,12 @@ macro_rules! field_setter { } } }; - ($range:expr,$method:ident,$name:literal,$ty:ty) => { + ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { paste::paste! { #[doc = "Sets the value of the"] #[doc = $name] #[doc = "field."] - pub fn [](&mut self,value:$ty) -> &mut Self { + $vis fn [](&mut self,value:$ty) -> &mut Self { use bit_field::BitField; use core::convert::TryInto; self.0.set_bits($range,value.try_into().unwrap()); @@ -249,21 +249,21 @@ macro_rules! field_setter { } macro_rules! ro_field { - ([$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { - field_getter!([$offset]($range), $method, $name, $ty); + ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { + field_getter!($vis, [$offset]($range), $method, $name, $ty); }; - ($range:expr,$method:ident,$name:literal,$ty:ty) => { - field_getter!($range, $method, $name, $ty); + ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { + field_getter!($vis, $range, $method, $name, $ty); }; } macro_rules! rw_field { - ([$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { - field_getter!([$offset]($range), $method, $name, $ty); - field_setter!([$offset]($range), $method, $name, $ty); + ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { + field_getter!($vis, [$offset]($range), $method, $name, $ty); + field_setter!($vis, [$offset]($range), $method, $name, $ty); }; - ($range:expr,$method:ident,$name:literal,$ty:ty) => { - field_getter!($range, $method, $name, $ty); - field_setter!($range, $method, $name, $ty); + ($vis:vis, $range:expr,$method:ident,$name:literal,$ty:ty) => { + field_getter!($vis, $range, $method, $name, $ty); + field_setter!($vis, $range, $method, $name, $ty); }; } diff --git a/src/registers/capability.rs b/src/registers/capability.rs index 323863c..cc3b1fa 100644 --- a/src/registers/capability.rs +++ b/src/registers/capability.rs @@ -105,9 +105,9 @@ impl InterfaceVersionNumber { #[derive(Copy, Clone)] pub struct StructuralParameters1(u32); impl StructuralParameters1 { - ro_field!(0..=7, number_of_device_slots, "Number of Device Slots", u8); - ro_field!(8..=18, number_of_interrupts, "Number of Interrupts", u16); - ro_field!(24..=31, number_of_ports, "Number of Ports", u8); + ro_field!(pub, 0..=7, number_of_device_slots, "Number of Device Slots", u8); + ro_field!(pub, 8..=18, number_of_interrupts, "Number of Interrupts", u16); + ro_field!(pub, 24..=31, number_of_ports, "Number of Ports", u8); } impl_debug_from_methods! { StructuralParameters1{ @@ -122,7 +122,7 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct StructuralParameters2(u32); impl StructuralParameters2 { - ro_field!( + ro_field!(pub, 0..=3, isochronous_scheduling_threshold, "Isochronous Scheduling Threshold", @@ -147,7 +147,7 @@ impl StructuralParameters2 { h << 5 | l } - ro_bit!(26, scratchpad_restore, "Scratchpad Restore"); + ro_bit!(pub, 26, scratchpad_restore, "Scratchpad Restore"); fn erst_max(self) -> u32 { self.0.get_bits(4..=7) @@ -175,8 +175,8 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct StructuralParameters3(u32); impl StructuralParameters3 { - ro_field!(0..=7, u1_device_exit_latency, "U1 Device Exit Latency", u8); - ro_field!( + ro_field!(pub, 0..=7, u1_device_exit_latency, "U1 Device Exit Latency", u8); + ro_field!(pub, 16..=31, u2_device_exit_latency, "U2 Device Exit Latency", @@ -196,37 +196,37 @@ impl_debug_from_methods! { #[allow(clippy::module_name_repetitions)] pub struct CapabilityParameters1(u32); impl CapabilityParameters1 { - ro_bit!(0, addressing_capability, "64-bit Addressing Capability"); - ro_bit!(1, bw_negotiation_capability, "BW Negotiation Capability"); - ro_bit!(2, context_size, "Context Size"); - ro_bit!(3, port_power_control, "Port Power Control"); - ro_bit!(4, port_indicators, "Port Indicators"); - ro_bit!(5, light_hc_reset_capability, "Light HC Reset Capability"); - ro_bit!( + ro_bit!(pub, 0, addressing_capability, "64-bit Addressing Capability"); + ro_bit!(pub, 1, bw_negotiation_capability, "BW Negotiation Capability"); + ro_bit!(pub, 2, context_size, "Context Size"); + ro_bit!(pub, 3, port_power_control, "Port Power Control"); + ro_bit!(pub, 4, port_indicators, "Port Indicators"); + ro_bit!(pub, 5, light_hc_reset_capability, "Light HC Reset Capability"); + ro_bit!(pub, 6, latency_tolerance_messaging_capability, "Latency Tolerance Messaging Capability" ); - ro_bit!(7, no_secondary_sid_support, "No Secondary SID Support"); - ro_bit!(8, parse_all_event_data, "Parse All Event Data"); - ro_bit!( + ro_bit!(pub, 7, no_secondary_sid_support, "No Secondary SID Support"); + ro_bit!(pub, 8, parse_all_event_data, "Parse All Event Data"); + ro_bit!(pub, 9, stopped_short_packet_capability, "Stopped - Short Packet Capability" ); - ro_bit!(10, stopped_edtla_capability, "Stopped EDTLA Capability"); - ro_bit!( + ro_bit!(pub, 10, stopped_edtla_capability, "Stopped EDTLA Capability"); + ro_bit!(pub, 11, contiguous_frame_id_capability, "Contiguous Frame ID Capability" ); - ro_field!( + ro_field!(pub, 12..=15, maximum_primary_stream_array_size, "Maximum Primary Stream Array Size", u8 ); - ro_field!( + ro_field!(pub, 16..=31, xhci_extended_capabilities_pointer, "xHCI Extended Capabilities Pointer", @@ -282,44 +282,44 @@ impl RuntimeRegisterSpaceOffset { #[derive(Copy, Clone)] pub struct CapabilityParameters2(u32); impl CapabilityParameters2 { - ro_bit!(0, u3_entry_capability, "U3 Entry Capability"); - ro_bit!( + ro_bit!(pub, 0, u3_entry_capability, "U3 Entry Capability"); + ro_bit!(pub, 1, configure_endpoint_command_max_exit_latency_too_large_capability, "Configure Endpoint Command Max Exit Latency Too Large Capability" ); - ro_bit!( + ro_bit!(pub, 2, force_save_context_capability, "Force Save Context Capability" ); - ro_bit!( + ro_bit!(pub, 3, compliance_transition_capability, "Compliance Transition Capability" ); - ro_bit!( + ro_bit!(pub, 4, large_esit_payload_capability, "Large ESIT Payload Capability" ); - ro_bit!( + ro_bit!(pub, 5, configuration_information_capability, "Configuration Information Capability" ); - ro_bit!(6, extended_tbc_capability, "Extended TBC Capability"); - ro_bit!( + ro_bit!(pub, 6, extended_tbc_capability, "Extended TBC Capability"); + ro_bit!(pub, 7, extended_tbc_trb_status_capability, "Extended TBC TRB Status Capability" ); - ro_bit!( + ro_bit!(pub, 8, get_set_extended_property_capability, "Get/Set Extended Property Capability" ); - ro_bit!( + ro_bit!(pub, 9, virtualization_based_trusted_io_capability, "Virtualization Based Trusted I/O Capability" diff --git a/src/registers/doorbell.rs b/src/registers/doorbell.rs index 0406013..f3bc52e 100644 --- a/src/registers/doorbell.rs +++ b/src/registers/doorbell.rs @@ -45,8 +45,8 @@ impl Doorbell { ) } - rw_field!(0..=7, doorbell_target, "Doorbell Target", u8); - rw_field!(16..=31, doorbell_stream_id, "Doorbell Stream ID", u16); + rw_field!(pub, 0..=7, doorbell_target, "Doorbell Target", u8); + rw_field!(pub, 16..=31, doorbell_stream_id, "Doorbell Stream ID", u16); } impl fmt::Debug for Doorbell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/registers/operational.rs b/src/registers/operational.rs index 02f1050..b08a627 100644 --- a/src/registers/operational.rs +++ b/src/registers/operational.rs @@ -77,27 +77,27 @@ where #[derive(Copy, Clone)] pub struct UsbCommandRegister(u32); impl UsbCommandRegister { - rw_bit!(0, run_stop, "Run/Stop"); - rw_bit!(1, host_controller_reset, "Host Controller Reset"); - rw_bit!(2, interrupter_enable, "Interrupter Enable"); - rw_bit!(3, host_system_error_enable, "Host System Error Enable"); - rw_bit!( + rw_bit!(pub, 0, run_stop, "Run/Stop"); + rw_bit!(pub, 1, host_controller_reset, "Host Controller Reset"); + rw_bit!(pub, 2, interrupter_enable, "Interrupter Enable"); + rw_bit!(pub, 3, host_system_error_enable, "Host System Error Enable"); + rw_bit!(pub, 7, light_host_controller_reset, "Light Host Controller Reset" ); - rw_bit!(8, controller_save_state, "Controller Save State"); - rw_bit!(9, controller_restore_state, "Controller Restore State"); - rw_bit!(10, enable_wrap_event, "Enable Wrap Event"); - rw_bit!(11, enable_u3_mfindex_stop, "Enable U3 MFINDEX Stop"); - rw_bit!(13, cem_enable, "CEM Enable"); - ro_bit!(14, extended_tbc_enable, "Extended TBC Enable"); - ro_bit!( + rw_bit!(pub, 8, controller_save_state, "Controller Save State"); + rw_bit!(pub, 9, controller_restore_state, "Controller Restore State"); + rw_bit!(pub, 10, enable_wrap_event, "Enable Wrap Event"); + rw_bit!(pub, 11, enable_u3_mfindex_stop, "Enable U3 MFINDEX Stop"); + rw_bit!(pub, 13, cem_enable, "CEM Enable"); + ro_bit!(pub, 14, extended_tbc_enable, "Extended TBC Enable"); + ro_bit!(pub, 15, extended_tbc_trb_status_enable, "Extended TBC TRB Status Enable" ); - rw_bit!(16, vtio_enable, "VTIO Enable"); + rw_bit!(pub, 16, vtio_enable, "VTIO Enable"); } impl_debug_from_methods! { UsbCommandRegister{ @@ -122,15 +122,15 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct UsbStatusRegister(u32); impl UsbStatusRegister { - ro_bit!(0, hc_halted, "HC Halted"); - rw1c_bit!(2, host_system_error, "Host System Error"); - rw1c_bit!(3, event_interrupt, "Event Interrupt"); - rw1c_bit!(4, port_change_detect, "Port Change Detect"); - ro_bit!(8, save_state_status, "Save State Status"); - ro_bit!(9, restore_state_status, "Restore State Status"); - rw1c_bit!(10, save_restore_error, "Save/Restore Error"); - ro_bit!(11, controller_not_ready, "Controller Not Ready"); - ro_bit!(12, host_controller_error, "Host Controller Error"); + ro_bit!(pub, 0, hc_halted, "HC Halted"); + rw1c_bit!(pub, 2, host_system_error, "Host System Error"); + rw1c_bit!(pub, 3, event_interrupt, "Event Interrupt"); + rw1c_bit!(pub, 4, port_change_detect, "Port Change Detect"); + ro_bit!(pub, 8, save_state_status, "Save State Status"); + ro_bit!(pub, 9, restore_state_status, "Restore State Status"); + rw1c_bit!(pub, 10, save_restore_error, "Save/Restore Error"); + ro_bit!(pub, 11, controller_not_ready, "Controller Not Ready"); + ro_bit!(pub, 12, host_controller_error, "Host Controller Error"); } impl_debug_from_methods! { UsbStatusRegister{ @@ -212,10 +212,10 @@ impl DeviceNotificationControl { #[derive(Copy, Clone)] pub struct CommandRingControlRegister(u64); impl CommandRingControlRegister { - wo_bit!(0, ring_cycle_state, "Ring Cycle State"); - w1s_bit!(1, command_stop, "Command Stop"); - w1s_bit!(2, command_abort, "Command Abort"); - ro_bit!(3, command_ring_running, "Command Ring Running"); + wo_bit!(pub, 0, ring_cycle_state, "Ring Cycle State"); + w1s_bit!(pub, 1, command_stop, "Command Stop"); + w1s_bit!(pub, 2, command_abort, "Command Abort"); + ro_bit!(pub, 3, command_ring_running, "Command Ring Running"); /// Sets the value of the Command Ring Pointer field. It must be 64 byte aligned. /// @@ -268,14 +268,14 @@ impl DeviceContextBaseAddressArrayPointerRegister { #[derive(Copy, Clone)] pub struct ConfigureRegister(u32); impl ConfigureRegister { - rw_field!( + rw_field!(pub, 0..=7, max_device_slots_enabled, "Max Device Slots Enabled", u8 ); - rw_bit!(8, u3_entry_enable, "U3 Entry Enable"); - rw_bit!( + rw_bit!(pub, 8, u3_entry_enable, "U3 Entry Enable"); + rw_bit!(pub, 9, configuration_information_enable, "Configuration Information Enable" @@ -340,45 +340,45 @@ impl PortRegisterSet { #[derive(Copy, Clone)] pub struct PortStatusAndControlRegister(u32); impl PortStatusAndControlRegister { - ro_bit!(0, current_connect_status, "Current Connect Status"); - rw1c_bit!(1, port_enabled_disabled, "Port Enabled/Disabled"); - ro_bit!(3, over_current_active, "Over-current Active"); - rw1s_bit!(4, port_reset, "Port Reset"); - rw_field!(5..=8, port_link_state, "Port Link State", u8); - rw_bit!(9, port_power, "Port Power"); - ro_field!(10..=13, port_speed, "Port Speed", u8); - rw_field!( + ro_bit!(pub, 0, current_connect_status, "Current Connect Status"); + rw1c_bit!(pub, 1, port_enabled_disabled, "Port Enabled/Disabled"); + ro_bit!(pub, 3, over_current_active, "Over-current Active"); + rw1s_bit!(pub, 4, port_reset, "Port Reset"); + rw_field!(pub, 5..=8, port_link_state, "Port Link State", u8); + rw_bit!(pub, 9, port_power, "Port Power"); + ro_field!(pub, 10..=13, port_speed, "Port Speed", u8); + rw_field!(pub, 14..=15, port_indicator_control, "Port Indicator Control", PortIndicator ); - rw_bit!( + rw_bit!(pub, 16, port_link_state_write_strobe, "Port Link State Write Strobe" ); - rw1c_bit!(17, connect_status_change, "Connect Status Change"); - rw1c_bit!( + rw1c_bit!(pub, 17, connect_status_change, "Connect Status Change"); + rw1c_bit!(pub, 18, port_enabled_disabled_change, "Port Enabled/Disabled Change" ); - rw1c_bit!(19, warm_port_reset_change, "Warm Port Reset Change"); - rw1c_bit!(20, over_current_change, "Over-Current Change"); - rw1c_bit!(21, port_reset_change, "Port Reset Change"); - rw1c_bit!(22, port_link_state_change, "Port Link State Change"); - rw1c_bit!(23, port_config_error_change, "Port Config Error Change"); - ro_bit!(24, cold_attach_status, "Cold Attach Status"); - rw_bit!(25, wake_on_connect_enable, "Wake on Connect Enable"); - rw_bit!(26, wake_on_disconnect_enable, "Wake on Disconnect Enable"); - rw_bit!( + rw1c_bit!(pub, 19, warm_port_reset_change, "Warm Port Reset Change"); + rw1c_bit!(pub, 20, over_current_change, "Over-Current Change"); + rw1c_bit!(pub, 21, port_reset_change, "Port Reset Change"); + rw1c_bit!(pub, 22, port_link_state_change, "Port Link State Change"); + rw1c_bit!(pub, 23, port_config_error_change, "Port Config Error Change"); + ro_bit!(pub, 24, cold_attach_status, "Cold Attach Status"); + rw_bit!(pub, 25, wake_on_connect_enable, "Wake on Connect Enable"); + rw_bit!(pub, 26, wake_on_disconnect_enable, "Wake on Disconnect Enable"); + rw_bit!(pub, 27, wake_on_over_current_enable, "Wake on Over-Current Enable" ); - ro_bit!(30, device_removable, "Device Removable"); - rw1s_bit!(31, warm_port_reset, "Warm Port Reset"); + ro_bit!(pub, 30, device_removable, "Device Removable"); + rw1s_bit!(pub, 31, warm_port_reset, "Warm Port Reset"); } impl_debug_from_methods! { PortStatusAndControlRegister{ @@ -413,9 +413,9 @@ impl_debug_from_methods! { pub struct PortPowerManagementStatusAndControlRegister(u32); /// **These methods are only valid for USB3.** impl PortPowerManagementStatusAndControlRegister { - rw_field!(0..=7, u1_timeout, "U1 Timeout", u8); - rw_field!(8..=15, u2_timeout, "U2 Timeout", u8); - rw_bit!(16, force_link_pm_accept, "Force Link PM Accept"); + rw_field!(pub, 0..=7, u1_timeout, "U1 Timeout", u8); + rw_field!(pub, 8..=15, u2_timeout, "U2 Timeout", u8); + rw_bit!(pub, 16, force_link_pm_accept, "Force Link PM Accept"); } /// **These methods are only valid for USB2.** impl PortPowerManagementStatusAndControlRegister { @@ -428,15 +428,15 @@ impl PortPowerManagementStatusAndControlRegister { FromPrimitive::from_u32(s) } - rw_bit!(3, remote_wake_enable, "Remote Wake Enable"); - rw_field!( + rw_bit!(pub, 3, remote_wake_enable, "Remote Wake Enable"); + rw_field!(pub, 4..=7, best_effort_service_latency, "Best Effort Service Latency", u8 ); - rw_field!(8..=15, l1_device_slot, "L1 Device Slot", u8); - rw_bit!(16, hardware_lpm_enable, "Hardware LPM Enable"); + rw_field!(pub, 8..=15, l1_device_slot, "L1 Device Slot", u8); + rw_bit!(pub, 16, hardware_lpm_enable, "Hardware LPM Enable"); /// Returns the value of the Port Test Control field. /// @@ -474,9 +474,9 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PortLinkInfoRegister(u32); impl PortLinkInfoRegister { - rw_field!(0..=15, link_error_count, "Link Error Count", u16); - ro_field!(16..=19, rx_lane_count, "Rx Lane Count", u8); - ro_field!(20..=23, tx_lane_count, "Tx Lane Count", u8); + rw_field!(pub, 0..=15, link_error_count, "Link Error Count", u16); + ro_field!(pub, 16..=19, rx_lane_count, "Rx Lane Count", u8); + ro_field!(pub, 20..=23, tx_lane_count, "Tx Lane Count", u8); } impl_debug_from_methods! { PortLinkInfoRegister{ @@ -493,14 +493,14 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PortHardwareLpmControlRegister(u32); impl PortHardwareLpmControlRegister { - rw_field!( + rw_field!(pub, 0..=1, host_initiated_resume_duration_mode, "Host Initiated Resume Duration Mode", u8 ); - rw_field!(2..=9, l1_timeout, "L1 Timeout", u8); - rw_field!( + rw_field!(pub, 2..=9, l1_timeout, "L1 Timeout", u8); + rw_field!(pub, 10..=13, best_effort_service_latency_deep, "Best Effort Service Latency Depp", diff --git a/src/registers/runtime.rs b/src/registers/runtime.rs index 159e847..e106905 100644 --- a/src/registers/runtime.rs +++ b/src/registers/runtime.rs @@ -51,7 +51,7 @@ where #[derive(Copy, Clone)] pub struct MicroframeIndexRegister(u32); impl MicroframeIndexRegister { - ro_field!(0..=13, microframe_index, "Microframe Index", u16); + ro_field!(pub, 0..=13, microframe_index, "Microframe Index", u16); } impl_debug_from_methods! { MicroframeIndexRegister { @@ -166,8 +166,8 @@ where #[derive(Copy, Clone)] pub struct InterrupterManagementRegister(u32); impl InterrupterManagementRegister { - rw1c_bit!(0, interrupt_pending, "Interrupt Pending"); - rw_bit!(1, interrupt_enable, "Interrupt Enable"); + rw1c_bit!(pub, 0, interrupt_pending, "Interrupt Pending"); + rw_bit!(pub, 1, interrupt_enable, "Interrupt Enable"); } impl_debug_from_methods! { InterrupterManagementRegister { @@ -181,13 +181,13 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Default)] pub struct InterrupterModerationRegister(u32); impl InterrupterModerationRegister { - rw_field!( + rw_field!(pub, 0..=15, interrupt_moderation_interval, "Interrupt Moderation Interval", u16 ); - rw_field!( + rw_field!(pub, 16..=31, interrupt_moderation_counter, "Interrupt Moderation Counter", @@ -248,13 +248,13 @@ impl EventRingSegmentTableBaseAddressRegister { #[derive(Copy, Clone, Default)] pub struct EventRingDequeuePointerRegister(u64); impl EventRingDequeuePointerRegister { - rw_field!( + rw_field!(pub, 0..=2, dequeue_erst_segment_index, "Dequeue ERST Segment Index", u8 ); - rw1c_bit!(3, event_handler_busy, "Event Handler Busy"); + rw1c_bit!(pub, 3, event_handler_busy, "Event Handler Busy"); /// Returns the address of the current Event Ring Dequeue Pointer. #[must_use] diff --git a/src/ring/trb/command.rs b/src/ring/trb/command.rs index d5cb52e..3e7accf 100644 --- a/src/ring/trb/command.rs +++ b/src/ring/trb/command.rs @@ -94,7 +94,7 @@ reserved!(EnableSlot(Type::EnableSlot) { [3]21..=31; }); impl EnableSlot { - rw_field!([3](16..=20), slot_type, "Slot Type", u8); + rw_field!(pub, [3](16..=20), slot_type, "Slot Type", u8); } impl_debug_for_trb!(EnableSlot { slot_type }); @@ -107,7 +107,7 @@ reserved!(DisableSlot(Type::DisableSlot) { [3]16..=23; }); impl DisableSlot { - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(DisableSlot { slot_id }); @@ -152,12 +152,12 @@ impl AddressDevice { (u << 32) | l } - rw_bit!( + rw_bit!(pub, [3](9), block_set_address_request, "Block Set Address Request" ); - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(AddressDevice { input_context_pointer, @@ -206,8 +206,8 @@ impl ConfigureEndpoint { (u << 32) | l } - rw_bit!([3](9), deconfigure, "Deconfigure"); - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_bit!(pub, [3](9), deconfigure, "Deconfigure"); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(ConfigureEndpoint { input_context_pointer, @@ -255,7 +255,7 @@ impl EvaluateContext { (u << 32) | l } - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(EvaluateContext { input_context_pointer, @@ -275,9 +275,9 @@ reserved!(ResetEndpoint(Type::ResetEndpoint) { [3]21..=23; }); impl ResetEndpoint { - rw_bit!([3](9), transfer_state_preserve, "Transfer State Preserve"); - rw_field!([3](16..=20), endpoint_id, "Endpoint ID", u8); - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_bit!(pub, [3](9), transfer_state_preserve, "Transfer State Preserve"); + rw_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(ResetEndpoint { transfer_state_preserve, @@ -298,9 +298,9 @@ reserved!(StopEndpoint(Type::StopEndpoint) { [3]21..=22; }); impl StopEndpoint { - rw_field!([3](16..=20), endpoint_id, "Endpoint ID", u8); - rw_bit!([3](23), suspend, "Suspend"); - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); + rw_bit!(pub, [3](23), suspend, "Suspend"); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(StopEndpoint { endpoint_id, @@ -319,8 +319,8 @@ reserved!(SetTrDequeuePointer(Type::SetTrDequeuePointer) { [3]21..=23; }); impl SetTrDequeuePointer { - rw_bit!([0](0), dequeue_cycle_state, "Dequeue Cycle State"); - rw_field!([0](1..=3), stream_context_type, "Stream Context Type", u8); + rw_bit!(pub, [0](0), dequeue_cycle_state, "Dequeue Cycle State"); + rw_field!(pub, [0](1..=3), stream_context_type, "Stream Context Type", u8); /// Sets the value of the New TR Dequeue Pointer field. /// @@ -351,9 +351,9 @@ impl SetTrDequeuePointer { ((u << 32) | l) & 0xffff_fff0 } - rw_field!([2](16..=31), stream_id, "Stream ID", u16); - rw_field!([3](16..=20), endpoint_id, "Endpoint ID", u8); - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [2](16..=31), stream_id, "Stream ID", u16); + rw_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(SetTrDequeuePointer { dequeue_cycle_state, @@ -373,7 +373,7 @@ reserved!(ResetDevice(Type::ResetDevice) { [3]16..=23; }); impl ResetDevice { - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(ResetDevice { slot_id }); @@ -411,13 +411,13 @@ impl ForceEvent { (u << 32) | l } - rw_field!( + rw_field!(pub, [2](22..=31), vf_interrupter_target, "VF Interrupter Target", u16 ); - rw_field!([3](16..=23), vf_id, "VF ID", u8); + rw_field!(pub, [3](16..=23), vf_id, "VF ID", u8); } impl_debug_for_trb!(ForceEvent { event_trb_pointer, @@ -438,7 +438,7 @@ reserved!(NegotiateBandwidth(Type::NegotiateBandwidth) { [3]16..=23; }); impl NegotiateBandwidth { - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(NegotiateBandwidth { slot_id }); @@ -455,7 +455,7 @@ reserved!(SetLatencyToleranceValue(Type::SetLatencyToleranceValue) { [3]28..=31; }); impl SetLatencyToleranceValue { - rw_field!( + rw_field!(pub, [3](16..=27), best_effort_latency_tolerance_value, "Best Effort Latency Tolerance Value", @@ -506,8 +506,8 @@ impl GetPortBandwidth { (u << 32) | l } - rw_field!([3](16..=19), dev_speed, "Dev Speed", u8); - rw_field!([3](24..=31), hub_slot_id, "Hub Slot ID", u8); + rw_field!(pub, [3](16..=19), dev_speed, "Dev Speed", u8); + rw_field!(pub, [3](24..=31), hub_slot_id, "Hub Slot ID", u8); } impl_debug_for_trb!(GetPortBandwidth { port_bandwidth_context_pointer, @@ -521,7 +521,7 @@ reserved!(ForceHeader(Type::ForceHeader) { [3]16..=23; }); impl ForceHeader { - rw_field!([0](0..=4), packet_type, "Packet Type", u8); + rw_field!(pub, [0](0..=4), packet_type, "Packet Type", u8); /// Sets the value of the Header Info field. /// @@ -546,7 +546,7 @@ impl ForceHeader { [self.0[0] & 0xffff_ffe0, self.0[1], self.0[2]] } - rw_field!( + rw_field!(pub, [3](24..=31), root_hub_port_number, "Root Hub Port Number", @@ -599,15 +599,15 @@ impl GetExtendedProperty { (u << 32) | l } - rw_field!( + rw_field!(pub, [2](0..=15), extended_capability_identifier, "Extended Capability Identifier", u16 ); - rw_field!([3](16..=18), command_sub_type, "Command Sub Type", u8); - rw_field!([3](19..=23), endpoint_id, "Endpoint ID", u8); - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](16..=18), command_sub_type, "Command Sub Type", u8); + rw_field!(pub, [3](19..=23), endpoint_id, "Endpoint ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(GetExtendedProperty { extended_property_context_pointer, @@ -629,21 +629,21 @@ reserved!(SetExtendedProperty(Type::SetExtendedProperty) { [3]1..=9; }); impl SetExtendedProperty { - rw_field!( + rw_field!(pub, [2](0..=15), extended_capability_identifier, "Extended Cpaability Identifier", u16 ); - rw_field!( + rw_field!(pub, [2](16..=23), capability_parameter, "Capability Parameter", u8 ); - rw_field!([3](16..=18), command_sub_type, "Command Sub Type", u8); - rw_field!([3](19..=23), endpoint_id, "Endpoint ID", u8); - rw_field!([3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, [3](16..=18), command_sub_type, "Command Sub Type", u8); + rw_field!(pub, [3](19..=23), endpoint_id, "Endpoint ID", u8); + rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(SetExtendedProperty { extended_capability_identifier, diff --git a/src/ring/trb/event.rs b/src/ring/trb/event.rs index 200a045..1dc90c3 100644 --- a/src/ring/trb/event.rs +++ b/src/ring/trb/event.rs @@ -97,7 +97,7 @@ reserved!(PortStatusChange(Type::PortStatusChange){ [3]16..=31; }); impl PortStatusChange { - ro_field!([0](24..=31), port_id, "Port ID", u8); + ro_field!(pub, [0](24..=31), port_id, "Port ID", u8); } impl_debug_for_event_trb!(PortStatusChange { port_id }); @@ -117,10 +117,10 @@ impl TransferEvent { (u << 32) | l } - ro_field!([2](0..=23), trb_transfer_length, "TRB Transfer Length", u32); - ro_bit!([3](2), event_data, "Event Data"); - ro_field!([3](16..=20), endpoint_id, "Endpoint ID", u8); - ro_field!([3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, [2](0..=23), trb_transfer_length, "TRB Transfer Length", u32); + ro_bit!(pub, [3](2), event_data, "Event Data"); + ro_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); + ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(TransferEvent { trb_pointer, @@ -149,14 +149,14 @@ impl CommandCompletion { (u << 32) | l } - ro_field!( + ro_field!(pub, [2](0..=23), command_completion_parameter, "Command Completion Parameter", u32 ); - ro_field!([3](16..=23), vf_id, "VF ID", u8); - ro_field!([3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, [3](16..=23), vf_id, "VF ID", u8); + ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(CommandCompletion { command_trb_pointer, @@ -178,7 +178,7 @@ reserved!(BandwidthRequest(Type::BandwidthRequest){ [3]16..=23; }); impl BandwidthRequest { - ro_field!([3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(BandwidthRequest { slot_id }); @@ -190,9 +190,9 @@ reserved!(Doorbell(Type::Doorbell){ [3]1..=9; }); impl Doorbell { - ro_field!([0](0..=4), db_reason, "DB Reason", u8); - ro_field!([3](16..=23), vf_id, "VF ID", u8); - ro_field!([3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, [0](0..=4), db_reason, "DB Reason", u8); + ro_field!(pub, [3](16..=23), vf_id, "VF ID", u8); + ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(Doorbell { db_reason, @@ -227,7 +227,7 @@ reserved!(DeviceNotification(Type::DeviceNotification){ [3]16..=31; }); impl DeviceNotification { - ro_field!([0](4..=7), notification_type, "Notification Type", u8); + ro_field!(pub, [0](4..=7), notification_type, "Notification Type", u8); /// Returns the value of the Device Notification Data field. #[must_use] @@ -238,7 +238,7 @@ impl DeviceNotification { ((u << 32) | l) >> 8 } - ro_field!([3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(DeviceNotification { notification_type, diff --git a/src/ring/trb/mod.rs b/src/ring/trb/mod.rs index 20fa883..6fe9095 100644 --- a/src/ring/trb/mod.rs +++ b/src/ring/trb/mod.rs @@ -58,7 +58,7 @@ macro_rules! add_trb { self.0 } - rw_bit!([3](0), cycle_bit, "Cycle bit"); + rw_bit!(pub, [3](0), cycle_bit, "Cycle bit"); fn set_trb_type(&mut self) -> &mut Self { use crate::ring::trb::Type; @@ -231,10 +231,10 @@ impl Link { (u << 32) | l } - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u32); - rw_bit!([3](1), toggle_cycle, "Toggle Cycle"); - rw_bit!([3](4), chain_bit, "Chain bit"); - rw_bit!([3](5), interrupt_on_completion, "Interrupt On Completion"); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u32); + rw_bit!(pub, [3](1), toggle_cycle, "Toggle Cycle"); + rw_bit!(pub, [3](4), chain_bit, "Chain bit"); + rw_bit!(pub, [3](5), interrupt_on_completion, "Interrupt On Completion"); } impl_debug_for_trb!(Link { ring_segment_pointer, diff --git a/src/ring/trb/transfer.rs b/src/ring/trb/transfer.rs index 87a1a4f..3f8a99c 100644 --- a/src/ring/trb/transfer.rs +++ b/src/ring/trb/transfer.rs @@ -123,7 +123,7 @@ impl TryFrom<[u32; 4]> for Allowed { macro_rules! interrupt_on_completion { ($name:ident) => { impl $name { - rw_bit!([3](5), interrupt_on_completion, "Interrupt On Completion"); + rw_bit!(pub, [3](5), interrupt_on_completion, "Interrupt On Completion"); } }; } @@ -180,19 +180,19 @@ impl Normal { (u << 32) | l } - rw_field!([2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); - rw_field!([2](17..=21), td_size, "TD Size", u8); - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!([3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!( + rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); + rw_field!(pub, [2](17..=21), td_size, "TD Size", u8); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, [3](2), interrupt_on_short_packet, "Interrupt-on Short Packet" ); - rw_bit!([3](3), no_snoop, "No Snoop"); - rw_bit!([3](4), chain_bit, "Chain bit"); - rw_bit!([3](6), immediate_data, "Immediate Data"); - rw_bit!([3](9), block_event_interrupt, "Block Event Interrupt"); + rw_bit!(pub, [3](3), no_snoop, "No Snoop"); + rw_bit!(pub, [3](4), chain_bit, "Chain bit"); + rw_bit!(pub, [3](6), immediate_data, "Immediate Data"); + rw_bit!(pub, [3](9), block_event_interrupt, "Block Event Interrupt"); } impl_debug_for_transfer_trb! { Normal { @@ -231,12 +231,12 @@ impl SetupStage { .set_trb_transfer_length() } - rw_field!([0](0..=7), request_type, "bmRequestType", u8); - rw_field!([0](8..=15), request, "bRequest", u8); - rw_field!([0](16..=31), value, "wValue", u16); - rw_field!([1](0..=15), index, "wIndex", u16); - rw_field!([1](16..=31), length, "wLength", u16); - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_field!(pub, [0](0..=7), request_type, "bmRequestType", u8); + rw_field!(pub, [0](8..=15), request, "bRequest", u8); + rw_field!(pub, [0](16..=31), value, "wValue", u16); + rw_field!(pub, [1](0..=15), index, "wIndex", u16); + rw_field!(pub, [1](16..=31), length, "wLength", u16); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); /// Sets the value of the Transfer Type field. pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self { @@ -304,18 +304,18 @@ impl DataStage { (u << 32) | l } - rw_field!([2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); - rw_field!([2](17..=21), td_size, "TD Size", u8); - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!([3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!( + rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); + rw_field!(pub, [2](17..=21), td_size, "TD Size", u8); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, [3](2), interrupt_on_short_packet, "Interrupt-on Short Packet" ); - rw_bit!([3](3), no_snoop, "No Snoop"); - rw_bit!([3](4), chain_bit, "Chain bit"); - rw_bit!([3](6), immediate_data, "Immediate Data"); + rw_bit!(pub, [3](3), no_snoop, "No Snoop"); + rw_bit!(pub, [3](4), chain_bit, "Chain bit"); + rw_bit!(pub, [3](6), immediate_data, "Immediate Data"); /// Sets the value of the Direction field. pub fn set_direction(&mut self, d: Direction) -> &mut Self { @@ -353,10 +353,10 @@ reserved!(StatusStage(Type::StatusStage) { [3]17..=31; }); impl StatusStage { - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!([3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!([3](4), chain_bit, "Chain bit"); - rw_bit!([3](16), direction, "Direction"); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, [3](4), chain_bit, "Chain bit"); + rw_bit!(pub, [3](16), direction, "Direction"); } impl_debug_for_transfer_trb! { StatusStage { @@ -390,28 +390,28 @@ impl Isoch { (u << 32) | l } - rw_field!([2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); - rw_field!([2](17..=21), td_size_or_tbc, "TD Size/TBC", u8); - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!([3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!( + rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); + rw_field!(pub, [2](17..=21), td_size_or_tbc, "TD Size/TBC", u8); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, [3](2), interrupt_on_short_packet, "Interrupt on Short Packet" ); - rw_bit!([3](3), no_snoop, "No Snoop"); - rw_bit!([3](4), chain_bit, "Chain bit"); - rw_bit!([3](6), immediate_data, "Immediate Data"); - rw_field!([3](7..=8), transfer_burst_count, "Transfer Burst Count", u8); - rw_bit!([3](9), block_event_interrupt, "Block Event Interrupt"); - rw_field!( + rw_bit!(pub, [3](3), no_snoop, "No Snoop"); + rw_bit!(pub, [3](4), chain_bit, "Chain bit"); + rw_bit!(pub, [3](6), immediate_data, "Immediate Data"); + rw_field!(pub, [3](7..=8), transfer_burst_count, "Transfer Burst Count", u8); + rw_bit!(pub, [3](9), block_event_interrupt, "Block Event Interrupt"); + rw_field!(pub, [3](16..=19), transfer_last_burst_packet_count, "Transfer Last Burst Packet Count", u8 ); - rw_field!([3](20..=30), frame_id, "Frame ID", u16); - rw_bit!([3](31), start_isoch_asap, "Start Isoch ASAP"); + rw_field!(pub, [3](20..=30), frame_id, "Frame ID", u16); + rw_bit!(pub, [3](31), start_isoch_asap, "Start Isoch ASAP"); } impl_debug_for_transfer_trb!(Isoch { data_buffer_pointer, @@ -457,10 +457,10 @@ impl EventData { (u << 32) | l } - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!([3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!([3](4), chain_bit, "Chain bit"); - rw_bit!([3](9), block_event_interrupt, "Block Event Interrupt"); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, [3](4), chain_bit, "Chain bit"); + rw_bit!(pub, [3](9), block_event_interrupt, "Block Event Interrupt"); } impl_debug_for_transfer_trb!(EventData { event_data, @@ -480,9 +480,9 @@ reserved!(Noop(Type::NoopTransfer) { [3]16..=31; }); impl Noop { - rw_field!([2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!([3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!([3](4), chain_bit, "Chain bit"); + rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, [3](4), chain_bit, "Chain bit"); } impl_debug_for_transfer_trb!(Noop { interrupter_target, From 38692663a2fad4b7726357568a6c4eb275b56dc5 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Tue, 5 Dec 2023 15:54:14 +0000 Subject: [PATCH 06/17] more macro use --- src/extended_capabilities/debug.rs | 165 +++------- .../xhci_local_memory.rs | 22 +- .../xhci_message_interrupt.rs | 36 +-- src/macros.rs | 283 +++++++++++++++--- src/registers/operational.rs | 46 +-- src/registers/runtime.rs | 65 ++-- src/ring/trb/command.rs | 252 ++++------------ src/ring/trb/event.rs | 38 +-- src/ring/trb/mod.rs | 37 +-- src/ring/trb/transfer.rs | 104 ++----- 10 files changed, 441 insertions(+), 607 deletions(-) diff --git a/src/extended_capabilities/debug.rs b/src/extended_capabilities/debug.rs index d02e588..f31d017 100644 --- a/src/extended_capabilities/debug.rs +++ b/src/extended_capabilities/debug.rs @@ -85,11 +85,13 @@ where #[derive(Copy, Clone)] pub struct Id(u32); impl Id { - /// Returns the value of the Debug Capability Event Ring Segment Table Max field. - #[must_use] - pub fn debug_capability_event_ring_segment_table_max(self) -> u8 { - self.0.get_bits(16..=20).try_into().unwrap() - } + ro_field!( + pub, + 16..=20, + debug_capability_event_ring_segment_table_max, + "Debug Capability Event Ring Segment Table Max", + u8 + ); } impl_debug_from_methods! { Id { @@ -102,10 +104,7 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Debug)] pub struct Doorbell(u32); impl Doorbell { - /// Sets the value of the Doorbell Target field. - pub fn set_doorbell_target(&mut self, target: u8) { - self.0.set_bits(8..=15, target.into()); - } + field_setter!(pub, 8..=15, "Doorbell Target", u8); } /// Debug Capability Event Ring Segment Table Size Register. @@ -113,16 +112,7 @@ impl Doorbell { #[derive(Copy, Clone)] pub struct EventRingSegmentTableSize(u32); impl EventRingSegmentTableSize { - /// Returns the value of the Event Ring Segment Table Size field. - #[must_use] - pub fn get(self) -> u16 { - self.0.get_bits(0..=15).try_into().unwrap() - } - - /// Sets the value of the Event Ring Segment Table Size field. - pub fn set(&mut self, sz: u16) { - self.0.set_bits(0..=15, sz.into()); - } + rw_field!(pub, 0..=15, "Event Ring Segment Table Size", u16); } impl_debug_from_methods! { EventRingSegmentTableSize { @@ -135,25 +125,12 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct EventRingSegmentTableBaseAddress(u64); impl EventRingSegmentTableBaseAddress { - /// Returns the value of the Event Ring Segment Table Base Address field. - #[must_use] - pub fn get(self) -> u64 { - self.0 - } - - /// Sets the value of the Event Ring Segment Table Base Address field. - /// - /// # Panics - /// - /// This method panics if the address is not 16-byte aligned. - pub fn set(&mut self, a: u64) { - assert!( - a.trailing_zeros() >= 4, - "The base address of the Event Ring Segment Table must be 16-byte aligned." - ); - - self.0 = a; - } + rw_field!( + pub, + []{4, "64-byte aligned"}, + "Event Ring Segment Table Base Address", + u64 + ); } impl_debug_from_methods! { EventRingSegmentTableBaseAddress { @@ -166,36 +143,20 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct EventRingDequeuePointer(u64); impl EventRingDequeuePointer { - /// Returns the value of the Dequeue ERST Segment Index field. - #[must_use] - pub fn dequeue_erst_segment_index(self) -> u8 { - self.0.get_bits(0..=2).try_into().unwrap() - } - - /// Sets the value of the Dequeue ERST Segment Index field. - pub fn set_dequeue_erst_segment_index(&mut self, i: u8) { - self.0.set_bits(0..=2, i.into()); - } - - /// Returns the value of the Dequeue Pointer field. - #[must_use] - pub fn dequeue_pointer(self) -> u64 { - self.0 & !0b1111 - } - - /// Sets the value of the Dequeue Pointer field. - /// - /// # Panics - /// - /// This method panics if the address is not 16-byte aligned. - pub fn set_dequeue_pointer(&mut self, a: u64) { - assert!( - a.trailing_zeros() >= 4, - "The Event Ring Dequeue Pointer must be 16-byte aligned." - ); - - self.0.set_bits(4..=63, a.get_bits(4..=63)); - } + rw_field!( + pub, + 0..=2, + dequeue_erst_segment_index, + "Dequeue ERST Segment Index", + u8 + ); + rw_field!( + pub, + []{4, "16-byte aligned"}, + dequeue_pointer, + "Event Ring Dequeue Pointer", + u64 + ); } impl_debug_from_methods! { EventRingDequeuePointer { @@ -309,22 +270,12 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Debug)] pub struct ContextPointer(u64); impl ContextPointer { - /// Returns the start address of the Debug Capability Context data structure. - #[must_use] - pub fn get(self) -> u64 { - self.0 - } - - /// Sets the start address of the Debug Capability Context data structure. - /// - /// # Panics - /// - /// This method panics if the address is not 16-byte aligned. - pub fn set(&mut self, a: u64) { - assert!(a.trailing_zeros()>=4,"The start address of the Debug Capability Context data structure must be 16-byte aligned."); - - self.0 = a; - } + rw_field!( + pub, + []{4, "16-byte aligned"}, + "Debug Capability Context Base Pointer", + u64 + ); } /// Debug Capability Device Descriptor Info Register 1 @@ -332,27 +283,8 @@ impl ContextPointer { #[derive(Copy, Clone)] pub struct DeviceDescriptorInfo1(u32); impl DeviceDescriptorInfo1 { - /// Returns the value of the DbC Protocol field. - #[must_use] - pub fn dbc_protocol(self) -> u8 { - self.0.get_bits(0..=7).try_into().unwrap() - } - - /// Sets the value of the DbC Protocol field. - pub fn set_dbc_protocol(&mut self, protocol: u8) { - self.0.set_bits(0..=7, protocol.into()); - } - - /// Returns the value of the Vendor ID field. - #[must_use] - pub fn vendor_id(self) -> u16 { - self.0.get_bits(16..=31).try_into().unwrap() - } - - /// Sets the value of the Vendor ID field. - pub fn set_vendor_id(&mut self, id: u16) { - self.0.set_bits(16..=31, id.into()); - } + rw_field!(pub, 0..=7, dbc_protocol, "DbC Protocol", u8); + rw_field!(pub, 16..=31, vendor_id, "Vendor ID", u16); } impl_debug_from_methods! { DeviceDescriptorInfo1 { @@ -366,27 +298,8 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct DeviceDescriptorInfo2(u32); impl DeviceDescriptorInfo2 { - /// Returns the value of the Product ID field. - #[must_use] - pub fn product_id(self) -> u16 { - self.0.get_bits(0..=15).try_into().unwrap() - } - - /// Sets the value of the Product ID field. - pub fn set_product_id(&mut self, id: u16) { - self.0.set_bits(0..=15, id.into()); - } - - /// Returns the value of the Device Revision field. - #[must_use] - pub fn device_revision(self) -> u16 { - self.0.get_bits(16..=31).try_into().unwrap() - } - - /// Sets the value of the Device Revision field. - pub fn set_device_revision(&mut self, revision: u16) { - self.0.set_bits(16..=31, revision.into()); - } + rw_field!(pub, 0..=15, product_id, "Product ID", u16); + rw_field!(pub, 16..=31, device_revision, "Device Revision", u16); } impl_debug_from_methods! { DeviceDescriptorInfo2 { diff --git a/src/extended_capabilities/xhci_local_memory.rs b/src/extended_capabilities/xhci_local_memory.rs index bc2d296..0d1bf5f 100644 --- a/src/extended_capabilities/xhci_local_memory.rs +++ b/src/extended_capabilities/xhci_local_memory.rs @@ -2,7 +2,6 @@ use super::ExtendedCapability; use accessor::{array, single, Mapper}; -use bit_field::BitField; use core::convert::TryInto; /// xHCI Local Memory Capability. @@ -61,21 +60,12 @@ where #[derive(Copy, Clone)] pub struct Header([u32; 2]); impl Header { - /// Returns the Local Memory Enable bit. - #[must_use] - pub fn local_memory_enable(self) -> bool { - self.0[0].get_bit(16) - } - - /// Sets the Local Memory Enable bit. - pub fn set_local_memory_enable(&mut self) { - self.0[0].set_bit(16, true); - } - - /// Clears the Local Memory Enable bit. - pub fn clear_local_memory_enable(&mut self) { - self.0[0].set_bit(16, false); - } + rw_bit!( + pub, + [0](16), + local_memory_enable, + "Local Memory Enable" + ); fn size(self) -> u32 { self.0[1] diff --git a/src/extended_capabilities/xhci_message_interrupt.rs b/src/extended_capabilities/xhci_message_interrupt.rs index 0a3f17a..ff91b8a 100644 --- a/src/extended_capabilities/xhci_message_interrupt.rs +++ b/src/extended_capabilities/xhci_message_interrupt.rs @@ -113,27 +113,23 @@ impl MessageAddress for u64 {} #[derive(Copy, Clone)] pub struct MessageControl(u16); impl MessageControl { - ro_bit!(pub, 8, per_vector_masking_capable, "Per-vector masking capable"); - ro_bit!(pub, 7, bit64_address_capable, "64 bit address capable"); - - /// Returns the value of the Multiple Message Enable field. - #[must_use] - pub fn multiple_message_enable(self) -> u8 { - self.0.get_bits(4..=6).try_into().unwrap() - } - - /// Sets the value of the Multiple Message Enable field. - pub fn set_multiple_message_enable(&mut self, m: u8) { - self.0.set_bits(4..=6, m.into()); - } - - /// Returns the value of the Multiple Message Capable field. - #[must_use] - pub fn multiple_message_capable(self) -> u8 { - self.0.get_bits(1..=3).try_into().unwrap() - } - rw_bit!(pub, 0, msi_enable, "MSI Enable"); + ro_field!( + pub, + 1..=3, + multiple_message_capable, + "Multiple Message Capable", + u8 + ); + rw_field!( + pub, + 4..=6, + multiple_message_enable, + "Multiple Message Enable", + u8 + ); + ro_bit!(pub, 7, bit64_address_capable, "64 bit address capable"); + ro_bit!(pub, 8, per_vector_masking_capable, "Per-vector masking capable"); } impl_debug_from_methods! { MessageControl { diff --git a/src/macros.rs b/src/macros.rs index 376724f..37ed321 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -18,7 +18,7 @@ macro_rules! bit_getter { #[doc = $name] #[doc = "bit."] #[must_use] - $vis fn $method(self) -> bool { + $vis fn $method(&self) -> bool { use bit_field::BitField; self.0[$offset].get_bit($bit) } @@ -28,7 +28,7 @@ macro_rules! bit_getter { #[doc = $name] #[doc = "bit."] #[must_use] - $vis fn $method(self) -> bool { + $vis fn $method(&self) -> bool { use bit_field::BitField; self.0.get_bit($bit) } @@ -80,38 +80,8 @@ macro_rules! bit_modifier { }; } -macro_rules! ro_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_getter!($vis, $bit, $method, $name); - }; -} - -macro_rules! wo_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_modifier!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_modifier!($vis, $bit, $method, $name); - }; -} - -macro_rules! rw_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!($vis, [$offset]($bit), $method, $name); - bit_modifier!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_getter!($vis, $bit, $method, $name); - bit_modifier!($vis, $bit, $method, $name); - }; -} - -macro_rules! rw1c_bit { +macro_rules! bit_modifier_w1c { ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!($vis, [$offset]($bit), $method, $name); paste::paste! { #[doc = "Assigns 1 to the"] #[doc = $name] @@ -133,7 +103,6 @@ macro_rules! rw1c_bit { } }; ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_getter!($vis, $bit, $method, $name); paste::paste! { #[doc = "Assigns 1 to the"] #[doc = $name] @@ -156,6 +125,46 @@ macro_rules! rw1c_bit { }; } +macro_rules! ro_bit { + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_getter!($vis, [$offset]($bit), $method, $name); + }; + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $bit, $method, $name); + }; +} + +macro_rules! wo_bit { + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_modifier!($vis, [$offset]($bit), $method, $name); + }; + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_modifier!($vis, $bit, $method, $name); + }; +} + +macro_rules! rw_bit { + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_getter!($vis, [$offset]($bit), $method, $name); + bit_modifier!($vis, [$offset]($bit), $method, $name); + }; + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $bit, $method, $name); + bit_modifier!($vis, $bit, $method, $name); + }; +} + +macro_rules! rw1c_bit { + ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + bit_getter!($vis, [$offset]($bit), $method, $name); + bit_modifier_w1c!($vis, [$offset]($bit), $method, $name); + }; + ($vis:vis,$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $bit, $method, $name); + bit_modifier_w1c!($vis, $bit, $method, $name); + }; +} + macro_rules! w1s_bit { ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { paste::paste! { @@ -200,7 +209,7 @@ macro_rules! field_getter { #[doc = $name] #[doc = "field."] #[must_use] - $vis fn $method(self) -> $ty { + $vis fn $method(&self) -> $ty { use bit_field::BitField; use core::convert::TryInto; self.0[$offset].get_bits($range).try_into().unwrap() @@ -211,12 +220,45 @@ macro_rules! field_getter { #[doc = $name] #[doc = "field."] #[must_use] - $vis fn $method(self) -> $ty { + $vis fn $method(&self) -> $ty { use bit_field::BitField; use core::convert::TryInto; self.0.get_bits($range).try_into().unwrap() } }; + ($vis:vis,$range:expr,$name:literal,$ty:ty) => { + #[doc = "Returns the value of the"] + #[doc = $name] + #[doc = "field."] + #[must_use] + $vis fn get(&self) -> $ty { + use bit_field::BitField; + use core::convert::TryInto; + self.0.get_bits($range).try_into().unwrap() + } + }; + ($vis:vis,[]{$start:literal},$method:ident,$name:literal,$ty:ty) => { + #[doc = "Returns the value of the"] + #[doc = $name] + #[doc = "field."] + #[must_use] + $vis fn $method(&self) -> $ty { + // use bit_field::BitField; + use core::convert::TryInto; + (self.0 >> $start << $start).try_into().unwrap() + } + }; + ($vis:vis,[]{$start:literal},$name:literal,$ty:ty) => { + #[doc = "Returns the value of the"] + #[doc = $name] + #[doc = "field."] + #[must_use] + $vis fn get(&self) -> $ty { + // use bit_field::BitField; + use core::convert::TryInto; + (self.0 >> $start << $start).try_into().unwrap() + } + } } macro_rules! field_setter { @@ -246,6 +288,57 @@ macro_rules! field_setter { } } }; + ($vis:vis,$range:expr,$name:literal,$ty:ty) => { + paste::paste! { + #[doc = "Sets the value of the"] + #[doc = $name] + #[doc = "field."] + $vis fn set(&mut self,value:$ty) -> &mut Self { + use bit_field::BitField; + use core::convert::TryInto; + self.0.set_bits($range,value.try_into().unwrap()); + self + } + } + }; + ($vis:vis,[]{$start:literal,$expect:literal},$method:ident,$name:literal,$ty:ty) => { + paste::paste! { + #[doc = "Sets the value of the"] + #[doc = $name] + #[doc = "field."] + #[doc = "\n\n# Panics \n\n"] + #[doc = "This method panics if the given value is not"] + #[doc = $expect] + #[doc = "."] + $vis fn [](&mut self,value:$ty) -> &mut Self { + use bit_field::BitField; + + assert!(value.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); + + self.0.set_bits($start.., value.get_bits($start..)); + self + } + } + }; + ($vis:vis,[]{$start:literal,$expect:literal},$name:literal,$ty:ty) => { + paste::paste! { + #[doc = "Sets the value of the"] + #[doc = $name] + #[doc = "field."] + #[doc = "\n\n# Panics \n\n"] + #[doc = "This method panics if the given value is not"] + #[doc = $expect] + #[doc = "."] + $vis fn set(&mut self,value:$ty) -> &mut Self { + use bit_field::BitField; + + assert!(value.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); + + self.0.set_bits($start.., value.get_bits($start..)); + self + } + } + }; } macro_rules! ro_field { @@ -255,6 +348,15 @@ macro_rules! ro_field { ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { field_getter!($vis, $range, $method, $name, $ty); }; + ($vis:vis,$range:expr,$name:literal,$ty:ty) => { + field_getter!($vis, $range, $name, $ty); + }; + ($vis:vis,[]{$start:literal},$method:ident,$name:literal,$ty:ty) => { + field_getter!($vis, []{$start}, $method, $name, $ty); + }; + ($vis:vis,[]{$start:literal},$name:literal,$ty:ty) => { + field_getter!($vis, []{$start}, $name, $ty); + }; } macro_rules! rw_field { @@ -262,8 +364,115 @@ macro_rules! rw_field { field_getter!($vis, [$offset]($range), $method, $name, $ty); field_setter!($vis, [$offset]($range), $method, $name, $ty); }; - ($vis:vis, $range:expr,$method:ident,$name:literal,$ty:ty) => { + ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { field_getter!($vis, $range, $method, $name, $ty); field_setter!($vis, $range, $method, $name, $ty); }; + ($vis:vis,$range:expr,$name:literal,$ty:ty) => { + field_getter!($vis, $range, $name, $ty); + field_setter!($vis, $range, $name, $ty); + }; + ($vis:vis,[]{$start:literal,$expect:literal},$method:ident,$name:literal,$ty:ty) => { + field_getter!($vis, []{$start}, $method, $name, $ty); + field_setter!($vis, []{$start, $expect}, $method, $name, $ty); + }; + ($vis:vis,[]{$start:literal,$expect:literal},$name:literal,$ty:ty) => { + field_getter!($vis, []{$start}, $name, $ty); + field_setter!($vis, []{$start, $expect}, $name, $ty); + }; +} + +macro_rules! double_field_getter { + ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + #[doc = "Returns the value of the"] + #[doc = $name] + #[doc = "field."] + #[must_use] + $vis fn $method(&self) -> $ty { + let lo = self.0[$off_lo] as $ty; + let hi = self.0[$off_hi] as $ty; + + (hi << $bits) | lo + } + }; + ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { + #[doc = "Returns the value of the"] + #[doc = $name] + #[doc = "field."] + #[must_use] + $vis fn $method(&self) -> $ty { + let lo = (self.0[$off_lo] as $ty) >> $start << $start; + let hi = self.0[$off_hi] as $ty; + + (hi << $bits) | lo + } + }; } + +macro_rules! double_field_setter { + ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + paste::paste! { + #[doc = "Sets the value of the"] + #[doc = $name] + #[doc = "field."] + $vis fn [](&mut self, value: $ty) -> &mut Self { + use bit_field::BitField; + use core::convert::TryInto; + + let lo = value.get_bits(..$bits); + let hi = value.get_bits($bits..); + + self.0[$off_lo] = lo.try_into().unwrap(); + self.0[$off_hi] = hi.try_into().unwrap(); + self + } + } + }; + ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal,$expect:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { + paste::paste! { + #[doc = "Sets the value of the"] + #[doc = $name] + #[doc = "field."] + #[doc = "\n\n# Panics \n\n"] + #[doc = "This method panics if the given value is not"] + #[doc = $expect] + #[doc = "."] + $vis fn [](&mut self, value: $ty) -> &mut Self { + use bit_field::BitField; + use core::convert::TryInto; + + let lo = value.get_bits(..$bits); + let hi = value.get_bits($bits..); + + assert!(lo.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); + + self.0[$off_lo].set_bits( + $start.., + lo.get_bits($start..).try_into().unwrap() + ); + self.0[$off_hi] = hi.try_into().unwrap(); + self + } + } + }; +} + +macro_rules! ro_double_field { + ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + double_field_getter!($vis, [$off_lo, $off_hi], $method, $name, $bits, $ty); + }; + ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { + double_field_getter!($vis, [$off_lo, $off_hi]{$start}, $method, $name, $bits, $ty); + }; +} + +macro_rules! rw_double_field { + ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + double_field_getter!($vis, [$off_lo, $off_hi], $method, $name, $bits, $ty); + double_field_setter!($vis, [$off_lo, $off_hi], $method, $name, $bits, $ty); + }; + ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal,$expect:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { + double_field_getter!($vis, [$off_lo, $off_hi]{$start}, $method, $name, $bits, $ty); + double_field_setter!($vis, [$off_lo, $off_hi]{$start, $expect}, $method, $name, $bits, $ty); + }; +} \ No newline at end of file diff --git a/src/registers/operational.rs b/src/registers/operational.rs index b08a627..4bea0ff 100644 --- a/src/registers/operational.rs +++ b/src/registers/operational.rs @@ -216,21 +216,13 @@ impl CommandRingControlRegister { w1s_bit!(pub, 1, command_stop, "Command Stop"); w1s_bit!(pub, 2, command_abort, "Command Abort"); ro_bit!(pub, 3, command_ring_running, "Command Ring Running"); - - /// Sets the value of the Command Ring Pointer field. It must be 64 byte aligned. - /// - /// # Panics - /// - /// This method panics if the given pointer is not 64 byte aligned. - pub fn set_command_ring_pointer(&mut self, p: u64) { - assert!( - p.trailing_zeros() >= 6, - "The Command Ring Pointer must be 64-byte aligned." - ); - - let p = p >> 6; - self.0.set_bits(6..=63, p); - } + rw_field!( + pub, + []{6, "64-byte aligned"}, + command_ring_pointer, + "Command Ring Pointer", + u64 + ); } impl_debug_from_methods! { CommandRingControlRegister{ @@ -243,24 +235,12 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Debug, Default)] pub struct DeviceContextBaseAddressArrayPointerRegister(u64); impl DeviceContextBaseAddressArrayPointerRegister { - /// Returns the value of the Device Context Base Address Array Pointer. - #[must_use] - pub fn get(self) -> u64 { - self.0 - } - - /// Sets the value of the Device Context Base Address Array Pointer. It must be 64 byte aligned. - /// - /// # Panics - /// - /// This method panics if the given pointer is not 64 byte aligned. - pub fn set(&mut self, p: u64) { - assert!( - p.trailing_zeros() >= 6, - "The Device Context Base Address Array Pointer must be 64-byte aligned." - ); - self.0 = p; - } + rw_field!( + pub, + []{6, "64-byte aligned"}, + "Device Context Base Address Array Pointer", + u64 + ); } /// Configure Register diff --git a/src/registers/runtime.rs b/src/registers/runtime.rs index e106905..4566ee6 100644 --- a/src/registers/runtime.rs +++ b/src/registers/runtime.rs @@ -206,16 +206,12 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Debug)] pub struct EventRingSegmentTableSizeRegister(u32); impl EventRingSegmentTableSizeRegister { - /// Returns the number of segments the Event Ring Segment Table supports. - #[must_use] - pub fn get(self) -> u16 { - self.0.try_into().unwrap() - } - - /// Sets the number of segments the Event Ring Segment Table supports. - pub fn set(&mut self, s: u16) { - self.0 = s.into(); - } + rw_field!( + pub, + 0..=15, + "Event Ring Segment Table Size (the number of segments)", + u16 + ); } /// Event Ring Segment Table Base Address Register. @@ -223,24 +219,12 @@ impl EventRingSegmentTableSizeRegister { #[derive(Copy, Clone, Debug)] pub struct EventRingSegmentTableBaseAddressRegister(u64); impl EventRingSegmentTableBaseAddressRegister { - /// Returns the base address of the Event Ring Segment Table. - #[must_use] - pub fn get(self) -> u64 { - self.0 - } - - /// Sets the base address of the Event Ring Segment Table. It must be 64 byte aligned. - /// - /// # Panics - /// - /// This method panics if the address is not 64 byte aligned. - pub fn set(&mut self, a: u64) { - assert!( - a.trailing_zeros() >= 6, - "The Event Ring Segment Table Base Address must be 64-byte aligned." - ); - self.0 = a; - } + rw_field!( + pub, + []{6, "64-byte aligned"}, + "Event Ring Segment Table Base Address", + u64 + ); } /// Event Ring Dequeue Pointer Register. @@ -256,24 +240,13 @@ impl EventRingDequeuePointerRegister { ); rw1c_bit!(pub, 3, event_handler_busy, "Event Handler Busy"); - /// Returns the address of the current Event Ring Dequeue Pointer. - #[must_use] - pub fn event_ring_dequeue_pointer(self) -> u64 { - self.0 & !0b1111 - } - - /// Sets the address of the current Event Ring Dequeue Pointer. It must be 16 byte aligned. - /// - /// # Panics - /// - /// This method panics if the address is not 16 byte aligned. - pub fn set_event_ring_dequeue_pointer(&mut self, p: u64) { - assert!( - p.trailing_zeros() >= 4, - "The Event Ring Dequeue Pointer must be 16-byte aligned." - ); - self.0 = p; - } + rw_field!( + pub, + []{4, "16-byte aligned"}, + event_ring_dequeue_pointer, + "current Event Ring Dequeue Pointer", + u64 + ); } impl_debug_from_methods! { EventRingDequeuePointerRegister{ diff --git a/src/ring/trb/command.rs b/src/ring/trb/command.rs index 3e7accf..0b82c6c 100644 --- a/src/ring/trb/command.rs +++ b/src/ring/trb/command.rs @@ -2,7 +2,6 @@ use super::{Link, Type}; use bit_field::BitField; -use core::convert::TryInto; use num_traits::FromPrimitive; allowed! { @@ -123,36 +122,15 @@ reserved!(AddressDevice(Type::AddressDevice) { [3]16..=23; }); impl AddressDevice { - /// Sets the value of the Input Context Pointer field. - /// - /// # Panics - /// - /// This method panics if `p` is not 16-byte aligned. - pub fn set_input_context_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 16, - 0, - "The Input Context Pointer must be 16-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Input Context Pointer field. - #[must_use] - pub fn input_context_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - - rw_bit!(pub, + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + input_context_pointer, + "Input Context Pointer", + 32, u64 + ); + rw_bit!( + pub, [3](9), block_set_address_request, "Block Set Address Request" @@ -177,35 +155,13 @@ reserved!(ConfigureEndpoint(Type::ConfigureEndpoint) { [3]16..=23; }); impl ConfigureEndpoint { - /// Sets the value of the Input Context Pointer field. - /// - /// # Panics - /// - /// This method panics if `p` is not 16-byte aligned. - pub fn set_input_context_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 16, - 0, - "The Input Context Pointer must be 16-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Input Context Pointer field. - #[must_use] - pub fn input_context_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + input_context_pointer, + "Input Context Pointer", + 32, u64 + ); rw_bit!(pub, [3](9), deconfigure, "Deconfigure"); rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } @@ -227,34 +183,13 @@ reserved!(EvaluateContext(Type::EvaluateContext) { [3]16..=23; }); impl EvaluateContext { - /// Sets the value of the Input Context Pointer field. - /// - /// # Panics - /// - /// This method panics if `p` is not 16-byte aligned. - pub fn set_input_context_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 16, - 0, - "The Input Context Pointer must be 16-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Input Context Pointer field. - #[must_use] - pub fn input_context_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + input_context_pointer, + "Input Context Pointer", + 32, u64 + ); rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); } impl_debug_for_trb!(EvaluateContext { @@ -321,36 +256,13 @@ reserved!(SetTrDequeuePointer(Type::SetTrDequeuePointer) { impl SetTrDequeuePointer { rw_bit!(pub, [0](0), dequeue_cycle_state, "Dequeue Cycle State"); rw_field!(pub, [0](1..=3), stream_context_type, "Stream Context Type", u8); - - /// Sets the value of the New TR Dequeue Pointer field. - /// - /// # Panics - /// - /// This method panics if `p` is not 16-byte aligned. - pub fn set_new_tr_dequeue_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 16, - 0, - "The New TR Dequeue Pointer must be 16-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0].set_bits(4..32, l.get_bits(4..32).try_into().unwrap()); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the New TR Dequeue Pointer field. - #[must_use] - pub fn new_tr_dequeue_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - ((u << 32) | l) & 0xffff_fff0 - } - + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + new_tr_dequeue_pointer, + "New TR Dequeue Pointer", + 32, u64 + ); rw_field!(pub, [2](16..=31), stream_id, "Stream ID", u16); rw_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); @@ -385,32 +297,13 @@ reserved!(ForceEvent(Type::ForceEvent) { [3]24..=31; }); impl ForceEvent { - /// Sets the value of the Event TRB Pointer field. - /// - /// # Panics - /// - /// This method panics if the `p` is not 16-byte aligned. - pub fn set_event_trb_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!(p % 16, 0, "The Event TRB Pointer must be 16-byte aligned."); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - - self - } - - /// Returns the value of the Event TRB Pointer field. - #[must_use] - pub fn event_trb_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + event_trb_pointer, + "Event TRB Pointer", + 32, u64 + ); rw_field!(pub, [2](22..=31), vf_interrupter_target, @@ -478,34 +371,13 @@ reserved!(GetPortBandwidth(Type::GetPortBandwidth) { [3]20..=23; }); impl GetPortBandwidth { - /// Sets the value of the Port Bandwidth Context Pointer field. - /// - /// # Panics - /// - /// This method panics if the `p` is not 16-byte aligned. - pub fn set_port_bandwidth_context_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 16, - 0, - "The Port Bandwidth Context Pointer must be 16-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Port Bandwidth Context Pointer field. - #[must_use] - pub fn port_bandwidth_context_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + port_bandwidth_context_pointer, + "Port Bandwidth Context Pointer", + 32, u64 + ); rw_field!(pub, [3](16..=19), dev_speed, "Dev Speed", u8); rw_field!(pub, [3](24..=31), hub_slot_id, "Hub Slot ID", u8); } @@ -570,35 +442,13 @@ reserved!(GetExtendedProperty(Type::GetExtendedProperty) { [3]1..=9; }); impl GetExtendedProperty { - /// Sets the value of the Extended Property Context Pointer field. - /// - /// # Panics - /// - /// This method panics if the `p` is not 16-byte aligned. - pub fn set_extended_property_context_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 16, - 0, - "The Extended Property Context Pointer must be 16-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Extended Property Context Pointer field. - #[must_use] - pub fn extended_property_context_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + extended_property_context_pointer, + "Extended Property Context Pointer", + 32, u64 + ); rw_field!(pub, [2](0..=15), extended_capability_identifier, diff --git a/src/ring/trb/event.rs b/src/ring/trb/event.rs index 1dc90c3..1bba25b 100644 --- a/src/ring/trb/event.rs +++ b/src/ring/trb/event.rs @@ -108,15 +108,7 @@ reserved!(TransferEvent(Type::TransferEvent){ [3]21..=23; }); impl TransferEvent { - /// Returns the value of the TRB Pointer field. - #[must_use] - pub fn trb_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + ro_double_field!(pub, [0, 1], trb_pointer, "TRB Pointer", 32, u64); ro_field!(pub, [2](0..=23), trb_transfer_length, "TRB Transfer Length", u32); ro_bit!(pub, [3](2), event_data, "Event Data"); ro_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); @@ -140,15 +132,13 @@ reserved!(CommandCompletion(Type::CommandCompletion){ [3]1..=9; }); impl CommandCompletion { - /// Returns the value of the Command TRB Pointer field. - #[must_use] - pub fn command_trb_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + ro_double_field!( + pub, + [0, 1], + command_trb_pointer, + "Command TRB Pointer", + 32, u64 + ); ro_field!(pub, [2](0..=23), command_completion_parameter, @@ -228,14 +218,18 @@ reserved!(DeviceNotification(Type::DeviceNotification){ }); impl DeviceNotification { ro_field!(pub, [0](4..=7), notification_type, "Notification Type", u8); + ro_double_field!( + pub(self), + [0, 1]{8}, + device_notification_data_raw, + "Device Notification Data Raw", + 32, u64 + ); /// Returns the value of the Device Notification Data field. #[must_use] pub fn device_notification_data(&self) -> u64 { - let l: u64 = self.0[0].get_bits(8..=31).into(); - let u: u64 = self.0[1].into(); - - ((u << 32) | l) >> 8 + self.device_notification_data_raw() >> 8 } ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); diff --git a/src/ring/trb/mod.rs b/src/ring/trb/mod.rs index 6fe9095..49b5568 100644 --- a/src/ring/trb/mod.rs +++ b/src/ring/trb/mod.rs @@ -1,7 +1,6 @@ //! TRB (Transfer Request Block). use bit_field::BitField; -use core::convert::TryInto; use num_derive::FromPrimitive; macro_rules! reserved{ @@ -202,35 +201,13 @@ reserved!(Link(Type::Link){ [3]16..=31; }); impl Link { - /// Sets the value of the Ring Segment Pointer field. - /// - /// # Panics - /// - /// This method panics if `p` is not 16-byte aligned. - pub fn set_ring_segment_pointer(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 16, - 0, - "The Ring Segment Pointer must be 16-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Ring Segment Pointer field. - #[must_use] - pub fn ring_segment_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1]{4, "16-byte aligned"}, + ring_segment_pointer, + "Ring Segment Pointer", + 32, u64 + ); rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u32); rw_bit!(pub, [3](1), toggle_cycle, "Toggle Cycle"); rw_bit!(pub, [3](4), chain_bit, "Chain bit"); diff --git a/src/ring/trb/transfer.rs b/src/ring/trb/transfer.rs index 3f8a99c..4ad40d2 100644 --- a/src/ring/trb/transfer.rs +++ b/src/ring/trb/transfer.rs @@ -161,25 +161,13 @@ reserved!(Normal(Type::Normal) { [3]16..=31; }); impl Normal { - /// Sets the value of the Data Buffer Pointer field. - pub fn set_data_buffer_pointer(&mut self, p: u64) -> &mut Self { - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Data Buffer Pointer field. - #[must_use] - pub fn data_buffer_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1], + data_buffer_pointer, + "Data Buffer Pointer", + 32, u64 + ); rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); rw_field!(pub, [2](17..=21), td_size, "TD Size", u8); rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); @@ -285,25 +273,13 @@ reserved!(DataStage(Type::DataStage) { [3]17..=31; }); impl DataStage { - /// Sets the value of the Data Buffer Pointer field. - pub fn set_data_buffer_pointer(&mut self, p: u64) -> &mut Self { - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Data Buffer Pointer field. - #[must_use] - pub fn data_buffer_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1], + data_buffer_pointer, + "Data Buffer Pointer", + 32, u64 + ); rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); rw_field!(pub, [2](17..=21), td_size, "TD Size", u8); rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); @@ -371,25 +347,13 @@ impl_debug_for_transfer_trb! { transfer_trb_with_default!(Isoch, "Isoch TRB", Type::Isoch); reserved!(Isoch(Type::Isoch) {}); impl Isoch { - /// Sets the value of the Data Buffer Pointer. - pub fn set_data_buffer_pointer(&mut self, p: u64) -> &mut Self { - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Data Buffer Pointer. - #[must_use] - pub fn data_buffer_pointer(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1], + data_buffer_pointer, + "Data Buffer Pointer", + 32, u64 + ); rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); rw_field!(pub, [2](17..=21), td_size_or_tbc, "TD Size/TBC", u8); rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); @@ -438,25 +402,13 @@ reserved!(EventData(Type::EventData) { [3]16..=31; }); impl EventData { - /// Sets the value of the Event Data field. - pub fn set_event_data(&mut self, d: u64) -> &mut Self { - let l = d.get_bits(0..32); - let u = d.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Event Data field. - #[must_use] - pub fn event_data(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - + rw_double_field!( + pub, + [0, 1], + event_data, + "Event Data", + 32, u64 + ); rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); rw_bit!(pub, [3](4), chain_bit, "Chain bit"); From da807014eb74e48df71c0397340844f65cae8d4a Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Wed, 6 Dec 2023 05:47:14 +0000 Subject: [PATCH 07/17] improve macros --- src/extended_capabilities/debug.rs | 73 +-- .../hci_extended_power_management.rs | 28 +- .../usb_legacy_support_capability.rs | 27 +- .../xhci_extended_message_interrupt.rs | 2 +- .../xhci_local_memory.rs | 4 +- .../xhci_message_interrupt.rs | 16 +- src/macros.rs | 453 ++++++------------ src/registers/capability.rs | 132 ++--- src/registers/doorbell.rs | 4 +- src/registers/operational.rs | 173 +++---- src/registers/runtime.rs | 42 +- src/ring/trb/command.rs | 134 +++--- src/ring/trb/event.rs | 41 +- src/ring/trb/mod.rs | 16 +- src/ring/trb/transfer.rs | 126 ++--- 15 files changed, 582 insertions(+), 689 deletions(-) diff --git a/src/extended_capabilities/debug.rs b/src/extended_capabilities/debug.rs index f31d017..8018951 100644 --- a/src/extended_capabilities/debug.rs +++ b/src/extended_capabilities/debug.rs @@ -86,8 +86,8 @@ where pub struct Id(u32); impl Id { ro_field!( - pub, - 16..=20, + pub, self, + self.0; 16..=20, debug_capability_event_ring_segment_table_max, "Debug Capability Event Ring Segment Table Max", u8 @@ -104,7 +104,12 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Debug)] pub struct Doorbell(u32); impl Doorbell { - field_setter!(pub, 8..=15, "Doorbell Target", u8); + rw_field!( + pub, self, + self.0; 8..=15, + "Doorbell Target", + u8 + ); } /// Debug Capability Event Ring Segment Table Size Register. @@ -112,7 +117,7 @@ impl Doorbell { #[derive(Copy, Clone)] pub struct EventRingSegmentTableSize(u32); impl EventRingSegmentTableSize { - rw_field!(pub, 0..=15, "Event Ring Segment Table Size", u16); + rw_field!(pub, self, self.0; 0..=15, "Event Ring Segment Table Size", u16); } impl_debug_from_methods! { EventRingSegmentTableSize { @@ -125,9 +130,9 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct EventRingSegmentTableBaseAddress(u64); impl EventRingSegmentTableBaseAddress { - rw_field!( - pub, - []{4, "64-byte aligned"}, + rw_zero_trailing!( + pub, self, + self.0; 4~; "64-byte aligned", "Event Ring Segment Table Base Address", u64 ); @@ -144,15 +149,15 @@ impl_debug_from_methods! { pub struct EventRingDequeuePointer(u64); impl EventRingDequeuePointer { rw_field!( - pub, - 0..=2, + pub, self, + self.0; 0..=2, dequeue_erst_segment_index, "Dequeue ERST Segment Index", u8 ); - rw_field!( - pub, - []{4, "16-byte aligned"}, + rw_zero_trailing!( + pub, self, + self.0; 4~; "16-byte aligned", dequeue_pointer, "Event Ring Dequeue Pointer", u64 @@ -170,11 +175,11 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct Control(u32); impl Control { - ro_bit!(pub, 0, dbc_run, "DbC Run"); - rw_bit!(pub, 1, link_status_event_enable, "Link Status Event Enable"); - rw1s_bit!(pub, 2, halt_out_tr, "Halt OUT TR"); - rw1s_bit!(pub, 3, halt_in_tr, "Halt IN TR"); - rw1c_bit!(pub, 4, dbc_run_change, "DbC Run Change"); + ro_bit!(pub, self, self.0; 0, dbc_run, "DbC Run"); + rw_bit!(pub, self, self.0; 1, link_status_event_enable, "Link Status Event Enable"); + rw1s_bit!(pub, self, self.0; 2, halt_out_tr, "Halt OUT TR"); + rw1s_bit!(pub, self, self.0; 3, halt_in_tr, "Halt IN TR"); + rw1c_bit!(pub, self, self.0; 4, dbc_run_change, "DbC Run Change"); /// Returns the value of the Debug Max Burst Size field. #[must_use] @@ -188,7 +193,7 @@ impl Control { self.0.get_bits(24..=30).try_into().unwrap() } - rw_bit!(pub, 31, debug_capability_enable, "Debug Capability Enable"); + rw_bit!(pub, self, self.0; 31, debug_capability_enable, "Debug Capability Enable"); } impl_debug_from_methods! { Control { @@ -208,8 +213,8 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct Status(u32); impl Status { - ro_bit!(pub, 0, event_ring_not_empty, "Event Ring Not Empty"); - ro_bit!(pub, 1, dbc_system_bus_reset, "DbC System Bus Reset"); + ro_bit!(pub, self, self.0; 0, event_ring_not_empty, "Event Ring Not Empty"); + ro_bit!(pub, self, self.0; 1, dbc_system_bus_reset, "DbC System Bus Reset"); /// Returns the value of the Debug Port Number field. #[must_use] @@ -230,9 +235,9 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PortStatusAndControl(u32); impl PortStatusAndControl { - ro_bit!(pub, 0, current_connect_status, "Current Connect Status"); - rw_bit!(pub, 1, port_enabled_disabled, "Port Enabled/Disabled"); - ro_bit!(pub, 4, port_reset, "Port Reset"); + ro_bit!(pub, self, self.0; 0, current_connect_status, "Current Connect Status"); + rw_bit!(pub, self, self.0; 1, port_enabled_disabled, "Port Enabled/Disabled"); + ro_bit!(pub, self, self.0; 4, port_reset, "Port Reset"); /// Returns the value of the Port Link State field. #[must_use] @@ -246,10 +251,10 @@ impl PortStatusAndControl { self.0.get_bits(10..=13).try_into().unwrap() } - rw1c_bit!(pub, 17, connect_status_change, "Connect Status Change"); - rw1c_bit!(pub, 21, port_reset_change, "Port Reset Change"); - rw1c_bit!(pub, 22, port_link_status_change, "Port Link Status Change"); - rw1c_bit!(pub, 23, port_config_error_change, "Port Config Error Change"); + rw1c_bit!(pub, self, self.0; 17, connect_status_change, "Connect Status Change"); + rw1c_bit!(pub, self, self.0; 21, port_reset_change, "Port Reset Change"); + rw1c_bit!(pub, self, self.0; 22, port_link_status_change, "Port Link Status Change"); + rw1c_bit!(pub, self, self.0; 23, port_config_error_change, "Port Config Error Change"); } impl_debug_from_methods! { PortStatusAndControl { @@ -270,9 +275,9 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Debug)] pub struct ContextPointer(u64); impl ContextPointer { - rw_field!( - pub, - []{4, "16-byte aligned"}, + rw_zero_trailing!( + pub, self, + self.0; 4~; "16-byte aligned", "Debug Capability Context Base Pointer", u64 ); @@ -283,8 +288,8 @@ impl ContextPointer { #[derive(Copy, Clone)] pub struct DeviceDescriptorInfo1(u32); impl DeviceDescriptorInfo1 { - rw_field!(pub, 0..=7, dbc_protocol, "DbC Protocol", u8); - rw_field!(pub, 16..=31, vendor_id, "Vendor ID", u16); + rw_field!(pub, self, self.0; 0..=7, dbc_protocol, "DbC Protocol", u8); + rw_field!(pub, self, self.0; 16..=31, vendor_id, "Vendor ID", u16); } impl_debug_from_methods! { DeviceDescriptorInfo1 { @@ -298,8 +303,8 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct DeviceDescriptorInfo2(u32); impl DeviceDescriptorInfo2 { - rw_field!(pub, 0..=15, product_id, "Product ID", u16); - rw_field!(pub, 16..=31, device_revision, "Device Revision", u16); + rw_field!(pub, self, self.0; 0..=15, product_id, "Product ID", u16); + rw_field!(pub, self, self.0; 16..=31, device_revision, "Device Revision", u16); } impl_debug_from_methods! { DeviceDescriptorInfo2 { diff --git a/src/extended_capabilities/hci_extended_power_management.rs b/src/extended_capabilities/hci_extended_power_management.rs index 4bc2535..86e5324 100644 --- a/src/extended_capabilities/hci_extended_power_management.rs +++ b/src/extended_capabilities/hci_extended_power_management.rs @@ -32,13 +32,13 @@ where #[derive(Copy, Clone)] pub struct PowerManagementCapabilities(u16); impl PowerManagementCapabilities { - ro_field!(pub, 11..=15, pme_support, "PME_Support", u8); - ro_bit!(pub, 10, d2_support, "D2_Support"); - ro_bit!(pub, 9, d1_support, "D1_Support"); - ro_field!(pub, 6..=8, aux_current, "Aux_Current", u8); - ro_bit!(pub, 5, dsi, "DSI"); - ro_bit!(pub, 3, pme_clock, "PME Clock"); - ro_field!(pub, 0..=2, version, "Version", u8); + ro_field!(pub, self, self.0; 11..=15, pme_support, "PME_Support", u8); + ro_bit!(pub, self, self.0; 10, d2_support, "D2_Support"); + ro_bit!(pub, self, self.0; 9, d1_support, "D1_Support"); + ro_field!(pub, self, self.0; 6..=8, aux_current, "Aux_Current", u8); + ro_bit!(pub, self, self.0; 5, dsi, "DSI"); + ro_bit!(pub, self, self.0; 3, pme_clock, "PME Clock"); + ro_field!(pub, self, self.0; 0..=2, version, "Version", u8); } impl_debug_from_methods! { PowerManagementCapabilities { @@ -57,11 +57,11 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PowerManagementControlStatusRegister(u16); impl PowerManagementControlStatusRegister { - rw1c_bit!(pub, 15, pme_status, "PME_Status"); - ro_field!(pub, 13..=14, data_scale, "Data_Scale", u8); - rw_field!(pub, 9..=12, data_select, "Data_Select", u8); - rw_bit!(pub, 8, pme_en, "PME_En"); - rw_field!(pub, 0..=1, power_state, "PowerState", u8); + rw1c_bit!(pub, self, self.0; 15, pme_status, "PME_Status"); + ro_field!(pub, self, self.0; 13..=14, data_scale, "Data_Scale", u8); + rw_field!(pub, self, self.0; 9..=12, data_select, "Data_Select", u8); + rw_bit!(pub, self, self.0; 8, pme_en, "PME_En"); + rw_field!(pub, self, self.0; 0..=1, power_state, "PowerState", u8); } impl_debug_from_methods! { PowerManagementControlStatusRegister { @@ -78,8 +78,8 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PmesrBse(u8); impl PmesrBse { - ro_bit!(pub, 7, bpcc_en, "BPCC_En"); - ro_bit!(pub, 6, b2_b3, "B2_B3"); + ro_bit!(pub, self, self.0; 7, bpcc_en, "BPCC_En"); + ro_bit!(pub, self, self.0; 6, b2_b3, "B2_B3"); } impl_debug_from_methods! { PmesrBse { diff --git a/src/extended_capabilities/usb_legacy_support_capability.rs b/src/extended_capabilities/usb_legacy_support_capability.rs index 38363e2..d496da6 100644 --- a/src/extended_capabilities/usb_legacy_support_capability.rs +++ b/src/extended_capabilities/usb_legacy_support_capability.rs @@ -53,8 +53,8 @@ where #[derive(Copy, Clone)] pub struct LegSup(u32); impl LegSup { - rw_bit!(pub, 16, hc_bios_owned_semaphore, "HC BIOS Owned Semaphore"); - rw_bit!(pub, 24, hc_os_owned_semaphore, "HC OS Owned Semaphore"); + rw_bit!(pub, self, self.0; 16, hc_bios_owned_semaphore, "HC BIOS Owned Semaphore"); + rw_bit!(pub, self, self.0; 24, hc_os_owned_semaphore, "HC OS Owned Semaphore"); } impl_debug_from_methods! { LegSup { @@ -68,20 +68,21 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct UsbLegacySupportControlStatus(u32); impl UsbLegacySupportControlStatus { - rw_bit!(pub, 0, usb_smi_enable, "USB SMI Enable"); - rw_bit!(pub, - 4, + rw_bit!(pub, self, self.0; 0, usb_smi_enable, "USB SMI Enable"); + rw_bit!( + pub, self, + self.0; 4, smi_on_host_system_error_enable, "SMI on Host System Error Enable" ); - rw_bit!(pub, 13, smi_on_os_ownership_enable, "SMI on OS Ownership Enable"); - rw_bit!(pub, 14, smi_on_pci_command_enable, "SMI on PCI Command Enable"); - rw_bit!(pub, 15, smi_on_bar_enable, "SMI on BAR Enable"); - ro_bit!(pub, 16, smi_on_event_interrupt, "SMI on Event Interrupt"); - ro_bit!(pub, 20, smi_on_host_system_error, "SMI on Host System Error"); - rw1c_bit!(pub, 29, smi_on_os_ownership_change, "SMI on OS Ownership Change"); - rw1c_bit!(pub, 30, smi_on_pci_command, "SMI on PCI Command"); - rw1c_bit!(pub, 31, smi_on_bar, "SMI on BAR"); + rw_bit!(pub, self, self.0; 13, smi_on_os_ownership_enable, "SMI on OS Ownership Enable"); + rw_bit!(pub, self, self.0; 14, smi_on_pci_command_enable, "SMI on PCI Command Enable"); + rw_bit!(pub, self, self.0; 15, smi_on_bar_enable, "SMI on BAR Enable"); + ro_bit!(pub, self, self.0; 16, smi_on_event_interrupt, "SMI on Event Interrupt"); + ro_bit!(pub, self, self.0; 20, smi_on_host_system_error, "SMI on Host System Error"); + rw1c_bit!(pub, self, self.0; 29, smi_on_os_ownership_change, "SMI on OS Ownership Change"); + rw1c_bit!(pub, self, self.0; 30, smi_on_pci_command, "SMI on PCI Command"); + rw1c_bit!(pub, self, self.0; 31, smi_on_bar, "SMI on BAR"); } impl_debug_from_methods! { UsbLegacySupportControlStatus { diff --git a/src/extended_capabilities/xhci_extended_message_interrupt.rs b/src/extended_capabilities/xhci_extended_message_interrupt.rs index 9544b57..3bf689d 100644 --- a/src/extended_capabilities/xhci_extended_message_interrupt.rs +++ b/src/extended_capabilities/xhci_extended_message_interrupt.rs @@ -33,7 +33,7 @@ where #[derive(Copy, Clone)] pub struct MessageControl(u16); impl MessageControl { - rw_bit!(pub, 15, msi_x_enable, "MSI-X Enable"); + rw_bit!(pub, self, self.0; 15, msi_x_enable, "MSI-X Enable"); /// Returns the value of the Table Size field. #[must_use] diff --git a/src/extended_capabilities/xhci_local_memory.rs b/src/extended_capabilities/xhci_local_memory.rs index 0d1bf5f..05ffba9 100644 --- a/src/extended_capabilities/xhci_local_memory.rs +++ b/src/extended_capabilities/xhci_local_memory.rs @@ -61,8 +61,8 @@ where pub struct Header([u32; 2]); impl Header { rw_bit!( - pub, - [0](16), + pub, self, + self.0[0]; 16, local_memory_enable, "Local Memory Enable" ); diff --git a/src/extended_capabilities/xhci_message_interrupt.rs b/src/extended_capabilities/xhci_message_interrupt.rs index ff91b8a..6a19973 100644 --- a/src/extended_capabilities/xhci_message_interrupt.rs +++ b/src/extended_capabilities/xhci_message_interrupt.rs @@ -3,7 +3,7 @@ use super::ExtendedCapability; use accessor::single; use accessor::Mapper; -use bit_field::BitField; +// use bit_field::BitField; use core::convert::TryFrom; use core::convert::TryInto; @@ -113,23 +113,23 @@ impl MessageAddress for u64 {} #[derive(Copy, Clone)] pub struct MessageControl(u16); impl MessageControl { - rw_bit!(pub, 0, msi_enable, "MSI Enable"); + rw_bit!(pub, self, self.0; 0, msi_enable, "MSI Enable"); ro_field!( - pub, - 1..=3, + pub, self, + self.0; 1..=3, multiple_message_capable, "Multiple Message Capable", u8 ); rw_field!( - pub, - 4..=6, + pub, self, + self.0; 4..=6, multiple_message_enable, "Multiple Message Enable", u8 ); - ro_bit!(pub, 7, bit64_address_capable, "64 bit address capable"); - ro_bit!(pub, 8, per_vector_masking_capable, "Per-vector masking capable"); + ro_bit!(pub, self, self.0; 7, bit64_address_capable, "64 bit address capable"); + ro_bit!(pub, self, self.0; 8, per_vector_masking_capable, "Per-vector masking capable"); } impl_debug_from_methods! { MessageControl { diff --git a/src/macros.rs b/src/macros.rs index 37ed321..3b62471 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,314 +13,158 @@ macro_rules! impl_debug_from_methods { } macro_rules! bit_getter { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { #[doc = "Returns the"] #[doc = $name] #[doc = "bit."] #[must_use] - $vis fn $method(&self) -> bool { + $vis fn $method(&$self_) -> bool { use bit_field::BitField; - self.0[$offset].get_bit($bit) - } - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - #[doc = "Returns the"] - #[doc = $name] - #[doc = "bit."] - #[must_use] - $vis fn $method(&self) -> bool { - use bit_field::BitField; - self.0.get_bit($bit) + $from.get_bit($bit) } }; } -macro_rules! bit_modifier { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { +macro_rules! bit_raiser { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { paste::paste! { #[doc = "Sets the"] #[doc = $name] #[doc = "bit."] - $vis fn [](&mut self)->&mut Self{ + $vis fn [](&mut $self_)->&mut Self{ use bit_field::BitField; - self.0[$offset].set_bit($bit,true); - self - } - - #[doc = "Clears the"] - #[doc = $name] - #[doc = "bit."] - $vis fn [](&mut self)->&mut Self{ - use bit_field::BitField; - self.0[$offset].set_bit($bit,false); - self + $from.set_bit($bit,true); + $self_ } } }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - paste::paste! { - #[doc = "Sets the"] - #[doc = $name] - #[doc = "bit."] - $vis fn [](&mut self)->&mut Self{ - use bit_field::BitField; - self.0.set_bit($bit,true); - self - } +} +macro_rules! bit_clearer { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { + paste::paste! { #[doc = "Clears the"] #[doc = $name] #[doc = "bit."] - $vis fn [](&mut self)->&mut Self{ + $vis fn [](&mut $self_)->&mut Self{ use bit_field::BitField; - self.0.set_bit($bit,false); - self + $from.set_bit($bit,false); + $self_ } } }; } macro_rules! bit_modifier_w1c { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { paste::paste! { #[doc = "Assigns 1 to the"] #[doc = $name] #[doc = "bit. On register write, this results in clearing the bit."] - $vis fn [](&mut self)->&mut Self{ + $vis fn [](&mut $self_)->&mut Self{ use bit_field::BitField; - self.0[$offset].set_bit($bit,true); - self + $from.set_bit($bit,true); + $self_ } #[doc = "Assigns 0 to the"] #[doc = $name] #[doc = "bit, preventing the bit from being cleared on write."] - $vis fn [](&mut self) -> &mut Self { + $vis fn [](&mut $self_) -> &mut Self { use bit_field::BitField; - self.0[$offset].set_bit($bit,false); - self - } - } - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - paste::paste! { - #[doc = "Assigns 1 to the"] - #[doc = $name] - #[doc = "bit. On register write, this results in clearing the bit."] - $vis fn [](&mut self)->&mut Self{ - use bit_field::BitField; - self.0.set_bit($bit,true); - self - } - - #[doc = "Assigns 0 to the"] - #[doc = $name] - #[doc = "bit, preventing the bit from being cleared on write."] - $vis fn [](&mut self) -> &mut Self { - use bit_field::BitField; - self.0.set_bit($bit,false); - self + $from.set_bit($bit,false); + $self_ } } }; } macro_rules! ro_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_getter!($vis, $bit, $method, $name); + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $self_, $from;$bit, $method, $name); }; } macro_rules! wo_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_modifier!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_modifier!($vis, $bit, $method, $name); + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { + bit_raiser!($vis, $self_, $from;$bit, $method, $name); + bit_clearer!($vis, $self_, $from;$bit, $method, $name); }; } -macro_rules! rw_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!($vis, [$offset]($bit), $method, $name); - bit_modifier!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_getter!($vis, $bit, $method, $name); - bit_modifier!($vis, $bit, $method, $name); +macro_rules! w1s_bit { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { + bit_raiser!($vis, $self_, $from;$bit, $method, $name); }; } -macro_rules! rw1c_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!($vis, [$offset]($bit), $method, $name); - bit_modifier_w1c!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_getter!($vis, $bit, $method, $name); - bit_modifier_w1c!($vis, $bit, $method, $name); +macro_rules! rw_bit { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $self_, $from;$bit, $method, $name); + bit_raiser!($vis, $self_, $from;$bit, $method, $name); + bit_clearer!($vis, $self_, $from;$bit, $method, $name); }; } -macro_rules! w1s_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - paste::paste! { - #[doc = "Sets the"] - #[doc = $name] - #[doc = "bit."] - $vis fn [](&mut self)->&mut Self{ - use bit_field::BitField; - self.0[$offset].set_bit($bit,true); - self - } - } - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - paste::paste! { - #[doc = "Sets the"] - #[doc = $name] - #[doc = "bit."] - $vis fn [](&mut self)->&mut Self{ - use bit_field::BitField; - self.0.set_bit($bit,true); - self - } - } +macro_rules! rw1s_bit { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $self_, $from;$bit, $method, $name); + bit_raiser!($vis, $self_, $from;$bit, $method, $name); }; } -macro_rules! rw1s_bit { - ($vis:vis,[$offset:literal]($bit:literal),$method:ident,$name:literal) => { - bit_getter!($vis, [$offset]($bit), $method, $name); - w1s_bit!($vis, [$offset]($bit), $method, $name); - }; - ($vis:vis,$bit:literal,$method:ident,$name:literal) => { - bit_getter!($vis, $bit, $method, $name); - w1s_bit!($vis, $bit, $method, $name); +macro_rules! rw1c_bit { + ($vis:vis,$self_:ident,$from:expr;$bit:literal,$method:ident,$name:literal) => { + bit_getter!($vis, $self_, $from;$bit, $method, $name); + bit_modifier_w1c!($vis, $self_, $from;$bit, $method, $name); }; } macro_rules! field_getter { - ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { + ($vis:vis,$self_:ident,$from:expr;$range:expr,$method:ident,$name:literal,$ty:ty) => { #[doc = "Returns the value of the"] #[doc = $name] #[doc = "field."] #[must_use] - $vis fn $method(&self) -> $ty { + $vis fn $method(&$self_) -> $ty { use bit_field::BitField; use core::convert::TryInto; - self.0[$offset].get_bits($range).try_into().unwrap() + $from.get_bits($range).try_into().unwrap() } }; - ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { - #[doc = "Returns the value of the"] - #[doc = $name] - #[doc = "field."] - #[must_use] - $vis fn $method(&self) -> $ty { - use bit_field::BitField; - use core::convert::TryInto; - self.0.get_bits($range).try_into().unwrap() - } - }; - ($vis:vis,$range:expr,$name:literal,$ty:ty) => { - #[doc = "Returns the value of the"] - #[doc = $name] - #[doc = "field."] - #[must_use] - $vis fn get(&self) -> $ty { - use bit_field::BitField; - use core::convert::TryInto; - self.0.get_bits($range).try_into().unwrap() - } - }; - ($vis:vis,[]{$start:literal},$method:ident,$name:literal,$ty:ty) => { +} + +macro_rules! zero_trailing_getter { + ($vis:vis,$self_:ident,$from:expr;$start:literal~,$method:ident,$name:literal,$ty:ty) => { #[doc = "Returns the value of the"] #[doc = $name] #[doc = "field."] #[must_use] - $vis fn $method(&self) -> $ty { - // use bit_field::BitField; + $vis fn $method(&$self_) -> $ty { use core::convert::TryInto; - (self.0 >> $start << $start).try_into().unwrap() + ($from >> $start << $start).try_into().unwrap() } }; - ($vis:vis,[]{$start:literal},$name:literal,$ty:ty) => { - #[doc = "Returns the value of the"] - #[doc = $name] - #[doc = "field."] - #[must_use] - $vis fn get(&self) -> $ty { - // use bit_field::BitField; - use core::convert::TryInto; - (self.0 >> $start << $start).try_into().unwrap() - } - } } macro_rules! field_setter { - ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { + ($vis:vis,$self_:ident,$from:expr;$range:expr,$method:ident,$name:literal,$ty:ty) => { paste::paste! { #[doc = "Sets the value of the"] #[doc = $name] #[doc = "field."] - $vis fn [](&mut self,value:$ty) -> &mut Self { + $vis fn $method(&mut $self_,value:$ty) -> &mut Self { use bit_field::BitField; use core::convert::TryInto; - self.0[$offset].set_bits($range,value.try_into().unwrap()); - self + $from.set_bits($range,value.try_into().unwrap()); + $self_ } } }; - ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { - paste::paste! { - #[doc = "Sets the value of the"] - #[doc = $name] - #[doc = "field."] - $vis fn [](&mut self,value:$ty) -> &mut Self { - use bit_field::BitField; - use core::convert::TryInto; - self.0.set_bits($range,value.try_into().unwrap()); - self - } - } - }; - ($vis:vis,$range:expr,$name:literal,$ty:ty) => { - paste::paste! { - #[doc = "Sets the value of the"] - #[doc = $name] - #[doc = "field."] - $vis fn set(&mut self,value:$ty) -> &mut Self { - use bit_field::BitField; - use core::convert::TryInto; - self.0.set_bits($range,value.try_into().unwrap()); - self - } - } - }; - ($vis:vis,[]{$start:literal,$expect:literal},$method:ident,$name:literal,$ty:ty) => { - paste::paste! { - #[doc = "Sets the value of the"] - #[doc = $name] - #[doc = "field."] - #[doc = "\n\n# Panics \n\n"] - #[doc = "This method panics if the given value is not"] - #[doc = $expect] - #[doc = "."] - $vis fn [](&mut self,value:$ty) -> &mut Self { - use bit_field::BitField; - - assert!(value.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); +} - self.0.set_bits($start.., value.get_bits($start..)); - self - } - } - }; - ($vis:vis,[]{$start:literal,$expect:literal},$name:literal,$ty:ty) => { +macro_rules! zero_trailing_setter { + ($vis:vis,$self_:ident,$from:expr;$start:literal~;$expect:literal,$method:ident,$name:literal,$ty:ty) => { paste::paste! { #[doc = "Sets the value of the"] #[doc = $name] @@ -329,80 +173,77 @@ macro_rules! field_setter { #[doc = "This method panics if the given value is not"] #[doc = $expect] #[doc = "."] - $vis fn set(&mut self,value:$ty) -> &mut Self { + $vis fn set(&mut $self_,value:$ty) -> &mut Self { use bit_field::BitField; assert!(value.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); - self.0.set_bits($start.., value.get_bits($start..)); - self + $from.set_bits($start.., value.get_bits($start..)); + $self_ } } }; } macro_rules! ro_field { - ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { - field_getter!($vis, [$offset]($range), $method, $name, $ty); - }; - ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { - field_getter!($vis, $range, $method, $name, $ty); - }; - ($vis:vis,$range:expr,$name:literal,$ty:ty) => { - field_getter!($vis, $range, $name, $ty); + ($vis:vis,$self_:ident,$from:expr;$range:expr,$method:ident,$name:literal,$ty:ty) => { + field_getter!($vis, $self_, $from;$range, $method, $name, $ty); }; - ($vis:vis,[]{$start:literal},$method:ident,$name:literal,$ty:ty) => { - field_getter!($vis, []{$start}, $method, $name, $ty); - }; - ($vis:vis,[]{$start:literal},$name:literal,$ty:ty) => { - field_getter!($vis, []{$start}, $name, $ty); + ($vis:vis,$self_:ident,$from:expr,$range:expr,$name:literal,$ty:ty) => { + field_getter!($vis, $self_, $from;$range, get, $name, $ty); }; } macro_rules! rw_field { - ($vis:vis,[$offset:literal]($range:expr),$method:ident,$name:literal,$ty:ty) => { - field_getter!($vis, [$offset]($range), $method, $name, $ty); - field_setter!($vis, [$offset]($range), $method, $name, $ty); - }; - ($vis:vis,$range:expr,$method:ident,$name:literal,$ty:ty) => { - field_getter!($vis, $range, $method, $name, $ty); - field_setter!($vis, $range, $method, $name, $ty); + ($vis:vis,$self_:ident,$from:expr;$range:expr,$method:ident,$name:literal,$ty:ty) => { + paste::paste!{ + field_getter!($vis, $self_, $from;$range, $method, $name, $ty); + field_setter!($vis, $self_, $from;$range, [], $name, $ty); + } }; - ($vis:vis,$range:expr,$name:literal,$ty:ty) => { - field_getter!($vis, $range, $name, $ty); - field_setter!($vis, $range, $name, $ty); + ($vis:vis,$self_:ident,$from:expr;$range:expr,$name:literal,$ty:ty) => { + field_getter!($vis, $self_, $from;$range, get, $name, $ty); + field_setter!($vis, $self_, $from;$range, set, $name, $ty); }; - ($vis:vis,[]{$start:literal,$expect:literal},$method:ident,$name:literal,$ty:ty) => { - field_getter!($vis, []{$start}, $method, $name, $ty); - field_setter!($vis, []{$start, $expect}, $method, $name, $ty); +} + +macro_rules! rw_zero_trailing { + ($vis:vis,$self_:ident,$from:expr;$start:literal~;$expect:literal,$method:ident,$name:literal,$ty:ty) => { + paste::paste!{ + zero_trailing_getter!($vis, $self_, $from;$start~, $method, $name, $ty); + zero_trailing_setter!($vis, $self_, $from;$start~;$expect, [], $name, $ty); + } }; - ($vis:vis,[]{$start:literal,$expect:literal},$name:literal,$ty:ty) => { - field_getter!($vis, []{$start}, $name, $ty); - field_setter!($vis, []{$start, $expect}, $name, $ty); + ($vis:vis,$self_:ident,$from:expr;$start:literal~;$expect:literal,$name:literal,$ty:ty) => { + zero_trailing_getter!($vis, $self_, $from;$start~, get, $name, $ty); + zero_trailing_setter!($vis, $self_, $from;$start~;$expect, set, $name, $ty); }; } macro_rules! double_field_getter { - ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { #[doc = "Returns the value of the"] #[doc = $name] #[doc = "field."] #[must_use] - $vis fn $method(&self) -> $ty { - let lo = self.0[$off_lo] as $ty; - let hi = self.0[$off_hi] as $ty; + $vis fn $method(&$self_) -> $ty { + let lo = $arr[$off_lo] as $ty; + let hi = $arr[$off_hi] as $ty; (hi << $bits) | lo } }; - ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { +} + +macro_rules! double_zero_trailing_getter { + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal];$start:literal~,$method:ident,$name:literal,$bits:literal,$ty:ty) => { #[doc = "Returns the value of the"] #[doc = $name] #[doc = "field."] #[must_use] - $vis fn $method(&self) -> $ty { - let lo = (self.0[$off_lo] as $ty) >> $start << $start; - let hi = self.0[$off_hi] as $ty; + $vis fn $method(&$self_) -> $ty { + let lo = ($arr[$off_lo] as $ty) >> $start << $start; + let hi = $arr[$off_hi] as $ty; (hi << $bits) | lo } @@ -410,69 +251,79 @@ macro_rules! double_field_getter { } macro_rules! double_field_setter { - ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { - paste::paste! { - #[doc = "Sets the value of the"] - #[doc = $name] - #[doc = "field."] - $vis fn [](&mut self, value: $ty) -> &mut Self { - use bit_field::BitField; - use core::convert::TryInto; + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + #[doc = "Sets the value of the"] + #[doc = $name] + #[doc = "field."] + $vis fn $method(&mut $self_, value: $ty) -> &mut Self { + use bit_field::BitField; + use core::convert::TryInto; - let lo = value.get_bits(..$bits); - let hi = value.get_bits($bits..); + let lo = value.get_bits(..$bits); + let hi = value.get_bits($bits..); - self.0[$off_lo] = lo.try_into().unwrap(); - self.0[$off_hi] = hi.try_into().unwrap(); - self - } + $arr[$off_lo] = lo.try_into().unwrap(); + $arr[$off_hi] = hi.try_into().unwrap(); + $self_ } }; - ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal,$expect:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { - paste::paste! { - #[doc = "Sets the value of the"] - #[doc = $name] - #[doc = "field."] - #[doc = "\n\n# Panics \n\n"] - #[doc = "This method panics if the given value is not"] - #[doc = $expect] - #[doc = "."] - $vis fn [](&mut self, value: $ty) -> &mut Self { - use bit_field::BitField; - use core::convert::TryInto; +} + +macro_rules! double_zero_trailing_setter { + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal];$start:literal~;$expect:literal,$method:ident,$name:literal,$bits:literal,$ty:ty) => { + #[doc = "Sets the value of the"] + #[doc = $name] + #[doc = "field."] + #[doc = "\n\n# Panics \n\n"] + #[doc = "This method panics if the given value is not"] + #[doc = $expect] + #[doc = "."] + $vis fn $method(&mut $self_, value: $ty) -> &mut Self { + use bit_field::BitField; + use core::convert::TryInto; - let lo = value.get_bits(..$bits); - let hi = value.get_bits($bits..); + let lo = value.get_bits(..$bits); + let hi = value.get_bits($bits..); - assert!(lo.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); + assert!(lo.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); - self.0[$off_lo].set_bits( - $start.., - lo.get_bits($start..).try_into().unwrap() - ); - self.0[$off_hi] = hi.try_into().unwrap(); - self - } + $arr[$off_lo].set_bits( + $start.., + lo.get_bits($start..).try_into().unwrap() + ); + $arr[$off_hi] = hi.try_into().unwrap(); + $self_ } }; } macro_rules! ro_double_field { - ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { - double_field_getter!($vis, [$off_lo, $off_hi], $method, $name, $bits, $ty); + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + double_field_getter!($vis, $self_, $arr; [$off_lo, $off_hi], $method, $name, $bits, $ty); }; - ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { - double_field_getter!($vis, [$off_lo, $off_hi]{$start}, $method, $name, $bits, $ty); + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal],$name:literal,$bits:literal,$ty:ty) => { + double_field_getter!($vis, $self_, $arr; [$off_lo, $off_hi], get, $name, $bits, $ty); }; } macro_rules! rw_double_field { - ($vis:vis,[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { - double_field_getter!($vis, [$off_lo, $off_hi], $method, $name, $bits, $ty); - double_field_setter!($vis, [$off_lo, $off_hi], $method, $name, $bits, $ty); + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal],$method:ident,$name:literal,$bits:literal,$ty:ty) => { + paste::paste! { + double_field_getter!($vis, $self_, $arr; [$off_lo, $off_hi], $method, $name, $bits, $ty); + double_field_setter!($vis, $self_, $arr; [$off_lo, $off_hi], [], $name, $bits, $ty); + } }; - ($vis:vis,[$off_lo:literal,$off_hi:literal]{$start:literal,$expect:literal},$method:ident,$name:literal,$bits:literal,$ty:ty) => { - double_field_getter!($vis, [$off_lo, $off_hi]{$start}, $method, $name, $bits, $ty); - double_field_setter!($vis, [$off_lo, $off_hi]{$start, $expect}, $method, $name, $bits, $ty); + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal],$name:literal,$bits:literal,$ty:ty) => { + double_field_getter!($vis, $self_, $arr; [$off_lo, $off_hi], get, $name, $bits, $ty); + double_field_setter!($vis, $self_, $arr; [$off_lo, $off_hi], set, $name, $bits, $ty); + }; +} + +macro_rules! rw_double_zero_trailing { + ($vis:vis,$self_:ident,$arr:expr;[$off_lo:literal,$off_hi:literal];$start:literal~;$expect:literal,$method:ident,$name:literal,$bits:literal,$ty:ty) => { + paste::paste! { + double_zero_trailing_getter!($vis, $self_, $arr; [$off_lo, $off_hi]; $start~, $method, $name, $bits, $ty); + double_zero_trailing_setter!($vis, $self_, $arr; [$off_lo, $off_hi]; $start~; $expect, [], $name, $bits, $ty); + } }; } \ No newline at end of file diff --git a/src/registers/capability.rs b/src/registers/capability.rs index cc3b1fa..af74ca2 100644 --- a/src/registers/capability.rs +++ b/src/registers/capability.rs @@ -2,7 +2,7 @@ use accessor::single; use accessor::Mapper; -use bit_field::BitField; +// use bit_field::BitField; /// Host Controller Capability Registers #[derive(Debug)] @@ -105,9 +105,9 @@ impl InterfaceVersionNumber { #[derive(Copy, Clone)] pub struct StructuralParameters1(u32); impl StructuralParameters1 { - ro_field!(pub, 0..=7, number_of_device_slots, "Number of Device Slots", u8); - ro_field!(pub, 8..=18, number_of_interrupts, "Number of Interrupts", u16); - ro_field!(pub, 24..=31, number_of_ports, "Number of Ports", u8); + ro_field!(pub, self, self.0; 0..=7, number_of_device_slots, "Number of Device Slots", u8); + ro_field!(pub, self, self.0; 8..=18, number_of_interrupts, "Number of Interrupts", u16); + ro_field!(pub, self, self.0; 24..=31, number_of_ports, "Number of Ports", u8); } impl_debug_from_methods! { StructuralParameters1{ @@ -122,12 +122,18 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct StructuralParameters2(u32); impl StructuralParameters2 { - ro_field!(pub, - 0..=3, + ro_field!( + pub, self, + self.0; 0..=3, isochronous_scheduling_threshold, "Isochronous Scheduling Threshold", u8 ); + ro_field!(pub(self), self, self.0; 4..=7, erst_max, "ERST Max", u32); + + ro_field!(pub(self), self, self.0; 21..=25, max_scratchpad_buffers_hi, "Max Scratchpad Buffers HI", u32); + ro_bit!(pub, self, self.0; 26, scratchpad_restore, "Scratchpad Restore"); + ro_field!(pub(self), self, self.0; 27..=31, max_scratchpad_buffers_lo, "Max Scratchpad Buffers LO", u32); /// Returns the maximum number of the elements the Event Ring Segment Table can contain. /// @@ -146,20 +152,6 @@ impl StructuralParameters2 { h << 5 | l } - - ro_bit!(pub, 26, scratchpad_restore, "Scratchpad Restore"); - - fn erst_max(self) -> u32 { - self.0.get_bits(4..=7) - } - - fn max_scratchpad_buffers_hi(self) -> u32 { - self.0.get_bits(21..=25) - } - - fn max_scratchpad_buffers_lo(self) -> u32 { - self.0.get_bits(27..=31) - } } impl_debug_from_methods! { StructuralParameters2{ @@ -175,9 +167,16 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct StructuralParameters3(u32); impl StructuralParameters3 { - ro_field!(pub, 0..=7, u1_device_exit_latency, "U1 Device Exit Latency", u8); - ro_field!(pub, - 16..=31, + ro_field!( + pub, self, + self.0; 0..=7, + u1_device_exit_latency, + "U1 Device Exit Latency", + u8 + ); + ro_field!( + pub, self, + self.0; 16..=31, u2_device_exit_latency, "U2 Device Exit Latency", u16 @@ -196,38 +195,43 @@ impl_debug_from_methods! { #[allow(clippy::module_name_repetitions)] pub struct CapabilityParameters1(u32); impl CapabilityParameters1 { - ro_bit!(pub, 0, addressing_capability, "64-bit Addressing Capability"); - ro_bit!(pub, 1, bw_negotiation_capability, "BW Negotiation Capability"); - ro_bit!(pub, 2, context_size, "Context Size"); - ro_bit!(pub, 3, port_power_control, "Port Power Control"); - ro_bit!(pub, 4, port_indicators, "Port Indicators"); - ro_bit!(pub, 5, light_hc_reset_capability, "Light HC Reset Capability"); - ro_bit!(pub, - 6, + ro_bit!(pub, self, self.0; 0, addressing_capability, "64-bit Addressing Capability"); + ro_bit!(pub, self, self.0; 1, bw_negotiation_capability, "BW Negotiation Capability"); + ro_bit!(pub, self, self.0; 2, context_size, "Context Size"); + ro_bit!(pub, self, self.0; 3, port_power_control, "Port Power Control"); + ro_bit!(pub, self, self.0; 4, port_indicators, "Port Indicators"); + ro_bit!(pub, self, self.0; 5, light_hc_reset_capability, "Light HC Reset Capability"); + ro_bit!( + pub, self, + self.0; 6, latency_tolerance_messaging_capability, "Latency Tolerance Messaging Capability" ); - ro_bit!(pub, 7, no_secondary_sid_support, "No Secondary SID Support"); - ro_bit!(pub, 8, parse_all_event_data, "Parse All Event Data"); - ro_bit!(pub, - 9, + ro_bit!(pub, self, self.0; 7, no_secondary_sid_support, "No Secondary SID Support"); + ro_bit!(pub, self, self.0; 8, parse_all_event_data, "Parse All Event Data"); + ro_bit!( + pub, self, + self.0; 9, stopped_short_packet_capability, "Stopped - Short Packet Capability" ); - ro_bit!(pub, 10, stopped_edtla_capability, "Stopped EDTLA Capability"); - ro_bit!(pub, - 11, + ro_bit!(pub, self, self.0; 10, stopped_edtla_capability, "Stopped EDTLA Capability"); + ro_bit!( + pub, self, + self.0; 11, contiguous_frame_id_capability, "Contiguous Frame ID Capability" ); - ro_field!(pub, - 12..=15, + ro_field!( + pub, self, + self.0; 12..=15, maximum_primary_stream_array_size, "Maximum Primary Stream Array Size", u8 ); - ro_field!(pub, - 16..=31, + ro_field!( + pub, self, + self.0; 16..=31, xhci_extended_capabilities_pointer, "xHCI Extended Capabilities Pointer", u16 @@ -282,45 +286,53 @@ impl RuntimeRegisterSpaceOffset { #[derive(Copy, Clone)] pub struct CapabilityParameters2(u32); impl CapabilityParameters2 { - ro_bit!(pub, 0, u3_entry_capability, "U3 Entry Capability"); - ro_bit!(pub, - 1, + ro_bit!(pub, self, self.0; 0, u3_entry_capability, "U3 Entry Capability"); + ro_bit!( + pub, self, + self.0; 1, configure_endpoint_command_max_exit_latency_too_large_capability, "Configure Endpoint Command Max Exit Latency Too Large Capability" ); - ro_bit!(pub, - 2, + ro_bit!( + pub, self, + self.0; 2, force_save_context_capability, "Force Save Context Capability" ); - ro_bit!(pub, - 3, + ro_bit!( + pub, self, + self.0; 3, compliance_transition_capability, "Compliance Transition Capability" ); - ro_bit!(pub, - 4, + ro_bit!( + pub, self, + self.0; 4, large_esit_payload_capability, "Large ESIT Payload Capability" ); - ro_bit!(pub, - 5, + ro_bit!( + pub, self, + self.0; 5, configuration_information_capability, "Configuration Information Capability" ); - ro_bit!(pub, 6, extended_tbc_capability, "Extended TBC Capability"); - ro_bit!(pub, - 7, + ro_bit!(pub, self, self.0; 6, extended_tbc_capability, "Extended TBC Capability"); + ro_bit!( + pub, self, + self.0; 7, extended_tbc_trb_status_capability, "Extended TBC TRB Status Capability" ); - ro_bit!(pub, - 8, + ro_bit!( + pub, self, + self.0; 8, get_set_extended_property_capability, "Get/Set Extended Property Capability" ); - ro_bit!(pub, - 9, + ro_bit!( + pub, self, + self.0; 9, virtualization_based_trusted_io_capability, "Virtualization Based Trusted I/O Capability" ); diff --git a/src/registers/doorbell.rs b/src/registers/doorbell.rs index f3bc52e..bdf73c7 100644 --- a/src/registers/doorbell.rs +++ b/src/registers/doorbell.rs @@ -45,8 +45,8 @@ impl Doorbell { ) } - rw_field!(pub, 0..=7, doorbell_target, "Doorbell Target", u8); - rw_field!(pub, 16..=31, doorbell_stream_id, "Doorbell Stream ID", u16); + rw_field!(pub, self, self.0; 0..=7, doorbell_target, "Doorbell Target", u8); + rw_field!(pub, self, self.0; 16..=31, doorbell_stream_id, "Doorbell Stream ID", u16); } impl fmt::Debug for Doorbell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/registers/operational.rs b/src/registers/operational.rs index 4bea0ff..be18dbe 100644 --- a/src/registers/operational.rs +++ b/src/registers/operational.rs @@ -77,27 +77,29 @@ where #[derive(Copy, Clone)] pub struct UsbCommandRegister(u32); impl UsbCommandRegister { - rw_bit!(pub, 0, run_stop, "Run/Stop"); - rw_bit!(pub, 1, host_controller_reset, "Host Controller Reset"); - rw_bit!(pub, 2, interrupter_enable, "Interrupter Enable"); - rw_bit!(pub, 3, host_system_error_enable, "Host System Error Enable"); - rw_bit!(pub, - 7, + rw_bit!(pub, self, self.0; 0, run_stop, "Run/Stop"); + rw_bit!(pub, self, self.0; 1, host_controller_reset, "Host Controller Reset"); + rw_bit!(pub, self, self.0; 2, interrupter_enable, "Interrupter Enable"); + rw_bit!(pub, self, self.0; 3, host_system_error_enable, "Host System Error Enable"); + rw_bit!( + pub, self, + self.0; 7, light_host_controller_reset, "Light Host Controller Reset" ); - rw_bit!(pub, 8, controller_save_state, "Controller Save State"); - rw_bit!(pub, 9, controller_restore_state, "Controller Restore State"); - rw_bit!(pub, 10, enable_wrap_event, "Enable Wrap Event"); - rw_bit!(pub, 11, enable_u3_mfindex_stop, "Enable U3 MFINDEX Stop"); - rw_bit!(pub, 13, cem_enable, "CEM Enable"); - ro_bit!(pub, 14, extended_tbc_enable, "Extended TBC Enable"); - ro_bit!(pub, - 15, + rw_bit!(pub, self, self.0; 8, controller_save_state, "Controller Save State"); + rw_bit!(pub, self, self.0; 9, controller_restore_state, "Controller Restore State"); + rw_bit!(pub, self, self.0; 10, enable_wrap_event, "Enable Wrap Event"); + rw_bit!(pub, self, self.0; 11, enable_u3_mfindex_stop, "Enable U3 MFINDEX Stop"); + rw_bit!(pub, self, self.0; 13, cem_enable, "CEM Enable"); + ro_bit!(pub, self, self.0; 14, extended_tbc_enable, "Extended TBC Enable"); + ro_bit!( + pub, self, + self.0; 15, extended_tbc_trb_status_enable, "Extended TBC TRB Status Enable" ); - rw_bit!(pub, 16, vtio_enable, "VTIO Enable"); + rw_bit!(pub, self, self.0; 16, vtio_enable, "VTIO Enable"); } impl_debug_from_methods! { UsbCommandRegister{ @@ -122,15 +124,15 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct UsbStatusRegister(u32); impl UsbStatusRegister { - ro_bit!(pub, 0, hc_halted, "HC Halted"); - rw1c_bit!(pub, 2, host_system_error, "Host System Error"); - rw1c_bit!(pub, 3, event_interrupt, "Event Interrupt"); - rw1c_bit!(pub, 4, port_change_detect, "Port Change Detect"); - ro_bit!(pub, 8, save_state_status, "Save State Status"); - ro_bit!(pub, 9, restore_state_status, "Restore State Status"); - rw1c_bit!(pub, 10, save_restore_error, "Save/Restore Error"); - ro_bit!(pub, 11, controller_not_ready, "Controller Not Ready"); - ro_bit!(pub, 12, host_controller_error, "Host Controller Error"); + ro_bit!(pub, self, self.0; 0, hc_halted, "HC Halted"); + rw1c_bit!(pub, self, self.0; 2, host_system_error, "Host System Error"); + rw1c_bit!(pub, self, self.0; 3, event_interrupt, "Event Interrupt"); + rw1c_bit!(pub, self, self.0; 4, port_change_detect, "Port Change Detect"); + ro_bit!(pub, self, self.0; 8, save_state_status, "Save State Status"); + ro_bit!(pub, self, self.0; 9, restore_state_status, "Restore State Status"); + rw1c_bit!(pub, self, self.0; 10, save_restore_error, "Save/Restore Error"); + ro_bit!(pub, self, self.0; 11, controller_not_ready, "Controller Not Ready"); + ro_bit!(pub, self, self.0; 12, host_controller_error, "Host Controller Error"); } impl_debug_from_methods! { UsbStatusRegister{ @@ -212,13 +214,13 @@ impl DeviceNotificationControl { #[derive(Copy, Clone)] pub struct CommandRingControlRegister(u64); impl CommandRingControlRegister { - wo_bit!(pub, 0, ring_cycle_state, "Ring Cycle State"); - w1s_bit!(pub, 1, command_stop, "Command Stop"); - w1s_bit!(pub, 2, command_abort, "Command Abort"); - ro_bit!(pub, 3, command_ring_running, "Command Ring Running"); - rw_field!( - pub, - []{6, "64-byte aligned"}, + wo_bit!(pub, self, self.0; 0, ring_cycle_state, "Ring Cycle State"); + w1s_bit!(pub, self, self.0; 1, command_stop, "Command Stop"); + w1s_bit!(pub, self, self.0; 2, command_abort, "Command Abort"); + ro_bit!(pub, self, self.0; 3, command_ring_running, "Command Ring Running"); + rw_zero_trailing!( + pub, self, + self.0; 6~; "64-byte aligned", command_ring_pointer, "Command Ring Pointer", u64 @@ -235,9 +237,9 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Debug, Default)] pub struct DeviceContextBaseAddressArrayPointerRegister(u64); impl DeviceContextBaseAddressArrayPointerRegister { - rw_field!( - pub, - []{6, "64-byte aligned"}, + rw_zero_trailing!( + pub, self, + self.0; 6~;"64-byte aligned", "Device Context Base Address Array Pointer", u64 ); @@ -248,15 +250,17 @@ impl DeviceContextBaseAddressArrayPointerRegister { #[derive(Copy, Clone)] pub struct ConfigureRegister(u32); impl ConfigureRegister { - rw_field!(pub, - 0..=7, + rw_field!( + pub, self, + self.0; 0..=7, max_device_slots_enabled, "Max Device Slots Enabled", u8 ); - rw_bit!(pub, 8, u3_entry_enable, "U3 Entry Enable"); - rw_bit!(pub, - 9, + rw_bit!(pub, self, self.0; 8, u3_entry_enable, "U3 Entry Enable"); + rw_bit!( + pub, self, + self.0; 9, configuration_information_enable, "Configuration Information Enable" ); @@ -320,45 +324,49 @@ impl PortRegisterSet { #[derive(Copy, Clone)] pub struct PortStatusAndControlRegister(u32); impl PortStatusAndControlRegister { - ro_bit!(pub, 0, current_connect_status, "Current Connect Status"); - rw1c_bit!(pub, 1, port_enabled_disabled, "Port Enabled/Disabled"); - ro_bit!(pub, 3, over_current_active, "Over-current Active"); - rw1s_bit!(pub, 4, port_reset, "Port Reset"); - rw_field!(pub, 5..=8, port_link_state, "Port Link State", u8); - rw_bit!(pub, 9, port_power, "Port Power"); - ro_field!(pub, 10..=13, port_speed, "Port Speed", u8); - rw_field!(pub, - 14..=15, + ro_bit!(pub, self, self.0; 0, current_connect_status, "Current Connect Status"); + rw1c_bit!(pub, self, self.0; 1, port_enabled_disabled, "Port Enabled/Disabled"); + ro_bit!(pub, self, self.0; 3, over_current_active, "Over-current Active"); + rw1s_bit!(pub, self, self.0; 4, port_reset, "Port Reset"); + rw_field!(pub, self, self.0; 5..=8, port_link_state, "Port Link State", u8); + rw_bit!(pub, self, self.0; 9, port_power, "Port Power"); + ro_field!(pub, self, self.0; 10..=13, port_speed, "Port Speed", u8); + rw_field!( + pub, self, + self.0; 14..=15, port_indicator_control, "Port Indicator Control", PortIndicator ); - rw_bit!(pub, - 16, + rw_bit!( + pub, self, + self.0; 16, port_link_state_write_strobe, "Port Link State Write Strobe" ); - rw1c_bit!(pub, 17, connect_status_change, "Connect Status Change"); - rw1c_bit!(pub, - 18, + rw1c_bit!(pub, self, self.0; 17, connect_status_change, "Connect Status Change"); + rw1c_bit!( + pub, self, + self.0; 18, port_enabled_disabled_change, "Port Enabled/Disabled Change" ); - rw1c_bit!(pub, 19, warm_port_reset_change, "Warm Port Reset Change"); - rw1c_bit!(pub, 20, over_current_change, "Over-Current Change"); - rw1c_bit!(pub, 21, port_reset_change, "Port Reset Change"); - rw1c_bit!(pub, 22, port_link_state_change, "Port Link State Change"); - rw1c_bit!(pub, 23, port_config_error_change, "Port Config Error Change"); - ro_bit!(pub, 24, cold_attach_status, "Cold Attach Status"); - rw_bit!(pub, 25, wake_on_connect_enable, "Wake on Connect Enable"); - rw_bit!(pub, 26, wake_on_disconnect_enable, "Wake on Disconnect Enable"); - rw_bit!(pub, - 27, + rw1c_bit!(pub, self, self.0; 19, warm_port_reset_change, "Warm Port Reset Change"); + rw1c_bit!(pub, self, self.0; 20, over_current_change, "Over-Current Change"); + rw1c_bit!(pub, self, self.0; 21, port_reset_change, "Port Reset Change"); + rw1c_bit!(pub, self, self.0; 22, port_link_state_change, "Port Link State Change"); + rw1c_bit!(pub, self, self.0; 23, port_config_error_change, "Port Config Error Change"); + ro_bit!(pub, self, self.0; 24, cold_attach_status, "Cold Attach Status"); + rw_bit!(pub, self, self.0; 25, wake_on_connect_enable, "Wake on Connect Enable"); + rw_bit!(pub, self, self.0; 26, wake_on_disconnect_enable, "Wake on Disconnect Enable"); + rw_bit!( + pub, self, + self.0; 27, wake_on_over_current_enable, "Wake on Over-Current Enable" ); - ro_bit!(pub, 30, device_removable, "Device Removable"); - rw1s_bit!(pub, 31, warm_port_reset, "Warm Port Reset"); + ro_bit!(pub, self, self.0; 30, device_removable, "Device Removable"); + rw1s_bit!(pub, self, self.0; 31, warm_port_reset, "Warm Port Reset"); } impl_debug_from_methods! { PortStatusAndControlRegister{ @@ -393,9 +401,9 @@ impl_debug_from_methods! { pub struct PortPowerManagementStatusAndControlRegister(u32); /// **These methods are only valid for USB3.** impl PortPowerManagementStatusAndControlRegister { - rw_field!(pub, 0..=7, u1_timeout, "U1 Timeout", u8); - rw_field!(pub, 8..=15, u2_timeout, "U2 Timeout", u8); - rw_bit!(pub, 16, force_link_pm_accept, "Force Link PM Accept"); + rw_field!(pub, self, self.0; 0..=7, u1_timeout, "U1 Timeout", u8); + rw_field!(pub, self, self.0; 8..=15, u2_timeout, "U2 Timeout", u8); + rw_bit!(pub, self, self.0; 16, force_link_pm_accept, "Force Link PM Accept"); } /// **These methods are only valid for USB2.** impl PortPowerManagementStatusAndControlRegister { @@ -408,15 +416,16 @@ impl PortPowerManagementStatusAndControlRegister { FromPrimitive::from_u32(s) } - rw_bit!(pub, 3, remote_wake_enable, "Remote Wake Enable"); - rw_field!(pub, - 4..=7, + rw_bit!(pub, self, self.0; 3, remote_wake_enable, "Remote Wake Enable"); + rw_field!( + pub, self, + self.0; 4..=7, best_effort_service_latency, "Best Effort Service Latency", u8 ); - rw_field!(pub, 8..=15, l1_device_slot, "L1 Device Slot", u8); - rw_bit!(pub, 16, hardware_lpm_enable, "Hardware LPM Enable"); + rw_field!(pub, self, self.0; 8..=15, l1_device_slot, "L1 Device Slot", u8); + rw_bit!(pub, self, self.0; 16, hardware_lpm_enable, "Hardware LPM Enable"); /// Returns the value of the Port Test Control field. /// @@ -454,9 +463,9 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PortLinkInfoRegister(u32); impl PortLinkInfoRegister { - rw_field!(pub, 0..=15, link_error_count, "Link Error Count", u16); - ro_field!(pub, 16..=19, rx_lane_count, "Rx Lane Count", u8); - ro_field!(pub, 20..=23, tx_lane_count, "Tx Lane Count", u8); + rw_field!(pub, self, self.0; 0..=15, link_error_count, "Link Error Count", u16); + ro_field!(pub, self, self.0; 16..=19, rx_lane_count, "Rx Lane Count", u8); + ro_field!(pub, self, self.0; 20..=23, tx_lane_count, "Tx Lane Count", u8); } impl_debug_from_methods! { PortLinkInfoRegister{ @@ -473,15 +482,17 @@ impl_debug_from_methods! { #[derive(Copy, Clone)] pub struct PortHardwareLpmControlRegister(u32); impl PortHardwareLpmControlRegister { - rw_field!(pub, - 0..=1, + rw_field!( + pub, self, + self.0; 0..=1, host_initiated_resume_duration_mode, "Host Initiated Resume Duration Mode", u8 ); - rw_field!(pub, 2..=9, l1_timeout, "L1 Timeout", u8); - rw_field!(pub, - 10..=13, + rw_field!(pub, self, self.0; 2..=9, l1_timeout, "L1 Timeout", u8); + rw_field!( + pub, self, + self.0; 10..=13, best_effort_service_latency_deep, "Best Effort Service Latency Depp", u8 diff --git a/src/registers/runtime.rs b/src/registers/runtime.rs index 4566ee6..1d9308d 100644 --- a/src/registers/runtime.rs +++ b/src/registers/runtime.rs @@ -8,7 +8,7 @@ use accessor::marker::Readable; use accessor::single; use accessor::Mapper; use core::convert::TryFrom; -use core::convert::TryInto; +// use core::convert::TryInto; use core::marker::PhantomData; /// Runtime Registers @@ -51,7 +51,7 @@ where #[derive(Copy, Clone)] pub struct MicroframeIndexRegister(u32); impl MicroframeIndexRegister { - ro_field!(pub, 0..=13, microframe_index, "Microframe Index", u16); + ro_field!(pub, self, self.0; 0..=13, microframe_index, "Microframe Index", u16); } impl_debug_from_methods! { MicroframeIndexRegister { @@ -166,8 +166,8 @@ where #[derive(Copy, Clone)] pub struct InterrupterManagementRegister(u32); impl InterrupterManagementRegister { - rw1c_bit!(pub, 0, interrupt_pending, "Interrupt Pending"); - rw_bit!(pub, 1, interrupt_enable, "Interrupt Enable"); + rw1c_bit!(pub, self, self.0; 0, interrupt_pending, "Interrupt Pending"); + rw_bit!(pub, self, self.0; 1, interrupt_enable, "Interrupt Enable"); } impl_debug_from_methods! { InterrupterManagementRegister { @@ -181,14 +181,16 @@ impl_debug_from_methods! { #[derive(Copy, Clone, Default)] pub struct InterrupterModerationRegister(u32); impl InterrupterModerationRegister { - rw_field!(pub, - 0..=15, + rw_field!( + pub, self, + self.0; 0..=15, interrupt_moderation_interval, "Interrupt Moderation Interval", u16 ); - rw_field!(pub, - 16..=31, + rw_field!( + pub, self, + self.0; 16..=31, interrupt_moderation_counter, "Interrupt Moderation Counter", u16 @@ -207,8 +209,8 @@ impl_debug_from_methods! { pub struct EventRingSegmentTableSizeRegister(u32); impl EventRingSegmentTableSizeRegister { rw_field!( - pub, - 0..=15, + pub, self, + self.0; 0..=15, "Event Ring Segment Table Size (the number of segments)", u16 ); @@ -219,9 +221,9 @@ impl EventRingSegmentTableSizeRegister { #[derive(Copy, Clone, Debug)] pub struct EventRingSegmentTableBaseAddressRegister(u64); impl EventRingSegmentTableBaseAddressRegister { - rw_field!( - pub, - []{6, "64-byte aligned"}, + rw_zero_trailing!( + pub, self, + self.0; 6~; "64-byte aligned", "Event Ring Segment Table Base Address", u64 ); @@ -232,17 +234,17 @@ impl EventRingSegmentTableBaseAddressRegister { #[derive(Copy, Clone, Default)] pub struct EventRingDequeuePointerRegister(u64); impl EventRingDequeuePointerRegister { - rw_field!(pub, - 0..=2, + rw_field!( + pub, self, + self.0; 0..=2, dequeue_erst_segment_index, "Dequeue ERST Segment Index", u8 ); - rw1c_bit!(pub, 3, event_handler_busy, "Event Handler Busy"); - - rw_field!( - pub, - []{4, "16-byte aligned"}, + rw1c_bit!(pub, self, self.0; 3, event_handler_busy, "Event Handler Busy"); + rw_zero_trailing!( + pub, self, + self.0; 4~; "16-byte aligned", event_ring_dequeue_pointer, "current Event Ring Dequeue Pointer", u64 diff --git a/src/ring/trb/command.rs b/src/ring/trb/command.rs index 0b82c6c..a9a0c29 100644 --- a/src/ring/trb/command.rs +++ b/src/ring/trb/command.rs @@ -93,7 +93,7 @@ reserved!(EnableSlot(Type::EnableSlot) { [3]21..=31; }); impl EnableSlot { - rw_field!(pub, [3](16..=20), slot_type, "Slot Type", u8); + rw_field!(pub, self, self.0[3]; 16..=20, slot_type, "Slot Type", u8); } impl_debug_for_trb!(EnableSlot { slot_type }); @@ -106,7 +106,7 @@ reserved!(DisableSlot(Type::DisableSlot) { [3]16..=23; }); impl DisableSlot { - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(DisableSlot { slot_id }); @@ -122,20 +122,20 @@ reserved!(AddressDevice(Type::AddressDevice) { [3]16..=23; }); impl AddressDevice { - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", input_context_pointer, "Input Context Pointer", 32, u64 ); rw_bit!( - pub, - [3](9), + pub, self, + self.0[3]; 9, block_set_address_request, "Block Set Address Request" ); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(AddressDevice { input_context_pointer, @@ -155,15 +155,15 @@ reserved!(ConfigureEndpoint(Type::ConfigureEndpoint) { [3]16..=23; }); impl ConfigureEndpoint { - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", input_context_pointer, "Input Context Pointer", 32, u64 ); - rw_bit!(pub, [3](9), deconfigure, "Deconfigure"); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_bit!(pub, self, self.0[3]; 9, deconfigure, "Deconfigure"); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(ConfigureEndpoint { input_context_pointer, @@ -183,14 +183,14 @@ reserved!(EvaluateContext(Type::EvaluateContext) { [3]16..=23; }); impl EvaluateContext { - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", input_context_pointer, "Input Context Pointer", 32, u64 ); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(EvaluateContext { input_context_pointer, @@ -210,9 +210,9 @@ reserved!(ResetEndpoint(Type::ResetEndpoint) { [3]21..=23; }); impl ResetEndpoint { - rw_bit!(pub, [3](9), transfer_state_preserve, "Transfer State Preserve"); - rw_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_bit!(pub, self, self.0[3]; 9, transfer_state_preserve, "Transfer State Preserve"); + rw_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(ResetEndpoint { transfer_state_preserve, @@ -233,9 +233,9 @@ reserved!(StopEndpoint(Type::StopEndpoint) { [3]21..=22; }); impl StopEndpoint { - rw_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); - rw_bit!(pub, [3](23), suspend, "Suspend"); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); + rw_bit!(pub, self, self.0[3]; 23, suspend, "Suspend"); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(StopEndpoint { endpoint_id, @@ -254,18 +254,18 @@ reserved!(SetTrDequeuePointer(Type::SetTrDequeuePointer) { [3]21..=23; }); impl SetTrDequeuePointer { - rw_bit!(pub, [0](0), dequeue_cycle_state, "Dequeue Cycle State"); - rw_field!(pub, [0](1..=3), stream_context_type, "Stream Context Type", u8); - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_bit!(pub, self, self.0[0]; 0, dequeue_cycle_state, "Dequeue Cycle State"); + rw_field!(pub, self, self.0[0]; 1..=3, stream_context_type, "Stream Context Type", u8); + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", new_tr_dequeue_pointer, "New TR Dequeue Pointer", 32, u64 ); - rw_field!(pub, [2](16..=31), stream_id, "Stream ID", u16); - rw_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[2]; 16..=31, stream_id, "Stream ID", u16); + rw_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(SetTrDequeuePointer { dequeue_cycle_state, @@ -285,7 +285,7 @@ reserved!(ResetDevice(Type::ResetDevice) { [3]16..=23; }); impl ResetDevice { - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(ResetDevice { slot_id }); @@ -297,20 +297,21 @@ reserved!(ForceEvent(Type::ForceEvent) { [3]24..=31; }); impl ForceEvent { - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", event_trb_pointer, "Event TRB Pointer", 32, u64 ); - rw_field!(pub, - [2](22..=31), + rw_field!( + pub, self, + self.0[2]; 22..=31, vf_interrupter_target, "VF Interrupter Target", u16 ); - rw_field!(pub, [3](16..=23), vf_id, "VF ID", u8); + rw_field!(pub, self, self.0[3]; 16..=23, vf_id, "VF ID", u8); } impl_debug_for_trb!(ForceEvent { event_trb_pointer, @@ -331,7 +332,7 @@ reserved!(NegotiateBandwidth(Type::NegotiateBandwidth) { [3]16..=23; }); impl NegotiateBandwidth { - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(NegotiateBandwidth { slot_id }); @@ -348,8 +349,9 @@ reserved!(SetLatencyToleranceValue(Type::SetLatencyToleranceValue) { [3]28..=31; }); impl SetLatencyToleranceValue { - rw_field!(pub, - [3](16..=27), + rw_field!( + pub, self, + self.0[3]; 16..=27, best_effort_latency_tolerance_value, "Best Effort Latency Tolerance Value", u16 @@ -371,15 +373,15 @@ reserved!(GetPortBandwidth(Type::GetPortBandwidth) { [3]20..=23; }); impl GetPortBandwidth { - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", port_bandwidth_context_pointer, "Port Bandwidth Context Pointer", 32, u64 ); - rw_field!(pub, [3](16..=19), dev_speed, "Dev Speed", u8); - rw_field!(pub, [3](24..=31), hub_slot_id, "Hub Slot ID", u8); + rw_field!(pub, self, self.0[3]; 16..=19, dev_speed, "Dev Speed", u8); + rw_field!(pub, self, self.0[3]; 24..=31, hub_slot_id, "Hub Slot ID", u8); } impl_debug_for_trb!(GetPortBandwidth { port_bandwidth_context_pointer, @@ -393,7 +395,7 @@ reserved!(ForceHeader(Type::ForceHeader) { [3]16..=23; }); impl ForceHeader { - rw_field!(pub, [0](0..=4), packet_type, "Packet Type", u8); + rw_field!(pub, self, self.0[0]; 0..=4, packet_type, "Packet Type", u8); /// Sets the value of the Header Info field. /// @@ -418,8 +420,9 @@ impl ForceHeader { [self.0[0] & 0xffff_ffe0, self.0[1], self.0[2]] } - rw_field!(pub, - [3](24..=31), + rw_field!( + pub, self, + self.0[3]; 24..=31, root_hub_port_number, "Root Hub Port Number", u8 @@ -442,22 +445,23 @@ reserved!(GetExtendedProperty(Type::GetExtendedProperty) { [3]1..=9; }); impl GetExtendedProperty { - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", extended_property_context_pointer, "Extended Property Context Pointer", 32, u64 ); - rw_field!(pub, - [2](0..=15), + rw_field!( + pub, self, + self.0[2]; 0..=15, extended_capability_identifier, "Extended Capability Identifier", u16 ); - rw_field!(pub, [3](16..=18), command_sub_type, "Command Sub Type", u8); - rw_field!(pub, [3](19..=23), endpoint_id, "Endpoint ID", u8); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 16..=18, command_sub_type, "Command Sub Type", u8); + rw_field!(pub, self, self.0[3]; 19..=23, endpoint_id, "Endpoint ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(GetExtendedProperty { extended_property_context_pointer, @@ -479,21 +483,23 @@ reserved!(SetExtendedProperty(Type::SetExtendedProperty) { [3]1..=9; }); impl SetExtendedProperty { - rw_field!(pub, - [2](0..=15), + rw_field!( + pub, self, + self.0[2]; 0..=15, extended_capability_identifier, "Extended Cpaability Identifier", u16 ); - rw_field!(pub, - [2](16..=23), + rw_field!( + pub, self, + self.0[2]; 16..=23, capability_parameter, "Capability Parameter", u8 ); - rw_field!(pub, [3](16..=18), command_sub_type, "Command Sub Type", u8); - rw_field!(pub, [3](19..=23), endpoint_id, "Endpoint ID", u8); - rw_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + rw_field!(pub, self, self.0[3]; 16..=18, command_sub_type, "Command Sub Type", u8); + rw_field!(pub, self, self.0[3]; 19..=23, endpoint_id, "Endpoint ID", u8); + rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_trb!(SetExtendedProperty { extended_capability_identifier, diff --git a/src/ring/trb/event.rs b/src/ring/trb/event.rs index 1bba25b..2c2dec4 100644 --- a/src/ring/trb/event.rs +++ b/src/ring/trb/event.rs @@ -97,7 +97,7 @@ reserved!(PortStatusChange(Type::PortStatusChange){ [3]16..=31; }); impl PortStatusChange { - ro_field!(pub, [0](24..=31), port_id, "Port ID", u8); + ro_field!(pub, self, self.0[0]; 24..=31, port_id, "Port ID", u8); } impl_debug_for_event_trb!(PortStatusChange { port_id }); @@ -108,11 +108,11 @@ reserved!(TransferEvent(Type::TransferEvent){ [3]21..=23; }); impl TransferEvent { - ro_double_field!(pub, [0, 1], trb_pointer, "TRB Pointer", 32, u64); - ro_field!(pub, [2](0..=23), trb_transfer_length, "TRB Transfer Length", u32); - ro_bit!(pub, [3](2), event_data, "Event Data"); - ro_field!(pub, [3](16..=20), endpoint_id, "Endpoint ID", u8); - ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + ro_double_field!(pub, self, self.0; [0, 1], trb_pointer, "TRB Pointer", 32, u64); + ro_field!(pub, self, self.0[2]; 0..=23, trb_transfer_length, "TRB Transfer Length", u32); + ro_bit!(pub, self, self.0[3]; 2, event_data, "Event Data"); + ro_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); + ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(TransferEvent { trb_pointer, @@ -133,20 +133,21 @@ reserved!(CommandCompletion(Type::CommandCompletion){ }); impl CommandCompletion { ro_double_field!( - pub, - [0, 1], + pub, self, + self.0; [0, 1], command_trb_pointer, "Command TRB Pointer", 32, u64 ); - ro_field!(pub, - [2](0..=23), + ro_field!( + pub, self, + self.0[2]; 0..=23, command_completion_parameter, "Command Completion Parameter", u32 ); - ro_field!(pub, [3](16..=23), vf_id, "VF ID", u8); - ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, self, self.0[3]; 16..=23, vf_id, "VF ID", u8); + ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(CommandCompletion { command_trb_pointer, @@ -168,7 +169,7 @@ reserved!(BandwidthRequest(Type::BandwidthRequest){ [3]16..=23; }); impl BandwidthRequest { - ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(BandwidthRequest { slot_id }); @@ -180,9 +181,9 @@ reserved!(Doorbell(Type::Doorbell){ [3]1..=9; }); impl Doorbell { - ro_field!(pub, [0](0..=4), db_reason, "DB Reason", u8); - ro_field!(pub, [3](16..=23), vf_id, "VF ID", u8); - ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, self, self.0[0]; 0..=4, db_reason, "DB Reason", u8); + ro_field!(pub, self, self.0[3]; 24..=31, vf_id, "VF ID", u8); + ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(Doorbell { db_reason, @@ -217,10 +218,10 @@ reserved!(DeviceNotification(Type::DeviceNotification){ [3]16..=31; }); impl DeviceNotification { - ro_field!(pub, [0](4..=7), notification_type, "Notification Type", u8); + ro_field!(pub, self, self.0[0]; 4..=7, notification_type, "Notification Type", u8); ro_double_field!( - pub(self), - [0, 1]{8}, + pub(self), self, + self.0; [0, 1], device_notification_data_raw, "Device Notification Data Raw", 32, u64 @@ -232,7 +233,7 @@ impl DeviceNotification { self.device_notification_data_raw() >> 8 } - ro_field!(pub, [3](24..=31), slot_id, "Slot ID", u8); + ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(DeviceNotification { notification_type, diff --git a/src/ring/trb/mod.rs b/src/ring/trb/mod.rs index 49b5568..250207c 100644 --- a/src/ring/trb/mod.rs +++ b/src/ring/trb/mod.rs @@ -57,7 +57,7 @@ macro_rules! add_trb { self.0 } - rw_bit!(pub, [3](0), cycle_bit, "Cycle bit"); + rw_bit!(pub, self, self.0[3]; 0, cycle_bit, "Cycle bit"); fn set_trb_type(&mut self) -> &mut Self { use crate::ring::trb::Type; @@ -201,17 +201,17 @@ reserved!(Link(Type::Link){ [3]16..=31; }); impl Link { - rw_double_field!( - pub, - [0, 1]{4, "16-byte aligned"}, + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 4~; "16-byte aligned", ring_segment_pointer, "Ring Segment Pointer", 32, u64 ); - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u32); - rw_bit!(pub, [3](1), toggle_cycle, "Toggle Cycle"); - rw_bit!(pub, [3](4), chain_bit, "Chain bit"); - rw_bit!(pub, [3](5), interrupt_on_completion, "Interrupt On Completion"); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u32); + rw_bit!(pub, self, self.0[3]; 1, toggle_cycle, "Toggle Cycle"); + rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); + rw_bit!(pub, self, self.0[3]; 5, interrupt_on_completion, "Interrupt On Completion"); } impl_debug_for_trb!(Link { ring_segment_pointer, diff --git a/src/ring/trb/transfer.rs b/src/ring/trb/transfer.rs index 4ad40d2..c71c930 100644 --- a/src/ring/trb/transfer.rs +++ b/src/ring/trb/transfer.rs @@ -2,7 +2,7 @@ use super::{Link, Type}; use bit_field::BitField; -use core::convert::TryInto; +// use core::convert::TryInto; use num_derive::FromPrimitive; use num_traits::FromPrimitive; @@ -123,7 +123,7 @@ impl TryFrom<[u32; 4]> for Allowed { macro_rules! interrupt_on_completion { ($name:ident) => { impl $name { - rw_bit!(pub, [3](5), interrupt_on_completion, "Interrupt On Completion"); + rw_bit!(pub, self, self.0[3]; 5, interrupt_on_completion, "Interrupt On Completion"); } }; } @@ -162,25 +162,26 @@ reserved!(Normal(Type::Normal) { }); impl Normal { rw_double_field!( - pub, - [0, 1], + pub, self, + self.0; [0, 1], data_buffer_pointer, "Data Buffer Pointer", 32, u64 ); - rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); - rw_field!(pub, [2](17..=21), td_size, "TD Size", u8); - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, - [3](2), + rw_field!(pub, self, self.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); + rw_field!(pub, self, self.0[2]; 17..=21, td_size, "TD Size", u8); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!( + pub, self, + self.0[3]; 2, interrupt_on_short_packet, "Interrupt-on Short Packet" ); - rw_bit!(pub, [3](3), no_snoop, "No Snoop"); - rw_bit!(pub, [3](4), chain_bit, "Chain bit"); - rw_bit!(pub, [3](6), immediate_data, "Immediate Data"); - rw_bit!(pub, [3](9), block_event_interrupt, "Block Event Interrupt"); + rw_bit!(pub, self, self.0[3]; 3, no_snoop, "No Snoop"); + rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); + rw_bit!(pub, self, self.0[3]; 6, immediate_data, "Immediate Data"); + rw_bit!(pub, self, self.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); } impl_debug_for_transfer_trb! { Normal { @@ -219,12 +220,12 @@ impl SetupStage { .set_trb_transfer_length() } - rw_field!(pub, [0](0..=7), request_type, "bmRequestType", u8); - rw_field!(pub, [0](8..=15), request, "bRequest", u8); - rw_field!(pub, [0](16..=31), value, "wValue", u16); - rw_field!(pub, [1](0..=15), index, "wIndex", u16); - rw_field!(pub, [1](16..=31), length, "wLength", u16); - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); + rw_field!(pub, self, self.0[0]; 0..=7, request_type, "bmRequestType", u8); + rw_field!(pub, self, self.0[0]; 8..=15, request, "bRequest", u8); + rw_field!(pub, self, self.0[0]; 16..=31, value, "wValue", u16); + rw_field!(pub, self, self.0[1]; 0..=15, index, "wIndex", u16); + rw_field!(pub, self, self.0[1]; 16..=31, length, "wLength", u16); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); /// Sets the value of the Transfer Type field. pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self { @@ -274,24 +275,25 @@ reserved!(DataStage(Type::DataStage) { }); impl DataStage { rw_double_field!( - pub, - [0, 1], + pub, self, + self.0; [0, 1], data_buffer_pointer, "Data Buffer Pointer", 32, u64 ); - rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); - rw_field!(pub, [2](17..=21), td_size, "TD Size", u8); - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, - [3](2), + rw_field!(pub, self, self.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); + rw_field!(pub, self, self.0[2]; 17..=21, td_size, "TD Size", u8); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!( + pub, self, + self.0[3]; 2, interrupt_on_short_packet, "Interrupt-on Short Packet" ); - rw_bit!(pub, [3](3), no_snoop, "No Snoop"); - rw_bit!(pub, [3](4), chain_bit, "Chain bit"); - rw_bit!(pub, [3](6), immediate_data, "Immediate Data"); + rw_bit!(pub, self, self.0[3]; 3, no_snoop, "No Snoop"); + rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); + rw_bit!(pub, self, self.0[3]; 6, immediate_data, "Immediate Data"); /// Sets the value of the Direction field. pub fn set_direction(&mut self, d: Direction) -> &mut Self { @@ -329,10 +331,10 @@ reserved!(StatusStage(Type::StatusStage) { [3]17..=31; }); impl StatusStage { - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, [3](4), chain_bit, "Chain bit"); - rw_bit!(pub, [3](16), direction, "Direction"); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); + rw_bit!(pub, self, self.0[3]; 16, direction, "Direction"); } impl_debug_for_transfer_trb! { StatusStage { @@ -348,34 +350,36 @@ transfer_trb_with_default!(Isoch, "Isoch TRB", Type::Isoch); reserved!(Isoch(Type::Isoch) {}); impl Isoch { rw_double_field!( - pub, - [0, 1], + pub, self, + self.0; [0, 1], data_buffer_pointer, "Data Buffer Pointer", 32, u64 ); - rw_field!(pub, [2](0..=16), trb_transfer_length, "TRB Transfer Length", u32); - rw_field!(pub, [2](17..=21), td_size_or_tbc, "TD Size/TBC", u8); - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, - [3](2), + rw_field!(pub, self, self.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); + rw_field!(pub, self, self.0[2]; 17..=21, td_size_or_tbc, "TD Size/TBC", u8); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!( + pub, self, + self.0[3]; 2, interrupt_on_short_packet, "Interrupt on Short Packet" ); - rw_bit!(pub, [3](3), no_snoop, "No Snoop"); - rw_bit!(pub, [3](4), chain_bit, "Chain bit"); - rw_bit!(pub, [3](6), immediate_data, "Immediate Data"); - rw_field!(pub, [3](7..=8), transfer_burst_count, "Transfer Burst Count", u8); - rw_bit!(pub, [3](9), block_event_interrupt, "Block Event Interrupt"); - rw_field!(pub, - [3](16..=19), + rw_bit!(pub, self, self.0[3]; 3, no_snoop, "No Snoop"); + rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); + rw_bit!(pub, self, self.0[3]; 6, immediate_data, "Immediate Data"); + rw_field!(pub, self, self.0[3]; 7..=8, transfer_burst_count, "Transfer Burst Count", u8); + rw_bit!(pub, self, self.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); + rw_field!( + pub, self, + self.0[3]; 16..=19, transfer_last_burst_packet_count, "Transfer Last Burst Packet Count", u8 ); - rw_field!(pub, [3](20..=30), frame_id, "Frame ID", u16); - rw_bit!(pub, [3](31), start_isoch_asap, "Start Isoch ASAP"); + rw_field!(pub, self, self.0[3]; 20..=30, frame_id, "Frame ID", u16); + rw_bit!(pub, self, self.0[3]; 31, start_isoch_asap, "Start Isoch ASAP"); } impl_debug_for_transfer_trb!(Isoch { data_buffer_pointer, @@ -403,16 +407,16 @@ reserved!(EventData(Type::EventData) { }); impl EventData { rw_double_field!( - pub, - [0, 1], + pub, self, + self.0; [0, 1], event_data, "Event Data", 32, u64 ); - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, [3](4), chain_bit, "Chain bit"); - rw_bit!(pub, [3](9), block_event_interrupt, "Block Event Interrupt"); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); + rw_bit!(pub, self, self.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); } impl_debug_for_transfer_trb!(EventData { event_data, @@ -432,9 +436,9 @@ reserved!(Noop(Type::NoopTransfer) { [3]16..=31; }); impl Noop { - rw_field!(pub, [2](22..=31), interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, [3](1), evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, [3](4), chain_bit, "Chain bit"); + rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); } impl_debug_for_transfer_trb!(Noop { interrupter_target, From b49e2e8e9121a7b629bbab0aa084d2ef9eb89b78 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Wed, 6 Dec 2023 14:54:15 +0000 Subject: [PATCH 08/17] error fix --- src/ring/trb/event.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ring/trb/event.rs b/src/ring/trb/event.rs index 2c2dec4..d8c5e92 100644 --- a/src/ring/trb/event.rs +++ b/src/ring/trb/event.rs @@ -182,7 +182,7 @@ reserved!(Doorbell(Type::Doorbell){ }); impl Doorbell { ro_field!(pub, self, self.0[0]; 0..=4, db_reason, "DB Reason", u8); - ro_field!(pub, self, self.0[3]; 24..=31, vf_id, "VF ID", u8); + ro_field!(pub, self, self.0[3]; 16..=23, vf_id, "VF ID", u8); ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); } impl_debug_for_event_trb!(Doorbell { @@ -211,11 +211,10 @@ event!( Type::DeviceNotification ); reserved!(DeviceNotification(Type::DeviceNotification){ - [0]0..=31; - [1]0..=31; + [0]0..=3; [2]0..=23; [3]1..=9; - [3]16..=31; + [3]16..=23; }); impl DeviceNotification { ro_field!(pub, self, self.0[0]; 4..=7, notification_type, "Notification Type", u8); @@ -243,10 +242,11 @@ impl_debug_for_event_trb!(DeviceNotification { event!(MfindexWrap, "MFINDEX Wrap Event TRB", Type::MfindexWrap); reserved!(MfindexWrap(Type::MfindexWrap){ - [0]0..=3; + [0]0..=31; + [1]0..=31; [2]0..=23; [3]1..=9; - [3]16..=23; + [3]16..=31; }); impl_debug_for_event_trb!(MfindexWrap {}); From 6a8e585c2b08c8f1a5b4e63e0a8c792ee0e71555 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Wed, 6 Dec 2023 16:15:22 +0000 Subject: [PATCH 09/17] add `ring::trb` replacement --- src/ring/block/command.rs | 433 +++++++++++++++++++++++++++++++++++++ src/ring/block/event.rs | 316 +++++++++++++++++++++++++++ src/ring/block/mod.rs | 173 +++++++++++++++ src/ring/block/transfer.rs | 384 ++++++++++++++++++++++++++++++++ src/ring/mod.rs | 3 + 5 files changed, 1309 insertions(+) create mode 100644 src/ring/block/command.rs create mode 100644 src/ring/block/event.rs create mode 100644 src/ring/block/mod.rs create mode 100644 src/ring/block/transfer.rs diff --git a/src/ring/block/command.rs b/src/ring/block/command.rs new file mode 100644 index 0000000..24b6181 --- /dev/null +++ b/src/ring/block/command.rs @@ -0,0 +1,433 @@ +//! Command TRBs. + +use bit_field::BitField; +// use core::convert::TryInto; +use num_derive::FromPrimitive; +use num_traits::FromPrimitive; + +macro_rules! impl_input_context_pointer { + () => { + param_align_16!(input_context_pointer, "Input Context Pointer"); + } +} + +macro_rules! impl_subtype { + () => { + rw_field!(pub, self, self.0.0[3]; 16..=18, command_sub_type, "Command Sub Type", u8); + } +} + +allowed_trb!("Command TRB", { + /// Link TRB + Link = 6, + /// Enable Slot Command TRB + EnableSlot = 9, + /// Disable Slot Command TRB + DisableSlot = 10, + /// Address Device Command TRB + AddressDevice = 11, + /// Configure Endpoint Command TRB + ConfigureEndpoint = 12, + /// Evaluate Context Command TRB + EvaluateContext = 13, + /// Reset Endpoint Command TRB + ResetEndpoint = 14, + /// Stop Endpoint Command TRB + StopEndpoint = 15, + /// Set TR Dequeue Pointer Command TRB + SetTrDequeuePointer = 16, + /// Reset Device Command TRB + ResetDevice = 17, + /// Force Event Command TRB + ForceEvent = 18, + /// Negotiate Bandwidth Command TRB + NegotiateBandwidth = 19, + /// Set Latency Tolerance Value Command TRB + SetLatencyToleranceValue = 20, + /// Get Port Bandwidth Command TRB + GetPortBandwidth = 21, + /// Force Header Command TRB + ForceHeader = 22, + /// NoOp Command TRB + NoOp = 23, + /// Get Extended Property Command TRB + GetExtendedProperty = 24, + /// Set Extended Property Command TRB + SetExtendedProperty = 25, +}); + +impl Link { + impl_ring_segment_pointer!(); + + // impl_interrupter_target!(); // ignored in command ring + + impl_tc!(); + // impl_ch!(); // ignored in command ring + impl_ioc!(); +} +rsvdz_checking_try_from!(Link { + [0];0..=3, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];16..=31, +}); +impl_debug_from_methods!(Link { + ring_segment_pointer, + // interrupter_target, + toggle_cycle, + // chain_bit, + interrupt_on_completion, +}); + +impl NoOp {} +rsvdz_checking_try_from!(NoOp { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=31, +}); +impl_debug_from_methods!(NoOp {}); + +impl EnableSlot { + rw_field!(pub, self, self.0.0[3]; 16..=20, slot_type, "Slot Type", u8); +} +impl_debug_from_methods!(EnableSlot { + slot_type, +}); +rsvdz_checking_try_from!(EnableSlot { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];21..=31, +}); + +impl DisableSlot { + impl_slot_id!(); +} +impl_debug_from_methods!(DisableSlot { + slot_id, +}); +rsvdz_checking_try_from!(DisableSlot { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=23, +}); + +impl AddressDevice { + impl_input_context_pointer!(); + + rw_bit!(pub, self, self.0.0[3]; 9, block_set_address_request, "Block Set Address Request"); + impl_slot_id!(); +} +impl_debug_from_methods!(AddressDevice { + input_context_pointer, + block_set_address_request, + slot_id, +}); +rsvdz_checking_try_from!(AddressDevice { + [0];0..=3, + [2];0..=31, + [3];1..=8, + [3];16..=23, +}); + +impl ConfigureEndpoint { + impl_input_context_pointer!(); + + rw_bit!(pub, self, self.0.0[3]; 9, deconfigure, "Deconfigure"); + impl_slot_id!(); +} +impl_debug_from_methods!(ConfigureEndpoint { + input_context_pointer, + deconfigure, + slot_id, +}); +rsvdz_checking_try_from!(ConfigureEndpoint { + [0];0..=3, + [2];0..=31, + [3];1..=8, + [3];16..=23, +}); + +impl EvaluateContext { + impl_input_context_pointer!(); + + // rw_bit!(pub, self, self.0.0[3]; 9, block_set_address_request, "Block Set Address Request"); // unused (no rsvdz) + impl_slot_id!(); +} +impl_debug_from_methods!(EvaluateContext { + input_context_pointer, + slot_id, +}); +rsvdz_checking_try_from!(EvaluateContext { + [0];0..=3, + [2];0..=31, + [3];1..=8, + [3];16..=23, +}); + +impl ResetEndpoint { + rw_bit!(pub, self, self.0.0[3]; 9, transfer_state_preserve, "Transfer State Preserve"); + impl_ep_id!(); + impl_slot_id!(); +} +impl_debug_from_methods!(ResetEndpoint { + transfer_state_preserve, + endpoint_id, + slot_id, +}); +rsvdz_checking_try_from!(ResetEndpoint { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=8, + [3];21..=23, +}); + +impl StopEndpoint { + impl_ep_id!(); + rw_bit!(pub, self, self.0.0[3]; 23, suspend, "Suspend"); + impl_slot_id!(); +} +impl_debug_from_methods!(StopEndpoint { + endpoint_id, + suspend, + slot_id, +}); +rsvdz_checking_try_from!(StopEndpoint { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];21..=22, +}); + +impl SetTrDequeuePointer { + rw_bit!(pub, self, self.0.0[0]; 0, dequeue_cycle_state, "Dequeue Cycle State"); + rw_field!(pub, self, self.0.0[0]; 1..=3, stream_context_type, "Stream Context Type", u8); + param_align_16!(new_tr_dequeue_pointer, "New TR Dequeue Pointer"); + rw_field!(pub, self, self.0.0[2]; 16..=31, stream_id, "Stream ID", u16); + + impl_ep_id!(); + impl_slot_id!(); +} +impl_debug_from_methods!(SetTrDequeuePointer { + dequeue_cycle_state, + stream_context_type, + new_tr_dequeue_pointer, + stream_id, + endpoint_id, + slot_id, +}); +rsvdz_checking_try_from!(SetTrDequeuePointer { + [2];0..=15, + [3];1..=9, + [3];21..=23, +}); + +impl ResetDevice { + impl_slot_id!(); +} +impl_debug_from_methods!(ResetDevice { + slot_id, +}); +rsvdz_checking_try_from!(ResetDevice { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=23, +}); + +impl ForceEvent { + param_align_16!(event_trb_pointer, "Event TRB Pointer"); + + rw_field!( + pub, self, + self.0.0[2]; 22..=31, + vf_interrupter_target, + "VF Interrupter Target", + u16 + ); + + impl_vf_id!(); +} +impl_debug_from_methods!(ForceEvent { + event_trb_pointer, + vf_interrupter_target, + vf_id +}); +rsvdz_checking_try_from!(ForceEvent { + [0];0..=3, + [2];0..=21, + [3];1..=9, + [3];24..=31, +}); + +impl NegotiateBandwidth { + impl_slot_id!(); +} +impl_debug_from_methods!(NegotiateBandwidth { + slot_id, +}); +rsvdz_checking_try_from!(NegotiateBandwidth { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=23, +}); + +impl SetLatencyToleranceValue { + rw_field!( + pub, self, + self.0.0[3]; 16..=27, + best_effort_latency_tolerance_value, + "Best Effort Latency Tolerance Value", + u16 + ); +} +impl_debug_from_methods!(SetLatencyToleranceValue { + best_effort_latency_tolerance_value, +}); +rsvdz_checking_try_from!(SetLatencyToleranceValue { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];28..=31, +}); + +impl GetPortBandwidth { + param_align_16!( + port_bandwidth_context_pointer, + "Port Bandwidth Context Pointer" + ); + + rw_field!(pub, self, self.0.0[3]; 16..=19, dev_speed, "Dev Speed", u8); + rw_field!(pub, self, self.0.0[3]; 24..=31, hub_slot_id, "Hub Slot ID", u8); +} +impl_debug_from_methods!(GetPortBandwidth { + port_bandwidth_context_pointer, + dev_speed, + hub_slot_id +}); +rsvdz_checking_try_from!(GetPortBandwidth { + [0];0..=3, + [2];0..=31, + [3];1..=9, + [3];20..=23, +}); + +impl ForceHeader { + rw_field!(pub, self, self.0.0[0]; 0..=4, packet_type, "Packet Type", u8); + + /// Sets the value of the Header Info field. + /// + /// # Panics + /// + /// This method panics if the lowest 5 bits of the `info[0]` are not 0. + pub fn set_header_info(&mut self, info: [u32; 3]) -> &mut Self { + assert!( + info[0].trailing_zeros() >= 5, + "The lowest 5 bits of the Header Info Low must be 0." + ); + + self.0.0[0].set_bits(5.., info[0].get_bits(5..)); + self.0.0[1] = info[1]; + self.0.0[2] = info[2]; + self + } + + /// Returns the value of the Header Info field. + #[must_use] + pub fn header_info(&self) -> [u32; 3] { + [self.0.0[0] >> 5 << 5, self.0.0[1], self.0.0[2]] + } + + rw_field!( + pub, self, + self.0.0[3]; 24..=31, + root_hub_port_number, + "Root Hub Port Number", + u8 + ); +} +impl_debug_from_methods!(ForceHeader { + packet_type, + header_info, + root_hub_port_number, +}); +rsvdz_checking_try_from!(ForceHeader { + [3];1..=9, + [3];16..=23, +}); + +impl GetExtendedProperty { + param_align_16!( + extended_property_context_pointer, + "Extended Property Context Pointer" + ); + + rw_field!( + pub, self, + self.0.0[2]; 0..=15, + extended_capability_identifier, + "Extended Capability Identifier", + u16 + ); + + impl_subtype!(); + impl_ep_id!(); + impl_slot_id!(); +} +impl_debug_from_methods!(GetExtendedProperty { + extended_property_context_pointer, + extended_capability_identifier, + command_sub_type, + endpoint_id, + slot_id, +}); +rsvdz_checking_try_from!(GetExtendedProperty { + [0];0..=3, + [2];16..=31, + [3];1..=9, +}); + +impl SetExtendedProperty { + rw_field!( + pub, self, + self.0.0[2]; 0..=15, + extended_capability_identifier, + "Extended Capability Identifier", + u16 + ); + rw_field!( + pub, self, + self.0.0[2]; 16..=23, + capability_parameter, + "Capability Parameter", + u8 + ); + + impl_subtype!(); + impl_ep_id!(); + impl_slot_id!(); +} +impl_debug_from_methods!(SetExtendedProperty { + extended_capability_identifier, + capability_parameter, + command_sub_type, + endpoint_id, + slot_id, +}); +rsvdz_checking_try_from!(SetExtendedProperty { + [0];0..=3, + [2];16..=31, + [3];1..=9, +}); \ No newline at end of file diff --git a/src/ring/block/event.rs b/src/ring/block/event.rs new file mode 100644 index 0000000..3fb3375 --- /dev/null +++ b/src/ring/block/event.rs @@ -0,0 +1,316 @@ +//! Event TRBs. + +use bit_field::BitField; +// use core::convert::TryInto; +use num_derive::FromPrimitive; +use num_traits::FromPrimitive; + +macro_rules! impl_cc { + (ro) => { + /// Returns the Completion Code. + /// + /// # Errors + /// + /// This method may return an [`Err`] variant with the Completion Code that is either reserved or + /// not implemented in this crate. + pub fn completion_code(&self) -> Result { + let c: u8 = self.0.0[2].get_bits(24..=31).try_into().unwrap(); + CompletionCode::from_u8(c).ok_or(c) + } + } +} + +allowed_trb!("Transfer TRB", { + /// Transfer Event TRB + TransferEvent = 32, + /// Command Completion Event TRB + CommandCompletion = 33, + /// Port Status Change Event TRB + PortStatusChange = 34, + /// Bandwidth Request Event TRB + BandwidthRequest = 35, + /// Doorbell Event TRB + Doorbell = 36, + /// Host Controller Event TRB + HostController = 37, + /// Device Notification Event TRB + DeviceNotification = 38, + /// MFINDEX Wrap Event TRB + MfindexWrap = 39, +}); + +impl TransferEvent { + ro_double_field!(pub, self, self.0.0; [0, 1], trb_pointer, "TRB Pointer (or event data)", 32, u64); + + ro_field!(pub, self, self.0.0[2]; 0..=23, trb_transfer_length, "TRB Transfer Length", u32); + impl_cc!(ro); + + ro_bit!(pub, self, self.0.0[3]; 2, event_data, "Event Data Flag"); + impl_ep_id!(ro); + impl_slot_id!(ro); +} +impl_debug_from_methods!(TransferEvent { + trb_pointer, + trb_transfer_length, + completion_code, + event_data, + endpoint_id, + slot_id, +}); +rsvdz_checking_try_from!(TransferEvent { + [3];1..=1, + [3];3..=9, + [3];21..=23, +}); + +impl CommandCompletion { + ro_double_field!( + pub, self, + self.0.0; [0, 1], + command_trb_pointer, + "Command TRB Pointer", + 32, u64 + ); + + ro_field!( + pub, self, + self.0.0[2]; 0..=23, + command_completion_parameter, + "Command Completion Parameter", + u32 + ); + impl_cc!(ro); + + impl_vf_id!(ro); + impl_slot_id!(ro); +} +impl_debug_from_methods!(CommandCompletion { + command_trb_pointer, + command_completion_parameter, + completion_code, + vf_id, + slot_id, +}); +rsvdz_checking_try_from!(CommandCompletion { + [0];0..=3, + [3];1..=9, +}); + +impl PortStatusChange { + ro_field!(pub, self, self.0.0[0]; 24..=31, port_id, "Port ID", u8); + + impl_cc!(ro); +} +impl_debug_from_methods!(PortStatusChange { + port_id, + completion_code, +}); +rsvdz_checking_try_from!(PortStatusChange { + [0];0..=23, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=31, +}); + +impl BandwidthRequest { + impl_cc!(ro); + + impl_slot_id!(ro); +} +impl_debug_from_methods!(BandwidthRequest { + completion_code, + slot_id, +}); +rsvdz_checking_try_from!(BandwidthRequest { + [0];0..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=23, +}); + +impl Doorbell { + ro_field!(pub, self, self.0.0[0]; 0..=4, db_reason, "DB Reason", u8); + + impl_cc!(ro); + + impl_vf_id!(ro); + impl_slot_id!(ro); +} +impl_debug_from_methods!(Doorbell { + db_reason, + completion_code, + vf_id, + slot_id, +}); +rsvdz_checking_try_from!(Doorbell { + [0];5..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, +}); + +impl HostController { + impl_cc!(ro); +} +impl_debug_from_methods!(HostController { + completion_code, +}); +rsvdz_checking_try_from!(HostController { + [0];0..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=31, +}); + +impl DeviceNotification { + ro_field!( + pub, self, + self.0.0[0]; 4..=7, + notification_type, + "Notification Type", + u8 + ); + ro_double_field!( + pub(self), self, + self.0.0; [0, 1], + device_notification_data_raw, + "Device Notification Data Raw", + 32, u64 + ); + /// Returns the value of the Device Notification Data field. + #[must_use] + pub fn device_notification_data(&self) -> u64 { + self.device_notification_data_raw() >> 8 + } + + impl_cc!(ro); + + impl_slot_id!(ro); +} +impl_debug_from_methods!(DeviceNotification { + notification_type, + device_notification_data, + completion_code, + slot_id, +}); +rsvdz_checking_try_from!(DeviceNotification { + [0];0..=3, + [2];0..=23, + [3];1..=9, + [3];16..=31, +}); + +impl MfindexWrap { + impl_cc!(ro); +} +impl_debug_from_methods!(MfindexWrap { + completion_code, +}); +rsvdz_checking_try_from!(MfindexWrap { + [0];0..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=31, +}); + + +/// The TRB Completion Codes. +/// +/// The description of each error is quoted from eXtensible Host Controller Interface for Universal +/// Serial Bus (xHCI) Requirements Specification May 2019 Revision 1.2, Section 6.4.5, Table 6-90. +/// Refer to this specification for more detail. +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] +pub enum CompletionCode { + /// Indicates that the Completion Code field has not been updated by the TRB producer. + Invalid = 0, + /// Indicates successful completion of the TRB operation. + Success = 1, + /// Indicates that the Host Controller is unable to keep up the reception of incoming data + /// (overrun) or is unable to supply data fast enough during transmission (underrun). + DataBufferError = 2, + /// Asserted when "babbling" is detected during the transaction generated by this TRB. + BabbleDetectedError = 3, + /// Asserted in the case where the host did not receive a valid response from the device. + UsbTransactionError = 4, + /// Asserted when a TRB parameter error condition is detected in a TRB. + TrbError = 5, + /// Asserted when a Stall condition is detected for a TRB. + StallError = 6, + /// Asserted by a Configure Endpoint Command or an Address Device Command if there are not + /// adequate xHC resources available to successfully complete the command. + ResourceError = 7, + /// Asserted by a Configure Endpoint Command if periodic endpoints are declared and the xHC is + /// not able to allocate the required Bandwidth. + BandwidthError = 8, + /// Asserted if a adding one more device would result in the host controller to exceed the + /// maximum Number of Device Slots for this implementation. + NoSlotsAvailableError = 9, + /// Asserted if an invalid Stream Context Type value is detected. + InvalidStreamTypeError = 10, + /// Asserted if a command is issued to a Device Slot that is in the Disabled state. + SlotNotEnabledError = 11, + /// Asserted if a doorbell is rung for an endpoint that is in the Disabled state. + EndpointNotEnabledError = 12, + /// Asserted if the number of bytes received was less than the TD Transfer Size. + ShortPacket = 13, + /// Asserted in a Transfer Event TRB if the Transfer Ring is empty when an enabled Isoch + /// endpoint is scheduled to transmit data. + RingUnderrun = 14, + /// Asserted in a Transfer Event TRB if the Transfer Ring is empty when an enabled Isoch + /// endpoint is scheduled to receive data. + RingOverrun = 15, + /// Asserted by a Force Event command if the target VF's Event Ring is full. + VfEventRingFullError = 16, + /// Asserted by a command if a Context parameter is invalid. + ParameterError = 17, + /// Asserted during an Isoch transfer if the TD exceeds the bandwidth allocated to the + /// endpoint. + BandwidthOverrunError = 18, + /// Asserted if a command is issued to transition from an illegal context state. + ContextStateError = 19, + /// Asserted if the xHC was unable to complete a periodic data transfer associated within the + /// ESIT, because it did not receive a PING_RESPONSE in time. + NoPingResponseError = 20, + /// Asserted if the Event Ring is full, the xHC is unable to post an Event to the ring. + EventRingFullError = 21, + /// Asserted if the xHC detects a problem with a device that does not allow it to be + /// successfully accessed. + IncompatibleDeviceError = 22, + /// Asserted if the xHC was unable to service a Isochronous endpoint within the Interval time. + MissedServiceError = 23, + /// Asserted in a Command Completion Event due to a Command Stop operation. + CommandRingStopped = 24, + /// Asserted in a Command Completion Event of an aborted command if the command was terminated + /// by a Command Abort (CA) operation. + CommandAborted = 25, + /// Asserted in a Transfer Event if the transfer was terminated by a Stop Endpoint Command. + Stopped = 26, + /// Asserted in a Transfer Event if the transfer was terminated by a Stop Endpoint Command and + /// the Transfer Event TRB Transfer Length field is invalid. + StoppedLengthInvalid = 27, + /// Asserted in a Transfer Event if the transfer was terminated by a Stop Endpoint Command, and + /// the transfer was stopped after Short Packet conditions were met, but before the end of the + /// TD was reached. + StoppedShortPacket = 28, + /// Asserted by the Evaluate Context Command if the proposed Max Exit Latency would not allow + /// the periodic endpoints of the Device Slot to be scheduled. + MaxExitLatencyTooLargeError = 29, + /// Asserted if the data buffer defined by an Isoch TD on an IN endpoint is less than the Max + /// ESIT Payload in size and the device attempts to send more data than it can hold. + IsochBufferOverrun = 31, + /// Asserted if the xHC internal event overrun condition. + EventLostError = 32, + /// May be reported by an event when other error codes do not apply. + UndefinedError = 33, + /// Asserted if an invalid Stream ID is received. + InvalidStreamIdError = 34, + /// Asserted by a Configure Endpoint Command if periodic endpoints are declared and the xHC is + /// not able to allocate the required Bandwidth due to a Secondary Bandwidth Domain. + SecondaryBandwidthError = 35, + /// Asserted if an error is detected on a USB2 protocol endpoint for a split transaction. + SplitTransactionError = 36, +} \ No newline at end of file diff --git a/src/ring/block/mod.rs b/src/ring/block/mod.rs new file mode 100644 index 0000000..6297cf3 --- /dev/null +++ b/src/ring/block/mod.rs @@ -0,0 +1,173 @@ +//! TRB (Transfer Request Block). + +/// The bytes of a TRB. +pub const BYTES: usize = 16; + +macro_rules! param_align_16 { + ($method:ident,$name:literal) => { + rw_double_zero_trailing!( + pub, self, + self.0.0; [0, 1]; 4~; "16-byte aligned", + $method, $name, 32, u64 + ); + } +} + +macro_rules! impl_ring_segment_pointer { + () => { + param_align_16!(ring_segment_pointer, "Ring Segment Pointer"); + } +} + +macro_rules! impl_tc { + () => { + rw_bit!(pub, self, self.0.0[3]; 1, toggle_cycle, "Toggle Cycle"); + } +} + +macro_rules! impl_ioc { + () => { + rw_bit!( + pub, self, + self.0.0[3]; 5, + interrupt_on_completion, + "Interrupt On Completion" + ); + } +} + +macro_rules! impl_ep_id { + () => { + rw_field!(pub, self, self.0.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); + }; + (ro) => { + ro_field!(pub, self, self.0.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); + }; +} + +macro_rules! impl_vf_id { + () => { + rw_field!(pub, self, self.0.0[3]; 16..=23, vf_id, "VF ID", u8); + }; + (ro) => { + ro_field!(pub, self, self.0.0[3]; 16..=23, vf_id, "VF ID", u8); + }; +} + +macro_rules! impl_slot_id { + () => { + rw_field!(pub, self, self.0.0[3]; 24..=31, slot_id, "Slot ID", u8); + }; + (ro) => { + ro_field!(pub, self, self.0.0[3]; 24..=31, slot_id, "Slot ID", u8); + }; +} + +macro_rules! allowed_trb { + ($name:literal, { + $($(#[$docs:meta])* $($deco:literal)? $variant:ident = $val:literal),+ $(,)? + }) => { + // defining AllowedType + paste::paste!( + #[doc = "Allowed TRB Type for " $name "."] + #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] + pub enum AllowedType { + $( + $(#[$docs])* + #[doc = ", " $val ""] + $variant = $val + ),+ + } + ); + + // defining common block + paste::paste!( + #[doc = "A raw " $name " Block."] + #[repr(transparent)] + #[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Hash)] + pub struct TRB(pub(crate) [u32; 4]); + impl TRB { + pub(crate) fn new(ty: AllowedType) -> Self { + *Self([0; 4]) + .set_trb_type(ty) + } + + pub(crate) fn trb_type(&self) -> Option { + AllowedType::from_u32(self.0[3].get_bits(10..=15)) + } + + fn set_trb_type(&mut self, ty: AllowedType) -> &mut Self { + self.0[3].set_bits(10..=15, ty as u32); + self + } + + rw_bit!(pub, self, self.0[3]; 0, cycle_bit, "Cycle"); + } + ); + + // defining individual TRB types + // all TRB types require `Self::new()`. Derive by simple default or manually implement it. + $( + paste::paste! { + #[doc = "A "] + $(#[$docs])* + #[doc = "."] + #[repr(transparent)] + #[derive(Clone, Copy, PartialEq, Eq, Hash)] + pub struct $variant(TRB); + + impl From<$variant> for TRB { + fn from(v: $variant) -> Self { + v.0 + } + } + + impl Default for $variant { + fn default() -> Self { + Self::new() + } + } + + simple_default!($(#[$docs])* $($deco)? $variant); // this branches whether $def is "default" or empty. + } + )+ + } +} + +macro_rules! simple_default { + ($(#[$docs:meta])* $variant:ident) => { + impl $variant{ + #[doc = "Creates a new "] + $(#[$docs])* + #[doc = ".\n\nThis method sets the value of the TRB Type field properly. "] + #[doc = "All the other fields are set to 0."] + #[must_use] + pub fn new() -> Self{ + Self(TRB::new(AllowedType::$variant)) + } + } + }; + ($(#[$docs:meta])* "no-new" $variant:ident) => {}; +} + +macro_rules! rsvdz_checking_try_from { + ($name:ident { + $([$index:expr];$range:expr),* $(,)? + }) => { + impl TryFrom for $name { + type Error = TRB; + + fn try_from(block: TRB) -> Result { + if block.trb_type() != Some(AllowedType::$name) + $(|| block.0[$index].get_bits($range) != 0 )* { + return Err(block); + } + Ok(Self(block)) + } + } + } +} + +pub mod transfer; +pub mod event; +pub mod command; \ No newline at end of file diff --git a/src/ring/block/transfer.rs b/src/ring/block/transfer.rs new file mode 100644 index 0000000..5968618 --- /dev/null +++ b/src/ring/block/transfer.rs @@ -0,0 +1,384 @@ +//! Transfer TRBs. + +use bit_field::BitField; +// use core::convert::TryInto; +use num_derive::FromPrimitive; +use num_traits::FromPrimitive; + +macro_rules! impl_data_buffer_pointer { + () => { + rw_double_field!( + pub, self, + self.0.0; [0, 1], + data_buffer_pointer, + "Data Buffer Pointer", + 32, u64 + ); + } +} + +// 17-bit trb transfer length only. +macro_rules! impl_trb_transfer_length { + () => { + rw_field!(pub, self, self.0.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); + }; + (prv) => { + rw_field!(pub(self), self, self.0.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); + }; +} + +macro_rules! impl_td_size { + () => { + rw_field!(pub, self, self.0.0[2]; 17..=21, td_size, "TD Size", u8); + }; +} + +macro_rules! impl_interrupter_target { + () => { + rw_field!(pub, self, self.0.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + }; +} + +macro_rules! impl_ent { + () => { + rw_bit!(pub, self, self.0.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + }; +} +macro_rules! impl_isp { + () => { + rw_bit!( + pub, self, + self.0.0[3]; 2, + interrupt_on_short_packet, + "Interrupt on Short Packet" + ); + }; +} +macro_rules! impl_ns { + () => { + rw_bit!(pub, self, self.0.0[3]; 3, no_snoop, "No Snoop"); + }; +} +macro_rules! impl_ch { + () => { + rw_bit!(pub, self, self.0.0[3]; 4, chain_bit, "Chain"); + }; +} +macro_rules! impl_idt { + () => { + rw_bit!(pub, self, self.0.0[3]; 6, immediate_data, "Immediate Data"); + }; +} +macro_rules! implprv_idt { + () => { + rw1s_bit!(pub(self), self, self.0.0[3]; 6, immediate_data, "Immediate Data"); + }; +} +macro_rules! impl_bei { + () => { + rw_bit!(pub, self, self.0.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); + }; +} +macro_rules! impl_dir { + () => { + rw_bit!(pub, self, self.0.0[3]; 16, direction, "Direction (is-in)"); + } +} + +allowed_trb!("Transfer TRB", { + /// Normal TRB + Normal = 1, + /// Setup Stage TRB + "no-new" SetupStage = 2, + /// Data Stage TRB + DataStage = 3, + /// Status Stage TRB + StatusStage = 4, + /// Isoch TRB + Isoch = 5, + /// Link TRB + Link = 6, + /// Event Data TRB + EventData = 7, + /// No Op Transfer TRB + NoOp = 8, +}); + +impl Normal { + impl_data_buffer_pointer!(); + + impl_trb_transfer_length!(); + impl_td_size!(); + impl_interrupter_target!(); + + impl_ent!(); + impl_isp!(); + impl_ns!(); + impl_ch!(); + impl_ioc!(); + impl_idt!(); + impl_bei!(); +} +impl_debug_from_methods!(Normal { + data_buffer_pointer, + trb_transfer_length, + td_size, + interrupter_target, + evaluate_next_trb, + interrupt_on_short_packet, + no_snoop, + chain_bit, + interrupt_on_completion, + immediate_data, + block_event_interrupt, +}); +rsvdz_checking_try_from!(Normal { + [3];7..=8, + [3];16..=31, +}); + +impl SetupStage { + /// Creates a new Setup Stage TRB. + /// + /// This method sets the value of the TRB Type, TRB Transfer Length, and the Immediate Data field properly. All the other fields are set to 0. + #[must_use] + pub fn new() -> Self { + *Self(TRB::new(AllowedType::SetupStage)) + .set_immediate_data() + .set_trb_transfer_length(8) + } + + rw_field!(pub, self, self.0.0[0]; 0..=7, request_type, "bmRequestType", u8); + rw_field!(pub, self, self.0.0[0]; 8..=15, request, "bRequest", u8); + rw_field!(pub, self, self.0.0[0]; 16..=31, value, "wValue", u16); + rw_field!(pub, self, self.0.0[1]; 0..=15, index, "wIndex", u16); + rw_field!(pub, self, self.0.0[1]; 16..=31, length, "wLength", u16); + + impl_trb_transfer_length!(prv); + impl_interrupter_target!(); + + impl_ioc!(); + implprv_idt!(); + + /// Sets the value of the Transfer Type field. + pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self { + self.0.0[3].set_bits(16..=17, t as _); + self + } + + /// Returns the value of the Transfer Type field. + /// + /// # Panics + /// + /// This method panics if the Transfer Type field contains 1 which is reserved. + #[must_use] + pub fn transfer_type(&self) -> TransferType { + FromPrimitive::from_u32(self.0.0[3].get_bits(16..=17)) + .expect("Transfer Type 1 is reserved.") + } +} +impl_debug_from_methods!(SetupStage { + request_type, + request, + value, + index, + length, + trb_transfer_length, + interrupter_target, + interrupt_on_completion, + immediate_data, // always true + transfer_type, +}); +rsvdz_checking_try_from!(SetupStage { // this won't check IDT and transfer length field. + [2];17..=21, + [3];1..=4, + [3];7..=9, + [3];18..=31, +}); + +impl DataStage { + impl_data_buffer_pointer!(); + + impl_trb_transfer_length!(); + impl_td_size!(); + impl_interrupter_target!(); + + impl_ent!(); + impl_isp!(); + impl_ns!(); + impl_ch!(); + impl_ioc!(); + impl_idt!(); + impl_dir!(); +} +impl_debug_from_methods!(DataStage { + data_buffer_pointer, + trb_transfer_length, + td_size, + interrupter_target, + evaluate_next_trb, + interrupt_on_short_packet, + no_snoop, + chain_bit, + interrupt_on_completion, + immediate_data, + direction, +}); +rsvdz_checking_try_from!(DataStage { + [3];7..=9, + [3];17..=31, +}); + +impl StatusStage { + impl_interrupter_target!(); + + impl_ent!(); + impl_ch!(); + impl_ioc!(); + impl_dir!(); +} +impl_debug_from_methods!(StatusStage { + interrupter_target, + evaluate_next_trb, + chain_bit, + interrupt_on_completion, + direction, +}); +rsvdz_checking_try_from!(StatusStage { + [0];0..=31, + [1];0..=31, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];17..=31, +}); + +impl Isoch { + impl_data_buffer_pointer!(); + + impl_trb_transfer_length!(); + rw_field!(pub, self, self.0.0[2]; 17..=21, td_size_or_tbc, "TD Size/TBC", u8); + impl_interrupter_target!(); + + impl_ent!(); + impl_isp!(); + impl_ns!(); + impl_ch!(); + impl_ioc!(); + impl_idt!(); + rw_field!(pub, self, self.0.0[3]; 7..=8, tbc_or_sts, "TBC/TRBSts", u8); + impl_bei!(); + rw_field!( + pub, self, + self.0.0[3]; 16..=19, + transfer_last_burst_packet_count, + "Transfer Last Burst Packet Count", + u8 + ); + rw_field!(pub, self, self.0.0[3]; 20..=30, frame_id, "Frame ID", u16); + rw_bit!(pub, self, self.0.0[3]; 31, start_isoch_asap, "Start Isoch ASAP"); +} +impl_debug_from_methods!(Isoch { + data_buffer_pointer, + trb_transfer_length, + td_size_or_tbc, + interrupter_target, + evaluate_next_trb, + interrupt_on_short_packet, + no_snoop, + chain_bit, + interrupt_on_completion, + immediate_data, + tbc_or_sts, + block_event_interrupt, + transfer_last_burst_packet_count, + frame_id, + start_isoch_asap, +}); +rsvdz_checking_try_from!(Isoch {}); + +impl Link { + impl_ring_segment_pointer!(); + + impl_interrupter_target!(); + + impl_tc!(); + impl_ch!(); + impl_ioc!(); +} +rsvdz_checking_try_from!(Link { + [0];0..=3, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];16..=31, +}); +impl_debug_from_methods!(Link { + ring_segment_pointer, + interrupter_target, + toggle_cycle, + chain_bit, + interrupt_on_completion, +}); + +impl EventData { + rw_double_field!( + pub, self, + self.0.0; [0, 1], + event_data, + "Event Data", + 32, u64 + ); + impl_interrupter_target!(); + impl_ent!(); + impl_ch!(); + impl_ioc!(); + impl_bei!(); +} +impl_debug_from_methods!(EventData { + event_data, + interrupter_target, + evaluate_next_trb, + chain_bit, + interrupt_on_completion, + block_event_interrupt, +}); +rsvdz_checking_try_from!(EventData { + [2];0..=21, + [3];2..=3, + [3];6..=8, + [3];16..=31, +}); + +impl NoOp { + impl_interrupter_target!(); + impl_ent!(); + impl_ch!(); + impl_ioc!(); +} +impl_debug_from_methods!(NoOp { + interrupter_target, + evaluate_next_trb, + chain_bit, + interrupt_on_completion, +}); +rsvdz_checking_try_from!(NoOp { + [0];0..=31, + [1];0..=31, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];16..=31, +}); + +/// Transfer Type. +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] +#[allow(clippy::module_name_repetitions)] +pub enum TransferType { + /// No Data Stage. + No = 0, + /// Out Data Stage. + Out = 2, + /// In Data Stage. + In = 3, +} \ No newline at end of file diff --git a/src/ring/mod.rs b/src/ring/mod.rs index 4bf525a..ac6c3f8 100644 --- a/src/ring/mod.rs +++ b/src/ring/mod.rs @@ -1,3 +1,6 @@ //! TRB Ring. pub mod trb; + + +pub mod block; \ No newline at end of file From 876f2992847c347a12fad0bdc4efd6a1b6dbda69 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Wed, 6 Dec 2023 16:16:31 +0000 Subject: [PATCH 10/17] replace `ring::trb` with previous `ring::block` --- src/ring/block/command.rs | 433 ------------------------- src/ring/block/event.rs | 316 ------------------- src/ring/block/mod.rs | 173 ---------- src/ring/block/transfer.rs | 384 ----------------------- src/ring/mod.rs | 5 +- src/ring/trb/command.rs | 623 ++++++++++++++++-------------------- src/ring/trb/event.rs | 353 +++++++++------------ src/ring/trb/mod.rs | 400 +++++++++-------------- src/ring/trb/transfer.rs | 628 +++++++++++++++---------------------- 9 files changed, 816 insertions(+), 2499 deletions(-) delete mode 100644 src/ring/block/command.rs delete mode 100644 src/ring/block/event.rs delete mode 100644 src/ring/block/mod.rs delete mode 100644 src/ring/block/transfer.rs diff --git a/src/ring/block/command.rs b/src/ring/block/command.rs deleted file mode 100644 index 24b6181..0000000 --- a/src/ring/block/command.rs +++ /dev/null @@ -1,433 +0,0 @@ -//! Command TRBs. - -use bit_field::BitField; -// use core::convert::TryInto; -use num_derive::FromPrimitive; -use num_traits::FromPrimitive; - -macro_rules! impl_input_context_pointer { - () => { - param_align_16!(input_context_pointer, "Input Context Pointer"); - } -} - -macro_rules! impl_subtype { - () => { - rw_field!(pub, self, self.0.0[3]; 16..=18, command_sub_type, "Command Sub Type", u8); - } -} - -allowed_trb!("Command TRB", { - /// Link TRB - Link = 6, - /// Enable Slot Command TRB - EnableSlot = 9, - /// Disable Slot Command TRB - DisableSlot = 10, - /// Address Device Command TRB - AddressDevice = 11, - /// Configure Endpoint Command TRB - ConfigureEndpoint = 12, - /// Evaluate Context Command TRB - EvaluateContext = 13, - /// Reset Endpoint Command TRB - ResetEndpoint = 14, - /// Stop Endpoint Command TRB - StopEndpoint = 15, - /// Set TR Dequeue Pointer Command TRB - SetTrDequeuePointer = 16, - /// Reset Device Command TRB - ResetDevice = 17, - /// Force Event Command TRB - ForceEvent = 18, - /// Negotiate Bandwidth Command TRB - NegotiateBandwidth = 19, - /// Set Latency Tolerance Value Command TRB - SetLatencyToleranceValue = 20, - /// Get Port Bandwidth Command TRB - GetPortBandwidth = 21, - /// Force Header Command TRB - ForceHeader = 22, - /// NoOp Command TRB - NoOp = 23, - /// Get Extended Property Command TRB - GetExtendedProperty = 24, - /// Set Extended Property Command TRB - SetExtendedProperty = 25, -}); - -impl Link { - impl_ring_segment_pointer!(); - - // impl_interrupter_target!(); // ignored in command ring - - impl_tc!(); - // impl_ch!(); // ignored in command ring - impl_ioc!(); -} -rsvdz_checking_try_from!(Link { - [0];0..=3, - [2];0..=21, - [3];2..=3, - [3];6..=9, - [3];16..=31, -}); -impl_debug_from_methods!(Link { - ring_segment_pointer, - // interrupter_target, - toggle_cycle, - // chain_bit, - interrupt_on_completion, -}); - -impl NoOp {} -rsvdz_checking_try_from!(NoOp { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=9, - [3];16..=31, -}); -impl_debug_from_methods!(NoOp {}); - -impl EnableSlot { - rw_field!(pub, self, self.0.0[3]; 16..=20, slot_type, "Slot Type", u8); -} -impl_debug_from_methods!(EnableSlot { - slot_type, -}); -rsvdz_checking_try_from!(EnableSlot { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=9, - [3];21..=31, -}); - -impl DisableSlot { - impl_slot_id!(); -} -impl_debug_from_methods!(DisableSlot { - slot_id, -}); -rsvdz_checking_try_from!(DisableSlot { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=9, - [3];16..=23, -}); - -impl AddressDevice { - impl_input_context_pointer!(); - - rw_bit!(pub, self, self.0.0[3]; 9, block_set_address_request, "Block Set Address Request"); - impl_slot_id!(); -} -impl_debug_from_methods!(AddressDevice { - input_context_pointer, - block_set_address_request, - slot_id, -}); -rsvdz_checking_try_from!(AddressDevice { - [0];0..=3, - [2];0..=31, - [3];1..=8, - [3];16..=23, -}); - -impl ConfigureEndpoint { - impl_input_context_pointer!(); - - rw_bit!(pub, self, self.0.0[3]; 9, deconfigure, "Deconfigure"); - impl_slot_id!(); -} -impl_debug_from_methods!(ConfigureEndpoint { - input_context_pointer, - deconfigure, - slot_id, -}); -rsvdz_checking_try_from!(ConfigureEndpoint { - [0];0..=3, - [2];0..=31, - [3];1..=8, - [3];16..=23, -}); - -impl EvaluateContext { - impl_input_context_pointer!(); - - // rw_bit!(pub, self, self.0.0[3]; 9, block_set_address_request, "Block Set Address Request"); // unused (no rsvdz) - impl_slot_id!(); -} -impl_debug_from_methods!(EvaluateContext { - input_context_pointer, - slot_id, -}); -rsvdz_checking_try_from!(EvaluateContext { - [0];0..=3, - [2];0..=31, - [3];1..=8, - [3];16..=23, -}); - -impl ResetEndpoint { - rw_bit!(pub, self, self.0.0[3]; 9, transfer_state_preserve, "Transfer State Preserve"); - impl_ep_id!(); - impl_slot_id!(); -} -impl_debug_from_methods!(ResetEndpoint { - transfer_state_preserve, - endpoint_id, - slot_id, -}); -rsvdz_checking_try_from!(ResetEndpoint { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=8, - [3];21..=23, -}); - -impl StopEndpoint { - impl_ep_id!(); - rw_bit!(pub, self, self.0.0[3]; 23, suspend, "Suspend"); - impl_slot_id!(); -} -impl_debug_from_methods!(StopEndpoint { - endpoint_id, - suspend, - slot_id, -}); -rsvdz_checking_try_from!(StopEndpoint { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=9, - [3];21..=22, -}); - -impl SetTrDequeuePointer { - rw_bit!(pub, self, self.0.0[0]; 0, dequeue_cycle_state, "Dequeue Cycle State"); - rw_field!(pub, self, self.0.0[0]; 1..=3, stream_context_type, "Stream Context Type", u8); - param_align_16!(new_tr_dequeue_pointer, "New TR Dequeue Pointer"); - rw_field!(pub, self, self.0.0[2]; 16..=31, stream_id, "Stream ID", u16); - - impl_ep_id!(); - impl_slot_id!(); -} -impl_debug_from_methods!(SetTrDequeuePointer { - dequeue_cycle_state, - stream_context_type, - new_tr_dequeue_pointer, - stream_id, - endpoint_id, - slot_id, -}); -rsvdz_checking_try_from!(SetTrDequeuePointer { - [2];0..=15, - [3];1..=9, - [3];21..=23, -}); - -impl ResetDevice { - impl_slot_id!(); -} -impl_debug_from_methods!(ResetDevice { - slot_id, -}); -rsvdz_checking_try_from!(ResetDevice { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=9, - [3];16..=23, -}); - -impl ForceEvent { - param_align_16!(event_trb_pointer, "Event TRB Pointer"); - - rw_field!( - pub, self, - self.0.0[2]; 22..=31, - vf_interrupter_target, - "VF Interrupter Target", - u16 - ); - - impl_vf_id!(); -} -impl_debug_from_methods!(ForceEvent { - event_trb_pointer, - vf_interrupter_target, - vf_id -}); -rsvdz_checking_try_from!(ForceEvent { - [0];0..=3, - [2];0..=21, - [3];1..=9, - [3];24..=31, -}); - -impl NegotiateBandwidth { - impl_slot_id!(); -} -impl_debug_from_methods!(NegotiateBandwidth { - slot_id, -}); -rsvdz_checking_try_from!(NegotiateBandwidth { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=9, - [3];16..=23, -}); - -impl SetLatencyToleranceValue { - rw_field!( - pub, self, - self.0.0[3]; 16..=27, - best_effort_latency_tolerance_value, - "Best Effort Latency Tolerance Value", - u16 - ); -} -impl_debug_from_methods!(SetLatencyToleranceValue { - best_effort_latency_tolerance_value, -}); -rsvdz_checking_try_from!(SetLatencyToleranceValue { - [0];0..=31, - [1];0..=31, - [2];0..=31, - [3];1..=9, - [3];28..=31, -}); - -impl GetPortBandwidth { - param_align_16!( - port_bandwidth_context_pointer, - "Port Bandwidth Context Pointer" - ); - - rw_field!(pub, self, self.0.0[3]; 16..=19, dev_speed, "Dev Speed", u8); - rw_field!(pub, self, self.0.0[3]; 24..=31, hub_slot_id, "Hub Slot ID", u8); -} -impl_debug_from_methods!(GetPortBandwidth { - port_bandwidth_context_pointer, - dev_speed, - hub_slot_id -}); -rsvdz_checking_try_from!(GetPortBandwidth { - [0];0..=3, - [2];0..=31, - [3];1..=9, - [3];20..=23, -}); - -impl ForceHeader { - rw_field!(pub, self, self.0.0[0]; 0..=4, packet_type, "Packet Type", u8); - - /// Sets the value of the Header Info field. - /// - /// # Panics - /// - /// This method panics if the lowest 5 bits of the `info[0]` are not 0. - pub fn set_header_info(&mut self, info: [u32; 3]) -> &mut Self { - assert!( - info[0].trailing_zeros() >= 5, - "The lowest 5 bits of the Header Info Low must be 0." - ); - - self.0.0[0].set_bits(5.., info[0].get_bits(5..)); - self.0.0[1] = info[1]; - self.0.0[2] = info[2]; - self - } - - /// Returns the value of the Header Info field. - #[must_use] - pub fn header_info(&self) -> [u32; 3] { - [self.0.0[0] >> 5 << 5, self.0.0[1], self.0.0[2]] - } - - rw_field!( - pub, self, - self.0.0[3]; 24..=31, - root_hub_port_number, - "Root Hub Port Number", - u8 - ); -} -impl_debug_from_methods!(ForceHeader { - packet_type, - header_info, - root_hub_port_number, -}); -rsvdz_checking_try_from!(ForceHeader { - [3];1..=9, - [3];16..=23, -}); - -impl GetExtendedProperty { - param_align_16!( - extended_property_context_pointer, - "Extended Property Context Pointer" - ); - - rw_field!( - pub, self, - self.0.0[2]; 0..=15, - extended_capability_identifier, - "Extended Capability Identifier", - u16 - ); - - impl_subtype!(); - impl_ep_id!(); - impl_slot_id!(); -} -impl_debug_from_methods!(GetExtendedProperty { - extended_property_context_pointer, - extended_capability_identifier, - command_sub_type, - endpoint_id, - slot_id, -}); -rsvdz_checking_try_from!(GetExtendedProperty { - [0];0..=3, - [2];16..=31, - [3];1..=9, -}); - -impl SetExtendedProperty { - rw_field!( - pub, self, - self.0.0[2]; 0..=15, - extended_capability_identifier, - "Extended Capability Identifier", - u16 - ); - rw_field!( - pub, self, - self.0.0[2]; 16..=23, - capability_parameter, - "Capability Parameter", - u8 - ); - - impl_subtype!(); - impl_ep_id!(); - impl_slot_id!(); -} -impl_debug_from_methods!(SetExtendedProperty { - extended_capability_identifier, - capability_parameter, - command_sub_type, - endpoint_id, - slot_id, -}); -rsvdz_checking_try_from!(SetExtendedProperty { - [0];0..=3, - [2];16..=31, - [3];1..=9, -}); \ No newline at end of file diff --git a/src/ring/block/event.rs b/src/ring/block/event.rs deleted file mode 100644 index 3fb3375..0000000 --- a/src/ring/block/event.rs +++ /dev/null @@ -1,316 +0,0 @@ -//! Event TRBs. - -use bit_field::BitField; -// use core::convert::TryInto; -use num_derive::FromPrimitive; -use num_traits::FromPrimitive; - -macro_rules! impl_cc { - (ro) => { - /// Returns the Completion Code. - /// - /// # Errors - /// - /// This method may return an [`Err`] variant with the Completion Code that is either reserved or - /// not implemented in this crate. - pub fn completion_code(&self) -> Result { - let c: u8 = self.0.0[2].get_bits(24..=31).try_into().unwrap(); - CompletionCode::from_u8(c).ok_or(c) - } - } -} - -allowed_trb!("Transfer TRB", { - /// Transfer Event TRB - TransferEvent = 32, - /// Command Completion Event TRB - CommandCompletion = 33, - /// Port Status Change Event TRB - PortStatusChange = 34, - /// Bandwidth Request Event TRB - BandwidthRequest = 35, - /// Doorbell Event TRB - Doorbell = 36, - /// Host Controller Event TRB - HostController = 37, - /// Device Notification Event TRB - DeviceNotification = 38, - /// MFINDEX Wrap Event TRB - MfindexWrap = 39, -}); - -impl TransferEvent { - ro_double_field!(pub, self, self.0.0; [0, 1], trb_pointer, "TRB Pointer (or event data)", 32, u64); - - ro_field!(pub, self, self.0.0[2]; 0..=23, trb_transfer_length, "TRB Transfer Length", u32); - impl_cc!(ro); - - ro_bit!(pub, self, self.0.0[3]; 2, event_data, "Event Data Flag"); - impl_ep_id!(ro); - impl_slot_id!(ro); -} -impl_debug_from_methods!(TransferEvent { - trb_pointer, - trb_transfer_length, - completion_code, - event_data, - endpoint_id, - slot_id, -}); -rsvdz_checking_try_from!(TransferEvent { - [3];1..=1, - [3];3..=9, - [3];21..=23, -}); - -impl CommandCompletion { - ro_double_field!( - pub, self, - self.0.0; [0, 1], - command_trb_pointer, - "Command TRB Pointer", - 32, u64 - ); - - ro_field!( - pub, self, - self.0.0[2]; 0..=23, - command_completion_parameter, - "Command Completion Parameter", - u32 - ); - impl_cc!(ro); - - impl_vf_id!(ro); - impl_slot_id!(ro); -} -impl_debug_from_methods!(CommandCompletion { - command_trb_pointer, - command_completion_parameter, - completion_code, - vf_id, - slot_id, -}); -rsvdz_checking_try_from!(CommandCompletion { - [0];0..=3, - [3];1..=9, -}); - -impl PortStatusChange { - ro_field!(pub, self, self.0.0[0]; 24..=31, port_id, "Port ID", u8); - - impl_cc!(ro); -} -impl_debug_from_methods!(PortStatusChange { - port_id, - completion_code, -}); -rsvdz_checking_try_from!(PortStatusChange { - [0];0..=23, - [1];0..=31, - [2];0..=23, - [3];1..=9, - [3];16..=31, -}); - -impl BandwidthRequest { - impl_cc!(ro); - - impl_slot_id!(ro); -} -impl_debug_from_methods!(BandwidthRequest { - completion_code, - slot_id, -}); -rsvdz_checking_try_from!(BandwidthRequest { - [0];0..=31, - [1];0..=31, - [2];0..=23, - [3];1..=9, - [3];16..=23, -}); - -impl Doorbell { - ro_field!(pub, self, self.0.0[0]; 0..=4, db_reason, "DB Reason", u8); - - impl_cc!(ro); - - impl_vf_id!(ro); - impl_slot_id!(ro); -} -impl_debug_from_methods!(Doorbell { - db_reason, - completion_code, - vf_id, - slot_id, -}); -rsvdz_checking_try_from!(Doorbell { - [0];5..=31, - [1];0..=31, - [2];0..=23, - [3];1..=9, -}); - -impl HostController { - impl_cc!(ro); -} -impl_debug_from_methods!(HostController { - completion_code, -}); -rsvdz_checking_try_from!(HostController { - [0];0..=31, - [1];0..=31, - [2];0..=23, - [3];1..=9, - [3];16..=31, -}); - -impl DeviceNotification { - ro_field!( - pub, self, - self.0.0[0]; 4..=7, - notification_type, - "Notification Type", - u8 - ); - ro_double_field!( - pub(self), self, - self.0.0; [0, 1], - device_notification_data_raw, - "Device Notification Data Raw", - 32, u64 - ); - /// Returns the value of the Device Notification Data field. - #[must_use] - pub fn device_notification_data(&self) -> u64 { - self.device_notification_data_raw() >> 8 - } - - impl_cc!(ro); - - impl_slot_id!(ro); -} -impl_debug_from_methods!(DeviceNotification { - notification_type, - device_notification_data, - completion_code, - slot_id, -}); -rsvdz_checking_try_from!(DeviceNotification { - [0];0..=3, - [2];0..=23, - [3];1..=9, - [3];16..=31, -}); - -impl MfindexWrap { - impl_cc!(ro); -} -impl_debug_from_methods!(MfindexWrap { - completion_code, -}); -rsvdz_checking_try_from!(MfindexWrap { - [0];0..=31, - [1];0..=31, - [2];0..=23, - [3];1..=9, - [3];16..=31, -}); - - -/// The TRB Completion Codes. -/// -/// The description of each error is quoted from eXtensible Host Controller Interface for Universal -/// Serial Bus (xHCI) Requirements Specification May 2019 Revision 1.2, Section 6.4.5, Table 6-90. -/// Refer to this specification for more detail. -#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] -pub enum CompletionCode { - /// Indicates that the Completion Code field has not been updated by the TRB producer. - Invalid = 0, - /// Indicates successful completion of the TRB operation. - Success = 1, - /// Indicates that the Host Controller is unable to keep up the reception of incoming data - /// (overrun) or is unable to supply data fast enough during transmission (underrun). - DataBufferError = 2, - /// Asserted when "babbling" is detected during the transaction generated by this TRB. - BabbleDetectedError = 3, - /// Asserted in the case where the host did not receive a valid response from the device. - UsbTransactionError = 4, - /// Asserted when a TRB parameter error condition is detected in a TRB. - TrbError = 5, - /// Asserted when a Stall condition is detected for a TRB. - StallError = 6, - /// Asserted by a Configure Endpoint Command or an Address Device Command if there are not - /// adequate xHC resources available to successfully complete the command. - ResourceError = 7, - /// Asserted by a Configure Endpoint Command if periodic endpoints are declared and the xHC is - /// not able to allocate the required Bandwidth. - BandwidthError = 8, - /// Asserted if a adding one more device would result in the host controller to exceed the - /// maximum Number of Device Slots for this implementation. - NoSlotsAvailableError = 9, - /// Asserted if an invalid Stream Context Type value is detected. - InvalidStreamTypeError = 10, - /// Asserted if a command is issued to a Device Slot that is in the Disabled state. - SlotNotEnabledError = 11, - /// Asserted if a doorbell is rung for an endpoint that is in the Disabled state. - EndpointNotEnabledError = 12, - /// Asserted if the number of bytes received was less than the TD Transfer Size. - ShortPacket = 13, - /// Asserted in a Transfer Event TRB if the Transfer Ring is empty when an enabled Isoch - /// endpoint is scheduled to transmit data. - RingUnderrun = 14, - /// Asserted in a Transfer Event TRB if the Transfer Ring is empty when an enabled Isoch - /// endpoint is scheduled to receive data. - RingOverrun = 15, - /// Asserted by a Force Event command if the target VF's Event Ring is full. - VfEventRingFullError = 16, - /// Asserted by a command if a Context parameter is invalid. - ParameterError = 17, - /// Asserted during an Isoch transfer if the TD exceeds the bandwidth allocated to the - /// endpoint. - BandwidthOverrunError = 18, - /// Asserted if a command is issued to transition from an illegal context state. - ContextStateError = 19, - /// Asserted if the xHC was unable to complete a periodic data transfer associated within the - /// ESIT, because it did not receive a PING_RESPONSE in time. - NoPingResponseError = 20, - /// Asserted if the Event Ring is full, the xHC is unable to post an Event to the ring. - EventRingFullError = 21, - /// Asserted if the xHC detects a problem with a device that does not allow it to be - /// successfully accessed. - IncompatibleDeviceError = 22, - /// Asserted if the xHC was unable to service a Isochronous endpoint within the Interval time. - MissedServiceError = 23, - /// Asserted in a Command Completion Event due to a Command Stop operation. - CommandRingStopped = 24, - /// Asserted in a Command Completion Event of an aborted command if the command was terminated - /// by a Command Abort (CA) operation. - CommandAborted = 25, - /// Asserted in a Transfer Event if the transfer was terminated by a Stop Endpoint Command. - Stopped = 26, - /// Asserted in a Transfer Event if the transfer was terminated by a Stop Endpoint Command and - /// the Transfer Event TRB Transfer Length field is invalid. - StoppedLengthInvalid = 27, - /// Asserted in a Transfer Event if the transfer was terminated by a Stop Endpoint Command, and - /// the transfer was stopped after Short Packet conditions were met, but before the end of the - /// TD was reached. - StoppedShortPacket = 28, - /// Asserted by the Evaluate Context Command if the proposed Max Exit Latency would not allow - /// the periodic endpoints of the Device Slot to be scheduled. - MaxExitLatencyTooLargeError = 29, - /// Asserted if the data buffer defined by an Isoch TD on an IN endpoint is less than the Max - /// ESIT Payload in size and the device attempts to send more data than it can hold. - IsochBufferOverrun = 31, - /// Asserted if the xHC internal event overrun condition. - EventLostError = 32, - /// May be reported by an event when other error codes do not apply. - UndefinedError = 33, - /// Asserted if an invalid Stream ID is received. - InvalidStreamIdError = 34, - /// Asserted by a Configure Endpoint Command if periodic endpoints are declared and the xHC is - /// not able to allocate the required Bandwidth due to a Secondary Bandwidth Domain. - SecondaryBandwidthError = 35, - /// Asserted if an error is detected on a USB2 protocol endpoint for a split transaction. - SplitTransactionError = 36, -} \ No newline at end of file diff --git a/src/ring/block/mod.rs b/src/ring/block/mod.rs deleted file mode 100644 index 6297cf3..0000000 --- a/src/ring/block/mod.rs +++ /dev/null @@ -1,173 +0,0 @@ -//! TRB (Transfer Request Block). - -/// The bytes of a TRB. -pub const BYTES: usize = 16; - -macro_rules! param_align_16 { - ($method:ident,$name:literal) => { - rw_double_zero_trailing!( - pub, self, - self.0.0; [0, 1]; 4~; "16-byte aligned", - $method, $name, 32, u64 - ); - } -} - -macro_rules! impl_ring_segment_pointer { - () => { - param_align_16!(ring_segment_pointer, "Ring Segment Pointer"); - } -} - -macro_rules! impl_tc { - () => { - rw_bit!(pub, self, self.0.0[3]; 1, toggle_cycle, "Toggle Cycle"); - } -} - -macro_rules! impl_ioc { - () => { - rw_bit!( - pub, self, - self.0.0[3]; 5, - interrupt_on_completion, - "Interrupt On Completion" - ); - } -} - -macro_rules! impl_ep_id { - () => { - rw_field!(pub, self, self.0.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); - }; - (ro) => { - ro_field!(pub, self, self.0.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); - }; -} - -macro_rules! impl_vf_id { - () => { - rw_field!(pub, self, self.0.0[3]; 16..=23, vf_id, "VF ID", u8); - }; - (ro) => { - ro_field!(pub, self, self.0.0[3]; 16..=23, vf_id, "VF ID", u8); - }; -} - -macro_rules! impl_slot_id { - () => { - rw_field!(pub, self, self.0.0[3]; 24..=31, slot_id, "Slot ID", u8); - }; - (ro) => { - ro_field!(pub, self, self.0.0[3]; 24..=31, slot_id, "Slot ID", u8); - }; -} - -macro_rules! allowed_trb { - ($name:literal, { - $($(#[$docs:meta])* $($deco:literal)? $variant:ident = $val:literal),+ $(,)? - }) => { - // defining AllowedType - paste::paste!( - #[doc = "Allowed TRB Type for " $name "."] - #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] - pub enum AllowedType { - $( - $(#[$docs])* - #[doc = ", " $val ""] - $variant = $val - ),+ - } - ); - - // defining common block - paste::paste!( - #[doc = "A raw " $name " Block."] - #[repr(transparent)] - #[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Hash)] - pub struct TRB(pub(crate) [u32; 4]); - impl TRB { - pub(crate) fn new(ty: AllowedType) -> Self { - *Self([0; 4]) - .set_trb_type(ty) - } - - pub(crate) fn trb_type(&self) -> Option { - AllowedType::from_u32(self.0[3].get_bits(10..=15)) - } - - fn set_trb_type(&mut self, ty: AllowedType) -> &mut Self { - self.0[3].set_bits(10..=15, ty as u32); - self - } - - rw_bit!(pub, self, self.0[3]; 0, cycle_bit, "Cycle"); - } - ); - - // defining individual TRB types - // all TRB types require `Self::new()`. Derive by simple default or manually implement it. - $( - paste::paste! { - #[doc = "A "] - $(#[$docs])* - #[doc = "."] - #[repr(transparent)] - #[derive(Clone, Copy, PartialEq, Eq, Hash)] - pub struct $variant(TRB); - - impl From<$variant> for TRB { - fn from(v: $variant) -> Self { - v.0 - } - } - - impl Default for $variant { - fn default() -> Self { - Self::new() - } - } - - simple_default!($(#[$docs])* $($deco)? $variant); // this branches whether $def is "default" or empty. - } - )+ - } -} - -macro_rules! simple_default { - ($(#[$docs:meta])* $variant:ident) => { - impl $variant{ - #[doc = "Creates a new "] - $(#[$docs])* - #[doc = ".\n\nThis method sets the value of the TRB Type field properly. "] - #[doc = "All the other fields are set to 0."] - #[must_use] - pub fn new() -> Self{ - Self(TRB::new(AllowedType::$variant)) - } - } - }; - ($(#[$docs:meta])* "no-new" $variant:ident) => {}; -} - -macro_rules! rsvdz_checking_try_from { - ($name:ident { - $([$index:expr];$range:expr),* $(,)? - }) => { - impl TryFrom for $name { - type Error = TRB; - - fn try_from(block: TRB) -> Result { - if block.trb_type() != Some(AllowedType::$name) - $(|| block.0[$index].get_bits($range) != 0 )* { - return Err(block); - } - Ok(Self(block)) - } - } - } -} - -pub mod transfer; -pub mod event; -pub mod command; \ No newline at end of file diff --git a/src/ring/block/transfer.rs b/src/ring/block/transfer.rs deleted file mode 100644 index 5968618..0000000 --- a/src/ring/block/transfer.rs +++ /dev/null @@ -1,384 +0,0 @@ -//! Transfer TRBs. - -use bit_field::BitField; -// use core::convert::TryInto; -use num_derive::FromPrimitive; -use num_traits::FromPrimitive; - -macro_rules! impl_data_buffer_pointer { - () => { - rw_double_field!( - pub, self, - self.0.0; [0, 1], - data_buffer_pointer, - "Data Buffer Pointer", - 32, u64 - ); - } -} - -// 17-bit trb transfer length only. -macro_rules! impl_trb_transfer_length { - () => { - rw_field!(pub, self, self.0.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); - }; - (prv) => { - rw_field!(pub(self), self, self.0.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); - }; -} - -macro_rules! impl_td_size { - () => { - rw_field!(pub, self, self.0.0[2]; 17..=21, td_size, "TD Size", u8); - }; -} - -macro_rules! impl_interrupter_target { - () => { - rw_field!(pub, self, self.0.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); - }; -} - -macro_rules! impl_ent { - () => { - rw_bit!(pub, self, self.0.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); - }; -} -macro_rules! impl_isp { - () => { - rw_bit!( - pub, self, - self.0.0[3]; 2, - interrupt_on_short_packet, - "Interrupt on Short Packet" - ); - }; -} -macro_rules! impl_ns { - () => { - rw_bit!(pub, self, self.0.0[3]; 3, no_snoop, "No Snoop"); - }; -} -macro_rules! impl_ch { - () => { - rw_bit!(pub, self, self.0.0[3]; 4, chain_bit, "Chain"); - }; -} -macro_rules! impl_idt { - () => { - rw_bit!(pub, self, self.0.0[3]; 6, immediate_data, "Immediate Data"); - }; -} -macro_rules! implprv_idt { - () => { - rw1s_bit!(pub(self), self, self.0.0[3]; 6, immediate_data, "Immediate Data"); - }; -} -macro_rules! impl_bei { - () => { - rw_bit!(pub, self, self.0.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); - }; -} -macro_rules! impl_dir { - () => { - rw_bit!(pub, self, self.0.0[3]; 16, direction, "Direction (is-in)"); - } -} - -allowed_trb!("Transfer TRB", { - /// Normal TRB - Normal = 1, - /// Setup Stage TRB - "no-new" SetupStage = 2, - /// Data Stage TRB - DataStage = 3, - /// Status Stage TRB - StatusStage = 4, - /// Isoch TRB - Isoch = 5, - /// Link TRB - Link = 6, - /// Event Data TRB - EventData = 7, - /// No Op Transfer TRB - NoOp = 8, -}); - -impl Normal { - impl_data_buffer_pointer!(); - - impl_trb_transfer_length!(); - impl_td_size!(); - impl_interrupter_target!(); - - impl_ent!(); - impl_isp!(); - impl_ns!(); - impl_ch!(); - impl_ioc!(); - impl_idt!(); - impl_bei!(); -} -impl_debug_from_methods!(Normal { - data_buffer_pointer, - trb_transfer_length, - td_size, - interrupter_target, - evaluate_next_trb, - interrupt_on_short_packet, - no_snoop, - chain_bit, - interrupt_on_completion, - immediate_data, - block_event_interrupt, -}); -rsvdz_checking_try_from!(Normal { - [3];7..=8, - [3];16..=31, -}); - -impl SetupStage { - /// Creates a new Setup Stage TRB. - /// - /// This method sets the value of the TRB Type, TRB Transfer Length, and the Immediate Data field properly. All the other fields are set to 0. - #[must_use] - pub fn new() -> Self { - *Self(TRB::new(AllowedType::SetupStage)) - .set_immediate_data() - .set_trb_transfer_length(8) - } - - rw_field!(pub, self, self.0.0[0]; 0..=7, request_type, "bmRequestType", u8); - rw_field!(pub, self, self.0.0[0]; 8..=15, request, "bRequest", u8); - rw_field!(pub, self, self.0.0[0]; 16..=31, value, "wValue", u16); - rw_field!(pub, self, self.0.0[1]; 0..=15, index, "wIndex", u16); - rw_field!(pub, self, self.0.0[1]; 16..=31, length, "wLength", u16); - - impl_trb_transfer_length!(prv); - impl_interrupter_target!(); - - impl_ioc!(); - implprv_idt!(); - - /// Sets the value of the Transfer Type field. - pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self { - self.0.0[3].set_bits(16..=17, t as _); - self - } - - /// Returns the value of the Transfer Type field. - /// - /// # Panics - /// - /// This method panics if the Transfer Type field contains 1 which is reserved. - #[must_use] - pub fn transfer_type(&self) -> TransferType { - FromPrimitive::from_u32(self.0.0[3].get_bits(16..=17)) - .expect("Transfer Type 1 is reserved.") - } -} -impl_debug_from_methods!(SetupStage { - request_type, - request, - value, - index, - length, - trb_transfer_length, - interrupter_target, - interrupt_on_completion, - immediate_data, // always true - transfer_type, -}); -rsvdz_checking_try_from!(SetupStage { // this won't check IDT and transfer length field. - [2];17..=21, - [3];1..=4, - [3];7..=9, - [3];18..=31, -}); - -impl DataStage { - impl_data_buffer_pointer!(); - - impl_trb_transfer_length!(); - impl_td_size!(); - impl_interrupter_target!(); - - impl_ent!(); - impl_isp!(); - impl_ns!(); - impl_ch!(); - impl_ioc!(); - impl_idt!(); - impl_dir!(); -} -impl_debug_from_methods!(DataStage { - data_buffer_pointer, - trb_transfer_length, - td_size, - interrupter_target, - evaluate_next_trb, - interrupt_on_short_packet, - no_snoop, - chain_bit, - interrupt_on_completion, - immediate_data, - direction, -}); -rsvdz_checking_try_from!(DataStage { - [3];7..=9, - [3];17..=31, -}); - -impl StatusStage { - impl_interrupter_target!(); - - impl_ent!(); - impl_ch!(); - impl_ioc!(); - impl_dir!(); -} -impl_debug_from_methods!(StatusStage { - interrupter_target, - evaluate_next_trb, - chain_bit, - interrupt_on_completion, - direction, -}); -rsvdz_checking_try_from!(StatusStage { - [0];0..=31, - [1];0..=31, - [2];0..=21, - [3];2..=3, - [3];6..=9, - [3];17..=31, -}); - -impl Isoch { - impl_data_buffer_pointer!(); - - impl_trb_transfer_length!(); - rw_field!(pub, self, self.0.0[2]; 17..=21, td_size_or_tbc, "TD Size/TBC", u8); - impl_interrupter_target!(); - - impl_ent!(); - impl_isp!(); - impl_ns!(); - impl_ch!(); - impl_ioc!(); - impl_idt!(); - rw_field!(pub, self, self.0.0[3]; 7..=8, tbc_or_sts, "TBC/TRBSts", u8); - impl_bei!(); - rw_field!( - pub, self, - self.0.0[3]; 16..=19, - transfer_last_burst_packet_count, - "Transfer Last Burst Packet Count", - u8 - ); - rw_field!(pub, self, self.0.0[3]; 20..=30, frame_id, "Frame ID", u16); - rw_bit!(pub, self, self.0.0[3]; 31, start_isoch_asap, "Start Isoch ASAP"); -} -impl_debug_from_methods!(Isoch { - data_buffer_pointer, - trb_transfer_length, - td_size_or_tbc, - interrupter_target, - evaluate_next_trb, - interrupt_on_short_packet, - no_snoop, - chain_bit, - interrupt_on_completion, - immediate_data, - tbc_or_sts, - block_event_interrupt, - transfer_last_burst_packet_count, - frame_id, - start_isoch_asap, -}); -rsvdz_checking_try_from!(Isoch {}); - -impl Link { - impl_ring_segment_pointer!(); - - impl_interrupter_target!(); - - impl_tc!(); - impl_ch!(); - impl_ioc!(); -} -rsvdz_checking_try_from!(Link { - [0];0..=3, - [2];0..=21, - [3];2..=3, - [3];6..=9, - [3];16..=31, -}); -impl_debug_from_methods!(Link { - ring_segment_pointer, - interrupter_target, - toggle_cycle, - chain_bit, - interrupt_on_completion, -}); - -impl EventData { - rw_double_field!( - pub, self, - self.0.0; [0, 1], - event_data, - "Event Data", - 32, u64 - ); - impl_interrupter_target!(); - impl_ent!(); - impl_ch!(); - impl_ioc!(); - impl_bei!(); -} -impl_debug_from_methods!(EventData { - event_data, - interrupter_target, - evaluate_next_trb, - chain_bit, - interrupt_on_completion, - block_event_interrupt, -}); -rsvdz_checking_try_from!(EventData { - [2];0..=21, - [3];2..=3, - [3];6..=8, - [3];16..=31, -}); - -impl NoOp { - impl_interrupter_target!(); - impl_ent!(); - impl_ch!(); - impl_ioc!(); -} -impl_debug_from_methods!(NoOp { - interrupter_target, - evaluate_next_trb, - chain_bit, - interrupt_on_completion, -}); -rsvdz_checking_try_from!(NoOp { - [0];0..=31, - [1];0..=31, - [2];0..=21, - [3];2..=3, - [3];6..=9, - [3];16..=31, -}); - -/// Transfer Type. -#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] -#[allow(clippy::module_name_repetitions)] -pub enum TransferType { - /// No Data Stage. - No = 0, - /// Out Data Stage. - Out = 2, - /// In Data Stage. - In = 3, -} \ No newline at end of file diff --git a/src/ring/mod.rs b/src/ring/mod.rs index ac6c3f8..9648d04 100644 --- a/src/ring/mod.rs +++ b/src/ring/mod.rs @@ -1,6 +1,3 @@ //! TRB Ring. -pub mod trb; - - -pub mod block; \ No newline at end of file +pub mod trb; \ No newline at end of file diff --git a/src/ring/trb/command.rs b/src/ring/trb/command.rs index a9a0c29..24b6181 100644 --- a/src/ring/trb/command.rs +++ b/src/ring/trb/command.rs @@ -1,510 +1,433 @@ //! Command TRBs. -use super::{Link, Type}; use bit_field::BitField; +// use core::convert::TryInto; +use num_derive::FromPrimitive; use num_traits::FromPrimitive; -allowed! { - /// TRBs which are allowed to be pushed to the Command Ring. - enum { - /// Link TRB - Link, - /// Enable Slot Command TRB - EnableSlot, - /// Disable Slot Command TRB - DisableSlot, - /// Address Device Command TRB - AddressDevice, - /// Configure Endpoint Command TRB - ConfigureEndpoint, - /// Evaluate Context Command TRB - EvaluateContext, - /// Reset Endpoint Command TRB - ResetEndpoint, - /// Stop Endpoint Command TRB - StopEndpoint, - /// Set TR Dequeue Pointer Command TRB - SetTrDequeuePointer, - /// Reset Device Command TRB - ResetDevice, - /// Force Event Command TRB - ForceEvent, - /// Negotiate Bandwidth Command TRB - NegotiateBandwidth, - /// Set Latency Tolerance Value Command TRB - SetLatencyToleranceValue, - /// Get Port Bandwidth Command TRB - GetPortBandwidth, - /// Force Header Command TRB - ForceHeader, - /// No Op Command TRB - Noop, - /// Get Extended Property Command TRB - GetExtendedProperty, - /// Set Extended Property Command TRB - SetExtendedProperty +macro_rules! impl_input_context_pointer { + () => { + param_align_16!(input_context_pointer, "Input Context Pointer"); } } -impl TryFrom<[u32; 4]> for Allowed { - type Error = [u32; 4]; - - fn try_from(raw: [u32; 4]) -> Result { - try_from!( - raw => - Link, - EnableSlot, - DisableSlot, - AddressDevice, - ConfigureEndpoint, - EvaluateContext, - ResetEndpoint, - StopEndpoint, - SetTrDequeuePointer, - ResetDevice, - ForceEvent, - NegotiateBandwidth, - SetLatencyToleranceValue, - GetPortBandwidth, - ForceHeader, - Noop(Command), - GetExtendedProperty, - SetExtendedProperty, - ); - Err(raw) + +macro_rules! impl_subtype { + () => { + rw_field!(pub, self, self.0.0[3]; 16..=18, command_sub_type, "Command Sub Type", u8); } } -add_trb_with_default!(Noop, "No Op Command TRB", Type::NoopCommand); -reserved!(Noop(Type::NoopCommand) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=9; - [3]21..=31; +allowed_trb!("Command TRB", { + /// Link TRB + Link = 6, + /// Enable Slot Command TRB + EnableSlot = 9, + /// Disable Slot Command TRB + DisableSlot = 10, + /// Address Device Command TRB + AddressDevice = 11, + /// Configure Endpoint Command TRB + ConfigureEndpoint = 12, + /// Evaluate Context Command TRB + EvaluateContext = 13, + /// Reset Endpoint Command TRB + ResetEndpoint = 14, + /// Stop Endpoint Command TRB + StopEndpoint = 15, + /// Set TR Dequeue Pointer Command TRB + SetTrDequeuePointer = 16, + /// Reset Device Command TRB + ResetDevice = 17, + /// Force Event Command TRB + ForceEvent = 18, + /// Negotiate Bandwidth Command TRB + NegotiateBandwidth = 19, + /// Set Latency Tolerance Value Command TRB + SetLatencyToleranceValue = 20, + /// Get Port Bandwidth Command TRB + GetPortBandwidth = 21, + /// Force Header Command TRB + ForceHeader = 22, + /// NoOp Command TRB + NoOp = 23, + /// Get Extended Property Command TRB + GetExtendedProperty = 24, + /// Set Extended Property Command TRB + SetExtendedProperty = 25, }); -impl_debug_for_trb!(Noop {}); -add_trb_with_default!(EnableSlot, "Enable Slot Command TRB", Type::EnableSlot); -reserved!(EnableSlot(Type::EnableSlot) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=9; - [3]21..=31; +impl Link { + impl_ring_segment_pointer!(); + + // impl_interrupter_target!(); // ignored in command ring + + impl_tc!(); + // impl_ch!(); // ignored in command ring + impl_ioc!(); +} +rsvdz_checking_try_from!(Link { + [0];0..=3, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];16..=31, }); +impl_debug_from_methods!(Link { + ring_segment_pointer, + // interrupter_target, + toggle_cycle, + // chain_bit, + interrupt_on_completion, +}); + +impl NoOp {} +rsvdz_checking_try_from!(NoOp { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=31, +}); +impl_debug_from_methods!(NoOp {}); + impl EnableSlot { - rw_field!(pub, self, self.0[3]; 16..=20, slot_type, "Slot Type", u8); + rw_field!(pub, self, self.0.0[3]; 16..=20, slot_type, "Slot Type", u8); } -impl_debug_for_trb!(EnableSlot { slot_type }); - -add_trb_with_default!(DisableSlot, "Disable Slot Command TRB", Type::DisableSlot); -reserved!(DisableSlot(Type::DisableSlot) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=9; - [3]16..=23; +impl_debug_from_methods!(EnableSlot { + slot_type, +}); +rsvdz_checking_try_from!(EnableSlot { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];21..=31, }); + impl DisableSlot { - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_slot_id!(); } -impl_debug_for_trb!(DisableSlot { slot_id }); - -add_trb_with_default!( - AddressDevice, - "Address Device Command TRB", - Type::AddressDevice -); -reserved!(AddressDevice(Type::AddressDevice) { - [0]0..=3; - [2]0..=31; - [3]1..=8; - [3]16..=23; +impl_debug_from_methods!(DisableSlot { + slot_id, +}); +rsvdz_checking_try_from!(DisableSlot { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=23, }); + impl AddressDevice { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", - input_context_pointer, - "Input Context Pointer", - 32, u64 - ); - rw_bit!( - pub, self, - self.0[3]; 9, - block_set_address_request, - "Block Set Address Request" - ); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_input_context_pointer!(); + + rw_bit!(pub, self, self.0.0[3]; 9, block_set_address_request, "Block Set Address Request"); + impl_slot_id!(); } -impl_debug_for_trb!(AddressDevice { +impl_debug_from_methods!(AddressDevice { input_context_pointer, block_set_address_request, - slot_id + slot_id, }); - -add_trb_with_default!( - ConfigureEndpoint, - "Configure Endpoint Command TRB", - Type::ConfigureEndpoint -); -reserved!(ConfigureEndpoint(Type::ConfigureEndpoint) { - [0]0..=3; - [2]0..=31; - [3]1..=8; - [3]16..=23; +rsvdz_checking_try_from!(AddressDevice { + [0];0..=3, + [2];0..=31, + [3];1..=8, + [3];16..=23, }); + impl ConfigureEndpoint { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", - input_context_pointer, - "Input Context Pointer", - 32, u64 - ); - rw_bit!(pub, self, self.0[3]; 9, deconfigure, "Deconfigure"); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_input_context_pointer!(); + + rw_bit!(pub, self, self.0.0[3]; 9, deconfigure, "Deconfigure"); + impl_slot_id!(); } -impl_debug_for_trb!(ConfigureEndpoint { +impl_debug_from_methods!(ConfigureEndpoint { input_context_pointer, deconfigure, - slot_id + slot_id, }); - -add_trb_with_default!( - EvaluateContext, - "Evaluate Context Command TRB", - Type::EvaluateContext -); -reserved!(EvaluateContext(Type::EvaluateContext) { - [0]0..=3; - [2]0..=31; - [3]1..=8; - [3]16..=23; +rsvdz_checking_try_from!(ConfigureEndpoint { + [0];0..=3, + [2];0..=31, + [3];1..=8, + [3];16..=23, }); + impl EvaluateContext { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", - input_context_pointer, - "Input Context Pointer", - 32, u64 - ); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_input_context_pointer!(); + + // rw_bit!(pub, self, self.0.0[3]; 9, block_set_address_request, "Block Set Address Request"); // unused (no rsvdz) + impl_slot_id!(); } -impl_debug_for_trb!(EvaluateContext { +impl_debug_from_methods!(EvaluateContext { input_context_pointer, - slot_id + slot_id, }); - -add_trb_with_default!( - ResetEndpoint, - "Reset Endpoint Command TRB", - Type::ResetEndpoint -); -reserved!(ResetEndpoint(Type::ResetEndpoint) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=8; - [3]21..=23; +rsvdz_checking_try_from!(EvaluateContext { + [0];0..=3, + [2];0..=31, + [3];1..=8, + [3];16..=23, }); + impl ResetEndpoint { - rw_bit!(pub, self, self.0[3]; 9, transfer_state_preserve, "Transfer State Preserve"); - rw_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + rw_bit!(pub, self, self.0.0[3]; 9, transfer_state_preserve, "Transfer State Preserve"); + impl_ep_id!(); + impl_slot_id!(); } -impl_debug_for_trb!(ResetEndpoint { +impl_debug_from_methods!(ResetEndpoint { transfer_state_preserve, endpoint_id, - slot_id + slot_id, }); - -add_trb_with_default!( - StopEndpoint, - "Stop Endpoint Command TRB", - Type::StopEndpoint -); -reserved!(StopEndpoint(Type::StopEndpoint) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=9; - [3]21..=22; +rsvdz_checking_try_from!(ResetEndpoint { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=8, + [3];21..=23, }); + impl StopEndpoint { - rw_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); - rw_bit!(pub, self, self.0[3]; 23, suspend, "Suspend"); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_ep_id!(); + rw_bit!(pub, self, self.0.0[3]; 23, suspend, "Suspend"); + impl_slot_id!(); } -impl_debug_for_trb!(StopEndpoint { +impl_debug_from_methods!(StopEndpoint { endpoint_id, suspend, - slot_id + slot_id, }); - -add_trb_with_default!( - SetTrDequeuePointer, - "Set TR Dequeue Pointer Command TRB", - Type::SetTrDequeuePointer -); -reserved!(SetTrDequeuePointer(Type::SetTrDequeuePointer) { - [2]0..=15; - [3]1..=9; - [3]21..=23; +rsvdz_checking_try_from!(StopEndpoint { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];21..=22, }); + impl SetTrDequeuePointer { - rw_bit!(pub, self, self.0[0]; 0, dequeue_cycle_state, "Dequeue Cycle State"); - rw_field!(pub, self, self.0[0]; 1..=3, stream_context_type, "Stream Context Type", u8); - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", - new_tr_dequeue_pointer, - "New TR Dequeue Pointer", - 32, u64 - ); - rw_field!(pub, self, self.0[2]; 16..=31, stream_id, "Stream ID", u16); - rw_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + rw_bit!(pub, self, self.0.0[0]; 0, dequeue_cycle_state, "Dequeue Cycle State"); + rw_field!(pub, self, self.0.0[0]; 1..=3, stream_context_type, "Stream Context Type", u8); + param_align_16!(new_tr_dequeue_pointer, "New TR Dequeue Pointer"); + rw_field!(pub, self, self.0.0[2]; 16..=31, stream_id, "Stream ID", u16); + + impl_ep_id!(); + impl_slot_id!(); } -impl_debug_for_trb!(SetTrDequeuePointer { +impl_debug_from_methods!(SetTrDequeuePointer { dequeue_cycle_state, stream_context_type, new_tr_dequeue_pointer, stream_id, endpoint_id, - slot_id + slot_id, }); - -add_trb_with_default!(ResetDevice, "Reset Device Command TRB", Type::ResetDevice); -reserved!(ResetDevice(Type::ResetDevice) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=9; - [3]16..=23; +rsvdz_checking_try_from!(SetTrDequeuePointer { + [2];0..=15, + [3];1..=9, + [3];21..=23, }); + impl ResetDevice { - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_slot_id!(); } -impl_debug_for_trb!(ResetDevice { slot_id }); - -add_trb_with_default!(ForceEvent, "Force Event Command TRB", Type::ForceEvent); -reserved!(ForceEvent(Type::ForceEvent) { - [0]0..=3; - [2]0..=21; - [3]1..=9; - [3]24..=31; +impl_debug_from_methods!(ResetDevice { + slot_id, +}); +rsvdz_checking_try_from!(ResetDevice { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=23, }); + impl ForceEvent { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", - event_trb_pointer, - "Event TRB Pointer", - 32, u64 - ); + param_align_16!(event_trb_pointer, "Event TRB Pointer"); + rw_field!( pub, self, - self.0[2]; 22..=31, + self.0.0[2]; 22..=31, vf_interrupter_target, "VF Interrupter Target", u16 ); - rw_field!(pub, self, self.0[3]; 16..=23, vf_id, "VF ID", u8); + + impl_vf_id!(); } -impl_debug_for_trb!(ForceEvent { +impl_debug_from_methods!(ForceEvent { event_trb_pointer, vf_interrupter_target, vf_id }); - -add_trb_with_default!( - NegotiateBandwidth, - "Negotiate Bandwidth Command TRB", - Type::NegotiateBandwidth -); -reserved!(NegotiateBandwidth(Type::NegotiateBandwidth) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=9; - [3]16..=23; +rsvdz_checking_try_from!(ForceEvent { + [0];0..=3, + [2];0..=21, + [3];1..=9, + [3];24..=31, }); + impl NegotiateBandwidth { - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_slot_id!(); } -impl_debug_for_trb!(NegotiateBandwidth { slot_id }); - -add_trb_with_default!( - SetLatencyToleranceValue, - "Set Latency Tolerance Value Command TRB", - Type::SetLatencyToleranceValue -); -reserved!(SetLatencyToleranceValue(Type::SetLatencyToleranceValue) { - [0]0..=31; - [1]0..=31; - [2]0..=31; - [3]1..=9; - [3]28..=31; +impl_debug_from_methods!(NegotiateBandwidth { + slot_id, +}); +rsvdz_checking_try_from!(NegotiateBandwidth { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];16..=23, }); + impl SetLatencyToleranceValue { rw_field!( pub, self, - self.0[3]; 16..=27, + self.0.0[3]; 16..=27, best_effort_latency_tolerance_value, "Best Effort Latency Tolerance Value", u16 ); } -impl_debug_for_trb!(SetLatencyToleranceValue { - best_effort_latency_tolerance_value +impl_debug_from_methods!(SetLatencyToleranceValue { + best_effort_latency_tolerance_value, }); - -add_trb_with_default!( - GetPortBandwidth, - "Get Port Bandwidth Command TRB", - Type::GetPortBandwidth -); -reserved!(GetPortBandwidth(Type::GetPortBandwidth) { - [0]0..=3; - [2]0..=31; - [3]1..=9; - [3]20..=23; +rsvdz_checking_try_from!(SetLatencyToleranceValue { + [0];0..=31, + [1];0..=31, + [2];0..=31, + [3];1..=9, + [3];28..=31, }); + impl GetPortBandwidth { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", + param_align_16!( port_bandwidth_context_pointer, - "Port Bandwidth Context Pointer", - 32, u64 + "Port Bandwidth Context Pointer" ); - rw_field!(pub, self, self.0[3]; 16..=19, dev_speed, "Dev Speed", u8); - rw_field!(pub, self, self.0[3]; 24..=31, hub_slot_id, "Hub Slot ID", u8); + + rw_field!(pub, self, self.0.0[3]; 16..=19, dev_speed, "Dev Speed", u8); + rw_field!(pub, self, self.0.0[3]; 24..=31, hub_slot_id, "Hub Slot ID", u8); } -impl_debug_for_trb!(GetPortBandwidth { +impl_debug_from_methods!(GetPortBandwidth { port_bandwidth_context_pointer, dev_speed, hub_slot_id }); - -add_trb_with_default!(ForceHeader, "Force Header Command TRB", Type::ForceHeader); -reserved!(ForceHeader(Type::ForceHeader) { - [3]1..=9; - [3]16..=23; +rsvdz_checking_try_from!(GetPortBandwidth { + [0];0..=3, + [2];0..=31, + [3];1..=9, + [3];20..=23, }); + impl ForceHeader { - rw_field!(pub, self, self.0[0]; 0..=4, packet_type, "Packet Type", u8); + rw_field!(pub, self, self.0.0[0]; 0..=4, packet_type, "Packet Type", u8); /// Sets the value of the Header Info field. /// /// # Panics /// - /// This method panics if the lowest 5 bits of the `i[0]` are not 0. + /// This method panics if the lowest 5 bits of the `info[0]` are not 0. pub fn set_header_info(&mut self, info: [u32; 3]) -> &mut Self { assert!( info[0].trailing_zeros() >= 5, "The lowest 5 bits of the Header Info Low must be 0." ); - self.0[0].set_bits(5..=31, info[0].get_bits(5..=31)); - self.0[1] = info[1]; - self.0[2] = info[2]; + self.0.0[0].set_bits(5.., info[0].get_bits(5..)); + self.0.0[1] = info[1]; + self.0.0[2] = info[2]; self } /// Returns the value of the Header Info field. #[must_use] pub fn header_info(&self) -> [u32; 3] { - [self.0[0] & 0xffff_ffe0, self.0[1], self.0[2]] + [self.0.0[0] >> 5 << 5, self.0.0[1], self.0.0[2]] } rw_field!( pub, self, - self.0[3]; 24..=31, + self.0.0[3]; 24..=31, root_hub_port_number, "Root Hub Port Number", u8 ); } -impl_debug_for_trb!(ForceHeader { +impl_debug_from_methods!(ForceHeader { packet_type, header_info, - root_hub_port_number + root_hub_port_number, }); - -add_trb_with_default!( - GetExtendedProperty, - "Get Extended Property Command TRB", - Type::GetExtendedProperty -); -reserved!(GetExtendedProperty(Type::GetExtendedProperty) { - [0]0..=3; - [2]16..=31; - [3]1..=9; +rsvdz_checking_try_from!(ForceHeader { + [3];1..=9, + [3];16..=23, }); + impl GetExtendedProperty { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", + param_align_16!( extended_property_context_pointer, - "Extended Property Context Pointer", - 32, u64 + "Extended Property Context Pointer" ); + rw_field!( pub, self, - self.0[2]; 0..=15, + self.0.0[2]; 0..=15, extended_capability_identifier, "Extended Capability Identifier", u16 ); - rw_field!(pub, self, self.0[3]; 16..=18, command_sub_type, "Command Sub Type", u8); - rw_field!(pub, self, self.0[3]; 19..=23, endpoint_id, "Endpoint ID", u8); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + + impl_subtype!(); + impl_ep_id!(); + impl_slot_id!(); } -impl_debug_for_trb!(GetExtendedProperty { +impl_debug_from_methods!(GetExtendedProperty { extended_property_context_pointer, extended_capability_identifier, command_sub_type, endpoint_id, - slot_id + slot_id, }); - -add_trb_with_default!( - SetExtendedProperty, - "Set Extended Property Command TRB", - Type::SetExtendedProperty -); -reserved!(SetExtendedProperty(Type::SetExtendedProperty) { - [0]0..=31; - [1]0..=31; - [2]24..=31; - [3]1..=9; +rsvdz_checking_try_from!(GetExtendedProperty { + [0];0..=3, + [2];16..=31, + [3];1..=9, }); + impl SetExtendedProperty { rw_field!( pub, self, - self.0[2]; 0..=15, + self.0.0[2]; 0..=15, extended_capability_identifier, - "Extended Cpaability Identifier", + "Extended Capability Identifier", u16 ); rw_field!( pub, self, - self.0[2]; 16..=23, + self.0.0[2]; 16..=23, capability_parameter, "Capability Parameter", u8 ); - rw_field!(pub, self, self.0[3]; 16..=18, command_sub_type, "Command Sub Type", u8); - rw_field!(pub, self, self.0[3]; 19..=23, endpoint_id, "Endpoint ID", u8); - rw_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + + impl_subtype!(); + impl_ep_id!(); + impl_slot_id!(); } -impl_debug_for_trb!(SetExtendedProperty { +impl_debug_from_methods!(SetExtendedProperty { extended_capability_identifier, capability_parameter, command_sub_type, endpoint_id, - slot_id + slot_id, }); +rsvdz_checking_try_from!(SetExtendedProperty { + [0];0..=3, + [2];16..=31, + [3];1..=9, +}); \ No newline at end of file diff --git a/src/ring/trb/event.rs b/src/ring/trb/event.rs index d8c5e92..3fb3375 100644 --- a/src/ring/trb/event.rs +++ b/src/ring/trb/event.rs @@ -1,254 +1,222 @@ //! Event TRBs. -use super::Type; use bit_field::BitField; -use core::convert::{TryFrom, TryInto}; +// use core::convert::TryInto; use num_derive::FromPrimitive; use num_traits::FromPrimitive; -allowed! { - /// TRBs which are allowed to be pushed to the Event Ring. - enum { - /// Transfer Event TRB. - TransferEvent, - /// Command Completion Event TRB. - CommandCompletion, - /// Port Status Change Event TRB. - PortStatusChange, - /// Bandwidth Request Event TRB. - BandwidthRequest, - /// Doorbell Event TRB. - Doorbell, - /// Host Controller Event TRB. - HostController, - /// Device Notification Event TRB. - DeviceNotification, - /// MFINDEX Wrap Event TRB. - MfindexWrap - } -} -impl TryFrom<[u32; 4]> for Allowed { - type Error = [u32; 4]; - - fn try_from(raw: [u32; 4]) -> Result { - try_from!( - raw => - TransferEvent, - CommandCompletion, - PortStatusChange, - BandwidthRequest, - Doorbell, - HostController, - DeviceNotification, - MfindexWrap, - ); - Err(raw) - } -} - -macro_rules! completion_code { - ($name:ident) => { - impl $name { - /// Returns the Completion Code. - /// - /// # Errors - /// - /// This method may return an [`Err`] value with the Completion Code that is either reserved or - /// not implemented by this crate. - pub fn completion_code(&self) -> Result { - let c: u8 = self.0[2].get_bits(24..=31).try_into().unwrap(); - CompletionCode::from_u8(c).ok_or(c) - } +macro_rules! impl_cc { + (ro) => { + /// Returns the Completion Code. + /// + /// # Errors + /// + /// This method may return an [`Err`] variant with the Completion Code that is either reserved or + /// not implemented in this crate. + pub fn completion_code(&self) -> Result { + let c: u8 = self.0.0[2].get_bits(24..=31).try_into().unwrap(); + CompletionCode::from_u8(c).ok_or(c) } - }; -} -macro_rules! event { - ($name:ident,$full:expr,$ty:expr) => { - add_trb_with_default!($name, $full, $ty); - completion_code!($name); - }; -} -macro_rules! impl_debug_for_event_trb{ - ($name:ident{})=>{ - impl_debug_for_trb!($name{ - completion_code - }); - }; - ($name:ident { - $($method:ident),* - })=>{ - impl_debug_for_trb!($name{ - completion_code, - $($method),* - }); } } -event!( - PortStatusChange, - "Port Status Change Event TRB", - Type::PortStatusChange -); -reserved!(PortStatusChange(Type::PortStatusChange){ - [0]0..=23; - [1]0..=31; - [2]0..=23; - [3]1..=9; - [3]16..=31; +allowed_trb!("Transfer TRB", { + /// Transfer Event TRB + TransferEvent = 32, + /// Command Completion Event TRB + CommandCompletion = 33, + /// Port Status Change Event TRB + PortStatusChange = 34, + /// Bandwidth Request Event TRB + BandwidthRequest = 35, + /// Doorbell Event TRB + Doorbell = 36, + /// Host Controller Event TRB + HostController = 37, + /// Device Notification Event TRB + DeviceNotification = 38, + /// MFINDEX Wrap Event TRB + MfindexWrap = 39, }); -impl PortStatusChange { - ro_field!(pub, self, self.0[0]; 24..=31, port_id, "Port ID", u8); -} -impl_debug_for_event_trb!(PortStatusChange { port_id }); -event!(TransferEvent, "Transfer Event TRB", Type::TransferEvent); -reserved!(TransferEvent(Type::TransferEvent){ - [3]1..=1; - [3]3..=9; - [3]21..=23; -}); impl TransferEvent { - ro_double_field!(pub, self, self.0; [0, 1], trb_pointer, "TRB Pointer", 32, u64); - ro_field!(pub, self, self.0[2]; 0..=23, trb_transfer_length, "TRB Transfer Length", u32); - ro_bit!(pub, self, self.0[3]; 2, event_data, "Event Data"); - ro_field!(pub, self, self.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); - ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + ro_double_field!(pub, self, self.0.0; [0, 1], trb_pointer, "TRB Pointer (or event data)", 32, u64); + + ro_field!(pub, self, self.0.0[2]; 0..=23, trb_transfer_length, "TRB Transfer Length", u32); + impl_cc!(ro); + + ro_bit!(pub, self, self.0.0[3]; 2, event_data, "Event Data Flag"); + impl_ep_id!(ro); + impl_slot_id!(ro); } -impl_debug_for_event_trb!(TransferEvent { +impl_debug_from_methods!(TransferEvent { trb_pointer, trb_transfer_length, + completion_code, event_data, endpoint_id, - slot_id + slot_id, }); - -event!( - CommandCompletion, - "Command Completion Event TRB", - Type::CommandCompletion -); -reserved!(CommandCompletion(Type::CommandCompletion){ - [0]0..=3; - [3]1..=9; +rsvdz_checking_try_from!(TransferEvent { + [3];1..=1, + [3];3..=9, + [3];21..=23, }); + impl CommandCompletion { ro_double_field!( pub, self, - self.0; [0, 1], + self.0.0; [0, 1], command_trb_pointer, "Command TRB Pointer", 32, u64 ); + ro_field!( pub, self, - self.0[2]; 0..=23, + self.0.0[2]; 0..=23, command_completion_parameter, "Command Completion Parameter", u32 ); - ro_field!(pub, self, self.0[3]; 16..=23, vf_id, "VF ID", u8); - ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_cc!(ro); + + impl_vf_id!(ro); + impl_slot_id!(ro); } -impl_debug_for_event_trb!(CommandCompletion { +impl_debug_from_methods!(CommandCompletion { command_trb_pointer, command_completion_parameter, + completion_code, vf_id, - slot_id + slot_id, +}); +rsvdz_checking_try_from!(CommandCompletion { + [0];0..=3, + [3];1..=9, }); -event!( - BandwidthRequest, - "Bandwidth Request Event TRB", - Type::BandwidthRequest -); -reserved!(BandwidthRequest(Type::BandwidthRequest){ - [0]0..=31; - [1]0..=31; - [2]0..=23; - [3]1..=9; - [3]16..=23; +impl PortStatusChange { + ro_field!(pub, self, self.0.0[0]; 24..=31, port_id, "Port ID", u8); + + impl_cc!(ro); +} +impl_debug_from_methods!(PortStatusChange { + port_id, + completion_code, }); +rsvdz_checking_try_from!(PortStatusChange { + [0];0..=23, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=31, +}); + impl BandwidthRequest { - ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); -} -impl_debug_for_event_trb!(BandwidthRequest { slot_id }); + impl_cc!(ro); -event!(Doorbell, "Doorbell Event TRB", Type::Doorbell); -reserved!(Doorbell(Type::Doorbell){ - [0]5..=31; - [1]0..=31; - [2]0..=23; - [3]1..=9; + impl_slot_id!(ro); +} +impl_debug_from_methods!(BandwidthRequest { + completion_code, + slot_id, +}); +rsvdz_checking_try_from!(BandwidthRequest { + [0];0..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=23, }); + impl Doorbell { - ro_field!(pub, self, self.0[0]; 0..=4, db_reason, "DB Reason", u8); - ro_field!(pub, self, self.0[3]; 16..=23, vf_id, "VF ID", u8); - ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + ro_field!(pub, self, self.0.0[0]; 0..=4, db_reason, "DB Reason", u8); + + impl_cc!(ro); + + impl_vf_id!(ro); + impl_slot_id!(ro); } -impl_debug_for_event_trb!(Doorbell { +impl_debug_from_methods!(Doorbell { db_reason, + completion_code, vf_id, - slot_id + slot_id, }); - -event!( - HostController, - "Host Controller Event TRB", - Type::HostController -); -reserved!(HostController(Type::HostController){ - [0]0..=31; - [1]0..=31; - [2]0..=23; - [3]1..=9; - [3]16..=31; +rsvdz_checking_try_from!(Doorbell { + [0];5..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, }); -impl_debug_for_event_trb!(HostController {}); -event!( - DeviceNotification, - "Device Notification Event TRB", - Type::DeviceNotification -); -reserved!(DeviceNotification(Type::DeviceNotification){ - [0]0..=3; - [2]0..=23; - [3]1..=9; - [3]16..=23; +impl HostController { + impl_cc!(ro); +} +impl_debug_from_methods!(HostController { + completion_code, +}); +rsvdz_checking_try_from!(HostController { + [0];0..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=31, }); + impl DeviceNotification { - ro_field!(pub, self, self.0[0]; 4..=7, notification_type, "Notification Type", u8); + ro_field!( + pub, self, + self.0.0[0]; 4..=7, + notification_type, + "Notification Type", + u8 + ); ro_double_field!( pub(self), self, - self.0; [0, 1], + self.0.0; [0, 1], device_notification_data_raw, "Device Notification Data Raw", 32, u64 ); - /// Returns the value of the Device Notification Data field. #[must_use] pub fn device_notification_data(&self) -> u64 { self.device_notification_data_raw() >> 8 } - ro_field!(pub, self, self.0[3]; 24..=31, slot_id, "Slot ID", u8); + impl_cc!(ro); + + impl_slot_id!(ro); } -impl_debug_for_event_trb!(DeviceNotification { +impl_debug_from_methods!(DeviceNotification { notification_type, device_notification_data, - slot_id + completion_code, + slot_id, +}); +rsvdz_checking_try_from!(DeviceNotification { + [0];0..=3, + [2];0..=23, + [3];1..=9, + [3];16..=31, }); -event!(MfindexWrap, "MFINDEX Wrap Event TRB", Type::MfindexWrap); -reserved!(MfindexWrap(Type::MfindexWrap){ - [0]0..=31; - [1]0..=31; - [2]0..=23; - [3]1..=9; - [3]16..=31; +impl MfindexWrap { + impl_cc!(ro); +} +impl_debug_from_methods!(MfindexWrap { + completion_code, +}); +rsvdz_checking_try_from!(MfindexWrap { + [0];0..=31, + [1];0..=31, + [2];0..=23, + [3];1..=9, + [3];16..=31, }); -impl_debug_for_event_trb!(MfindexWrap {}); + /// The TRB Completion Codes. /// @@ -345,25 +313,4 @@ pub enum CompletionCode { SecondaryBandwidthError = 35, /// Asserted if an error is detected on a USB2 protocol endpoint for a split transaction. SplitTransactionError = 36, -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn try_from_macro() { - let raw = [ - 0x00c8_8800, // address low - 0x0000_0000, // address high - 0x01_000000, // completion code 1, transfer length 0 - 0x0000_8401, // endpoint id 0, slot id 0, type 33, event data 0, cycle bit 1 - ]; - assert_eq!( - Allowed::try_from(raw), - Ok(Allowed::CommandCompletion( - CommandCompletion::try_from(raw).unwrap() - )), - ); - } -} +} \ No newline at end of file diff --git a/src/ring/trb/mod.rs b/src/ring/trb/mod.rs index 250207c..6297cf3 100644 --- a/src/ring/trb/mod.rs +++ b/src/ring/trb/mod.rs @@ -1,293 +1,173 @@ //! TRB (Transfer Request Block). -use bit_field::BitField; -use num_derive::FromPrimitive; +/// The bytes of a TRB. +pub const BYTES: usize = 16; -macro_rules! reserved{ - ($name:ident($ty:expr) { - $([$index:expr] $range:expr);* $(;)? - })=>{ - impl TryFrom<[u32; 4]> for $name{ - type Error=[u32; 4]; +macro_rules! param_align_16 { + ($method:ident,$name:literal) => { + rw_double_zero_trailing!( + pub, self, + self.0.0; [0, 1]; 4~; "16-byte aligned", + $method, $name, 32, u64 + ); + } +} - fn try_from(raw:[u32;4])->Result{ - use crate::ring::trb::Type; +macro_rules! impl_ring_segment_pointer { + () => { + param_align_16!(ring_segment_pointer, "Ring Segment Pointer"); + } +} - $(if raw[$index].get_bits($range) != 0{ - return Err(raw); - })* +macro_rules! impl_tc { + () => { + rw_bit!(pub, self, self.0.0[3]; 1, toggle_cycle, "Toggle Cycle"); + } +} - if raw[3].get_bits(10..=15)!=$ty as _ { - return Err(raw); - } +macro_rules! impl_ioc { + () => { + rw_bit!( + pub, self, + self.0.0[3]; 5, + interrupt_on_completion, + "Interrupt On Completion" + ); + } +} - Ok(Self(raw)) - } - } +macro_rules! impl_ep_id { + () => { + rw_field!(pub, self, self.0.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); + }; + (ro) => { + ro_field!(pub, self, self.0.0[3]; 16..=20, endpoint_id, "Endpoint ID", u8); }; } -macro_rules! try_from { - ($raw:ident => $($name:ident $(($t:ident))?),* $(,)?) => {{ - if let Some(ty) = Type::from_u32($raw[3].get_bits(10..=15)) { - paste::paste! { - match ty { - $( - Type::[<$name $($t)?>]=> { - if let Ok(t) = $name::try_from($raw) { - return Ok(Self::$name(t)); - } - } - )* - _ => {} - } - } - } - }}; -} -macro_rules! add_trb { - ($name:ident,$full:expr,$ty:expr) => { - #[doc = $full ] - #[repr(transparent)] - #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] - pub struct $name([u32; 4]); - impl $name { - /// Returns the wrapped array. - #[must_use] - pub fn into_raw(self) -> [u32; 4] { - self.0 - } - - rw_bit!(pub, self, self.0[3]; 0, cycle_bit, "Cycle bit"); - fn set_trb_type(&mut self) -> &mut Self { - use crate::ring::trb::Type; - use bit_field::BitField; - self.0[3].set_bits(10..=15, $ty as _); - self - } - } - impl AsRef<[u32]> for $name { - fn as_ref(&self) -> &[u32] { - &self.0 - } - } - impl From<$name> for [u32; 4] { - fn from(t: $name) -> Self { - t.0 - } - } +macro_rules! impl_vf_id { + () => { + rw_field!(pub, self, self.0.0[3]; 16..=23, vf_id, "VF ID", u8); }; -} -macro_rules! impl_default_simply_adds_trb_id { - ($name:ident,$full:expr) => { - impl $name{ - paste::paste! { - #[doc = "Creates a new " $full ".\n\nThis method sets the sets the value of the TRB Type field properly. All the other fieldds are set to 0."] - #[must_use] - pub fn new()->Self{ - *Self([0;4]).set_trb_type() - } - } - } - impl Default for $name { - fn default() -> Self { - Self::new() - } - } + (ro) => { + ro_field!(pub, self, self.0.0[3]; 16..=23, vf_id, "VF ID", u8); }; } -macro_rules! add_trb_with_default { - ($name:ident,$full:expr,$type:expr) => { - add_trb!($name, $full, $type); - impl_default_simply_adds_trb_id!($name, $full); + +macro_rules! impl_slot_id { + () => { + rw_field!(pub, self, self.0.0[3]; 24..=31, slot_id, "Slot ID", u8); + }; + (ro) => { + ro_field!(pub, self, self.0.0[3]; 24..=31, slot_id, "Slot ID", u8); }; -} -macro_rules! impl_debug_for_trb{ - ($name:ident { - $($method:ident),* - })=>{ - impl_debug_from_methods!{ - $name { - $($method,)* - cycle_bit - } - } - } } -macro_rules! allowed { - ( - $(#[$outer:meta])* - enum { - $($(#[$doc:meta])* $variant:ident),+ - } - ) => { - $(#[$outer])* - #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] - pub enum Allowed { - $($(#[$doc])* $variant($variant)),+ - } - impl Allowed{ - /// Sets the value of the Cycle Bit. - pub fn set_cycle_bit(&mut self)->&mut Self{ - match self{ - $( - Self::$variant(ref mut v) => { - v.set_cycle_bit(); - } - ),+ +macro_rules! allowed_trb { + ($name:literal, { + $($(#[$docs:meta])* $($deco:literal)? $variant:ident = $val:literal),+ $(,)? + }) => { + // defining AllowedType + paste::paste!( + #[doc = "Allowed TRB Type for " $name "."] + #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] + pub enum AllowedType { + $( + $(#[$docs])* + #[doc = ", " $val ""] + $variant = $val + ),+ + } + ); + + // defining common block + paste::paste!( + #[doc = "A raw " $name " Block."] + #[repr(transparent)] + #[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Hash)] + pub struct TRB(pub(crate) [u32; 4]); + impl TRB { + pub(crate) fn new(ty: AllowedType) -> Self { + *Self([0; 4]) + .set_trb_type(ty) } - self - } - /// Clears the value of the Cycle Bit. - pub fn clear_cycle_bit(&mut self)->&mut Self{ - match self{ - $( - Self::$variant(ref mut v) => { - v.clear_cycle_bit(); - } - ),+ + pub(crate) fn trb_type(&self) -> Option { + AllowedType::from_u32(self.0[3].get_bits(10..=15)) } - self + + fn set_trb_type(&mut self, ty: AllowedType) -> &mut Self { + self.0[3].set_bits(10..=15, ty as u32); + self + } + + rw_bit!(pub, self, self.0[3]; 0, cycle_bit, "Cycle"); } + ); + + // defining individual TRB types + // all TRB types require `Self::new()`. Derive by simple default or manually implement it. + $( + paste::paste! { + #[doc = "A "] + $(#[$docs])* + #[doc = "."] + #[repr(transparent)] + #[derive(Clone, Copy, PartialEq, Eq, Hash)] + pub struct $variant(TRB); + + impl From<$variant> for TRB { + fn from(v: $variant) -> Self { + v.0 + } + } - /// Returns the value of the Cycle Bit. - #[must_use] - pub fn cycle_bit(&self)->bool{ - match self{ - $( Self::$variant(ref v) => v.cycle_bit() ),+ + impl Default for $variant { + fn default() -> Self { + Self::new() + } } + + simple_default!($(#[$docs])* $($deco)? $variant); // this branches whether $def is "default" or empty. } + )+ + } +} - /// Returns the wrapped array. +macro_rules! simple_default { + ($(#[$docs:meta])* $variant:ident) => { + impl $variant{ + #[doc = "Creates a new "] + $(#[$docs])* + #[doc = ".\n\nThis method sets the value of the TRB Type field properly. "] + #[doc = "All the other fields are set to 0."] #[must_use] - pub fn into_raw(self)->[u32;4]{ - match self{ - $( Self::$variant(v) => v.into_raw() ),+ - } + pub fn new() -> Self{ + Self(TRB::new(AllowedType::$variant)) } } - impl AsRef<[u32]> for Allowed { - fn as_ref(&self) -> &[u32]{ - match self{ - $( Self::$variant(ref v) => v.as_ref() ),+ + }; + ($(#[$docs:meta])* "no-new" $variant:ident) => {}; +} + +macro_rules! rsvdz_checking_try_from { + ($name:ident { + $([$index:expr];$range:expr),* $(,)? + }) => { + impl TryFrom for $name { + type Error = TRB; + + fn try_from(block: TRB) -> Result { + if block.trb_type() != Some(AllowedType::$name) + $(|| block.0[$index].get_bits($range) != 0 )* { + return Err(block); } + Ok(Self(block)) } } - $( - impl From<$variant> for Allowed{ - fn from(v:$variant)->Self{ - Self::$variant(v) - } - } - )+ - }; + } } -pub mod command; -pub mod event; pub mod transfer; - -/// The bytes of a TRB. -pub const BYTES: usize = 16; - -add_trb_with_default!(Link, "Link TRB", Type::Link); -reserved!(Link(Type::Link){ - [0]0..=3; - [2]0..=21; - [3]2..=3; - [3]6..=9; - [3]16..=31; -}); -impl Link { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 4~; "16-byte aligned", - ring_segment_pointer, - "Ring Segment Pointer", - 32, u64 - ); - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u32); - rw_bit!(pub, self, self.0[3]; 1, toggle_cycle, "Toggle Cycle"); - rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); - rw_bit!(pub, self, self.0[3]; 5, interrupt_on_completion, "Interrupt On Completion"); -} -impl_debug_for_trb!(Link { - ring_segment_pointer, - interrupter_target, - toggle_cycle, - chain_bit, - interrupt_on_completion -}); - -/// TRB Type. -#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] -pub enum Type { - /// Normal TRB, 1 - Normal = 1, - /// Setup Stage TRB, 2 - SetupStage = 2, - /// Data Stage TRB, 3 - DataStage = 3, - /// Status Stage TRB, 4 - StatusStage = 4, - /// Isoch TRB, 5 - Isoch = 5, - /// Link TRB, 6 - Link = 6, - /// Event Data TRB, 7 - EventData = 7, - /// No Op TRB (Transfer), 8 - NoopTransfer = 8, - /// Enable Slot Command TRB, 9 - EnableSlot = 9, - /// Disable Slot Command TRB, 10 - DisableSlot = 10, - /// Address Device Command TRB, 11 - AddressDevice = 11, - /// Configure Endpoint Command TRB, 12 - ConfigureEndpoint = 12, - /// Evaluate Context Command TRB, 13 - EvaluateContext = 13, - /// Reset Endpoint Command TRB, 14 - ResetEndpoint = 14, - /// Stop Endpoint Command TRB, 15 - StopEndpoint = 15, - /// Set TR Dequeue Pointer Command TRB, 16 - SetTrDequeuePointer = 16, - /// Reset Device Command TRB, 17 - ResetDevice = 17, - /// Force Event Command TRB, 18 - ForceEvent = 18, - /// Negotiate Bandwidth Command TRB, 19 - NegotiateBandwidth = 19, - /// Set Latency Tolerance Value Command TRB, 20 - SetLatencyToleranceValue = 20, - /// Get Port Bandwidth Command TRB, 21 - GetPortBandwidth = 21, - /// Force Header Command TRB, 22 - ForceHeader = 22, - /// No Op Command TRB, 23 - NoopCommand = 23, - /// Get Extended Property Command TRB, 24 - GetExtendedProperty = 24, - /// Set Extended Property Command TRB, 25 - SetExtendedProperty = 25, - /// Transfer Event TRB, 32 - TransferEvent = 32, - /// Command Completion Event TRB, 33 - CommandCompletion = 33, - /// Port Status Change Event TRB, 34 - PortStatusChange = 34, - /// Bandwidth Request Event TRB, 35 - BandwidthRequest = 35, - /// Doorbell Event TRB, 36 - Doorbell = 36, - /// Host Controller Event TRB, 37 - HostController = 37, - /// Device Notification Event TRB, 38 - DeviceNotification = 38, - /// MFINDEX Wrap Event TRB, 39 - MfindexWrap = 39, -} +pub mod event; +pub mod command; \ No newline at end of file diff --git a/src/ring/trb/transfer.rs b/src/ring/trb/transfer.rs index c71c930..5968618 100644 --- a/src/ring/trb/transfer.rs +++ b/src/ring/trb/transfer.rs @@ -1,235 +1,168 @@ //! Transfer TRBs. -use super::{Link, Type}; use bit_field::BitField; // use core::convert::TryInto; use num_derive::FromPrimitive; use num_traits::FromPrimitive; -allowed! { - /// TRBs which are allowed to be pushed to the Transfer Ring. - enum { - /// Normal TRB. - Normal, - /// Setup Stage TRB. - SetupStage, - /// Data Stage TRB. - DataStage, - /// Status Stage TRB. - StatusStage, - /// Isoch TRB. - Isoch, - /// Link TRB. - Link, - /// Event Data TRB. - EventData, - /// No Op TRB. - Noop - } -} -impl Allowed { - /// Sets the value of the Interrupt On Completion field. - pub fn set_interrupt_on_completion(&mut self) { - macro_rules! arm{ - ($($variant:ident),*)=>{ - match self { - $(Self::$variant(ref mut x)=>{ - x.set_interrupt_on_completion(); - },)* - } - }; - } - - arm!( - Normal, - SetupStage, - DataStage, - StatusStage, - Isoch, - Link, - EventData, - Noop +macro_rules! impl_data_buffer_pointer { + () => { + rw_double_field!( + pub, self, + self.0.0; [0, 1], + data_buffer_pointer, + "Data Buffer Pointer", + 32, u64 ); } +} - /// Clears the Interrupt On Completion bit. - pub fn clear_interrupt_on_completion(&mut self) { - macro_rules! arm{ - ($($variant:ident),*)=>{ - match self { - $(Self::$variant(ref mut x)=>{ - x.clear_interrupt_on_completion(); - },)* - } - }; - } - - arm!( - Normal, - SetupStage, - DataStage, - StatusStage, - Isoch, - Link, - EventData, - Noop - ); - } +// 17-bit trb transfer length only. +macro_rules! impl_trb_transfer_length { + () => { + rw_field!(pub, self, self.0.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); + }; + (prv) => { + rw_field!(pub(self), self, self.0.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); + }; +} - /// Returns the value of the Interrupt On Completion field. - #[must_use] - pub fn interrupt_on_completion(&self) -> bool { - macro_rules! arm{ - ($($variant:ident),*)=>{ - match self { - $(Self::$variant(x)=>{ - x.interrupt_on_completion() - },)* - } - }; - } +macro_rules! impl_td_size { + () => { + rw_field!(pub, self, self.0.0[2]; 17..=21, td_size, "TD Size", u8); + }; +} - arm!( - Normal, - SetupStage, - DataStage, - StatusStage, - Isoch, - Link, - EventData, - Noop - ) - } +macro_rules! impl_interrupter_target { + () => { + rw_field!(pub, self, self.0.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + }; } -impl TryFrom<[u32; 4]> for Allowed { - type Error = [u32; 4]; - fn try_from(raw: [u32; 4]) -> Result { - try_from!( - raw => - Normal, - SetupStage, - DataStage, - StatusStage, - Isoch, - Link, - EventData, - Noop(Transfer), +macro_rules! impl_ent { + () => { + rw_bit!(pub, self, self.0.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); + }; +} +macro_rules! impl_isp { + () => { + rw_bit!( + pub, self, + self.0.0[3]; 2, + interrupt_on_short_packet, + "Interrupt on Short Packet" ); - Err(raw) - } + }; } - -macro_rules! interrupt_on_completion { - ($name:ident) => { - impl $name { - rw_bit!(pub, self, self.0[3]; 5, interrupt_on_completion, "Interrupt On Completion"); - } +macro_rules! impl_ns { + () => { + rw_bit!(pub, self, self.0.0[3]; 3, no_snoop, "No Snoop"); + }; +} +macro_rules! impl_ch { + () => { + rw_bit!(pub, self, self.0.0[3]; 4, chain_bit, "Chain"); }; } -macro_rules! transfer_trb { - ($name:ident,$full:expr,$type:expr) => { - add_trb!($name, $full, $type); - interrupt_on_completion!($name); +macro_rules! impl_idt { + () => { + rw_bit!(pub, self, self.0.0[3]; 6, immediate_data, "Immediate Data"); }; } -macro_rules! transfer_trb_with_default { - ($name:ident,$full:expr,$type:expr) => { - add_trb_with_default!($name, $full, $type); - interrupt_on_completion!($name); +macro_rules! implprv_idt { + () => { + rw1s_bit!(pub(self), self, self.0.0[3]; 6, immediate_data, "Immediate Data"); }; } -macro_rules! impl_debug_for_transfer_trb{ - ($name:ident {})=>{ - impl_debug_for_trb!($name{ - interrupt_on_completion - }); +macro_rules! impl_bei { + () => { + rw_bit!(pub, self, self.0.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); }; - ($name:ident { - $($method:ident),*$(,)? - })=>{ - impl_debug_for_trb!($name{ - interrupt_on_completion, - $($method),* - }); +} +macro_rules! impl_dir { + () => { + rw_bit!(pub, self, self.0.0[3]; 16, direction, "Direction (is-in)"); } } -transfer_trb_with_default!(Normal, "Normal TRB", Type::Normal); -reserved!(Normal(Type::Normal) { - [3]7..=8; - [3]16..=31; +allowed_trb!("Transfer TRB", { + /// Normal TRB + Normal = 1, + /// Setup Stage TRB + "no-new" SetupStage = 2, + /// Data Stage TRB + DataStage = 3, + /// Status Stage TRB + StatusStage = 4, + /// Isoch TRB + Isoch = 5, + /// Link TRB + Link = 6, + /// Event Data TRB + EventData = 7, + /// No Op Transfer TRB + NoOp = 8, }); + impl Normal { - rw_double_field!( - pub, self, - self.0; [0, 1], - data_buffer_pointer, - "Data Buffer Pointer", - 32, u64 - ); - rw_field!(pub, self, self.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); - rw_field!(pub, self, self.0[2]; 17..=21, td_size, "TD Size", u8); - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!( - pub, self, - self.0[3]; 2, - interrupt_on_short_packet, - "Interrupt-on Short Packet" - ); - rw_bit!(pub, self, self.0[3]; 3, no_snoop, "No Snoop"); - rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); - rw_bit!(pub, self, self.0[3]; 6, immediate_data, "Immediate Data"); - rw_bit!(pub, self, self.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); -} -impl_debug_for_transfer_trb! { - Normal { - data_buffer_pointer, - trb_transfer_length, - td_size, - interrupter_target, - cycle_bit, - evaluate_next_trb, - interrupt_on_short_packet, - no_snoop, - chain_bit, - interrupt_on_completion, - immediate_data, - block_event_interrupt, - } -} + impl_data_buffer_pointer!(); + + impl_trb_transfer_length!(); + impl_td_size!(); + impl_interrupter_target!(); -transfer_trb!(SetupStage, "Setup Stage TRB", Type::SetupStage); -reserved!(SetupStage(Type::SetupStage) { - [2]17..=21; - [3]1..=4; - [3]7..=9; - [3]18..=31; + impl_ent!(); + impl_isp!(); + impl_ns!(); + impl_ch!(); + impl_ioc!(); + impl_idt!(); + impl_bei!(); +} +impl_debug_from_methods!(Normal { + data_buffer_pointer, + trb_transfer_length, + td_size, + interrupter_target, + evaluate_next_trb, + interrupt_on_short_packet, + no_snoop, + chain_bit, + interrupt_on_completion, + immediate_data, + block_event_interrupt, }); +rsvdz_checking_try_from!(Normal { + [3];7..=8, + [3];16..=31, +}); + impl SetupStage { /// Creates a new Setup Stage TRB. /// - /// This method sets the value of the TRB Type, TRB Transfer Length, and the Immediate Data field properly. All the - /// other fields are set to 0. + /// This method sets the value of the TRB Type, TRB Transfer Length, and the Immediate Data field properly. All the other fields are set to 0. #[must_use] pub fn new() -> Self { - *Self([0; 4]) - .set_trb_type() - .set_idt() - .set_trb_transfer_length() + *Self(TRB::new(AllowedType::SetupStage)) + .set_immediate_data() + .set_trb_transfer_length(8) } - rw_field!(pub, self, self.0[0]; 0..=7, request_type, "bmRequestType", u8); - rw_field!(pub, self, self.0[0]; 8..=15, request, "bRequest", u8); - rw_field!(pub, self, self.0[0]; 16..=31, value, "wValue", u16); - rw_field!(pub, self, self.0[1]; 0..=15, index, "wIndex", u16); - rw_field!(pub, self, self.0[1]; 16..=31, length, "wLength", u16); - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); + rw_field!(pub, self, self.0.0[0]; 0..=7, request_type, "bmRequestType", u8); + rw_field!(pub, self, self.0.0[0]; 8..=15, request, "bRequest", u8); + rw_field!(pub, self, self.0.0[0]; 16..=31, value, "wValue", u16); + rw_field!(pub, self, self.0.0[1]; 0..=15, index, "wIndex", u16); + rw_field!(pub, self, self.0.0[1]; 16..=31, length, "wLength", u16); + + impl_trb_transfer_length!(prv); + impl_interrupter_target!(); + + impl_ioc!(); + implprv_idt!(); /// Sets the value of the Transfer Type field. pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self { - self.0[3].set_bits(16..=17, t as _); + self.0.0[3].set_bits(16..=17, t as _); self } @@ -240,74 +173,45 @@ impl SetupStage { /// This method panics if the Transfer Type field contains 1 which is reserved. #[must_use] pub fn transfer_type(&self) -> TransferType { - FromPrimitive::from_u32(self.0[3].get_bits(16..=17)).expect("Transfer Type 1 is reserved.") - } - - fn set_idt(&mut self) -> &mut Self { - self.0[3].set_bit(6, true); - self - } - - fn set_trb_transfer_length(&mut self) -> &mut Self { - self.0[2].set_bits(0..=16, 8); - self - } -} -impl Default for SetupStage { - fn default() -> Self { - Self::new() + FromPrimitive::from_u32(self.0.0[3].get_bits(16..=17)) + .expect("Transfer Type 1 is reserved.") } } -impl_debug_for_transfer_trb!(SetupStage { +impl_debug_from_methods!(SetupStage { request_type, request, value, index, length, + trb_transfer_length, + interrupter_target, interrupt_on_completion, + immediate_data, // always true transfer_type, }); - -transfer_trb_with_default!(DataStage, "Data Stage TRB", Type::DataStage); -reserved!(DataStage(Type::DataStage) { - [3]7..=9; - [3]17..=31; +rsvdz_checking_try_from!(SetupStage { // this won't check IDT and transfer length field. + [2];17..=21, + [3];1..=4, + [3];7..=9, + [3];18..=31, }); + impl DataStage { - rw_double_field!( - pub, self, - self.0; [0, 1], - data_buffer_pointer, - "Data Buffer Pointer", - 32, u64 - ); - rw_field!(pub, self, self.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); - rw_field!(pub, self, self.0[2]; 17..=21, td_size, "TD Size", u8); - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!( - pub, self, - self.0[3]; 2, - interrupt_on_short_packet, - "Interrupt-on Short Packet" - ); - rw_bit!(pub, self, self.0[3]; 3, no_snoop, "No Snoop"); - rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); - rw_bit!(pub, self, self.0[3]; 6, immediate_data, "Immediate Data"); + impl_data_buffer_pointer!(); - /// Sets the value of the Direction field. - pub fn set_direction(&mut self, d: Direction) -> &mut Self { - self.0[3].set_bit(16, d.into()); - self - } + impl_trb_transfer_length!(); + impl_td_size!(); + impl_interrupter_target!(); - /// Returns the value of the Direction field. - #[must_use] - pub fn direction(&self) -> Direction { - self.0[3].get_bit(16).into() - } + impl_ent!(); + impl_isp!(); + impl_ns!(); + impl_ch!(); + impl_ioc!(); + impl_idt!(); + impl_dir!(); } -impl_debug_for_transfer_trb!(DataStage { +impl_debug_from_methods!(DataStage { data_buffer_pointer, trb_transfer_length, td_size, @@ -318,70 +222,63 @@ impl_debug_for_transfer_trb!(DataStage { chain_bit, interrupt_on_completion, immediate_data, - direction + direction, }); - -transfer_trb_with_default!(StatusStage, "Status Stage TRB", Type::StatusStage); -reserved!(StatusStage(Type::StatusStage) { - [0]0..=31; - [1]0..=31; - [2]0..=21; - [3]2..=3; - [3]6..=9; - [3]17..=31; +rsvdz_checking_try_from!(DataStage { + [3];7..=9, + [3];17..=31, }); + impl StatusStage { - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); - rw_bit!(pub, self, self.0[3]; 16, direction, "Direction"); -} -impl_debug_for_transfer_trb! { - StatusStage { - interrupter_target, - evaluate_next_trb, - chain_bit, - interrupt_on_completion, - direction, - } + impl_interrupter_target!(); + + impl_ent!(); + impl_ch!(); + impl_ioc!(); + impl_dir!(); } +impl_debug_from_methods!(StatusStage { + interrupter_target, + evaluate_next_trb, + chain_bit, + interrupt_on_completion, + direction, +}); +rsvdz_checking_try_from!(StatusStage { + [0];0..=31, + [1];0..=31, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];17..=31, +}); -transfer_trb_with_default!(Isoch, "Isoch TRB", Type::Isoch); -reserved!(Isoch(Type::Isoch) {}); impl Isoch { - rw_double_field!( - pub, self, - self.0; [0, 1], - data_buffer_pointer, - "Data Buffer Pointer", - 32, u64 - ); - rw_field!(pub, self, self.0[2]; 0..=16, trb_transfer_length, "TRB Transfer Length", u32); - rw_field!(pub, self, self.0[2]; 17..=21, td_size_or_tbc, "TD Size/TBC", u8); - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!( - pub, self, - self.0[3]; 2, - interrupt_on_short_packet, - "Interrupt on Short Packet" - ); - rw_bit!(pub, self, self.0[3]; 3, no_snoop, "No Snoop"); - rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); - rw_bit!(pub, self, self.0[3]; 6, immediate_data, "Immediate Data"); - rw_field!(pub, self, self.0[3]; 7..=8, transfer_burst_count, "Transfer Burst Count", u8); - rw_bit!(pub, self, self.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); + impl_data_buffer_pointer!(); + + impl_trb_transfer_length!(); + rw_field!(pub, self, self.0.0[2]; 17..=21, td_size_or_tbc, "TD Size/TBC", u8); + impl_interrupter_target!(); + + impl_ent!(); + impl_isp!(); + impl_ns!(); + impl_ch!(); + impl_ioc!(); + impl_idt!(); + rw_field!(pub, self, self.0.0[3]; 7..=8, tbc_or_sts, "TBC/TRBSts", u8); + impl_bei!(); rw_field!( pub, self, - self.0[3]; 16..=19, + self.0.0[3]; 16..=19, transfer_last_burst_packet_count, "Transfer Last Burst Packet Count", u8 ); - rw_field!(pub, self, self.0[3]; 20..=30, frame_id, "Frame ID", u16); - rw_bit!(pub, self, self.0[3]; 31, start_isoch_asap, "Start Isoch ASAP"); + rw_field!(pub, self, self.0.0[3]; 20..=30, frame_id, "Frame ID", u16); + rw_bit!(pub, self, self.0.0[3]; 31, start_isoch_asap, "Start Isoch ASAP"); } -impl_debug_for_transfer_trb!(Isoch { +impl_debug_from_methods!(Isoch { data_buffer_pointer, trb_transfer_length, td_size_or_tbc, @@ -390,87 +287,89 @@ impl_debug_for_transfer_trb!(Isoch { interrupt_on_short_packet, no_snoop, chain_bit, + interrupt_on_completion, immediate_data, - transfer_burst_count, + tbc_or_sts, block_event_interrupt, transfer_last_burst_packet_count, frame_id, - start_isoch_asap + start_isoch_asap, }); +rsvdz_checking_try_from!(Isoch {}); + +impl Link { + impl_ring_segment_pointer!(); -transfer_trb_with_default!(EventData, "Event Data TRB", Type::EventData); -reserved!(EventData(Type::EventData) { - [2]0..=21; - [3]2..=3; - [3]6..=8; - [3]16..=31; + impl_interrupter_target!(); + + impl_tc!(); + impl_ch!(); + impl_ioc!(); +} +rsvdz_checking_try_from!(Link { + [0];0..=3, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];16..=31, +}); +impl_debug_from_methods!(Link { + ring_segment_pointer, + interrupter_target, + toggle_cycle, + chain_bit, + interrupt_on_completion, }); + impl EventData { rw_double_field!( pub, self, - self.0; [0, 1], + self.0.0; [0, 1], event_data, "Event Data", 32, u64 ); - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); - rw_bit!(pub, self, self.0[3]; 9, block_event_interrupt, "Block Event Interrupt"); + impl_interrupter_target!(); + impl_ent!(); + impl_ch!(); + impl_ioc!(); + impl_bei!(); } -impl_debug_for_transfer_trb!(EventData { +impl_debug_from_methods!(EventData { event_data, interrupter_target, evaluate_next_trb, chain_bit, - block_event_interrupt + interrupt_on_completion, + block_event_interrupt, }); - -transfer_trb_with_default!(Noop, "No Op TRB", Type::NoopTransfer); -reserved!(Noop(Type::NoopTransfer) { - [0]0..=31; - [1]0..=31; - [2]0..=21; - [3]2..=3; - [3]6..=9; - [3]16..=31; +rsvdz_checking_try_from!(EventData { + [2];0..=21, + [3];2..=3, + [3];6..=8, + [3];16..=31, }); -impl Noop { - rw_field!(pub, self, self.0[2]; 22..=31, interrupter_target, "Interrupter Target", u16); - rw_bit!(pub, self, self.0[3]; 1, evaluate_next_trb, "Evaluate Next TRB"); - rw_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain bit"); + +impl NoOp { + impl_interrupter_target!(); + impl_ent!(); + impl_ch!(); + impl_ioc!(); } -impl_debug_for_transfer_trb!(Noop { +impl_debug_from_methods!(NoOp { interrupter_target, evaluate_next_trb, - chain_bit + chain_bit, + interrupt_on_completion, +}); +rsvdz_checking_try_from!(NoOp { + [0];0..=31, + [1];0..=31, + [2];0..=21, + [3];2..=3, + [3];6..=9, + [3];16..=31, }); - -/// The direction of the data transfer. -#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] -pub enum Direction { - /// Out (Write Data) - Out = 0, - /// In (Read Data) - In = 1, -} -impl From for bool { - fn from(d: Direction) -> Self { - match d { - Direction::Out => false, - Direction::In => true, - } - } -} -impl From for Direction { - fn from(b: bool) -> Self { - if b { - Direction::In - } else { - Direction::Out - } - } -} /// Transfer Type. #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)] @@ -482,27 +381,4 @@ pub enum TransferType { Out = 2, /// In Data Stage. In = 3, -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn normal_data_buffer_pointer() { - let mut normal = Normal::new(); - let pointer = 0x12345678_9abcdef0; - normal.set_data_buffer_pointer(pointer); - let pointer_read = normal.data_buffer_pointer(); - assert_eq!(pointer, pointer_read); - } - - #[test] - fn isoch_data_buffer_pointer() { - let mut isoch = Isoch::new(); - let pointer = 0xabcd1234_567890ef; - isoch.set_data_buffer_pointer(pointer); - let pointer_read = isoch.data_buffer_pointer(); - assert_eq!(pointer, pointer_read); - } -} +} \ No newline at end of file From dfbeec505bcb491628b60447bb8b563d67a97d6b Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Wed, 6 Dec 2023 16:43:01 +0000 Subject: [PATCH 11/17] cargo fmt --- src/macros.rs | 6 +++--- src/registers/operational.rs | 4 ++-- src/ring/mod.rs | 2 +- src/ring/trb/command.rs | 28 ++++++++++------------------ src/ring/trb/event.rs | 17 ++++++----------- src/ring/trb/mod.rs | 11 +++++------ src/ring/trb/transfer.rs | 10 +++++----- 7 files changed, 32 insertions(+), 46 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 3b62471..80d4681 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -229,7 +229,7 @@ macro_rules! double_field_getter { $vis fn $method(&$self_) -> $ty { let lo = $arr[$off_lo] as $ty; let hi = $arr[$off_hi] as $ty; - + (hi << $bits) | lo } }; @@ -244,7 +244,7 @@ macro_rules! double_zero_trailing_getter { $vis fn $method(&$self_) -> $ty { let lo = ($arr[$off_lo] as $ty) >> $start << $start; let hi = $arr[$off_hi] as $ty; - + (hi << $bits) | lo } }; @@ -326,4 +326,4 @@ macro_rules! rw_double_zero_trailing { double_zero_trailing_setter!($vis, $self_, $arr; [$off_lo, $off_hi]; $start~; $expect, [], $name, $bits, $ty); } }; -} \ No newline at end of file +} diff --git a/src/registers/operational.rs b/src/registers/operational.rs index be18dbe..f8a3bf1 100644 --- a/src/registers/operational.rs +++ b/src/registers/operational.rs @@ -332,7 +332,7 @@ impl PortStatusAndControlRegister { rw_bit!(pub, self, self.0; 9, port_power, "Port Power"); ro_field!(pub, self, self.0; 10..=13, port_speed, "Port Speed", u8); rw_field!( - pub, self, + pub, self, self.0; 14..=15, port_indicator_control, "Port Indicator Control", @@ -483,7 +483,7 @@ impl_debug_from_methods! { pub struct PortHardwareLpmControlRegister(u32); impl PortHardwareLpmControlRegister { rw_field!( - pub, self, + pub, self, self.0; 0..=1, host_initiated_resume_duration_mode, "Host Initiated Resume Duration Mode", diff --git a/src/ring/mod.rs b/src/ring/mod.rs index 9648d04..4bf525a 100644 --- a/src/ring/mod.rs +++ b/src/ring/mod.rs @@ -1,3 +1,3 @@ //! TRB Ring. -pub mod trb; \ No newline at end of file +pub mod trb; diff --git a/src/ring/trb/command.rs b/src/ring/trb/command.rs index 24b6181..a6bddc8 100644 --- a/src/ring/trb/command.rs +++ b/src/ring/trb/command.rs @@ -8,7 +8,7 @@ use num_traits::FromPrimitive; macro_rules! impl_input_context_pointer { () => { param_align_16!(input_context_pointer, "Input Context Pointer"); - } + }; } macro_rules! impl_subtype { @@ -93,9 +93,7 @@ impl_debug_from_methods!(NoOp {}); impl EnableSlot { rw_field!(pub, self, self.0.0[3]; 16..=20, slot_type, "Slot Type", u8); } -impl_debug_from_methods!(EnableSlot { - slot_type, -}); +impl_debug_from_methods!(EnableSlot { slot_type }); rsvdz_checking_try_from!(EnableSlot { [0];0..=31, [1];0..=31, @@ -107,9 +105,7 @@ rsvdz_checking_try_from!(EnableSlot { impl DisableSlot { impl_slot_id!(); } -impl_debug_from_methods!(DisableSlot { - slot_id, -}); +impl_debug_from_methods!(DisableSlot { slot_id }); rsvdz_checking_try_from!(DisableSlot { [0];0..=31, [1];0..=31, @@ -233,9 +229,7 @@ rsvdz_checking_try_from!(SetTrDequeuePointer { impl ResetDevice { impl_slot_id!(); } -impl_debug_from_methods!(ResetDevice { - slot_id, -}); +impl_debug_from_methods!(ResetDevice { slot_id }); rsvdz_checking_try_from!(ResetDevice { [0];0..=31, [1];0..=31, @@ -272,9 +266,7 @@ rsvdz_checking_try_from!(ForceEvent { impl NegotiateBandwidth { impl_slot_id!(); } -impl_debug_from_methods!(NegotiateBandwidth { - slot_id, -}); +impl_debug_from_methods!(NegotiateBandwidth { slot_id }); rsvdz_checking_try_from!(NegotiateBandwidth { [0];0..=31, [1];0..=31, @@ -338,16 +330,16 @@ impl ForceHeader { "The lowest 5 bits of the Header Info Low must be 0." ); - self.0.0[0].set_bits(5.., info[0].get_bits(5..)); - self.0.0[1] = info[1]; - self.0.0[2] = info[2]; + self.0 .0[0].set_bits(5.., info[0].get_bits(5..)); + self.0 .0[1] = info[1]; + self.0 .0[2] = info[2]; self } /// Returns the value of the Header Info field. #[must_use] pub fn header_info(&self) -> [u32; 3] { - [self.0.0[0] >> 5 << 5, self.0.0[1], self.0.0[2]] + [self.0 .0[0] >> 5 << 5, self.0 .0[1], self.0 .0[2]] } rw_field!( @@ -430,4 +422,4 @@ rsvdz_checking_try_from!(SetExtendedProperty { [0];0..=3, [2];16..=31, [3];1..=9, -}); \ No newline at end of file +}); diff --git a/src/ring/trb/event.rs b/src/ring/trb/event.rs index 3fb3375..9e55376 100644 --- a/src/ring/trb/event.rs +++ b/src/ring/trb/event.rs @@ -14,10 +14,10 @@ macro_rules! impl_cc { /// This method may return an [`Err`] variant with the Completion Code that is either reserved or /// not implemented in this crate. pub fn completion_code(&self) -> Result { - let c: u8 = self.0.0[2].get_bits(24..=31).try_into().unwrap(); + let c: u8 = self.0 .0[2].get_bits(24..=31).try_into().unwrap(); CompletionCode::from_u8(c).ok_or(c) } - } + }; } allowed_trb!("Transfer TRB", { @@ -74,7 +74,7 @@ impl CommandCompletion { ro_field!( pub, self, - self.0.0[2]; 0..=23, + self.0.0[2]; 0..=23, command_completion_parameter, "Command Completion Parameter", u32 @@ -154,9 +154,7 @@ rsvdz_checking_try_from!(Doorbell { impl HostController { impl_cc!(ro); } -impl_debug_from_methods!(HostController { - completion_code, -}); +impl_debug_from_methods!(HostController { completion_code }); rsvdz_checking_try_from!(HostController { [0];0..=31, [1];0..=31, @@ -206,9 +204,7 @@ rsvdz_checking_try_from!(DeviceNotification { impl MfindexWrap { impl_cc!(ro); } -impl_debug_from_methods!(MfindexWrap { - completion_code, -}); +impl_debug_from_methods!(MfindexWrap { completion_code }); rsvdz_checking_try_from!(MfindexWrap { [0];0..=31, [1];0..=31, @@ -217,7 +213,6 @@ rsvdz_checking_try_from!(MfindexWrap { [3];16..=31, }); - /// The TRB Completion Codes. /// /// The description of each error is quoted from eXtensible Host Controller Interface for Universal @@ -313,4 +308,4 @@ pub enum CompletionCode { SecondaryBandwidthError = 35, /// Asserted if an error is detected on a USB2 protocol endpoint for a split transaction. SplitTransactionError = 36, -} \ No newline at end of file +} diff --git a/src/ring/trb/mod.rs b/src/ring/trb/mod.rs index 6297cf3..3f16d8d 100644 --- a/src/ring/trb/mod.rs +++ b/src/ring/trb/mod.rs @@ -16,7 +16,7 @@ macro_rules! param_align_16 { macro_rules! impl_ring_segment_pointer { () => { param_align_16!(ring_segment_pointer, "Ring Segment Pointer"); - } + }; } macro_rules! impl_tc { @@ -79,7 +79,7 @@ macro_rules! allowed_trb { ),+ } ); - + // defining common block paste::paste!( #[doc = "A raw " $name " Block."] @@ -104,12 +104,11 @@ macro_rules! allowed_trb { rw_bit!(pub, self, self.0[3]; 0, cycle_bit, "Cycle"); } ); - + // defining individual TRB types // all TRB types require `Self::new()`. Derive by simple default or manually implement it. $( paste::paste! { - #[doc = "A "] $(#[$docs])* #[doc = "."] #[repr(transparent)] @@ -168,6 +167,6 @@ macro_rules! rsvdz_checking_try_from { } } -pub mod transfer; +pub mod command; pub mod event; -pub mod command; \ No newline at end of file +pub mod transfer; diff --git a/src/ring/trb/transfer.rs b/src/ring/trb/transfer.rs index 5968618..2195404 100644 --- a/src/ring/trb/transfer.rs +++ b/src/ring/trb/transfer.rs @@ -106,7 +106,7 @@ allowed_trb!("Transfer TRB", { impl Normal { impl_data_buffer_pointer!(); - + impl_trb_transfer_length!(); impl_td_size!(); impl_interrupter_target!(); @@ -162,7 +162,7 @@ impl SetupStage { /// Sets the value of the Transfer Type field. pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self { - self.0.0[3].set_bits(16..=17, t as _); + self.0 .0[3].set_bits(16..=17, t as _); self } @@ -173,7 +173,7 @@ impl SetupStage { /// This method panics if the Transfer Type field contains 1 which is reserved. #[must_use] pub fn transfer_type(&self) -> TransferType { - FromPrimitive::from_u32(self.0.0[3].get_bits(16..=17)) + FromPrimitive::from_u32(self.0 .0[3].get_bits(16..=17)) .expect("Transfer Type 1 is reserved.") } } @@ -301,7 +301,7 @@ impl Link { impl_ring_segment_pointer!(); impl_interrupter_target!(); - + impl_tc!(); impl_ch!(); impl_ioc!(); @@ -381,4 +381,4 @@ pub enum TransferType { Out = 2, /// In Data Stage. In = 3, -} \ No newline at end of file +} From 22dcf11a4719584685ecc814ce475f5d34d90c57 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Wed, 6 Dec 2023 17:02:51 +0000 Subject: [PATCH 12/17] minor change --- src/ring/trb/transfer.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ring/trb/transfer.rs b/src/ring/trb/transfer.rs index 2195404..f81b293 100644 --- a/src/ring/trb/transfer.rs +++ b/src/ring/trb/transfer.rs @@ -68,9 +68,7 @@ macro_rules! impl_idt { () => { rw_bit!(pub, self, self.0.0[3]; 6, immediate_data, "Immediate Data"); }; -} -macro_rules! implprv_idt { - () => { + (prv) => { rw1s_bit!(pub(self), self, self.0.0[3]; 6, immediate_data, "Immediate Data"); }; } @@ -158,7 +156,7 @@ impl SetupStage { impl_interrupter_target!(); impl_ioc!(); - implprv_idt!(); + impl_idt!(prv); /// Sets the value of the Transfer Type field. pub fn set_transfer_type(&mut self, t: TransferType) -> &mut Self { From 18ac2aed90043eb54eb28e94caaff4c6bb1403e7 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Fri, 8 Dec 2023 15:34:07 +0000 Subject: [PATCH 13/17] Add ERST entry --- src/ring/erst.rs | 132 +++++++++++++++++++++++++++++++++++++++++++++++ src/ring/mod.rs | 101 ++++++++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 src/ring/erst.rs diff --git a/src/ring/erst.rs b/src/ring/erst.rs new file mode 100644 index 0000000..2bcf81d --- /dev/null +++ b/src/ring/erst.rs @@ -0,0 +1,132 @@ +//! Event Ring Segment Table Entry. + +use super::trb::event::TRB; +use bit_field::BitField; +use core::ops::{Index, IndexMut}; + +/// The Event Ring Segment Table entry. +/// This plays the same role as an array pointer, and require special care to guarantee memory safety. +/// +/// For example, the entry do not implement `Drop` trait, so the user should manually free its memory. +#[repr(transparent)] +#[derive(Clone, Copy, Debug)] +pub struct EventRingSegmentTableEntry([u32; 4]); + +impl EventRingSegmentTableEntry { + /// Create new segment table entry from base address `base` and entry count `len`. + /// `len` should be the entry count, not the size in bytes. + /// + /// # Panics + /// + /// This method will panic if `len >= 4096`. + pub unsafe fn new(base: *const Block, len: usize) -> Self { + let size_in_bytes = len * core::mem::size_of::(); + assert!(size_in_bytes <= u16::MAX as usize); + + let mut entry = Self([0; 4]); + entry + .set_ring_segment_base_address(base as usize as u64) + .set_ring_segment_size((len * core::mem::size_of::()) as u16); + entry + } + + /// Create new segment table entry from a block buffer. + pub unsafe fn from_buf(buf: &[Block]) -> Self { + Self::new(buf.as_ptr(), buf.len()) + } + + /// Returns the entry count of the segment. + pub fn len(&self) -> usize { + return self.ring_segment_size() as usize / core::mem::size_of::(); + } + + /// Returns the slice that this entry is representing. + pub fn as_slice(&self) -> &[Block] { + unsafe { + let base = self.ring_segment_base_address() as *const _; + let len = self.len(); + + core::slice::from_raw_parts(base, len) + } + } + + /// Returns the mutable slice that this entry is representing. + pub fn as_mut_slice(&mut self) -> &mut [Block] { + unsafe { + let base = self.ring_segment_base_address() as *mut _; + let len = self.len(); + + core::slice::from_raw_parts_mut(base, len) + } + } +} + +impl EventRingSegmentTableEntry { + /// Returns the value of the Ring Segment Base Address field. + pub(crate) unsafe fn ring_segment_base_address(&self) -> u64 { + let l: u64 = self.0[0].into(); + let u: u64 = self.0[1].into(); + + (u << 32) | l + } + + /// Sets the value of the Ring Segment Base Address field. + /// + /// # Panics + /// + /// This method panics if `p` is not 64-byte aligned. + pub(crate) unsafe fn set_ring_segment_base_address(&mut self, p: u64) -> &mut Self { + assert_eq!( + p % 64, + 0, + "The Ring Segment Base Address must be 64-byte aligned." + ); + + let l = p.get_bits(0..32); + let u = p.get_bits(32..64); + + self.0[0] = l.try_into().unwrap(); + self.0[1] = u.try_into().unwrap(); + self + } + + /// Returns the value of the Ring Segment Size field. + /// + /// This field represents size in bytes. + pub(crate) fn ring_segment_size(&self) -> u16 { + self.0[2].get_bits(0..16) as _ + } + /// Sets the value of the Ring Segment Size field. + /// + /// The value should be size in bytes. + pub(crate) unsafe fn set_ring_segment_size(&mut self, v: u16) -> &mut Self { + self.0[2].set_bits(0..16, v.into()); + self + } + // rw_field!([2](0..16), ring_segment_size, "Ring Segment Size", u16); + + /// Returns the value of the ring segment end address. + pub(crate) unsafe fn ring_segment_bound_address(&self) -> u64 { + self.ring_segment_base_address() + (self.ring_segment_size() as u64) + } +} + +impl Index for EventRingSegmentTableEntry { + type Output = Block; + + fn index(&self, index: usize) -> &Self::Output { + let slice = self.as_slice(); + assert!(index < slice.len()); + + &slice[index] + } +} + +impl IndexMut for EventRingSegmentTableEntry { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + let slice = self.as_mut_slice(); + assert!(index < slice.len()); + + &mut slice[index] + } +} diff --git a/src/ring/mod.rs b/src/ring/mod.rs index 4bf525a..581ef57 100644 --- a/src/ring/mod.rs +++ b/src/ring/mod.rs @@ -1,3 +1,104 @@ //! TRB Ring. pub mod trb; + +use trb::event; +use core::ops::{Index, IndexMut}; + +/// The Event Ring Segment Table entry. +/// This plays the same role as an array pointer, and require special care to guarantee memory safety. +/// +/// For example, the entry do not implement `Drop` trait, so the user should manually free its memory. +#[repr(transparent)] +#[derive(Clone, Copy, Debug)] +pub struct EventRingSegmentTableEntry([u32; 4]); + +impl EventRingSegmentTableEntry { + /// Create new segment table entry from base address `base` and entry count `len`. + /// `len` should be the entry count, not the size in bytes. + /// + /// # Panics + /// + /// This method will panic if `len >= 4096`. + pub unsafe fn new(base: *const event::TRB, len: usize) -> Self { + let size_in_bytes = len * trb::BYTES; + assert!(size_in_bytes <= u16::MAX as usize); + + let mut entry = Self([0; 4]); + entry + .set_ring_segment_base_address(base as usize as u64) + .set_ring_segment_size((len * trb::BYTES) as u16); + entry + } + + /// Create new segment table entry from a event::TRB buffer. + pub unsafe fn from_buf(buf: &[event::TRB]) -> Self { + Self::new(buf.as_ptr(), buf.len()) + } + + /// Returns the entry count of the segment. + pub fn len(&self) -> usize { + return self.ring_segment_size() as usize / trb::BYTES; + } + + /// Returns the slice that this entry is representing. + pub fn as_slice(&self) -> &[event::TRB] { + unsafe { + let base = self.ring_segment_base_address() as usize as *const _; + let len = self.len(); + + core::slice::from_raw_parts(base, len) + } + } + + /// Returns the mutable slice that this entry is representing. + pub fn as_mut_slice(&mut self) -> &mut [event::TRB] { + unsafe { + let base = self.ring_segment_base_address() as usize as *mut _; + let len = self.len(); + + core::slice::from_raw_parts_mut(base, len) + } + } +} + +impl EventRingSegmentTableEntry { + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 6~; "64-byte aligned", + ring_segment_base_address, + "Ring Segment Base Address", + 32, u64 + ); + + rw_field!( + pub, self, + self.0[2]; 0..=15, + ring_segment_size, + "Ring Segment Size (in bytes)", + u16 + ); + + /// Returns the value of the ring segment end address. + pub fn ring_segment_bound_address(&self) -> u64 { + self.ring_segment_base_address() + (self.ring_segment_size() as u64) + } +} + +impl Index for EventRingSegmentTableEntry { + type Output = event::TRB; + + fn index(&self, index: usize) -> &Self::Output { + let slice = self.as_slice(); + + &slice[index] + } +} + +impl IndexMut for EventRingSegmentTableEntry { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + let slice = self.as_mut_slice(); + + &mut slice[index] + } +} From 6b08e373ab9048337a384a2cd973c5c3cb98d34f Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Fri, 8 Dec 2023 15:35:44 +0000 Subject: [PATCH 14/17] oops --- src/ring/erst.rs | 132 ----------------------------------------------- 1 file changed, 132 deletions(-) delete mode 100644 src/ring/erst.rs diff --git a/src/ring/erst.rs b/src/ring/erst.rs deleted file mode 100644 index 2bcf81d..0000000 --- a/src/ring/erst.rs +++ /dev/null @@ -1,132 +0,0 @@ -//! Event Ring Segment Table Entry. - -use super::trb::event::TRB; -use bit_field::BitField; -use core::ops::{Index, IndexMut}; - -/// The Event Ring Segment Table entry. -/// This plays the same role as an array pointer, and require special care to guarantee memory safety. -/// -/// For example, the entry do not implement `Drop` trait, so the user should manually free its memory. -#[repr(transparent)] -#[derive(Clone, Copy, Debug)] -pub struct EventRingSegmentTableEntry([u32; 4]); - -impl EventRingSegmentTableEntry { - /// Create new segment table entry from base address `base` and entry count `len`. - /// `len` should be the entry count, not the size in bytes. - /// - /// # Panics - /// - /// This method will panic if `len >= 4096`. - pub unsafe fn new(base: *const Block, len: usize) -> Self { - let size_in_bytes = len * core::mem::size_of::(); - assert!(size_in_bytes <= u16::MAX as usize); - - let mut entry = Self([0; 4]); - entry - .set_ring_segment_base_address(base as usize as u64) - .set_ring_segment_size((len * core::mem::size_of::()) as u16); - entry - } - - /// Create new segment table entry from a block buffer. - pub unsafe fn from_buf(buf: &[Block]) -> Self { - Self::new(buf.as_ptr(), buf.len()) - } - - /// Returns the entry count of the segment. - pub fn len(&self) -> usize { - return self.ring_segment_size() as usize / core::mem::size_of::(); - } - - /// Returns the slice that this entry is representing. - pub fn as_slice(&self) -> &[Block] { - unsafe { - let base = self.ring_segment_base_address() as *const _; - let len = self.len(); - - core::slice::from_raw_parts(base, len) - } - } - - /// Returns the mutable slice that this entry is representing. - pub fn as_mut_slice(&mut self) -> &mut [Block] { - unsafe { - let base = self.ring_segment_base_address() as *mut _; - let len = self.len(); - - core::slice::from_raw_parts_mut(base, len) - } - } -} - -impl EventRingSegmentTableEntry { - /// Returns the value of the Ring Segment Base Address field. - pub(crate) unsafe fn ring_segment_base_address(&self) -> u64 { - let l: u64 = self.0[0].into(); - let u: u64 = self.0[1].into(); - - (u << 32) | l - } - - /// Sets the value of the Ring Segment Base Address field. - /// - /// # Panics - /// - /// This method panics if `p` is not 64-byte aligned. - pub(crate) unsafe fn set_ring_segment_base_address(&mut self, p: u64) -> &mut Self { - assert_eq!( - p % 64, - 0, - "The Ring Segment Base Address must be 64-byte aligned." - ); - - let l = p.get_bits(0..32); - let u = p.get_bits(32..64); - - self.0[0] = l.try_into().unwrap(); - self.0[1] = u.try_into().unwrap(); - self - } - - /// Returns the value of the Ring Segment Size field. - /// - /// This field represents size in bytes. - pub(crate) fn ring_segment_size(&self) -> u16 { - self.0[2].get_bits(0..16) as _ - } - /// Sets the value of the Ring Segment Size field. - /// - /// The value should be size in bytes. - pub(crate) unsafe fn set_ring_segment_size(&mut self, v: u16) -> &mut Self { - self.0[2].set_bits(0..16, v.into()); - self - } - // rw_field!([2](0..16), ring_segment_size, "Ring Segment Size", u16); - - /// Returns the value of the ring segment end address. - pub(crate) unsafe fn ring_segment_bound_address(&self) -> u64 { - self.ring_segment_base_address() + (self.ring_segment_size() as u64) - } -} - -impl Index for EventRingSegmentTableEntry { - type Output = Block; - - fn index(&self, index: usize) -> &Self::Output { - let slice = self.as_slice(); - assert!(index < slice.len()); - - &slice[index] - } -} - -impl IndexMut for EventRingSegmentTableEntry { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - let slice = self.as_mut_slice(); - assert!(index < slice.len()); - - &mut slice[index] - } -} From 75942820b5256496682cc3431dfa49206a196117 Mon Sep 17 00:00:00 2001 From: paulsohn Date: Mon, 11 Dec 2023 01:29:58 +0900 Subject: [PATCH 15/17] quick fix --- src/macros.rs | 2 +- src/ring/mod.rs | 3 --- src/ring/trb/transfer.rs | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 80d4681..b749592 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -173,7 +173,7 @@ macro_rules! zero_trailing_setter { #[doc = "This method panics if the given value is not"] #[doc = $expect] #[doc = "."] - $vis fn set(&mut $self_,value:$ty) -> &mut Self { + $vis fn $method(&mut $self_,value:$ty) -> &mut Self { use bit_field::BitField; assert!(value.trailing_zeros() >= $start, "The {} must be {}.", $name, $expect); diff --git a/src/ring/mod.rs b/src/ring/mod.rs index 581ef57..f16ad76 100644 --- a/src/ring/mod.rs +++ b/src/ring/mod.rs @@ -61,7 +61,6 @@ impl EventRingSegmentTableEntry { } } } - impl EventRingSegmentTableEntry { rw_double_zero_trailing!( pub, self, @@ -84,7 +83,6 @@ impl EventRingSegmentTableEntry { self.ring_segment_base_address() + (self.ring_segment_size() as u64) } } - impl Index for EventRingSegmentTableEntry { type Output = event::TRB; @@ -94,7 +92,6 @@ impl Index for EventRingSegmentTableEntry { &slice[index] } } - impl IndexMut for EventRingSegmentTableEntry { fn index_mut(&mut self, index: usize) -> &mut Self::Output { let slice = self.as_mut_slice(); diff --git a/src/ring/trb/transfer.rs b/src/ring/trb/transfer.rs index f81b293..e6bf364 100644 --- a/src/ring/trb/transfer.rs +++ b/src/ring/trb/transfer.rs @@ -101,6 +101,9 @@ allowed_trb!("Transfer TRB", { /// No Op Transfer TRB NoOp = 8, }); +impl TRB { + ro_bit!(pub, self, self.0[3]; 4, chain_bit, "Chain"); +} impl Normal { impl_data_buffer_pointer!(); From 66ede49b16e8c7890f8916867b0dc707b0b7a4ca Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Mon, 11 Dec 2023 05:30:47 +0000 Subject: [PATCH 16/17] fix arount erstsz --- src/ring/mod.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ring/mod.rs b/src/ring/mod.rs index f16ad76..c4055b4 100644 --- a/src/ring/mod.rs +++ b/src/ring/mod.rs @@ -21,13 +21,12 @@ impl EventRingSegmentTableEntry { /// /// This method will panic if `len >= 4096`. pub unsafe fn new(base: *const event::TRB, len: usize) -> Self { - let size_in_bytes = len * trb::BYTES; - assert!(size_in_bytes <= u16::MAX as usize); + assert!(len <= u16::MAX as usize); let mut entry = Self([0; 4]); entry .set_ring_segment_base_address(base as usize as u64) - .set_ring_segment_size((len * trb::BYTES) as u16); + .set_ring_segment_size(len as u16); entry } @@ -74,13 +73,13 @@ impl EventRingSegmentTableEntry { pub, self, self.0[2]; 0..=15, ring_segment_size, - "Ring Segment Size (in bytes)", + "Ring Segment Size (entry count)", u16 ); /// Returns the value of the ring segment end address. pub fn ring_segment_bound_address(&self) -> u64 { - self.ring_segment_base_address() + (self.ring_segment_size() as u64) + self.ring_segment_base_address() + (trb::BYTES * self.ring_segment_size() as usize) as u64 } } impl Index for EventRingSegmentTableEntry { From 79abd1028d787179601caa55d7f347443411d544 Mon Sep 17 00:00:00 2001 From: Taeseung Sohn Date: Mon, 11 Dec 2023 05:44:21 +0000 Subject: [PATCH 17/17] add erst submodule --- src/ring/erst.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++++ src/ring/mod.rs | 98 +------------------------------------------- 2 files changed, 106 insertions(+), 96 deletions(-) create mode 100644 src/ring/erst.rs diff --git a/src/ring/erst.rs b/src/ring/erst.rs new file mode 100644 index 0000000..5fc0fe5 --- /dev/null +++ b/src/ring/erst.rs @@ -0,0 +1,104 @@ +//! Data structures around the Event Ring Segment Table entry. + +use crate::ring::trb::{self, event}; +use core::ops::{Index, IndexMut}; +use core::mem::MaybeUninit; + +/// The Event Ring Segment Table entry. +/// This plays the same role as an array pointer, and require special care to guarantee memory safety. +/// +/// For example, the entry do not implement `Drop` trait, so the user should manually free its memory. +#[repr(transparent)] +#[derive(Clone, Copy, Debug)] +pub struct EventRingSegmentTableEntry([u32; 4]); + +impl EventRingSegmentTableEntry { + /// Create new segment table entry from base address `base` and entry count `len`. + /// `len` should be the entry count, not the size in bytes. + /// + /// # Panics + /// + /// This method will panic if `len >= 4096`. + pub unsafe fn new(base: *const event::TRB, len: usize) -> Self { + assert!(len <= u16::MAX as usize); + + let mut entry = Self([0; 4]); + entry + .set_ring_segment_base_address(base as usize as u64) + .set_ring_segment_size(len as u16); + entry + } + + /// Create new segment table entry from a event::TRB buffer. + pub unsafe fn from_buf(buf: &[event::TRB]) -> Self { + Self::new(buf.as_ptr(), buf.len()) + } + + /// Returns the entry count of the segment. + pub fn len(&self) -> usize { + return self.ring_segment_size() as usize / trb::BYTES; + } + + /// Returns the slice that this entry is representing. + pub fn as_slice(&self) -> &[event::TRB] { + unsafe { + let base = self.ring_segment_base_address() as usize as *const _; + let len = self.len(); + + core::slice::from_raw_parts(base, len) + } + } + + /// Returns the mutable slice that this entry is representing. + pub fn as_mut_slice(&mut self) -> &mut [event::TRB] { + unsafe { + let base = self.ring_segment_base_address() as usize as *mut _; + let len = self.len(); + + core::slice::from_raw_parts_mut(base, len) + } + } +} +impl EventRingSegmentTableEntry { + rw_double_zero_trailing!( + pub, self, + self.0; [0, 1]; 6~; "64-byte aligned", + ring_segment_base_address, + "Ring Segment Base Address", + 32, u64 + ); + + rw_field!( + pub, self, + self.0[2]; 0..=15, + ring_segment_size, + "Ring Segment Size (entry count)", + u16 + ); + + /// Returns the value of the ring segment end address. + pub fn ring_segment_bound_address(&self) -> u64 { + self.ring_segment_base_address() + (trb::BYTES * self.ring_segment_size() as usize) as u64 + } +} +impl Index for EventRingSegmentTableEntry { + type Output = event::TRB; + + fn index(&self, index: usize) -> &Self::Output { + let slice = self.as_slice(); + + &slice[index] + } +} +impl IndexMut for EventRingSegmentTableEntry { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + let slice = self.as_mut_slice(); + + &mut slice[index] + } +} + +/// An 64-byte aligned helper type to enforce the ERST base always 64-byte aligned. +#[derive(Copy, Clone, Debug)] +#[repr(align(64))] +pub struct EventRingSegmentTableEntryBlock(pub [MaybeUninit; 4]); diff --git a/src/ring/mod.rs b/src/ring/mod.rs index c4055b4..21bd47f 100644 --- a/src/ring/mod.rs +++ b/src/ring/mod.rs @@ -1,100 +1,6 @@ //! TRB Ring. pub mod trb; +pub mod erst; -use trb::event; -use core::ops::{Index, IndexMut}; - -/// The Event Ring Segment Table entry. -/// This plays the same role as an array pointer, and require special care to guarantee memory safety. -/// -/// For example, the entry do not implement `Drop` trait, so the user should manually free its memory. -#[repr(transparent)] -#[derive(Clone, Copy, Debug)] -pub struct EventRingSegmentTableEntry([u32; 4]); - -impl EventRingSegmentTableEntry { - /// Create new segment table entry from base address `base` and entry count `len`. - /// `len` should be the entry count, not the size in bytes. - /// - /// # Panics - /// - /// This method will panic if `len >= 4096`. - pub unsafe fn new(base: *const event::TRB, len: usize) -> Self { - assert!(len <= u16::MAX as usize); - - let mut entry = Self([0; 4]); - entry - .set_ring_segment_base_address(base as usize as u64) - .set_ring_segment_size(len as u16); - entry - } - - /// Create new segment table entry from a event::TRB buffer. - pub unsafe fn from_buf(buf: &[event::TRB]) -> Self { - Self::new(buf.as_ptr(), buf.len()) - } - - /// Returns the entry count of the segment. - pub fn len(&self) -> usize { - return self.ring_segment_size() as usize / trb::BYTES; - } - - /// Returns the slice that this entry is representing. - pub fn as_slice(&self) -> &[event::TRB] { - unsafe { - let base = self.ring_segment_base_address() as usize as *const _; - let len = self.len(); - - core::slice::from_raw_parts(base, len) - } - } - - /// Returns the mutable slice that this entry is representing. - pub fn as_mut_slice(&mut self) -> &mut [event::TRB] { - unsafe { - let base = self.ring_segment_base_address() as usize as *mut _; - let len = self.len(); - - core::slice::from_raw_parts_mut(base, len) - } - } -} -impl EventRingSegmentTableEntry { - rw_double_zero_trailing!( - pub, self, - self.0; [0, 1]; 6~; "64-byte aligned", - ring_segment_base_address, - "Ring Segment Base Address", - 32, u64 - ); - - rw_field!( - pub, self, - self.0[2]; 0..=15, - ring_segment_size, - "Ring Segment Size (entry count)", - u16 - ); - - /// Returns the value of the ring segment end address. - pub fn ring_segment_bound_address(&self) -> u64 { - self.ring_segment_base_address() + (trb::BYTES * self.ring_segment_size() as usize) as u64 - } -} -impl Index for EventRingSegmentTableEntry { - type Output = event::TRB; - - fn index(&self, index: usize) -> &Self::Output { - let slice = self.as_slice(); - - &slice[index] - } -} -impl IndexMut for EventRingSegmentTableEntry { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - let slice = self.as_mut_slice(); - - &mut slice[index] - } -} +pub use erst::EventRingSegmentTableEntry; \ No newline at end of file