xhcid: support MMIO on 32-bit systems

This commit is contained in:
Jeremy Soller
2023-09-09 12:05:42 -06:00
parent 15e523c8eb
commit 676b1cda67
8 changed files with 47 additions and 26 deletions
+4 -2
View File
@@ -166,11 +166,13 @@ impl StreamContextArray {
#[repr(packed)]
pub struct ScratchpadBufferEntry {
pub value: Mmio<u64>,
pub value_low: Mmio<u32>,
pub value_high: Mmio<u32>,
}
impl ScratchpadBufferEntry {
pub fn set_addr(&mut self, addr: u64) {
self.value.write(addr);
self.value_low.write(addr as u32);
self.value_high.write((addr >> 32) as u32);
}
}
+4 -2
View File
@@ -9,7 +9,8 @@ use super::trb::Trb;
#[repr(packed)]
pub struct EventRingSte {
pub address: Mmio<u64>,
pub address_low: Mmio<u32>,
pub address_high: Mmio<u32>,
pub size: Mmio<u16>,
_rsvd: Mmio<u16>,
_rsvd2: Mmio<u32>,
@@ -28,7 +29,8 @@ impl EventRing {
ring: Ring::new(ac64, 256, false)?,
};
ring.ste[0].address.write(ring.ring.trbs.physical() as u64);
ring.ste[0].address_low.write(ring.ring.trbs.physical() as u32);
ring.ste[0].address_high.write((ring.ring.trbs.physical() as u64 >> 32) as u32);
ring.ste[0].size.write(ring.ring.trbs.len() as u16);
Ok(ring)
+2 -1
View File
@@ -209,7 +209,8 @@ impl IrqReactor {
trace!("Updated ERDP to {:#0x}", dequeue_pointer);
self.hci.run.lock().unwrap().ints[0].erdp.write(dequeue_pointer);
self.hci.run.lock().unwrap().ints[0].erdp_low.write(dequeue_pointer as u32);
self.hci.run.lock().unwrap().ints[0].erdp_high.write((dequeue_pointer >> 32) as u32);
}
fn handle_requests(&mut self) {
self.states.extend(self.receiver.try_iter().inspect(|req| trace!("Received request: {:X?}", req)));
+10 -6
View File
@@ -367,13 +367,15 @@ impl Xhci {
// Set device context address array pointer
let dcbaap = self.dev_ctx.dcbaap();
debug!("Writing DCBAAP: {:X}", dcbaap);
self.op.get_mut().unwrap().dcbaap.write(dcbaap as u64);
self.op.get_mut().unwrap().dcbaap_low.write(dcbaap as u32);
self.op.get_mut().unwrap().dcbaap_high.write((dcbaap as u64 >> 32) as u32);
// Set command ring control register
let crcr = self.cmd.get_mut().unwrap().register();
assert_eq!(crcr & 0xFFFF_FFFF_FFFF_FFC1, crcr, "unaligned CRCR");
debug!("Writing CRCR: {:X}", crcr);
self.op.get_mut().unwrap().crcr.write(crcr as u64);
self.op.get_mut().unwrap().crcr_low.write(crcr as u32);
self.op.get_mut().unwrap().crcr_high.write((crcr as u64 >> 32) as u32);
// Set event ring segment table registers
debug!("Interrupter 0: {:p}", self.run.get_mut().unwrap().ints.as_ptr());
@@ -386,11 +388,13 @@ impl Xhci {
let erdp = self.primary_event_ring.get_mut().unwrap().erdp();
debug!("Writing ERDP: {:X}", erdp);
int.erdp.write(erdp as u64 | (1 << 3));
int.erdp_low.write(erdp as u32 | (1 << 3));
int.erdp_high.write((erdp as u64 >> 32) as u32);
let erstba = self.primary_event_ring.get_mut().unwrap().erstba();
debug!("Writing ERSTBA: {:X}", erstba);
int.erstba.write(erstba as u64);
int.erstba_low.write(erstba as u32);
int.erstba_high.write((erstba as u64 >> 32) as u32);
debug!("Writing IMODC and IMODI: {} and {}", 0, 0);
int.imod.write(0);
@@ -749,10 +753,10 @@ impl Xhci {
if self.uses_msi() || self.uses_msix() {
// Since using MSI and MSI-X implies having no IRQ sharing whatsoever, the IP bit
// doesn't have to be touched.
trace!("Successfully received MSI/MSI-X interrupt, IP={}, EHB={}", runtime_regs.ints[0].iman.readf(1), runtime_regs.ints[0].erdp.readf(3));
trace!("Successfully received MSI/MSI-X interrupt, IP={}, EHB={}", runtime_regs.ints[0].iman.readf(1), runtime_regs.ints[0].erdp_low.readf(3));
true
} else if runtime_regs.ints[0].iman.readf(1) {
trace!("Successfully received INTx# interrupt, IP={}, EHB={}", runtime_regs.ints[0].iman.readf(1), runtime_regs.ints[0].erdp.readf(3));
trace!("Successfully received INTx# interrupt, IP={}, EHB={}", runtime_regs.ints[0].iman.readf(1), runtime_regs.ints[0].erdp_low.readf(3));
// If MSI and/or MSI-X are not used, the interrupt might have to be shared, and thus there is
// a special register to specify whether the IRQ actually came from the xHC.
runtime_regs.ints[0].iman.writef(1, true);
+4 -2
View File
@@ -11,9 +11,11 @@ pub struct OperationalRegs {
pub page_size: Mmio<u32>,
_rsvd: [Mmio<u32>; 2],
pub dn_ctrl: Mmio<u32>,
pub crcr: Mmio<u64>,
pub crcr_low: Mmio<u32>,
pub crcr_high: Mmio<u32>,
_rsvd2: [Mmio<u32>; 4],
pub dcbaap: Mmio<u64>,
pub dcbaap_low: Mmio<u32>,
pub dcbaap_high: Mmio<u32>,
pub config: Mmio<u32>,
}
+4 -2
View File
@@ -6,8 +6,10 @@ pub struct Interrupter {
pub imod: Mmio<u32>,
pub erstsz: Mmio<u32>,
_rsvd: Mmio<u32>,
pub erstba: Mmio<u64>,
pub erdp: Mmio<u64>,
pub erstba_low: Mmio<u32>,
pub erstba_high: Mmio<u32>,
pub erdp_low: Mmio<u32>,
pub erdp_high: Mmio<u32>,
}
#[repr(packed)]
+3 -3
View File
@@ -259,8 +259,8 @@ impl Xhci {
//TODO: find out why this bit is set earlier!
let mut run = self.run.lock().unwrap();
let mut int = &mut run.ints[0];
if int.erdp.readf(1 << 3) {
int.erdp.writef(1 << 3, true);
if int.erdp_low.readf(1 << 3) {
int.erdp_low.writef(1 << 3, true);
}
}
@@ -2110,7 +2110,7 @@ impl Xhci {
pub fn event_handler_finished(&self) {
trace!("Event handler finished");
// write 1 to EHB to clear it
self.run.lock().unwrap().ints[0].erdp.writef(1 << 3, true);
self.run.lock().unwrap().ints[0].erdp_low.writef(1 << 3, true);
}
}
pub fn handle_event_trb(name: &str, event_trb: &Trb, command_trb: &Trb) -> Result<()> {
+16 -8
View File
@@ -110,14 +110,16 @@ pub enum TransferKind {
#[repr(packed)]
pub struct Trb {
pub data: Mmio<u64>,
pub data_low: Mmio<u32>,
pub data_high: Mmio<u32>,
pub status: Mmio<u32>,
pub control: Mmio<u32>,
}
impl Clone for Trb {
fn clone(&self) -> Self {
Self {
data: Mmio::from(self.data.read()),
data_low: Mmio::from(self.data_low.read()),
data_high: Mmio::from(self.data_high.read()),
status: Mmio::from(self.status.read()),
control: Mmio::from(self.control.read()),
}
@@ -144,7 +146,8 @@ pub const TRB_CONTROL_ENDPOINT_ID_SHIFT: u8 = 16;
impl Trb {
pub fn set(&mut self, data: u64, status: u32, control: u32) {
self.data.write(data);
self.data_low.write(data as u32);
self.data_high.write((data >> 32) as u32);
self.status.write(status);
self.control.write(control);
}
@@ -153,6 +156,11 @@ impl Trb {
self.set(0, 0, ((TrbType::Reserved as u32) << 10) | (cycle as u32));
}
pub fn read_data(&self) -> u64 {
(self.data_low.read() as u64) |
((self.data_high.read() as u64) << 32)
}
pub fn completion_code(&self) -> u8 {
(self.status.read() >> TRB_STATUS_COMPLETION_CODE_SHIFT) as u8
}
@@ -172,7 +180,7 @@ impl Trb {
debug_assert_eq!(self.trb_type(), TrbType::CommandCompletion as u8);
if self.has_completion_trb_pointer() {
Some(self.data.read())
Some(self.read_data())
} else {
None
}
@@ -181,7 +189,7 @@ impl Trb {
debug_assert_eq!(self.trb_type(), TrbType::Transfer as u8);
if self.has_completion_trb_pointer() {
Some(self.data.read())
Some(self.read_data())
} else {
None
}
@@ -199,7 +207,7 @@ impl Trb {
}
pub fn event_data(&self) -> Option<u64> {
if self.event_data_bit() {
Some(self.data.read())
Some(self.read_data())
} else {
None
}
@@ -459,7 +467,7 @@ impl fmt::Debug for Trb {
write!(
f,
"Trb {{ data: {:>016X}, status: {:>08X}, control: {:>08X} }}",
self.data.read(),
self.read_data(),
self.status.read(),
self.control.read()
)
@@ -471,7 +479,7 @@ impl fmt::Display for Trb {
write!(
f,
"({:>016X}, {:>08X}, {:>08X})",
self.data.read(),
self.read_data(),
self.status.read(),
self.control.read()
)