diff --git a/e1000d/src/device.rs b/e1000d/src/device.rs index d7be0e96300a63ccb6a1ef66edfb70d1ab2e8769..59e5dab6097275cfd0662736b0e653565c27205d 100644 --- a/e1000d/src/device.rs +++ b/e1000d/src/device.rs @@ -1,10 +1,11 @@ -use std::{cmp, mem, ptr, slice, thread, time}; +use std::{cmp, mem, ptr, slice, thread}; +use std::collections::BTreeMap; use netutils::setcfg; -use syscall::error::{Error, EACCES, EINVAL, EWOULDBLOCK, Result}; +use syscall::error::{Error, EACCES, EBADF, EINVAL, EWOULDBLOCK, Result}; use syscall::flag::O_NONBLOCK; use syscall::io::Dma; -use syscall::scheme::Scheme; +use syscall::scheme::SchemeMut; const CTRL: u32 = 0x00; const CTRL_LRST: u32 = 1 << 3; @@ -98,29 +99,41 @@ pub struct Intel8254x { receive_buffer: [Dma<[u8; 16384]>; 16], receive_ring: Dma<[Rd; 16]>, transmit_buffer: [Dma<[u8; 16384]>; 16], - transmit_ring: Dma<[Td; 16]> + transmit_ring: Dma<[Td; 16]>, + next_id: usize, + pub handles: BTreeMap, } -impl Scheme for Intel8254x { - fn open(&self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { +impl SchemeMut for Intel8254x { + fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { if uid == 0 { - Ok(flags) + self.next_id += 1; + self.handles.insert(self.next_id, flags); + Ok(self.next_id) } else { Err(Error::new(EACCES)) } } - fn dup(&self, id: usize, buf: &[u8]) -> Result { + fn dup(&mut self, id: usize, buf: &[u8]) -> Result { if ! buf.is_empty() { return Err(Error::new(EINVAL)); } - Ok(id) + let flags = { + let flags = self.handles.get(&id).ok_or(Error::new(EBADF))?; + *flags + }; + self.next_id += 1; + self.handles.insert(self.next_id, flags); + Ok(self.next_id) } - fn read(&self, id: usize, buf: &mut [u8]) -> Result { - let head = unsafe { self.read(RDH) }; - let mut tail = unsafe { self.read(RDT) }; + fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { + let flags = self.handles.get(&id).ok_or(Error::new(EBADF))?; + + let head = unsafe { self.read_reg(RDH) }; + let mut tail = unsafe { self.read_reg(RDT) }; tail += 1; if tail >= self.receive_ring.len() as u32 { @@ -140,23 +153,25 @@ impl Scheme for Intel8254x { i += 1; } - unsafe { self.write(RDT, tail) }; + unsafe { self.write_reg(RDT, tail) }; return Ok(i); } } - if id & O_NONBLOCK == O_NONBLOCK { + if flags & O_NONBLOCK == O_NONBLOCK { Ok(0) } else { Err(Error::new(EWOULDBLOCK)) } } - fn write(&self, _id: usize, buf: &[u8]) -> Result { + fn write(&mut self, id: usize, buf: &[u8]) -> Result { + let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?; + loop { - let head = unsafe { self.read(TDH) }; - let mut tail = unsafe { self.read(TDT) }; + let head = unsafe { self.read_reg(TDH) }; + let mut tail = unsafe { self.read_reg(TDT) }; let old_tail = tail; tail += 1; @@ -183,7 +198,7 @@ impl Scheme for Intel8254x { i += 1; } - unsafe { self.write(TDT, tail) }; + unsafe { self.write_reg(TDT, tail) }; while td.status == 0 { thread::yield_now(); @@ -194,11 +209,14 @@ impl Scheme for Intel8254x { } } - fn fevent(&self, _id: usize, _flags: usize) -> Result { - Ok(0) + fn fevent(&mut self, id: usize, _flags: usize) -> Result { + let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?; + Ok(id) } - fn fpath(&self, _id: usize, buf: &mut [u8]) -> Result { + fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { + let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?; + let mut i = 0; let scheme_path = b"network:"; while i < buf.len() && i < scheme_path.len() { @@ -208,11 +226,13 @@ impl Scheme for Intel8254x { Ok(i) } - fn fsync(&self, _id: usize) -> Result { + fn fsync(&mut self, id: usize) -> Result { + let _flags = self.handles.get(&id).ok_or(Error::new(EBADF))?; Ok(0) } - fn close(&self, _id: usize) -> Result { + fn close(&mut self, id: usize) -> Result { + self.handles.remove(&id).ok_or(Error::new(EBADF))?; Ok(0) } } @@ -230,7 +250,9 @@ impl Intel8254x { 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_ring: Dma::zeroed()?, + next_id: 0, + handles: BTreeMap::new() }; module.init(); @@ -239,13 +261,13 @@ impl Intel8254x { } pub unsafe fn irq(&self) -> bool { - let icr = self.read(ICR); + let icr = self.read_reg(ICR); icr != 0 } pub fn next_read(&self) -> usize { - let head = unsafe { self.read(RDH) }; - let mut tail = unsafe { self.read(RDT) }; + let head = unsafe { self.read_reg(RDH) }; + let mut tail = unsafe { self.read_reg(RDT) }; tail += 1; if tail >= self.receive_ring.len() as u32 { @@ -262,27 +284,27 @@ impl Intel8254x { 0 } - pub unsafe fn read(&self, register: u32) -> u32 { + pub unsafe fn read_reg(&self, register: u32) -> u32 { ptr::read_volatile((self.base + register as usize) as *mut u32) } - pub unsafe fn write(&self, register: u32, data: u32) -> u32 { + pub unsafe fn write_reg(&self, register: u32, data: u32) -> u32 { ptr::write_volatile((self.base + register as usize) as *mut u32, data); ptr::read_volatile((self.base + register as usize) as *mut u32) } pub unsafe fn flag(&self, register: u32, flag: u32, value: bool) { if value { - self.write(register, self.read(register) | flag); + self.write_reg(register, self.read_reg(register) | flag); } else { - self.write(register, self.read(register) & (0xFFFFFFFF - flag)); + self.write_reg(register, self.read_reg(register) & !flag); } } pub unsafe fn init(&mut self) { self.flag(CTRL, CTRL_RST, true); - while self.read(CTRL) & CTRL_RST == CTRL_RST { - print!(" - Waiting for reset: {:X}\n", self.read(CTRL)); + while self.read_reg(CTRL) & CTRL_RST == CTRL_RST { + print!(" - Waiting for reset: {:X}\n", self.read_reg(CTRL)); } // Enable auto negotiate, link, clear reset, do not Invert Loss-Of Signal @@ -290,18 +312,18 @@ impl Intel8254x { self.flag(CTRL, CTRL_LRST | CTRL_PHY_RST | CTRL_ILOS, false); // No flow control - self.write(FCAH, 0); - self.write(FCAL, 0); - self.write(FCT, 0); - self.write(FCTTV, 0); + self.write_reg(FCAH, 0); + self.write_reg(FCAL, 0); + self.write_reg(FCT, 0); + self.write_reg(FCTTV, 0); // Do not use VLANs self.flag(CTRL, CTRL_VME, false); // TODO: Clear statistical counters - let mac_low = self.read(RAL0); - let mac_high = self.read(RAH0); + let mac_low = self.read_reg(RAL0); + let mac_high = self.read_reg(RAH0); let mac = [mac_low as u8, (mac_low >> 8) as u8, (mac_low >> 16) as u8, @@ -320,24 +342,24 @@ impl Intel8254x { self.receive_ring[i].buffer = self.receive_buffer[i].physical() as u64; } - self.write(RDBAH, (self.receive_ring.physical() >> 32) as u32); - self.write(RDBAL, self.receive_ring.physical() as u32); - self.write(RDLEN, (self.receive_ring.len() * mem::size_of::()) as u32); - self.write(RDH, 0); - self.write(RDT, self.receive_ring.len() as u32 - 1); + self.write_reg(RDBAH, (self.receive_ring.physical() >> 32) as u32); + self.write_reg(RDBAL, self.receive_ring.physical() as u32); + self.write_reg(RDLEN, (self.receive_ring.len() * mem::size_of::()) as u32); + self.write_reg(RDH, 0); + self.write_reg(RDT, self.receive_ring.len() as u32 - 1); // Transmit Buffer for i in 0..self.transmit_ring.len() { self.transmit_ring[i].buffer = self.transmit_buffer[i].physical() as u64; } - self.write(TDBAH, (self.transmit_ring.physical() >> 32) as u32); - self.write(TDBAL, self.transmit_ring.physical() as u32); - self.write(TDLEN, (self.transmit_ring.len() * mem::size_of::()) as u32); - self.write(TDH, 0); - self.write(TDT, 0); + self.write_reg(TDBAH, (self.transmit_ring.physical() >> 32) as u32); + self.write_reg(TDBAL, self.transmit_ring.physical() as u32); + self.write_reg(TDLEN, (self.transmit_ring.len() * mem::size_of::()) as u32); + self.write_reg(TDH, 0); + self.write_reg(TDT, 0); - self.write(IMS, IMS_RXT | IMS_RX | IMS_RXDMT | IMS_RXSEQ); // | IMS_LSC | IMS_TXQE | IMS_TXDW + self.write_reg(IMS, IMS_RXT | IMS_RX | IMS_RXDMT | IMS_RXSEQ); // | IMS_LSC | IMS_TXQE | IMS_TXDW self.flag(RCTL, RCTL_EN, true); self.flag(RCTL, RCTL_UPE, true); @@ -359,10 +381,10 @@ impl Intel8254x { // TIPG Packet Gap // TODO ... - while self.read(STATUS) & 2 != 2 { - print!(" - Waiting for link up: {:X}\n", self.read(STATUS)); + while self.read_reg(STATUS) & 2 != 2 { + print!(" - Waiting for link up: {:X}\n", self.read_reg(STATUS)); } - print!(" - Link is up with speed {}\n", match (self.read(STATUS) >> 6) & 0b11 { + print!(" - Link is up with speed {}\n", match (self.read_reg(STATUS) >> 6) & 0b11 { 0b00 => "10 Mb/s", 0b01 => "100 Mb/s", _ => "1000 Mb/s", diff --git a/e1000d/src/main.rs b/e1000d/src/main.rs index 02b6bcb838209be0f0fb31964b92ca207807b54b..41e8e4d198c724bcfa40f887bfd0391f56e843c0 100644 --- a/e1000d/src/main.rs +++ b/e1000d/src/main.rs @@ -12,7 +12,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd}; use std::sync::Arc; use event::EventQueue; -use syscall::{Packet, Scheme, MAP_WRITE}; +use syscall::{Packet, SchemeMut, MAP_WRITE}; use syscall::error::EWOULDBLOCK; pub mod device; @@ -40,7 +40,7 @@ fn main() { let address = unsafe { syscall::physmap(bar, 128*1024, MAP_WRITE).expect("e1000d: failed to map address") }; { - let device = Arc::new(unsafe { device::Intel8254x::new(address).expect("e1000d: failed to allocate device") }); + let device = Arc::new(RefCell::new(unsafe { device::Intel8254x::new(address).expect("e1000d: failed to allocate device") })); let mut event_queue = EventQueue::::new().expect("e1000d: failed to create event queue"); @@ -54,14 +54,14 @@ fn main() { event_queue.add(irq_file.as_raw_fd(), move |_event| -> Result> { let mut irq = [0; 8]; irq_file.read(&mut irq)?; - if unsafe { device_irq.irq() } { + if unsafe { device_irq.borrow().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.handle(&mut todo[i]); + device_irq.borrow_mut().handle(&mut todo[i]); if todo[i].a == (-EWOULDBLOCK) as usize { todo[i].a = a; i += 1; @@ -71,7 +71,7 @@ fn main() { } } - let next_read = device_irq.next_read(); + let next_read = device_irq.borrow().next_read(); if next_read > 0 { return Ok(Some(next_read)); } @@ -79,6 +79,7 @@ fn main() { Ok(None) }).expect("e1000d: failed to catch events on IRQ file"); + let device_packet = device.clone(); let socket_packet = socket.clone(); event_queue.add(socket_fd, move |_event| -> Result> { loop { @@ -88,7 +89,7 @@ fn main() { } let a = packet.a; - device.handle(&mut packet); + device_packet.borrow_mut().handle(&mut packet); if packet.a == (-EWOULDBLOCK) as usize { packet.a = a; todo.borrow_mut().push(packet); @@ -97,7 +98,7 @@ fn main() { } } - let next_read = device.next_read(); + let next_read = device_packet.borrow().next_read(); if next_read > 0 { return Ok(Some(next_read)); } @@ -105,35 +106,31 @@ fn main() { Ok(None) }).expect("e1000d: failed to catch events on scheme file"); + let send_events = |event_count| { + for (handle_id, _handle) in device.borrow().handles.iter() { + socket.borrow_mut().write(&Packet { + id: 0, + pid: 0, + uid: 0, + gid: 0, + a: syscall::number::SYS_FEVENT, + b: *handle_id, + c: syscall::flag::EVENT_READ, + d: event_count + }).expect("e1000d: failed to write event"); + } + }; + for event_count in event_queue.trigger_all(event::Event { fd: 0, flags: 0, }).expect("e1000d: failed to trigger events") { - socket.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: 0, - c: syscall::flag::EVENT_READ, - d: event_count - }).expect("e1000d: failed to write event"); + send_events(event_count); } loop { let event_count = event_queue.run().expect("e1000d: failed to handle events"); - - socket.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: 0, - c: syscall::flag::EVENT_READ, - d: event_count - }).expect("e1000d: failed to write event"); + send_events(event_count); } } unsafe { let _ = syscall::physunmap(address); }