Commit 646e8c9e authored by Jeremy Soller's avatar Jeremy Soller

xhci: WIP grab device information

parent 1109da47
......@@ -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);
}
}
......@@ -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<CommandRing> {
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]
}
}
......@@ -3,12 +3,21 @@ use syscall::io::{Dma, Mmio};
#[repr(packed)]
pub struct SlotContext {
inner: [u8; 32]
pub a: Mmio<u32>,
pub b: Mmio<u32>,
pub c: Mmio<u32>,
pub d: Mmio<u32>,
_rsvd: [Mmio<u32>; 4],
}
#[repr(packed)]
pub struct EndpointContext {
inner: [u8; 32]
pub a: Mmio<u32>,
pub b: Mmio<u32>,
pub trl: Mmio<u32>,
pub trh: Mmio<u32>,
pub c: Mmio<u32>,
_rsvd: [Mmio<u32>; 3],
}
#[repr(packed)]
......
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);
}
println!(" - Running Enable Slot command");
if flags.contains(port::PORT_CCS) {
println!(" - Running Enable Slot command");
self.cmd.trbs[0].enable_slot(0, true);
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");
}
};
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());
{
let cmd = self.cmd.next_cmd();
cmd.enable_slot(0, true);
println!(" - Command: {}", cmd);
self.dbs[0].write(0);
run();
cmd.reserved(false);
}
let slot;
{
let event = self.cmd.next_event();
println!(" - Response: {}", event);
slot = (event.control.read() >> 24) as u8;
println!(" - Wait for command completion");
while self.op.crcr.readf(1 << 3) {
println!(" - Waiting for command completion");
event.reserved(false);
}
println!(" Slot {}", slot);
let mut trbs = Dma::<[trb::Trb; 256]>::zeroed()?;
let mut input = Dma::<device::InputContext>::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!(" - 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(())
}
}
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())
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment