From 646e8c9eac0fe62588b4aa2e595cb73f719d50dd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 3 Aug 2017 21:30:49 -0600 Subject: [PATCH] xhci: WIP grab device information --- xhcid/src/main.rs | 8 ++- xhcid/src/xhci/command.rs | 26 +++++++++- xhcid/src/xhci/device.rs | 13 ++++- xhcid/src/xhci/mod.rs | 102 +++++++++++++++++++++++++++++--------- xhcid/src/xhci/trb.rs | 30 +++++++++-- 5 files changed, 146 insertions(+), 33 deletions(-) diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index 586c3be9b1..2f09f8fe5a 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -25,13 +25,17 @@ fn main() { match Xhci::new(address) { Ok(mut xhci) => { - xhci.probe(); + if let Err(err) = xhci.probe() { + println!("xhcid: probe error: {}", err); + } }, Err(err) => { - println!("xhcid: error: {}", err); + println!("xhcid: open error: {}", err); } } unsafe { let _ = syscall::physunmap(address); } + + let _ = syscall::kill(1, syscall::SIGINT); } } diff --git a/xhcid/src/xhci/command.rs b/xhcid/src/xhci/command.rs index cbad816cff..3f0a5e8fe8 100644 --- a/xhcid/src/xhci/command.rs +++ b/xhcid/src/xhci/command.rs @@ -5,19 +5,43 @@ use super::event::EventRing; use super::trb::Trb; pub struct CommandRing { - pub trbs: Dma<[Trb; 256]>, + trbs: Dma<[Trb; 256]>, + cmd_i: usize, pub events: EventRing, + event_i: usize, } impl CommandRing { pub fn new() -> Result { Ok(CommandRing { trbs: Dma::zeroed()?, + cmd_i: 0, events: EventRing::new()?, + event_i: 0, }) } pub fn crcr(&self) -> u64 { self.trbs.physical() as u64 | 1 } + + pub fn next_cmd(&mut self) -> &mut Trb { + let i = self.cmd_i; + self.cmd_i += 1; + if self.cmd_i >= self.trbs.len() { + self.cmd_i = 0; + } + + &mut self.trbs[i] + } + + pub fn next_event(&mut self) -> &mut Trb { + let i = self.event_i; + self.event_i += 1; + if self.event_i >= self.events.trbs.len() { + self.event_i = 0; + } + + &mut self.events.trbs[i] + } } diff --git a/xhcid/src/xhci/device.rs b/xhcid/src/xhci/device.rs index 362549468e..d082f561ce 100644 --- a/xhcid/src/xhci/device.rs +++ b/xhcid/src/xhci/device.rs @@ -3,12 +3,21 @@ use syscall::io::{Dma, Mmio}; #[repr(packed)] pub struct SlotContext { - inner: [u8; 32] + pub a: Mmio, + pub b: Mmio, + pub c: Mmio, + pub d: Mmio, + _rsvd: [Mmio; 4], } #[repr(packed)] pub struct EndpointContext { - inner: [u8; 32] + pub a: Mmio, + pub b: Mmio, + pub trl: Mmio, + pub trh: Mmio, + pub c: Mmio, + _rsvd: [Mmio; 3], } #[repr(packed)] diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index 30db7b9a83..5fced67c70 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -1,6 +1,6 @@ use std::slice; use syscall::error::Result; -use syscall::io::Io; +use syscall::io::{Dma, Io}; mod capability; mod command; @@ -59,6 +59,12 @@ impl Xhci { println!(" - Waiting for XHCI stopped"); } + println!(" - Reset"); + op.usb_cmd.writef(1 << 1, true); + while op.usb_sts.readf(1 << 1) { + println!(" - Waiting for XHCI reset"); + } + println!(" - Read max slots"); // Read maximum slots and ports let hcs_params1 = cap.hcs_params1.read(); @@ -111,10 +117,10 @@ impl Xhci { // Set event ring segment table registers println!(" - Interrupter 0: {:X}", self.run.ints.as_ptr() as usize); - println!(" - Write ERDP"); - self.run.ints[0].erdp.write(self.cmd.events.trbs.physical() as u64); println!(" - Write ERSTZ"); self.run.ints[0].erstsz.write(1); + println!(" - Write ERDP"); + self.run.ints[0].erdp.write(self.cmd.events.trbs.physical() as u64); println!(" - Write ERSTBA: {:X}", self.cmd.events.ste.physical() as u64); self.run.ints[0].erstba.write(self.cmd.events.ste.physical() as u64); @@ -135,34 +141,82 @@ impl Xhci { println!(" - XHCI initialized"); } - pub fn probe(&mut self) { + pub fn probe(&mut self) -> Result<()> { for (i, port) in self.ports.iter().enumerate() { let data = port.read(); let state = port.state(); let speed = port.speed(); let flags = port.flags(); println!(" + XHCI Port {}: {:X}, State {}, Speed {}, Flags {:?}", i, data, state, speed, flags); + + if flags.contains(port::PORT_CCS) { + println!(" - Running Enable Slot command"); + + let db = &mut self.dbs[0]; + let crcr = &mut self.op.crcr; + let mut run = || { + db.write(0); + while crcr.readf(1 << 3) { + println!(" - Waiting for command completion"); + } + }; + + { + let cmd = self.cmd.next_cmd(); + cmd.enable_slot(0, true); + println!(" - Command: {}", cmd); + + run(); + + cmd.reserved(false); + } + + let slot; + { + let event = self.cmd.next_event(); + println!(" - Response: {}", event); + slot = (event.control.read() >> 24) as u8; + + event.reserved(false); + } + + println!(" Slot {}", slot); + + let mut trbs = Dma::<[trb::Trb; 256]>::zeroed()?; + let mut input = Dma::::zeroed()?; + { + input.add_context.write(1 << 1 | 1); + + input.device.slot.a.write(1 << 27); + input.device.slot.b.write(((i as u32 + 1) & 0xFF) << 16); + println!("{:>08X}", input.device.slot.b.read()); + + input.device.endpoints[0].b.write(4096 << 16 | 4 << 3 | 3 << 1); + input.device.endpoints[0].trh.write((trbs.physical() >> 32) as u32); + input.device.endpoints[0].trl.write(trbs.physical() as u32 | 1); + } + + { + let cmd = self.cmd.next_cmd(); + cmd.address_device(slot, input.physical(), true); + println!(" - Command: {}", cmd); + + run(); + + cmd.reserved(false); + } + + let address; + { + let event = self.cmd.next_event(); + println!(" - Response: {}", event); + address = (event.control.read() >> 24) as u8; + + event.reserved(false); + } + } } - println!(" - Running Enable Slot command"); - - self.cmd.trbs[0].enable_slot(0, true); - - println!(" - Command"); - println!(" - data: {:X}", self.cmd.trbs[0].data.read()); - println!(" - status: {:X}", self.cmd.trbs[0].status.read()); - println!(" - control: {:X}", self.cmd.trbs[0].control.read()); - - self.dbs[0].write(0); - - println!(" - Wait for command completion"); - while self.op.crcr.readf(1 << 3) { - println!(" - Waiting for command completion"); - } - - println!(" - Response"); - println!(" - data: {:X}", self.cmd.events.trbs[0].data.read()); - println!(" - status: {:X}", self.cmd.events.trbs[0].status.read()); - println!(" - control: {:X}", self.cmd.events.trbs[0].control.read()); + Ok(()) } } diff --git a/xhcid/src/xhci/trb.rs b/xhcid/src/xhci/trb.rs index 2e54fd3430..b57f23dfbd 100644 --- a/xhcid/src/xhci/trb.rs +++ b/xhcid/src/xhci/trb.rs @@ -1,3 +1,4 @@ +use std::fmt; use syscall::io::{Io, Mmio}; #[repr(u8)] @@ -101,11 +102,10 @@ pub struct Trb { } impl Trb { - pub fn reset(&mut self, param: u64, status: u32, control: u16, trb_type: TrbType, evaluate_next: bool, cycle: bool) { + pub fn reset(&mut self, param: u64, status: u32, control: u16, trb_type: TrbType, cycle: bool) { let full_control = (control as u32) << 16 | ((trb_type as u32) & 0x3F) << 10 | - if evaluate_next { 1 << 1 } else { 0 } | if cycle { 1 << 0 } else { 0 }; self.data.write(param); @@ -113,11 +113,33 @@ impl Trb { self.control.write(full_control); } + pub fn reserved(&mut self, cycle: bool) { + self.reset(0, 0, 0, TrbType::Reserved, cycle); + } + pub fn no_op_cmd(&mut self, cycle: bool) { - self.reset(0, 0, 0, TrbType::NoOpCmd, false, cycle); + self.reset(0, 0, 0, TrbType::NoOpCmd, cycle); } pub fn enable_slot(&mut self, slot_type: u8, cycle: bool) { - self.reset(0, 0, (slot_type as u16) & 0x1F, TrbType::EnableSlot, false, cycle); + self.reset(0, 0, (slot_type as u16) & 0x1F, TrbType::EnableSlot, cycle); + } + + pub fn address_device(&mut self, slot_id: u8, input: usize, cycle: bool) { + self.reset(input as u64, 0, (slot_id as u16) << 8, TrbType::AddressDevice, cycle); + } +} + +impl fmt::Debug for Trb { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Trb {{ data: {:>016X}, status: {:>08X}, control: {:>08X} }}", + self.data.read(), self.status.read(), self.control.read()) + } +} + +impl fmt::Display for Trb { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({:>016X}, {:>08X}, {:>08X})", + self.data.read(), self.status.read(), self.control.read()) } }