diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index 4839fd2cf8..18fba44441 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -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::::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> { - /* 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> { - /* 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"); diff --git a/xhcid/src/xhci/command.rs b/xhcid/src/xhci/command.rs index 8355d637fe..76ba0e6b4e 100644 --- a/xhcid/src/xhci/command.rs +++ b/xhcid/src/xhci/command.rs @@ -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 { 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; - } - - (&mut self.trbs[cmd_i], &mut self.events.trbs[event_i]) + pub fn erdp(&self) -> u64 { + self.events.ring.register() } - 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 erstba(&self) -> u64 { + self.events.ste.physical() as u64 + } - &mut self.trbs[i] + 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) + } + + 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() } } diff --git a/xhcid/src/xhci/context.rs b/xhcid/src/xhci/context.rs index 0203922628..5f9a978bfe 100644 --- a/xhcid/src/xhci/context.rs +++ b/xhcid/src/xhci/context.rs @@ -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 = Dma::zeroed()?; dcbaa[i] = context.physical() as u64; contexts.push(context); diff --git a/xhcid/src/xhci/event.rs b/xhcid/src/xhci/event.rs index 309eed226b..903b34cbb6 100644 --- a/xhcid/src/xhci/event.rs +++ b/xhcid/src/xhci/event.rs @@ -1,6 +1,7 @@ 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, - pub trbs: Dma<[Trb; 256]> + pub ring: Ring, } impl EventRing { pub fn new() -> Result { 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 + } } diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index 239995788c..795d9a7169 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -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(&mut self, kind: usb::DescriptorKind, index: u8, desc: &mut Dma) { let len = mem::size_of::(); - 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 { @@ -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::::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 + } + } } diff --git a/xhcid/src/xhci/ring.rs b/xhcid/src/xhci/ring.rs new file mode 100644 index 0000000000..e615e95a10 --- /dev/null +++ b/xhcid/src/xhci/ring.rs @@ -0,0 +1,53 @@ +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 { + 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) + } +} diff --git a/xhcid/src/xhci/scheme.rs b/xhcid/src/xhci/scheme.rs new file mode 100644 index 0000000000..e1531c7dd1 --- /dev/null +++ b/xhcid/src/xhci/scheme.rs @@ -0,0 +1,4 @@ +use super::Xhci; +use syscall::scheme::SchemeMut; + +impl SchemeMut for Xhci {} diff --git a/xhcid/src/xhci/trb.rs b/xhcid/src/xhci/trb.rs index 72c14c3dc8..c4193422ae 100644 --- a/xhcid/src/xhci/trb.rs +++ b/xhcid/src/xhci/trb.rs @@ -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) |