main.rs 5.15 KB
Newer Older
Jeremy Soller's avatar
Jeremy Soller committed
1 2
#![feature(asm)]

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

Jeremy Soller's avatar
Jeremy Soller committed
7
use std::cell::RefCell;
8
use std::env;
Jeremy Soller's avatar
Jeremy Soller committed
9
use std::fs::File;
Jeremy Soller's avatar
Jeremy Soller committed
10
use std::io::{Read, Write, Result};
11
use std::os::unix::io::{AsRawFd, FromRawFd};
Jeremy Soller's avatar
Jeremy Soller committed
12
use std::sync::Arc;
Jeremy Soller's avatar
Jeremy Soller committed
13

Jeremy Soller's avatar
Jeremy Soller committed
14
use event::EventQueue;
Jeremy Soller's avatar
Jeremy Soller committed
15
use syscall::{Packet, SchemeMut, MAP_WRITE};
Jeremy Soller's avatar
Jeremy Soller committed
16
use syscall::error::EWOULDBLOCK;
17 18

pub mod device;
Jeremy Soller's avatar
Jeremy Soller committed
19 20 21 22

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("e1000d: no name provided");
    name.push_str("_e1000");

Jeremy Soller's avatar
Jeremy Soller committed
26 27 28 29 30 31
    let bar_str = args.next().expect("e1000d: no address provided");
    let bar = usize::from_str_radix(&bar_str, 16).expect("e1000d: failed to parse address");

    let irq_str = args.next().expect("e1000d: no irq provided");
    let irq = irq_str.parse::<u8>().expect("e1000d: failed to parse irq");

32
    print!("{}", format!(" + E1000 {} on: {:X} IRQ: {}\n", name, bar, irq));
33

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

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

Jeremy Soller's avatar
Jeremy Soller committed
41
        let address = unsafe { syscall::physmap(bar, 128*1024, MAP_WRITE).expect("e1000d: failed to map address") };
Jeremy Soller's avatar
Jeremy Soller committed
42
        {
Jeremy Soller's avatar
Jeremy Soller committed
43
            let device = Arc::new(RefCell::new(unsafe { device::Intel8254x::new(address).expect("e1000d: failed to allocate device") }));
Jeremy Soller's avatar
Jeremy Soller committed
44

45
            let mut event_queue = EventQueue::<usize>::new().expect("e1000d: failed to create event queue");
Jeremy Soller's avatar
Jeremy Soller committed
46

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

Jeremy Soller's avatar
Jeremy Soller committed
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>> {
Jeremy Soller's avatar
Jeremy Soller committed
55 56
                let mut irq = [0; 8];
                irq_file.read(&mut irq)?;
Jeremy Soller's avatar
Jeremy Soller committed
57
                if unsafe { device_irq.borrow().irq() } {
Jeremy Soller's avatar
Jeremy Soller committed
58 59 60 61 62 63
                    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;
Jeremy Soller's avatar
Jeremy Soller committed
64
                        device_irq.borrow_mut().handle(&mut todo[i]);
Jeremy Soller's avatar
Jeremy Soller committed
65 66 67 68 69 70 71 72
                        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
73

Jeremy Soller's avatar
Jeremy Soller committed
74
                    let next_read = device_irq.borrow().next_read();
Jeremy Soller's avatar
Jeremy Soller committed
75 76 77
                    if next_read > 0 {
                        return Ok(Some(next_read));
                    }
Jeremy Soller's avatar
Jeremy Soller committed
78 79 80 81
                }
                Ok(None)
            }).expect("e1000d: failed to catch events on IRQ file");

Jeremy Soller's avatar
Jeremy Soller committed
82
            let device_packet = device.clone();
83
            let socket_packet = socket.clone();
Jeremy Soller's avatar
Jeremy Soller committed
84
            event_queue.add(socket_fd, move |_event| -> Result<Option<usize>> {
Jeremy Soller's avatar
Jeremy Soller committed
85 86 87 88 89 90 91
                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
92
                    device_packet.borrow_mut().handle(&mut packet);
Jeremy Soller's avatar
Jeremy Soller committed
93 94 95 96 97 98
                    if packet.a == (-EWOULDBLOCK) as usize {
                        packet.a = a;
                        todo.borrow_mut().push(packet);
                    } else {
                        socket_packet.borrow_mut().write(&mut packet)?;
                    }
Jeremy Soller's avatar
Jeremy Soller committed
99 100
                }

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

Jeremy Soller's avatar
Jeremy Soller committed
106
                Ok(None)
107
            }).expect("e1000d: failed to catch events on scheme file");
Jeremy Soller's avatar
Jeremy Soller committed
108

Jeremy Soller's avatar
Jeremy Soller committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
            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
124 125 126 127
            for event_count in event_queue.trigger_all(event::Event {
                fd: 0,
                flags: 0,
            }).expect("e1000d: failed to trigger events") {
Jeremy Soller's avatar
Jeremy Soller committed
128
                send_events(event_count);
Jeremy Soller's avatar
Jeremy Soller committed
129 130
            }

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