Files
RedBear-OS/rtl8168d/src/main.rs
T
2019-09-04 20:38:08 -06:00

202 lines
6.6 KiB
Rust

#![feature(asm)]
extern crate event;
extern crate netutils;
extern crate syscall;
use std::cell::RefCell;
use std::env;
use std::fs::File;
use std::io::{ErrorKind, Read, Result, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::Arc;
use event::EventQueue;
use syscall::{Packet, SchemeBlockMut, PHYSMAP_NO_CACHE, PHYSMAP_WRITE};
pub mod device;
fn handle_update(
socket: &mut File,
device: &mut device::Rtl8168,
todo: &mut Vec<Packet>,
) -> Result<bool> {
// Handle any blocked packets
let mut i = 0;
while i < todo.len() {
if let Some(a) = device.handle(&todo[i]) {
let mut packet = todo.remove(i);
packet.a = a;
socket.write(&packet)?;
} else {
i += 1;
}
}
// Check that the socket is empty
loop {
let mut packet = Packet::default();
match socket.read(&mut packet) {
Ok(0) => return Ok(true),
Ok(_) => (),
Err(err) => {
if err.kind() == ErrorKind::WouldBlock {
break;
} else {
return Err(err);
}
}
}
if let Some(a) = device.handle(&packet) {
packet.a = a;
socket.write(&packet)?;
} else {
todo.push(packet);
}
}
Ok(false)
}
fn main() {
let mut args = env::args().skip(1);
let mut name = args.next().expect("rtl8168d: no name provided");
name.push_str("_rtl8168");
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 bar_size_str = args.next().expect("rtl8168d: no address size provided");
let bar_size = usize::from_str_radix(&bar_str, 16).expect("rtl8168d: failed to parse address size");
let irq_str = args.next().expect("rtl8168d: no irq provided");
let irq = irq_str.parse::<u8>().expect("rtl8168d: failed to parse irq");
println!(" + RTL8168 {} on: {:X} size: {} IRQ: {}", name, bar, bar_size, irq);
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
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 as RawFd)
}));
let irq_fd = syscall::open(
format!("irq:{}", irq),
syscall::O_RDWR | syscall::O_NONBLOCK
).expect("rtl8168d: failed to open IRQ file");
let mut irq_file = unsafe { File::from_raw_fd(irq_fd as RawFd) };
let address = unsafe {
syscall::physmap(bar, bar_size, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
.expect("rtl8168d: failed to map address")
};
{
let device = Arc::new(RefCell::new(unsafe {
device::Rtl8168::new(address).expect("rtl8168d: failed to allocate device")
}));
let mut event_queue =
EventQueue::<usize>::new().expect("rtl8168d: failed to create event queue");
syscall::setrens(0, 0).expect("rtl8168d: failed to enter null namespace");
let todo = Arc::new(RefCell::new(Vec::<Packet>::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 |_event| -> Result<Option<usize>> {
let mut irq = [0; 8];
irq_file.read(&mut irq)?;
if unsafe { device_irq.borrow_mut().irq() } {
irq_file.write(&mut irq)?;
if handle_update(
&mut socket_irq.borrow_mut(),
&mut device_irq.borrow_mut(),
&mut todo_irq.borrow_mut(),
)? {
return Ok(Some(0));
}
let next_read = device_irq.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
}
Ok(None)
},
)
.expect("rtl8168d: failed to catch events on IRQ file");
let device_packet = device.clone();
let socket_packet = socket.clone();
event_queue
.add(socket_fd as RawFd, move |_event| -> Result<Option<usize>> {
if handle_update(
&mut socket_packet.borrow_mut(),
&mut device_packet.borrow_mut(),
&mut todo.borrow_mut(),
)? {
return Ok(Some(0));
}
let next_read = device_packet.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
Ok(None)
})
.expect("rtl8168d: 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("rtl8168d: failed to write event");
}
};
for event_count in event_queue
.trigger_all(event::Event { fd: 0, flags: 0 })
.expect("rtl8168d: failed to trigger events")
{
send_events(event_count);
}
loop {
let event_count = event_queue.run().expect("rtl8168d: failed to handle events");
if event_count == 0 {
//TODO: Handle todo
break;
}
send_events(event_count);
}
}
unsafe {
let _ = syscall::physunmap(address);
}
}
}