main.rs 5.21 KB
Newer Older
1 2 3
#![feature(asm)]

extern crate event;
Jeremy Soller's avatar
Jeremy Soller committed
4
extern crate netutils;
5 6 7
extern crate syscall;

use std::cell::RefCell;
8
use std::env;
9 10 11 12 13 14 15 16 17 18 19 20 21 22
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);

Jeremy Soller's avatar
Jeremy Soller committed
23 24 25
    let mut name = args.next().expect("rtl8168d: no name provided");
    name.push_str("_rtl8168");

26 27 28 29 30 31
    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::<u8>().expect("rtl8168d: failed to parse irq");

Jeremy Soller's avatar
Jeremy Soller committed
32
    print!("{}", format!(" + RTL8168 {} on: {:X}, IRQ: {}\n", name, bar, irq));
33

34 35
    // Daemonize
    if unsafe { syscall::clone(0).unwrap() } == 0 {
36 37 38
        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) }));

39 40
        let mut irq_file = File::open(format!("irq:{}", irq)).expect("rtl8168d: failed to open IRQ file");

41 42
        let address = unsafe { syscall::physmap(bar, 256, MAP_WRITE).expect("rtl8168d: failed to map address") };
        {
43
            let device = Arc::new(RefCell::new(unsafe { device::Rtl8168::new(address).expect("rtl8168d: failed to allocate device") }));
44

45
            let mut event_queue = EventQueue::<usize>::new().expect("rtl8168d: failed to create event queue");
46

47 48
            syscall::setrens(0, 0).expect("rtl8168d: failed to enter null namespace");

49 50 51 52 53
            let todo = Arc::new(RefCell::new(Vec::<Packet>::new()));

            let device_irq = device.clone();
            let socket_irq = socket.clone();
            let todo_irq = todo.clone();
Jeremy Soller's avatar
Jeremy Soller committed
54
            event_queue.add(irq_file.as_raw_fd(), move |_event| -> Result<Option<usize>> {
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
                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);
                        }
                    }
Jeremy Soller's avatar
Jeremy Soller committed
75 76 77 78 79

                    let next_read = device_irq.borrow().next_read();
                    if next_read > 0 {
                        return Ok(Some(next_read));
                    }
80 81 82 83
                }
                Ok(None)
            }).expect("rtl8168d: failed to catch events on IRQ file");

Jeremy Soller's avatar
Jeremy Soller committed
84
            let device_packet = device.clone();
85
            let socket_packet = socket.clone();
Jeremy Soller's avatar
Jeremy Soller committed
86
            event_queue.add(socket_fd, move |_event| -> Result<Option<usize>> {
Jeremy Soller's avatar
Jeremy Soller committed
87 88 89 90 91 92 93
                loop {
                    let mut packet = Packet::default();
                    if socket_packet.borrow_mut().read(&mut packet)? == 0 {
                        break;
                    }

                    let a = packet.a;
Jeremy Soller's avatar
Jeremy Soller committed
94
                    device_packet.borrow_mut().handle(&mut packet);
Jeremy Soller's avatar
Jeremy Soller committed
95 96 97 98 99 100
                    if packet.a == (-EWOULDBLOCK) as usize {
                        packet.a = a;
                        todo.borrow_mut().push(packet);
                    } else {
                        socket_packet.borrow_mut().write(&mut packet)?;
                    }
101 102
                }

Jeremy Soller's avatar
Jeremy Soller committed
103
                let next_read = device_packet.borrow().next_read();
Jeremy Soller's avatar
Jeremy Soller committed
104 105 106 107
                if next_read > 0 {
                    return Ok(Some(next_read));
                }

108
                Ok(None)
109
            }).expect("rtl8168d: failed to catch events on scheme file");
110

Jeremy Soller's avatar
Jeremy Soller committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
            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");
                }
            };

Jeremy Soller's avatar
Jeremy Soller committed
126 127 128 129
            for event_count in event_queue.trigger_all(event::Event {
                fd: 0,
                flags: 0,
            }).expect("rtl8168d: failed to trigger events") {
Jeremy Soller's avatar
Jeremy Soller committed
130
                send_events(event_count);
Jeremy Soller's avatar
Jeremy Soller committed
131 132
            }

133 134
            loop {
                let event_count = event_queue.run().expect("rtl8168d: failed to handle events");
Jeremy Soller's avatar
Jeremy Soller committed
135
                send_events(event_count);
136
            }
137 138
        }
        unsafe { let _ = syscall::physunmap(address); }
139
    }
140
}