Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased - ReleaseDate
### Added
- Configurable native, low-high, or high-low access for 64-bit registers.
- `registers::Doorbell` as an alias of `registers::doorbell::Doorbell`. ([#170])

### Changed
Expand Down
31 changes: 27 additions & 4 deletions src/registers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ use accessor::Mapper;
pub use capability::Capability;
pub use doorbell::Doorbell;
pub use operational::{Operational, PortRegisterSet};
pub use register64::Access64;
pub use runtime::InterrupterRegisterSet;
pub use runtime::Runtime;

pub mod capability;
pub mod doorbell;
pub mod operational;
pub mod register64;
pub mod runtime;

/// The access point to xHCI registers.
Expand Down Expand Up @@ -75,14 +77,35 @@ where
/// let r = unsafe { xhci::Registers::new(MMIO_BASE, mapper) };
/// ```
pub unsafe fn new(mmio_base: usize, mapper: M) -> Self {
Self::new_with_64bit_access(mmio_base, mapper, Access64::Native)
}

/// Creates an instance of [`Registers`] with the selected access mode for 64-bit registers.
///
/// # Safety
///
/// The caller must ensure that the xHCI registers are accessed only through this struct.
///
/// # Panics
///
/// This method panics if `mmio_base` is not aligned correctly.
pub unsafe fn new_with_64bit_access(mmio_base: usize, mapper: M, access64: Access64) -> Self {
let capability = Capability::new(mmio_base, &mapper);
let doorbell = Doorbell::new(mmio_base, &capability, mapper.clone());
let operational =
Operational::new(mmio_base, capability.caplength.read_volatile(), &mapper);
let operational = Operational::new_with_64bit_access(
mmio_base,
capability.caplength.read_volatile(),
&mapper,
access64,
);
let port_register_set = PortRegisterSet::new(mmio_base, &capability, mapper.clone());
let runtime = Runtime::new(mmio_base, capability.rtsoff.read_volatile(), mapper.clone());
let interrupter_register_set =
InterrupterRegisterSet::new(mmio_base, capability.rtsoff.read_volatile(), mapper);
let interrupter_register_set = InterrupterRegisterSet::new_with_64bit_access(
mmio_base,
capability.rtsoff.read_volatile(),
mapper,
access64,
);

Self {
capability,
Expand Down
52 changes: 48 additions & 4 deletions src/registers/operational.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Host Controller Operational Registers

use super::capability::{Capability, CapabilityRegistersLength};
use super::register64::{self, Access64};
use accessor::array;
use accessor::single;
use accessor::Mapper;
Expand All @@ -27,9 +28,9 @@ where
/// Device Notification Control
pub dnctrl: single::ReadWrite<DeviceNotificationControl, M>,
/// Command Ring Control Register
pub crcr: single::ReadWrite<CommandRingControlRegister, M>,
pub crcr: register64::ReadWrite<CommandRingControlRegister, M>,
/// Device Context Base Address Array Pointer Register
pub dcbaap: single::ReadWrite<DeviceContextBaseAddressArrayPointerRegister, M>,
pub dcbaap: register64::ReadWrite<DeviceContextBaseAddressArrayPointerRegister, M>,
/// Configure Register
pub config: single::ReadWrite<ConfigureRegister, M>,
}
Expand All @@ -49,6 +50,29 @@ where
/// This method panics if the base address of the Host Controller Operational Registers is not
/// aligned correctly.
pub unsafe fn new(mmio_base: usize, caplength: CapabilityRegistersLength, mapper: &M) -> Self
where
M: Mapper,
{
Self::new_with_64bit_access(mmio_base, caplength, mapper, Access64::Native)
}

/// Creates a new accessor with the selected access mode for 64-bit registers.
///
/// # Safety
///
/// The caller must ensure that the Host Controller Operational Registers are accessed only
/// through this struct.
///
/// # Panics
///
/// This method panics if the base address of the Host Controller Operational Registers is not
/// aligned correctly.
pub unsafe fn new_with_64bit_access(
mmio_base: usize,
caplength: CapabilityRegistersLength,
mapper: &M,
access64: Access64,
) -> Self
where
M: Mapper,
{
Expand All @@ -65,8 +89,8 @@ where
usbsts: m!(0x04),
pagesize: m!(0x08),
dnctrl: m!(0x14),
crcr: m!(0x18),
dcbaap: m!(0x30),
crcr: register64::ReadWrite::new(base + 0x18, access64, mapper.clone()),
dcbaap: register64::ReadWrite::new(base + 0x30, access64, mapper.clone()),
config: m!(0x38),
}
}
Expand Down Expand Up @@ -211,6 +235,16 @@ impl DeviceNotificationControl {
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct CommandRingControlRegister(u64);
impl From<u64> for CommandRingControlRegister {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<CommandRingControlRegister> for u64 {
fn from(value: CommandRingControlRegister) -> Self {
value.0
}
}
impl CommandRingControlRegister {
wo_bit!(0, ring_cycle_state, "Ring Cycle State");
w1s_bit!(1, command_stop, "Command Stop");
Expand Down Expand Up @@ -242,6 +276,16 @@ impl_debug_from_methods! {
#[repr(transparent)]
#[derive(Copy, Clone, Debug, Default)]
pub struct DeviceContextBaseAddressArrayPointerRegister(u64);
impl From<u64> for DeviceContextBaseAddressArrayPointerRegister {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<DeviceContextBaseAddressArrayPointerRegister> for u64 {
fn from(value: DeviceContextBaseAddressArrayPointerRegister) -> Self {
value.0
}
}
impl DeviceContextBaseAddressArrayPointerRegister {
/// Returns the value of the Device Context Base Address Array Pointer.
#[must_use]
Expand Down
Loading