Commit aaafbbad authored by Jeremy Soller's avatar Jeremy Soller

Update e1000d to new event

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