Commit 87342d6f authored by Jeremy Soller's avatar Jeremy Soller

Improve ring state machine

parent 14d81650
......@@ -43,31 +43,29 @@ fn main() {
let address = unsafe { syscall::physmap(bar, 65536, syscall::MAP_WRITE).expect("xhcid: failed to map address") };
{
let mut hci = Xhci::new(address).expect("xhcid: failed to allocate device");
let hci = Arc::new(RefCell::new(Xhci::new(address).expect("xhcid: failed to allocate device")));
hci.probe().expect("xhcid: failed to probe");
hci.borrow_mut().probe().expect("xhcid: failed to probe");
let mut event_queue = EventQueue::<()>::new().expect("xhcid: failed to create event queue");
let todo = Arc::new(RefCell::new(Vec::<Packet>::new()));
//let device_irq = device.clone();
let hci_irq = hci.clone();
let socket_irq = socket.clone();
let todo_irq = todo.clone();
event_queue.add(irq_file.as_raw_fd(), move |_count: usize| -> Result<Option<()>> {
/*
let mut irq = [0; 8];
irq_file.read(&mut irq)?;
let isr = unsafe { device_irq.borrow_mut().irq() };
if isr != 0 {
if hci_irq.borrow_mut().irq() {
irq_file.write(&mut irq)?;
let mut todo = todo_irq.borrow_mut();
let mut i = 0;
while i < todo.len() {
let a = todo[i].a;
device_irq.borrow_mut().handle(&mut todo[i]);
hci_irq.borrow_mut().handle(&mut todo[i]);
if todo[i].a == (-EWOULDBLOCK) as usize {
todo[i].a = a;
i += 1;
......@@ -77,14 +75,13 @@ fn main() {
}
}
}
*/
Ok(None)
}).expect("xhcid: failed to catch events on IRQ file");
let socket_fd = socket.borrow().as_raw_fd();
let socket_packet = socket.clone();
event_queue.add(socket_fd, move |_count: usize| -> Result<Option<()>> {
/*
loop {
let mut packet = Packet::default();
if socket_packet.borrow_mut().read(&mut packet)? == 0 {
......@@ -92,7 +89,7 @@ fn main() {
}
let a = packet.a;
device.borrow_mut().handle(&mut packet);
hci.borrow_mut().handle(&mut packet);
if packet.a == (-EWOULDBLOCK) as usize {
packet.a = a;
todo.borrow_mut().push(packet);
......@@ -100,7 +97,6 @@ fn main() {
socket_packet.borrow_mut().write(&mut packet)?;
}
}
*/
Ok(None)
}).expect("xhcid: failed to catch events on scheme file");
......
......@@ -2,62 +2,45 @@ use syscall::error::Result;
use syscall::io::Dma;
use super::event::EventRing;
use super::ring::Ring;
use super::trb::Trb;
pub struct CommandRing {
trbs: Dma<[Trb; 256]>,
cmd_i: usize,
pub ring: Ring,
pub events: EventRing,
event_i: usize,
}
impl CommandRing {
pub fn new() -> Result<CommandRing> {
Ok(CommandRing {
trbs: Dma::zeroed()?,
cmd_i: 0,
ring: Ring::new(true)?,
events: EventRing::new()?,
event_i: 0,
})
}
pub fn crcr(&self) -> u64 {
self.trbs.physical() as u64 | 1
self.ring.register()
}
pub fn next(&mut self) -> (&mut Trb, &mut Trb) {
let cmd_i = self.cmd_i;
self.cmd_i += 1;
if self.cmd_i >= self.trbs.len() {
self.cmd_i = 0;
}
let event_i = self.event_i;
self.event_i += 1;
if self.event_i >= self.events.trbs.len() {
self.event_i = 0;
}
pub fn erdp(&self) -> u64 {
self.events.ring.register()
}
(&mut self.trbs[cmd_i], &mut self.events.trbs[event_i])
pub fn erstba(&self) -> u64 {
self.events.ste.physical() as u64
}
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;
}
pub fn next(&mut self) -> (&mut Trb, bool, &mut Trb) {
let cmd = self.ring.next();
let event = self.events.next();
(cmd.0, cmd.1, event)
}
&mut self.trbs[i]
pub fn next_cmd(&mut self) -> (&mut Trb, bool) {
self.ring.next()
}
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]
self.events.next()
}
}
......@@ -47,7 +47,6 @@ impl DeviceContextList {
// Create device context buffers for each slot
for i in 0..max_slots as usize {
println!(" - Setup dev ctx {}", i);
let context: Dma<DeviceContext> = Dma::zeroed()?;
dcbaa[i] = context.physical() as u64;
contexts.push(context);
......
use syscall::error::Result;
use syscall::io::{Dma, Io, Mmio};
use super::ring::Ring;
use super::trb::Trb;
#[repr(packed)]
......@@ -13,19 +14,23 @@ pub struct EventRingSte {
pub struct EventRing {
pub ste: Dma<EventRingSte>,
pub trbs: Dma<[Trb; 256]>
pub ring: Ring,
}
impl EventRing {
pub fn new() -> Result<EventRing> {
let mut ring = EventRing {
ste: Dma::zeroed()?,
trbs: Dma::zeroed()?
ring: Ring::new(false)?,
};
ring.ste.address.write(ring.trbs.physical() as u64);
ring.ste.size.write(ring.trbs.len() as u16);
ring.ste.address.write(ring.ring.trbs.physical() as u64);
ring.ste.size.write(ring.ring.trbs.len() as u16);
Ok(ring)
}
pub fn next(&mut self) -> &mut Trb {
self.ring.next().0
}
}
......@@ -12,6 +12,8 @@ mod event;
mod operational;
mod port;
mod runtime;
mod ring;
mod scheme;
mod trb;
use self::capability::CapabilityRegs;
......@@ -20,41 +22,49 @@ use self::context::{DeviceContextList, InputContext};
use self::doorbell::Doorbell;
use self::operational::OperationalRegs;
use self::port::Port;
use self::runtime::RuntimeRegs;
use self::ring::Ring;
use self::runtime::{RuntimeRegs, Interrupter};
use self::trb::TransferKind;
struct Device<'a> {
trbs: Dma<[trb::Trb; 256]>,
trb_i: usize,
ring: &'a mut Ring,
cmd: &'a mut CommandRing,
db: &'a mut Doorbell,
int: &'a mut Interrupter,
}
impl<'a> Device<'a> {
fn get_desc<T>(&mut self, kind: usb::DescriptorKind, index: u8, desc: &mut Dma<T>) {
let len = mem::size_of::<T>();
self.trbs[self.trb_i].setup(
usb::Setup::get_descriptor(kind, index, 0, len as u16),
TransferKind::In, true
);
{
let (cmd, cycle) = self.ring.next();
cmd.setup(
usb::Setup::get_descriptor(kind, index, 0, len as u16),
TransferKind::In, cycle
);
}
self.trbs[self.trb_i + 1].data(desc.physical(), len as u16, true, true);
{
let (cmd, cycle) = self.ring.next();
cmd.data(desc.physical(), len as u16, true, cycle);
}
self.trbs[self.trb_i + 2].status(false, true);
{
let (cmd, cycle) = self.ring.next();
cmd.status(false, cycle);
}
self.db.write(1);
let event = self.cmd.next_event();
while event.data.read() == 0 {
println!(" - Waiting for event");
{
let event = self.cmd.next_event();
while event.data.read() == 0 {
println!(" - Waiting for event");
}
}
for _i in 0..3 {
self.trbs[self.trb_i].reserved(false);
self.trb_i += 1;
}
event.reserved(false);
self.int.erdp.write(self.cmd.erdp());
}
fn get_device(&mut self) -> Result<usb::DeviceDescriptor> {
......@@ -198,13 +208,16 @@ impl Xhci {
println!(" - Write ERSTZ: {}", erstz);
self.run.ints[0].erstsz.write(erstz);
let erdp = self.cmd.events.trbs.physical();
let erdp = self.cmd.erdp();
println!(" - Write ERDP: {:X}", erdp);
self.run.ints[0].erdp.write(erdp as u64);
let erstba = self.cmd.events.ste.physical();
let erstba = self.cmd.erstba();
println!(" - Write ERSTBA: {:X}", erstba);
self.run.ints[0].erstba.write(erstba as u64);
println!(" - Enable interrupts");
self.run.ints[0].iman.writef(1 << 1, true);
}
// Set run/stop to 1
......@@ -239,9 +252,9 @@ impl Xhci {
let slot;
{
let (cmd, event) = self.cmd.next();
let (cmd, cycle, event) = self.cmd.next();
cmd.enable_slot(0, true);
cmd.enable_slot(0, cycle);
self.dbs[0].write(0);
......@@ -254,9 +267,11 @@ impl Xhci {
event.reserved(false);
}
self.run.ints[0].erdp.write(self.cmd.erdp());
println!(" - Slot {}", slot);
let mut trbs = Dma::<[trb::Trb; 256]>::zeroed()?;
let mut ring = Ring::new(true)?;
let mut input = Dma::<InputContext>::zeroed()?;
{
......@@ -266,14 +281,15 @@ impl Xhci {
input.device.slot.b.write(((i as u32 + 1) & 0xFF) << 16);
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 tr = ring.register();
input.device.endpoints[0].trh.write((tr >> 32) as u32);
input.device.endpoints[0].trl.write(tr as u32);
}
{
let (cmd, event) = self.cmd.next();
let (cmd, cycle, event) = self.cmd.next();
cmd.address_device(slot, input.physical(), true);
cmd.address_device(slot, input.physical(), cycle);
self.dbs[0].write(0);
......@@ -285,11 +301,13 @@ impl Xhci {
event.reserved(false);
}
self.run.ints[0].erdp.write(self.cmd.erdp());
let mut dev = Device {
trbs: trbs,
trb_i: 0,
ring: &mut ring,
cmd: &mut self.cmd,
db: &mut self.dbs[slot as usize],
int: &mut self.run.ints[0],
};
println!(" - Get descriptor");
......@@ -347,4 +365,14 @@ impl Xhci {
Ok(())
}
pub fn irq(&mut self) -> bool {
if self.run.ints[0].iman.readf(1) {
println!("XHCI Interrupt");
self.run.ints[0].iman.writef(1, true);
true
} else {
false
}
}
}
use syscall::error::Result;
use syscall::io::Dma;
use super::trb::Trb;
pub struct Ring {
pub link: bool,
pub trbs: Dma<[Trb; 16]>,
pub i: usize,
pub cycle: bool,
}
impl Ring {
pub fn new(link: bool) -> Result<Ring> {
Ok(Ring {
link: link,
trbs: Dma::zeroed()?,
i: 0,
cycle: link,
})
}
pub fn register(&self) -> u64 {
let base = self.trbs.physical() as *const Trb;
let addr = unsafe { base.offset(self.i as isize) };
addr as u64 | self.cycle as u64
}
pub fn next(&mut self) -> (&mut Trb, bool) {
let mut i;
loop {
i = self.i;
self.i += 1;
if self.i >= self.trbs.len() {
self.i = 0;
if self.link {
println!("Link");
let address = self.trbs.physical();
self.trbs[i].link(address, true, self.cycle);
self.cycle = !self.cycle;
} else {
println!("No-link");
break;
}
} else {
break;
}
}
(&mut self.trbs[i], self.cycle)
}
}
use super::Xhci;
use syscall::scheme::SchemeMut;
impl SchemeMut for Xhci {}
......@@ -111,28 +111,44 @@ pub struct Trb {
}
impl Trb {
pub fn set(&mut self, data: u64, status: u32, control: u32) {
self.data.write(data);
self.status.write(status);
self.control.write(control);
}
pub fn reserved(&mut self, cycle: bool) {
self.data.write(0);
self.status.write(0);
self.control.write(
self.set(
0,
0,
((TrbType::Reserved as u32) << 10) |
(cycle as u32)
);
}
pub fn link(&mut self, address: usize, toggle: bool, cycle: bool) {
self.set(
address as u64,
0,
((TrbType::Link as u32) << 10) |
((toggle as u32) << 1) |
(cycle as u32)
);
}
pub fn no_op_cmd(&mut self, cycle: bool) {
self.data.write(0);
self.status.write(0);
self.control.write(
self.set(
0,
0,
((TrbType::NoOpCmd as u32) << 10) |
(cycle as u32)
);
}
pub fn enable_slot(&mut self, slot_type: u8, cycle: bool) {
self.data.write(0);
self.status.write(0);
self.control.write(
self.set(
0,
0,
(((slot_type as u32) & 0x1F) << 16) |
((TrbType::EnableSlot as u32) << 10) |
(cycle as u32)
......@@ -140,9 +156,9 @@ impl Trb {
}
pub fn address_device(&mut self, slot_id: u8, input: usize, cycle: bool) {
self.data.write(input as u64);
self.status.write(0);
self.control.write(
self.set(
input as u64,
0,
((slot_id as u32) << 24) |
((TrbType::AddressDevice as u32) << 10) |
(cycle as u32)
......@@ -150,9 +166,9 @@ impl Trb {
}
pub fn setup(&mut self, setup: usb::Setup, transfer: TransferKind, cycle: bool) {
self.data.write(unsafe { mem::transmute(setup) });
self.status.write((0 << 22) | 8);
self.control.write(
self.set(
unsafe { mem::transmute(setup) },
8,
((transfer as u32) << 16) |
((TrbType::SetupStage as u32) << 10) |
(1 << 6) |
......@@ -161,9 +177,9 @@ impl Trb {
}
pub fn data(&mut self, buffer: usize, length: u16, input: bool, cycle: bool) {
self.data.write(buffer as u64);
self.status.write((0 << 22) | length as u32);
self.control.write(
self.set(
buffer as u64,
length as u32,
((input as u32) << 16) |
((TrbType::DataStage as u32) << 10) |
(cycle as u32)
......@@ -171,9 +187,9 @@ impl Trb {
}
pub fn status(&mut self, input: bool, cycle: bool) {
self.data.write(0);
self.status.write(0 << 22);
self.control.write(
self.set(
0,
0,
((input as u32) << 16) |
((TrbType::StatusStage as u32) << 10) |
(1 << 5) |
......
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