main.rs 4.43 KB
Newer Older
1
2
3
#![feature(alloc)]
#![feature(asm)]
#![feature(heap_api)]
Jeremy Soller's avatar
Jeremy Soller committed
4
#![feature(question_mark)]
5
6

extern crate alloc;
Jeremy Soller's avatar
Jeremy Soller committed
7
extern crate ransid;
8
9
extern crate syscall;

Jeremy Soller's avatar
Jeremy Soller committed
10
use std::cell::RefCell;
11
use std::collections::VecDeque;
12
use std::fs::File;
Jeremy Soller's avatar
Jeremy Soller committed
13
use std::io::{Read, Write};
14
use std::{slice, thread};
Jeremy Soller's avatar
Jeremy Soller committed
15
use ransid::{Console, Event};
16
use syscall::{physmap, physunmap, Packet, Result, Scheme, MAP_WRITE, MAP_WRITE_COMBINE};
17
18
19

use display::Display;
use mode_info::VBEModeInfo;
20
use primitive::fast_set64;
21
22
23
24
25

pub mod display;
pub mod mode_info;
pub mod primitive;

Jeremy Soller's avatar
Jeremy Soller committed
26
27
struct DisplayScheme {
    console: RefCell<Console>,
28
29
    display: RefCell<Display>,
    input: RefCell<VecDeque<u8>>
Jeremy Soller's avatar
Jeremy Soller committed
30
31
32
}

impl Scheme for DisplayScheme {
33
34
35
36
37
38
    fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
        if path == b"input" {
            Ok(1)
        } else {
            Ok(0)
        }
Jeremy Soller's avatar
Jeremy Soller committed
39
40
    }

41
42
    fn dup(&self, id: usize) -> Result<usize> {
        Ok(id)
Jeremy Soller's avatar
Jeremy Soller committed
43
44
    }

45
46
47
48
    fn fsync(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    fn read(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        let mut input = self.input.borrow_mut();
        while i < buf.len() && ! input.is_empty() {
            buf[i] = input.pop_front().unwrap();
            i += 1;
        }
        Ok(i)
    }

    fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
        if id == 1 {
            let mut input = self.input.borrow_mut();
            for &b in buf.iter() {
                input.push_back(b);
Jeremy Soller's avatar
Jeremy Soller committed
64
            }
65
66
67
68
69
70
71
72
73
74
75
76
            Ok(buf.len())
        } else {
            let mut display = self.display.borrow_mut();
            self.console.borrow_mut().write(buf, |event| {
                match event {
                    Event::Char { x, y, c, color, .. } => display.char(x * 8, y * 16, c, color.data),
                    Event::Rect { x, y, w, h, color } => display.rect(x * 8, y * 16, w * 8, h * 16, color.data),
                    Event::Scroll { rows, color } => display.scroll(rows * 16, color.data)
                }
            });
            Ok(buf.len())
        }
Jeremy Soller's avatar
Jeremy Soller committed
77
78
    }

79
    fn close(&self, _id: usize) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
80
81
82
83
        Ok(0)
    }
}

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
fn main() {
    let width;
    let height;
    let physbaseptr;

    {
        let mode_info = unsafe { &*(physmap(0x5200, 4096, 0).expect("vesad: failed to map VBE info") as *const VBEModeInfo) };

        width = mode_info.xresolution as usize;
        height = mode_info.yresolution as usize;
        physbaseptr = mode_info.physbaseptr as usize;

        unsafe { let _ = physunmap(mode_info as *const _ as usize); }
    }

    if physbaseptr > 0 {
        thread::spawn(move || {
Jeremy Soller's avatar
Jeremy Soller committed
101
            let mut socket = File::create(":display").expect("vesad: failed to create display scheme");
Jeremy Soller's avatar
Jeremy Soller committed
102

103
104
105
106
107
108
109
110
            let size = width * height;

            let onscreen = unsafe { physmap(physbaseptr as usize, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
            unsafe { fast_set64(onscreen as *mut u64, 0, size/2) };

            let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) };
            unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };

Jeremy Soller's avatar
Jeremy Soller committed
111
112
113
114
115
            let scheme = DisplayScheme {
                console: RefCell::new(Console::new(width/8, height/16)),
                display: RefCell::new(Display::new(width, height,
                    unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
                    unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
116
117
                )),
                input: RefCell::new(VecDeque::new())
Jeremy Soller's avatar
Jeremy Soller committed
118
            };
119

120
            let mut blocked = VecDeque::new();
Jeremy Soller's avatar
Jeremy Soller committed
121
122
            loop {
                let mut packet = Packet::default();
123
                socket.read(&mut packet).expect("vesad: failed to read display scheme");
Jeremy Soller's avatar
Jeremy Soller committed
124
                //println!("vesad: {:?}", packet);
125
126
127
128
129
130
131
132
133
134
135
136
                if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.input.borrow().is_empty() {
                    blocked.push_back(packet);
                } else {
                    scheme.handle(&mut packet);
                    socket.write(&packet).expect("vesad: failed to write display scheme");
                }
                while ! scheme.input.borrow().is_empty() {
                    if let Some(mut packet) = blocked.pop_front() {
                        scheme.handle(&mut packet);
                        socket.write(&packet).expect("vesad: failed to write display scheme");
                    }
                }
Jeremy Soller's avatar
Jeremy Soller committed
137
            }
138
139
140
        });
    }
}