From a2ef986edd3a52309b9076c6fffc6e3e5ca82cd6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Oct 2016 12:52:58 -0600 Subject: [PATCH] Add rtl8168 driver, make drivers use O_NONBLOCK --- drivers/ahcid/src/main.rs | 6 +- drivers/e1000d/src/main.rs | 6 +- drivers/rtl8168d/Cargo.toml | 11 ++ drivers/rtl8168d/src/device.rs | 276 +++++++++++++++++++++++++++++++++ drivers/rtl8168d/src/main.rs | 99 ++++++++++++ 5 files changed, 392 insertions(+), 6 deletions(-) create mode 100644 drivers/rtl8168d/Cargo.toml create mode 100644 drivers/rtl8168d/src/device.rs create mode 100644 drivers/rtl8168d/src/main.rs diff --git a/drivers/ahcid/src/main.rs b/drivers/ahcid/src/main.rs index fba2503..d15aea9 100644 --- a/drivers/ahcid/src/main.rs +++ b/drivers/ahcid/src/main.rs @@ -10,7 +10,7 @@ extern crate syscall; use std::{env, thread, usize}; use std::fs::File; use std::io::{Read, Write}; -use std::os::unix::io::AsRawFd; +use std::os::unix::io::{AsRawFd, FromRawFd}; use syscall::{EVENT_READ, MAP_WRITE, Event, Packet, Scheme}; use scheme::DiskScheme; @@ -35,8 +35,8 @@ fn main() { let address = unsafe { syscall::physmap(bar, 4096, MAP_WRITE).expect("ahcid: failed to map address") }; { - let mut socket = File::create(":disk").expect("ahcid: failed to create disk scheme"); - let socket_fd = socket.as_raw_fd(); + let socket_fd = syscall::open(":disk", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ahcid: failed to create disk scheme"); + let mut socket = unsafe { File::from_raw_fd(socket_fd) }; syscall::fevent(socket_fd, EVENT_READ).expect("ahcid: failed to fevent disk scheme"); let mut irq_file = File::open(&format!("irq:{}", irq)).expect("ahcid: failed to open irq file"); diff --git a/drivers/e1000d/src/main.rs b/drivers/e1000d/src/main.rs index 00b31db..fcc7d6b 100644 --- a/drivers/e1000d/src/main.rs +++ b/drivers/e1000d/src/main.rs @@ -8,7 +8,7 @@ use std::cell::RefCell; use std::{env, thread}; use std::fs::File; use std::io::{Read, Write, Result}; -use std::os::unix::io::AsRawFd; +use std::os::unix::io::{AsRawFd, FromRawFd}; use std::sync::Arc; use event::EventQueue; @@ -32,7 +32,8 @@ fn main() { asm!("cli" :::: "intel", "volatile"); } - let socket = Arc::new(RefCell::new(File::create(":network").expect("e1000d: failed to create network scheme"))); + let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("e1000d: failed to create network scheme"); + let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); let address = unsafe { syscall::physmap(bar, 128*1024, MAP_WRITE).expect("e1000d: failed to map address") }; { @@ -69,7 +70,6 @@ fn main() { Ok(None) }).expect("e1000d: failed to catch events on IRQ file"); - let socket_fd = socket.borrow().as_raw_fd(); event_queue.add(socket_fd, move |_count: usize| -> Result> { let mut packet = Packet::default(); socket.borrow_mut().read(&mut packet)?; diff --git a/drivers/rtl8168d/Cargo.toml b/drivers/rtl8168d/Cargo.toml new file mode 100644 index 0000000..394f156 --- /dev/null +++ b/drivers/rtl8168d/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rtl8168d" +version = "0.1.0" + +[dependencies] +bitflags = "*" +dma = { path = "../../crates/dma/" } +event = { path = "../../crates/event/" } +io = { path = "../../crates/io/" } +spin = "*" +syscall = { path = "../../syscall/" } diff --git a/drivers/rtl8168d/src/device.rs b/drivers/rtl8168d/src/device.rs new file mode 100644 index 0000000..1318176 --- /dev/null +++ b/drivers/rtl8168d/src/device.rs @@ -0,0 +1,276 @@ +use std::{cmp, mem, slice}; + +use dma::Dma; +use io::{Mmio, Io, ReadOnly, WriteOnly}; +use syscall::error::{Error, EACCES, EWOULDBLOCK, Result}; +use syscall::scheme::SchemeMut; + +#[repr(packed)] +struct Regs { + mac: [Mmio; 2], + mar: Mmio, + dtccr: Mmio, + _rsv0: Mmio, + tnpds: Mmio, + thpds: Mmio, + _rsv1: [Mmio; 7], + cmd: Mmio, + tppoll: WriteOnly>, + _rsv2: [Mmio; 3], + imr: Mmio, + isr: Mmio, + tcr: Mmio, + rcr: Mmio, + tctr: Mmio, + _rsv3: Mmio, + cmd_9346: Mmio, + config: [Mmio; 6], + _rsv4: Mmio, + timer_int: Mmio, + _rsv5: Mmio, + phys_ar: Mmio, + _rsv6: Mmio, + phys_sts: ReadOnly>, + _rsv7: [Mmio; 23], + wakeup: [Mmio; 8], + crc: [Mmio; 5], + _rsv8: [Mmio; 12], + rms: Mmio, + _rsv9: Mmio, + c_plus_cr: Mmio, + _rsv10: Mmio, + rdsar: Mmio, + mtps: Mmio, + _rsv11: [Mmio; 19], +} + +const OWN: u16 = 1 << 15; +const EOR: u16 = 1 << 14; + +#[repr(packed)] +struct Rd { + length: Mmio, + flags: Mmio, + vlan: Mmio, + buffer: Mmio +} + +#[repr(packed)] +struct Td { + length: Mmio, + flags: Mmio, + vlan: Mmio, + buffer: Mmio +} + +pub struct Rtl8168 { + regs: &'static mut Regs, + irq: u8, + receive_buffer: [Dma<[u8; 0x1FF8]>; 16], + receive_ring: Dma<[Rd; 16]>, + transmit_buffer: [Dma<[u8; 0x1FF8]>; 16], + transmit_ring: Dma<[Td; 16]>, + transmit_buffer_h: [Dma<[u8; 0x1FF8]>; 1], + transmit_ring_h: Dma<[Td; 1]> +} + +impl SchemeMut for Rtl8168 { + fn open(&mut self, _path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result { + if uid == 0 { + Ok(0) + } else { + Err(Error::new(EACCES)) + } + } + + fn dup(&mut self, id: usize) -> Result { + Ok(id) + } + + fn read(&mut self, _id: usize, buf: &mut [u8]) -> Result { + println!("Try Receive {}", buf.len()); + for (rd_i, rd) in self.receive_ring.iter_mut().enumerate() { + if ! rd.flags.readf(OWN) { + println!("Receive {}: {}", rd_i, rd.length.read()); + + let data = &self.receive_buffer[rd_i as usize][.. rd.length.read() as usize]; + + let mut i = 0; + while i < buf.len() && i < data.len() { + buf[i] = data[i]; + i += 1; + } + + rd.flags.writef(OWN, true); + + return Ok(i); + } + } + + Err(Error::new(EWOULDBLOCK)) + } + + fn write(&mut self, _id: usize, buf: &[u8]) -> Result { + println!("Try Transmit {}", buf.len()); + loop { + for (td_i, td) in self.transmit_ring.iter_mut().enumerate() { + if ! td.flags.readf(OWN) { + println!("Transmit {}: Setup {}", td_i, buf.len()); + + let mut data = &mut self.transmit_buffer[td_i as usize]; + + let mut i = 0; + while i < buf.len() && i < data.len() { + data[i] = buf[i]; + i += 1; + } + + td.length.write(cmp::min(buf.len(), i) as u16); + + td.flags.writef(OWN | 1 << 13 | 1 << 12, true); + + self.regs.tppoll.writef(1 << 6, true); //Notify of normal priority packet + + return Ok(i); + } + } + + unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); } + } + } + + fn fsync(&mut self, _id: usize) -> Result { + Ok(0) + } + + fn close(&mut self, _id: usize) -> Result { + Ok(0) + } +} + +impl Rtl8168 { + pub unsafe fn new(base: usize, irq: u8) -> Result { + assert_eq!(mem::size_of::(), 256); + + let regs = &mut *(base as *mut Regs); + assert_eq!(®s.tnpds as *const _ as usize - base, 0x20); + assert_eq!(®s.cmd as *const _ as usize - base, 0x37); + assert_eq!(®s.tcr as *const _ as usize - base, 0x40); + assert_eq!(®s.rcr as *const _ as usize - base, 0x44); + assert_eq!(®s.cmd_9346 as *const _ as usize - base, 0x50); + assert_eq!(®s.phys_sts as *const _ as usize - base, 0x6C); + assert_eq!(®s.rms as *const _ as usize - base, 0xDA); + assert_eq!(®s.rdsar as *const _ as usize - base, 0xE4); + assert_eq!(®s.mtps as *const _ as usize - base, 0xEC); + + let mut module = Rtl8168 { + regs: regs, + irq: irq, + receive_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, + Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, + Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, + Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?], + receive_ring: Dma::zeroed()?, + transmit_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, + Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, + Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, + Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?], + transmit_ring: Dma::zeroed()?, + transmit_buffer_h: [Dma::zeroed()?], + transmit_ring_h: Dma::zeroed()? + }; + + module.init(); + + Ok(module) + } + + pub unsafe fn irq(&mut self) -> u16 { + // Read and then clear the ISR + let isr = self.regs.isr.read(); + self.regs.isr.write(isr); + isr + } + + pub unsafe fn init(&mut self) { + println!(" + RTL8168 on: {:X}, IRQ: {}", self.regs as *mut Regs as usize, self.irq); + + let mac_low = self.regs.mac[0].read(); + let mac_high = self.regs.mac[1].read(); + let mac = [mac_low as u8, + (mac_low >> 8) as u8, + (mac_low >> 16) as u8, + (mac_low >> 24) as u8, + mac_high as u8, + (mac_high >> 8) as u8]; + println!(" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + // Reset - this will disable tx and rx, reinitialize FIFOs, and set the system buffer pointer to the initial value + self.regs.cmd.writef(1 << 4, true); + while self.regs.cmd.readf(1 << 4) {} + + // Set up rx buffers + for i in 0..self.receive_ring.len() { + self.receive_ring[i].flags.writef(OWN, true); + self.receive_ring[i].length.write(self.receive_buffer[i].len() as u16); + self.receive_ring[i].buffer.write(self.receive_buffer[i].physical() as u64); + } + if let Some(mut rd) = self.receive_ring.last_mut() { + rd.flags.writef(OWN | EOR, true); + } + + // Set up normal priority tx buffers + for i in 0..self.transmit_ring.len() { + self.transmit_ring[i].buffer.write(self.transmit_buffer[i].physical() as u64); + } + if let Some(mut td) = self.transmit_ring.last_mut() { + td.flags.writef(EOR, true); + } + + // Set up high priority tx buffers + for i in 0..self.transmit_ring_h.len() { + self.transmit_ring_h[i].buffer.write(self.transmit_buffer_h[i].physical() as u64); + } + if let Some(mut td) = self.transmit_ring_h.last_mut() { + td.flags.writef(EOR, true); + } + + // Unlock config + self.regs.cmd_9346.write(1 << 7 | 1 << 6); + + // Accept broadcast (bit 3), multicast (bit 2), and unicast (bit 1) + self.regs.rcr.writef(0xE70F /*TODO: Not permiscuious*/, true); + + // Enable tx (bit 2) + self.regs.cmd.writef(1 << 2, true); + + // Set TX config + self.regs.tcr.write(0x03010700); + + // Max RX packet size + self.regs.rms.write(0x1FF8); + + // Max TX packet size + self.regs.mtps.write(0x3B); + + // Set tx low priority buffer address + self.regs.tnpds.write(self.transmit_ring.physical() as u64); + + // Set tx high priority buffer address + self.regs.thpds.write(self.transmit_ring_h.physical() as u64); + + // Set rx buffer address + self.regs.rdsar.write(self.receive_ring.physical() as u64); + + // Enable rx (bit 3) and tx (bit 2) + self.regs.cmd.writef(1 << 3 | 1 << 2, true); + + // Interrupt on tx error (bit 3), tx ok (bit 2), rx error(bit 1), and rx ok (bit 0) + self.regs.imr.write(1 << 15 | 1 << 14 | 1 << 7 | 1 << 6 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1); + + // Lock config + self.regs.cmd_9346.write(0); + + println!(" - Ready {:X}", self.regs.phys_sts.read()); + } +} diff --git a/drivers/rtl8168d/src/main.rs b/drivers/rtl8168d/src/main.rs new file mode 100644 index 0000000..bd4425c --- /dev/null +++ b/drivers/rtl8168d/src/main.rs @@ -0,0 +1,99 @@ +#![feature(asm)] + +extern crate dma; +extern crate event; +extern crate io; +extern crate syscall; + +use std::cell::RefCell; +use std::{env, thread}; +use std::fs::File; +use std::io::{Read, Write, Result}; +use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::sync::Arc; + +use event::EventQueue; +use syscall::{Packet, SchemeMut, MAP_WRITE}; +use syscall::error::EWOULDBLOCK; + +pub mod device; + +fn main() { + let mut args = env::args().skip(1); + + let bar_str = args.next().expect("rtl8168d: no address provided"); + let bar = usize::from_str_radix(&bar_str, 16).expect("rtl8168d: failed to parse address"); + + let irq_str = args.next().expect("rtl8168d: no irq provided"); + let irq = irq_str.parse::().expect("rtl8168d: failed to parse irq"); + + thread::spawn(move || { + unsafe { + syscall::iopl(3).expect("rtl8168d: failed to get I/O permission"); + asm!("cli" :::: "intel", "volatile"); + } + + let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("rtl8168d: failed to create network scheme"); + let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); + + let address = unsafe { syscall::physmap(bar, 256, MAP_WRITE).expect("rtl8168d: failed to map address") }; + { + let device = Arc::new(RefCell::new(unsafe { device::Rtl8168::new(address, irq).expect("rtl8168d: failed to allocate device") })); + + let mut event_queue = EventQueue::<()>::new().expect("rtl8168d: 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(); + let mut irq_file = File::open(format!("irq:{}", irq)).expect("rtl8168d: failed to open IRQ file"); + 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)?; + + println!("RTL8168 Interrupt {:X}", isr); + + 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); + } + } + } + Ok(None) + }).expect("rtl8168d: failed to catch events on IRQ file"); + + let socket_fd = socket.borrow().as_raw_fd(); + event_queue.add(socket_fd, move |_count: usize| -> Result> { + let mut packet = Packet::default(); + socket.borrow_mut().read(&mut packet)?; + + 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.borrow_mut().write(&mut packet)?; + } + + Ok(None) + }).expect("rtl8168d: failed to catch events on IRQ file"); + + event_queue.run().expect("rtl8168d: failed to handle events"); + } + unsafe { let _ = syscall::physunmap(address); } + }); +}