From 14d816507914b7c4c2c5e6389f3aeeea0e911b3f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 6 Aug 2017 15:19:56 -0600 Subject: [PATCH] Cleanup xhci, add basic IRQ event functions, cleanup e1000d and rtl8168d --- Cargo.lock | 10 +++ e1000d/src/main.rs | 4 +- rtl8168d/src/main.rs | 2 +- xhcid/Cargo.toml | 1 + xhcid/src/main.rs | 92 +++++++++++++++++++++--- xhcid/src/xhci/{device.rs => context.rs} | 8 +-- xhcid/src/xhci/mod.rs | 90 +++++++++++++---------- 7 files changed, 151 insertions(+), 56 deletions(-) rename xhcid/src/xhci/{device.rs => context.rs} (90%) diff --git a/Cargo.lock b/Cargo.lock index 5d16f15d8c..a0da78a630 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,6 +4,7 @@ version = "0.1.0" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "plain 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -416,6 +417,14 @@ dependencies = [ "redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_event" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.29" @@ -739,6 +748,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a" "checksum rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7febc28567082c345f10cddc3612c6ea020fc3297a1977d472cf9fdb73e6e493" "checksum redox_event 0.1.0 (git+https://github.com/redox-os/event.git)" = "" +"checksum redox_event 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98e1a40d38f45a3ad65fd088640eeee7b215adcd73041b9f94b92204cca9572a" "checksum redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9309631a35303bffb47e397198e3668cb544fe8834cd3da2a744441e70e524" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2a6dc7fc06a05e6de183c5b97058582e9da2de0c136eafe49609769c507724" diff --git a/e1000d/src/main.rs b/e1000d/src/main.rs index 0d59ed52b7..00a6d81301 100644 --- a/e1000d/src/main.rs +++ b/e1000d/src/main.rs @@ -29,7 +29,7 @@ fn main() { let irq_str = args.next().expect("e1000d: no irq provided"); let irq = irq_str.parse::().expect("e1000d: failed to parse irq"); - print!("{}", format!(" + E1000 {} on: {:X}, IRQ: {}\n", name, bar, irq)); + print!("{}", format!(" + E1000 {} on: {:X} IRQ: {}\n", name, bar, irq)); // Daemonize if unsafe { syscall::clone(0).unwrap() } == 0 { @@ -100,7 +100,7 @@ fn main() { } Ok(None) - }).expect("e1000d: failed to catch events on IRQ file"); + }).expect("e1000d: failed to catch events on scheme file"); for event_count in event_queue.trigger_all(0).expect("e1000d: failed to trigger events") { socket.borrow_mut().write(&Packet { diff --git a/rtl8168d/src/main.rs b/rtl8168d/src/main.rs index 27ba048aa7..3f7b905a58 100644 --- a/rtl8168d/src/main.rs +++ b/rtl8168d/src/main.rs @@ -104,7 +104,7 @@ fn main() { } Ok(None) - }).expect("rtl8168d: failed to catch events on IRQ file"); + }).expect("rtl8168d: failed to catch events on scheme file"); for event_count in event_queue.trigger_all(0).expect("rtl8168d: failed to trigger events") { socket.borrow_mut().write(&Packet { diff --git a/xhcid/Cargo.toml b/xhcid/Cargo.toml index e14cb52f24..3618ef835b 100644 --- a/xhcid/Cargo.toml +++ b/xhcid/Cargo.toml @@ -6,4 +6,5 @@ version = "0.1.0" bitflags = "0.7" plain = "0.2" spin = "0.4" +redox_event = "0.1" redox_syscall = "0.1" diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index cf8dcef795..4839fd2cf8 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -1,9 +1,19 @@ #[macro_use] extern crate bitflags; +extern crate event; extern crate plain; extern crate syscall; +use event::EventQueue; +use std::cell::RefCell; use std::env; +use std::fs::File; +use std::io::{Result, Read, Write}; +use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::sync::Arc; +use syscall::data::Packet; +use syscall::error::EWOULDBLOCK; +use syscall::scheme::SchemeMut; use xhci::Xhci; @@ -19,23 +29,85 @@ fn main() { let bar_str = args.next().expect("xhcid: no address provided"); let bar = usize::from_str_radix(&bar_str, 16).expect("xhcid: failed to parse address"); - print!("{}", format!(" + XHCI {} on: {:X}\n", name, bar)); + let irq_str = args.next().expect("xhcid: no IRQ provided"); + let irq = irq_str.parse::().expect("xhcid: failed to parse irq"); + + print!("{}", format!(" + XHCI {} on: {:X} IRQ: {}\n", name, bar, irq)); // Daemonize if unsafe { syscall::clone(0).unwrap() } == 0 { + let socket_fd = syscall::open(":usb", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("xhcid: failed to create usb scheme"); + let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); + + let mut irq_file = File::open(format!("irq:{}", irq)).expect("xhcid: failed to open IRQ file"); + 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"); - match Xhci::new(address) { - Ok(mut xhci) => { - if let Err(err) = xhci.probe() { - println!("xhcid: probe error: {}", err); + hci.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 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 { + 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]); + if todo[i].a == (-EWOULDBLOCK) as usize { + todo[i].a = a; + i += 1; + } else { + socket_irq.borrow_mut().write(&mut todo[i])?; + todo.remove(i); + } + } } - }, - Err(err) => { - println!("xhcid: open error: {}", err); - } - } + */ + 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 { + break; + } + + let a = packet.a; + device.borrow_mut().handle(&mut packet); + if packet.a == (-EWOULDBLOCK) as usize { + packet.a = a; + todo.borrow_mut().push(packet); + } else { + socket_packet.borrow_mut().write(&mut packet)?; + } + } + */ + Ok(None) + }).expect("xhcid: failed to catch events on scheme file"); + + event_queue.trigger_all(0).expect("xhcid: failed to trigger events"); + + event_queue.run().expect("xhcid: failed to handle events"); + } unsafe { let _ = syscall::physunmap(address); } } } diff --git a/xhcid/src/xhci/device.rs b/xhcid/src/xhci/context.rs similarity index 90% rename from xhcid/src/xhci/device.rs rename to xhcid/src/xhci/context.rs index d082f561ce..0203922628 100644 --- a/xhcid/src/xhci/device.rs +++ b/xhcid/src/xhci/context.rs @@ -35,13 +35,13 @@ pub struct InputContext { pub device: DeviceContext, } -pub struct DeviceList { +pub struct DeviceContextList { pub dcbaa: Dma<[u64; 256]>, pub contexts: Vec>, } -impl DeviceList { - pub fn new(max_slots: u8) -> Result { +impl DeviceContextList { + pub fn new(max_slots: u8) -> Result { let mut dcbaa = Dma::<[u64; 256]>::zeroed()?; let mut contexts = vec![]; @@ -53,7 +53,7 @@ impl DeviceList { contexts.push(context); } - Ok(DeviceList { + Ok(DeviceContextList { dcbaa: dcbaa, contexts: contexts }) diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index f2668595e2..239995788c 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -6,7 +6,7 @@ use usb; mod capability; mod command; -mod device; +mod context; mod doorbell; mod event; mod operational; @@ -16,7 +16,7 @@ mod trb; use self::capability::CapabilityRegs; use self::command::CommandRing; -use self::device::DeviceList; +use self::context::{DeviceContextList, InputContext}; use self::doorbell::Doorbell; use self::operational::OperationalRegs; use self::port::Port; @@ -57,6 +57,26 @@ impl<'a> Device<'a> { event.reserved(false); } + fn get_device(&mut self) -> Result { + let mut desc = Dma::::zeroed()?; + self.get_desc( + usb::DescriptorKind::Device, + 0, + &mut desc + ); + Ok(*desc) + } + + fn get_config(&mut self, config: u8) -> Result<(usb::ConfigDescriptor, [u8; 4087])> { + let mut desc = Dma::<(usb::ConfigDescriptor, [u8; 4087])>::zeroed()?; + self.get_desc( + usb::DescriptorKind::Configuration, + config, + &mut desc + ); + Ok(*desc) + } + fn get_string(&mut self, index: u8) -> Result { let mut sdesc = Dma::<(u8, u8, [u16; 127])>::zeroed()?; self.get_desc( @@ -80,7 +100,7 @@ pub struct Xhci { ports: &'static mut [Port], dbs: &'static mut [Doorbell], run: &'static mut RuntimeRegs, - devices: DeviceList, + dev_ctx: DeviceContextList, cmd: CommandRing, } @@ -146,7 +166,7 @@ impl Xhci { ports: ports, dbs: dbs, run: run, - devices: DeviceList::new(max_slots)?, + dev_ctx: DeviceContextList::new(max_slots)?, cmd: CommandRing::new()?, }; @@ -162,7 +182,7 @@ impl Xhci { println!(" - Enabled Slots: {}", self.op.config.read() & 0xFF); // Set device context address array pointer - let dcbaap = self.devices.dcbaap(); + let dcbaap = self.dev_ctx.dcbaap(); println!(" - Write DCBAAP: {:X}", dcbaap); self.op.dcbaap.write(dcbaap as u64); @@ -173,16 +193,19 @@ impl Xhci { // Set event ring segment table registers println!(" - Interrupter 0: {:X}", self.run.ints.as_ptr() as usize); - println!(" - Write ERSTZ"); - self.run.ints[0].erstsz.write(1); + { + let erstz = 1; + println!(" - Write ERSTZ: {}", erstz); + self.run.ints[0].erstsz.write(erstz); - let erdp = self.cmd.events.trbs.physical(); - println!(" - Write ERDP: {:X}", erdp); - self.run.ints[0].erdp.write(erdp as u64); + let erdp = self.cmd.events.trbs.physical(); + println!(" - Write ERDP: {:X}", erdp); + self.run.ints[0].erdp.write(erdp as u64); - let erstba = self.cmd.events.ste.physical(); - println!(" - Write ERSTBA: {:X}", erstba); - self.run.ints[0].erstba.write(erstba as u64); + let erstba = self.cmd.events.ste.physical(); + println!(" - Write ERSTBA: {:X}", erstba); + self.run.ints[0].erstba.write(erstba as u64); + } // Set run/stop to 1 println!(" - Start"); @@ -234,12 +257,12 @@ impl Xhci { println!(" - Slot {}", slot); let mut trbs = Dma::<[trb::Trb; 256]>::zeroed()?; - let mut trb_i = 0; - let mut input = Dma::::zeroed()?; + + let mut input = Dma::::zeroed()?; { input.add_context.write(1 << 1 | 1); - input.device.slot.a.write(1 << 27); + input.device.slot.a.write((1 << 27) | (speed << 20)); input.device.slot.b.write(((i as u32 + 1) & 0xFF) << 16); input.device.endpoints[0].b.write(4096 << 16 | 4 << 3 | 3 << 1); @@ -264,20 +287,15 @@ impl Xhci { let mut dev = Device { trbs: trbs, - trb_i: trb_i, + trb_i: 0, cmd: &mut self.cmd, db: &mut self.dbs[slot as usize], }; println!(" - Get descriptor"); - let mut ddesc = Dma::::zeroed()?; - dev.get_desc( - usb::DescriptorKind::Device, - 0, - &mut ddesc - ); - println!(" {:?}", *ddesc); + let ddesc = dev.get_device()?; + println!(" {:?}", ddesc); if ddesc.manufacturer_str > 0 { println!(" Manufacturer: {}", dev.get_string(ddesc.manufacturer_str)?); @@ -292,26 +310,20 @@ impl Xhci { } for config in 0..ddesc.configurations { - let mut cdesc = Dma::<(usb::ConfigDescriptor, [u8; 4087])>::zeroed()?; - dev.get_desc( - usb::DescriptorKind::Configuration, - config, - &mut cdesc - ); - println!(" {}: {:?}", config, cdesc.0); + let (cdesc, data) = dev.get_config(config)?; + println!(" {}: {:?}", config, cdesc); - if cdesc.0.configuration_str > 0 { - println!(" Name: {}", dev.get_string(cdesc.0.configuration_str)?); + if cdesc.configuration_str > 0 { + println!(" Name: {}", dev.get_string(cdesc.configuration_str)?); } - if cdesc.0.total_length as usize > mem::size_of::() { - let len = cdesc.0.total_length as usize - mem::size_of::(); - let data = &cdesc.1[..len]; + if cdesc.total_length as usize > mem::size_of::() { + let len = cdesc.total_length as usize - mem::size_of::(); let mut i = 0; - for interface in 0..cdesc.0.interfaces { + for interface in 0..cdesc.interfaces { let mut idesc = usb::InterfaceDescriptor::default(); - if i < data.len() && idesc.copy_from_bytes(&data[i..]).is_ok() { + if i < len && i < data.len() && idesc.copy_from_bytes(&data[i..len]).is_ok() { i += mem::size_of_val(&idesc); println!(" {}: {:?}", interface, idesc); @@ -321,7 +333,7 @@ impl Xhci { for endpoint in 0..idesc.endpoints { let mut edesc = usb::EndpointDescriptor::default(); - if i < data.len() && edesc.copy_from_bytes(&data[i..]).is_ok() { + if i < len && i < data.len() && edesc.copy_from_bytes(&data[i..len]).is_ok() { i += mem::size_of_val(&edesc); println!(" {}: {:?}", endpoint, edesc); }