Rust XHCI Implementation.
This commit is contained in:
parent
0b95098748
commit
a10c615b95
10 changed files with 438 additions and 30 deletions
64
'
Normal file
64
'
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
use core::{
|
||||||
|
ops::{Deref, Index, IndexMut},
|
||||||
|
slice::SliceIndex,
|
||||||
|
};
|
||||||
|
|
||||||
|
use alloc::{boxed::Box, vec};
|
||||||
|
use bitfield_struct::bitfield;
|
||||||
|
use mammoth::physical_box::PhysicalBox;
|
||||||
|
|
||||||
|
#[bitfield(u128)]
|
||||||
|
pub struct TransferRequestBlock {
|
||||||
|
parameter: u64,
|
||||||
|
status: u32,
|
||||||
|
cycle: bool,
|
||||||
|
evaluate_next: bool,
|
||||||
|
flag_2: bool,
|
||||||
|
flag_3: bool,
|
||||||
|
flag_4: bool,
|
||||||
|
flag_5: bool,
|
||||||
|
flag_6: bool,
|
||||||
|
flag_7: bool,
|
||||||
|
flag_8: bool,
|
||||||
|
flag_9: bool,
|
||||||
|
#[bits(6)]
|
||||||
|
trb_type: u8,
|
||||||
|
control: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct TrbRing(PhysicalBox<[TransferRequestBlock]>);
|
||||||
|
|
||||||
|
impl TrbRing {
|
||||||
|
pub fn new(size: usize) -> Self {
|
||||||
|
Self(PhysicalBox::default_with_count(
|
||||||
|
TransferRequestBlock::default(),
|
||||||
|
size,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.0.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn physical_address(&self) -> usize {
|
||||||
|
self.0.physical_address()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> Index<I> for TrbRing {
|
||||||
|
type Output = TransferRequestBlock;
|
||||||
|
|
||||||
|
fn index(&self, index: I) -> &Self::Output {
|
||||||
|
self.0[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> IndexMut<I> for TrbRing
|
||||||
|
where
|
||||||
|
I: SliceIndex<[TransferRequestBlock]>,
|
||||||
|
{
|
||||||
|
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
||||||
|
&mut self.0[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
37
rust/Cargo.lock
generated
37
rust/Cargo.lock
generated
|
|
@ -2,12 +2,6 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitfield-struct"
|
name = "bitfield-struct"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
@ -80,11 +74,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.12"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -105,9 +98,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettyplease"
|
name = "prettyplease"
|
||||||
version = "0.2.20"
|
version = "0.2.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"syn",
|
"syn",
|
||||||
|
|
@ -115,18 +108,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.86"
|
version = "1.0.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.36"
|
version = "1.0.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
@ -148,9 +141,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.72"
|
version = "2.0.111"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -178,15 +171,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.11.0"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "victoriafalls"
|
name = "victoriafalls"
|
||||||
|
|
@ -206,6 +199,8 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitfield-struct 0.12.1",
|
"bitfield-struct 0.12.1",
|
||||||
"mammoth",
|
"mammoth",
|
||||||
|
"pci",
|
||||||
|
"yellowstone-yunq",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -72,15 +72,15 @@ impl PciDevice {
|
||||||
control.capable_address_64(),
|
control.capable_address_64(),
|
||||||
"We don't handle the non-64bit case for MSI yet."
|
"We don't handle the non-64bit case for MSI yet."
|
||||||
);
|
);
|
||||||
assert!(
|
|
||||||
control.multi_message_capable() == 0,
|
if control.multi_message_capable() != 0 {
|
||||||
"We don't yet handle multi-message capable devices."
|
mammoth::debug!("WARN: We don't yet handle multi-message capable devices.");
|
||||||
);
|
}
|
||||||
|
|
||||||
// FIXME: These probably need to be volatile writes.
|
// FIXME: These probably need to be volatile writes.
|
||||||
let header: &mut PciDeviceHeader = self.memory_region.as_mut();
|
let header: &mut PciDeviceHeader = self.memory_region.as_mut();
|
||||||
header.command = header.command.with_interrupt_disable(true);
|
header.command = header.command.with_interrupt_disable(true);
|
||||||
msi_cap.msi_control = control.with_msi_enable(true);
|
msi_cap.msi_control = control.with_msi_enable(true).with_multi_message_enable(0);
|
||||||
|
|
||||||
// For setting addr and data field, see intel ref
|
// For setting addr and data field, see intel ref
|
||||||
// Vol 3. Section 11.11
|
// Vol 3. Section 11.11
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,9 @@ edition = "2024"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitfield-struct = "0.12"
|
bitfield-struct = "0.12"
|
||||||
mammoth = { path = "../../lib/mammoth/" }
|
mammoth = { path = "../../lib/mammoth/" }
|
||||||
|
pci = { path = "../../lib/pci" }
|
||||||
|
yellowstone-yunq = { version = "0.1.0", path = "../../lib/yellowstone" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["debug"]
|
||||||
|
debug = []
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,28 @@ extern crate alloc;
|
||||||
|
|
||||||
mod xhci;
|
mod xhci;
|
||||||
|
|
||||||
use mammoth::{debug, define_entry, zion::z_err_t};
|
use mammoth::{cap::Capability, debug, define_entry, zion::z_err_t};
|
||||||
|
use pci::PciDevice;
|
||||||
|
use xhci::driver::XHCIDriver;
|
||||||
|
|
||||||
define_entry!();
|
define_entry!();
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn main() -> z_err_t {
|
extern "C" fn main() -> z_err_t {
|
||||||
debug!("In Voyageurs");
|
#[cfg(feature = "debug")]
|
||||||
|
debug!("Voyageurs Starting.");
|
||||||
|
|
||||||
|
let yellowstone = yellowstone_yunq::from_init_endpoint();
|
||||||
|
|
||||||
|
let xhci_info = yellowstone
|
||||||
|
.get_xhci_info()
|
||||||
|
.expect("Failed to get XHCI info from yellowstone.");
|
||||||
|
|
||||||
|
let pci_device = PciDevice::from_cap(Capability::take(xhci_info.xhci_region)).unwrap();
|
||||||
|
|
||||||
|
let xhci_driver = XHCIDriver::from_pci_device(pci_device);
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
rust/sys/voyageurs/src/xhci/device_context_base_array.rs
Normal file
22
rust/sys/voyageurs/src/xhci/device_context_base_array.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
use mammoth::mem::MemoryRegion;
|
||||||
|
|
||||||
|
pub struct DeviceContextBaseArray {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
region: MemoryRegion,
|
||||||
|
physical_addr: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceContextBaseArray {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let (region, physical_addr) = MemoryRegion::contiguous_physical(0x1000).unwrap();
|
||||||
|
region.zero_region();
|
||||||
|
Self {
|
||||||
|
region,
|
||||||
|
physical_addr: physical_addr as usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn physical_addr(&self) -> usize {
|
||||||
|
self.physical_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
227
rust/sys/voyageurs/src/xhci/driver.rs
Normal file
227
rust/sys/voyageurs/src/xhci/driver.rs
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
use core::slice;
|
||||||
|
|
||||||
|
use mammoth::{map_unaligned_volatile, mem::MemoryRegion};
|
||||||
|
use mammoth::{read_unaligned_volatile, write_unaligned_volatile};
|
||||||
|
|
||||||
|
use super::registers::{self};
|
||||||
|
use crate::xhci::device_context_base_array::DeviceContextBaseArray;
|
||||||
|
use crate::xhci::event_ring::EventRing;
|
||||||
|
use crate::xhci::registers::HCSParams1;
|
||||||
|
use crate::xhci::trb_ring::{InputTrbRing, OutputTrbRing};
|
||||||
|
|
||||||
|
pub struct XHCIDriver {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pci_device: pci::PciDevice,
|
||||||
|
registers_region: MemoryRegion,
|
||||||
|
command_ring: OutputTrbRing,
|
||||||
|
event_ring: EventRing,
|
||||||
|
device_context_base_array: DeviceContextBaseArray,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XHCIDriver {
|
||||||
|
pub fn from_pci_device(mut pci_device: pci::PciDevice) -> Self {
|
||||||
|
// BAR0 Size Allocation
|
||||||
|
// If virtualization is supported, the Capability and Operational Register sets, and
|
||||||
|
// the Extended Capabilities may reside in a single page of virtual memory,
|
||||||
|
// however the RTSOFF and DBOFF Registers shall position the Runtime and
|
||||||
|
// Doorbell Registers to reside on their own respective virtual memory pages. The
|
||||||
|
// BAR0 size shall provide space that is sufficient to cover the offset between the
|
||||||
|
// respective register spaces (Capability, Operational, Runtime, etc.) and the
|
||||||
|
// register spaces themselves (e.g. a minimum of 3 virtual memory pages).
|
||||||
|
// If virtualization is not supported, all xHCI register spaces may reside on a single
|
||||||
|
// page pointed to by the BAR0.
|
||||||
|
let three_pages = 0x3000;
|
||||||
|
let address =
|
||||||
|
((pci_device.header().bars[1] as u64) << 32) | (pci_device.header().bars[0] as u64);
|
||||||
|
let registers_region = MemoryRegion::direct_physical(address, three_pages).unwrap();
|
||||||
|
|
||||||
|
let port_cap = pci_device.register_msi().unwrap();
|
||||||
|
|
||||||
|
let driver = Self {
|
||||||
|
pci_device,
|
||||||
|
registers_region,
|
||||||
|
command_ring: OutputTrbRing::new(),
|
||||||
|
event_ring: EventRing::new(),
|
||||||
|
device_context_base_array: DeviceContextBaseArray::new(),
|
||||||
|
};
|
||||||
|
driver.reset();
|
||||||
|
driver
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capabilities(&self) -> ®isters::HostControllerCapabilities {
|
||||||
|
self.registers_region.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn operational(&self) -> &mut registers::HostControllerOperational {
|
||||||
|
let cap_length: registers::HostControllerCapabilitiesLengthAndVersion =
|
||||||
|
read_unaligned_volatile!(self.capabilities(), cap_length_and_version);
|
||||||
|
let offset = cap_length.cap_length();
|
||||||
|
|
||||||
|
// TODO: Ensure exclusive access.
|
||||||
|
unsafe { self.registers_region.as_mut_ref_at_offset(offset as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interrupters(&self) -> &[registers::InterrupterRegisterSet] {
|
||||||
|
// See Table 5-35: Host Controller Runtime Registers
|
||||||
|
const INTERRUPTER_OFFSET_FROM_RUNTIME: u32 = 0x20;
|
||||||
|
let runtime = read_unaligned_volatile!(self.capabilities(), runtime_register_space_offset);
|
||||||
|
|
||||||
|
let interrupter_offset: usize = (runtime + INTERRUPTER_OFFSET_FROM_RUNTIME) as usize;
|
||||||
|
|
||||||
|
let params1: registers::HCSParams1 =
|
||||||
|
read_unaligned_volatile!(self.capabilities(), params_1);
|
||||||
|
|
||||||
|
// SAFETY: The XHCI spec says so?
|
||||||
|
unsafe {
|
||||||
|
slice::from_raw_parts(
|
||||||
|
self.registers_region
|
||||||
|
.raw_ptr_at_offset(interrupter_offset as u64),
|
||||||
|
params1.max_interrupters() as usize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn doorbells(&self) -> &[registers::Doorbell] {
|
||||||
|
let doorbell_offset = read_unaligned_volatile!(self.capabilities(), doorbell_offset);
|
||||||
|
|
||||||
|
let params1: registers::HCSParams1 =
|
||||||
|
read_unaligned_volatile!(self.capabilities(), params_1);
|
||||||
|
|
||||||
|
// SAFETY: The XHCI spec says so?
|
||||||
|
unsafe {
|
||||||
|
slice::from_raw_parts(
|
||||||
|
self.registers_region
|
||||||
|
.raw_ptr_at_offset(doorbell_offset as u64),
|
||||||
|
params1.max_device_slots() as usize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&self) {
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("Stopping XHCI Controller.");
|
||||||
|
|
||||||
|
// Stop the host controller.
|
||||||
|
// TODO: Make this volatile.
|
||||||
|
self.operational().usb_command = self.operational().usb_command.with_run_stop(false);
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("Waiting for controller to halt.");
|
||||||
|
|
||||||
|
// Sleep until the controller is halted.
|
||||||
|
let mut status: registers::UsbStatus =
|
||||||
|
read_unaligned_volatile!(self.operational(), usb_status);
|
||||||
|
while !status.host_controller_halted() {
|
||||||
|
// TODO: Sleep for how long?
|
||||||
|
mammoth::syscall::thread_sleep(50).unwrap();
|
||||||
|
status = read_unaligned_volatile!(self.operational(), usb_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("Resetting Controller.");
|
||||||
|
|
||||||
|
map_unaligned_volatile!(
|
||||||
|
self.operational(),
|
||||||
|
usb_command,
|
||||||
|
|c: registers::UsbCommand| c.with_host_controller_reset(true)
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut command: registers::UsbCommand =
|
||||||
|
read_unaligned_volatile!(self.operational(), usb_command);
|
||||||
|
while command.host_controller_reset() {
|
||||||
|
// TODO: Sleep for how long?
|
||||||
|
mammoth::syscall::thread_sleep(50).unwrap();
|
||||||
|
command = read_unaligned_volatile!(self.operational(), usb_command);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("XHCI Controller Reset, waiting ready.");
|
||||||
|
|
||||||
|
status = read_unaligned_volatile!(self.operational(), usb_status);
|
||||||
|
while status.controller_not_ready() {
|
||||||
|
// TODO: Sleep for how long?
|
||||||
|
mammoth::syscall::thread_sleep(50).unwrap();
|
||||||
|
status = read_unaligned_volatile!(self.operational(), usb_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("XHCI Controller Ready.");
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("Setting Command Ring");
|
||||||
|
|
||||||
|
// TODO: We should reset the command ring here.
|
||||||
|
write_unaligned_volatile!(
|
||||||
|
self.operational(),
|
||||||
|
command_ring_control,
|
||||||
|
self.command_ring.physical_addr()
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("Setting DCBA.");
|
||||||
|
|
||||||
|
write_unaligned_volatile!(
|
||||||
|
self.operational(),
|
||||||
|
device_context_base_address_array_pointer,
|
||||||
|
self.device_context_base_array.physical_addr()
|
||||||
|
);
|
||||||
|
|
||||||
|
// We tell the controller that we can support as many slots as it does because
|
||||||
|
// we allocate a full 4K page to the DCBA, which is 256 entries and the max
|
||||||
|
// slots are 255.
|
||||||
|
let params1: registers::HCSParams1 =
|
||||||
|
read_unaligned_volatile!(self.capabilities(), params_1);
|
||||||
|
map_unaligned_volatile!(
|
||||||
|
self.operational(),
|
||||||
|
configure,
|
||||||
|
|c: registers::UsbConfigure| c
|
||||||
|
.with_max_device_slots_enabled(params1.max_device_slots())
|
||||||
|
);
|
||||||
|
|
||||||
|
let params2: registers::HCSParams2 =
|
||||||
|
read_unaligned_volatile!(self.capabilities(), params_2);
|
||||||
|
|
||||||
|
let max_scratchpad_buffers =
|
||||||
|
(params2.max_scratchpad_buffers_hi() << 5) | params2.max_scratchpad_buffers_lo();
|
||||||
|
assert!(
|
||||||
|
max_scratchpad_buffers == 0,
|
||||||
|
"Unsupported scratchpad buffers."
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("Setting up initial event ring.");
|
||||||
|
|
||||||
|
let interrupter0 = &self.interrupters()[0];
|
||||||
|
write_unaligned_volatile!(
|
||||||
|
interrupter0,
|
||||||
|
event_ring_segment_table_base_address,
|
||||||
|
self.event_ring.segment_table().physical_address()
|
||||||
|
);
|
||||||
|
write_unaligned_volatile!(
|
||||||
|
interrupter0,
|
||||||
|
event_ring_segement_table_size,
|
||||||
|
self.event_ring.segment_table().len()
|
||||||
|
);
|
||||||
|
write_unaligned_volatile!(
|
||||||
|
interrupter0,
|
||||||
|
interrupter_moderation,
|
||||||
|
registers::InterrupterModeration::new()
|
||||||
|
.with_interrupt_moderation_interval(4000)
|
||||||
|
.with_interrupt_moderation_counter(0)
|
||||||
|
);
|
||||||
|
write_unaligned_volatile!(
|
||||||
|
interrupter0,
|
||||||
|
interrupter_management,
|
||||||
|
registers::InterrupterManagement::new().with_interrupt_enabled(true)
|
||||||
|
);
|
||||||
|
|
||||||
|
map_unaligned_volatile!(
|
||||||
|
self.operational(),
|
||||||
|
usb_command,
|
||||||
|
|c: registers::UsbCommand| c.with_run_stop(true)
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
mammoth::debug!("Enabled interrupts and controller.");
|
||||||
|
}
|
||||||
|
}
|
||||||
25
rust/sys/voyageurs/src/xhci/event_ring.rs
Normal file
25
rust/sys/voyageurs/src/xhci/event_ring.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use crate::xhci::data_structures::{EventRingSegmentTable, TrbRing};
|
||||||
|
|
||||||
|
pub struct EventRing {
|
||||||
|
segment_table: EventRingSegmentTable,
|
||||||
|
segments: Vec<TrbRing>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventRing {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut event_ring = Self {
|
||||||
|
segment_table: EventRingSegmentTable::new(1),
|
||||||
|
segments: [TrbRing::new(100)].into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
event_ring.segment_table[0].from_trb_fing(&event_ring.segments[0]);
|
||||||
|
|
||||||
|
event_ring
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn segment_table(&self) -> &EventRingSegmentTable {
|
||||||
|
&self.segment_table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,6 @@
|
||||||
pub mod data_structures;
|
mod data_structures;
|
||||||
pub mod registers;
|
mod device_context_base_array;
|
||||||
|
pub mod driver;
|
||||||
|
mod event_ring;
|
||||||
|
mod registers;
|
||||||
|
mod trb_ring;
|
||||||
|
|
|
||||||
49
rust/sys/voyageurs/src/xhci/trb_ring.rs
Normal file
49
rust/sys/voyageurs/src/xhci/trb_ring.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
use mammoth::mem::MemoryRegion;
|
||||||
|
|
||||||
|
struct TrbRing {
|
||||||
|
region: MemoryRegion,
|
||||||
|
physical_addr: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrbRing {
|
||||||
|
fn new() -> Self {
|
||||||
|
let (region, physical_addr) = MemoryRegion::contiguous_physical(0x1000).unwrap();
|
||||||
|
region.zero_region();
|
||||||
|
Self {
|
||||||
|
region,
|
||||||
|
physical_addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OutputTrbRing {
|
||||||
|
ring: TrbRing,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputTrbRing {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
ring: TrbRing::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn physical_addr(&self) -> u64 {
|
||||||
|
self.ring.physical_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InputTrbRing {
|
||||||
|
ring: TrbRing,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputTrbRing {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
ring: TrbRing::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn physical_addr(&self) -> u64 {
|
||||||
|
self.ring.physical_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue