WIP: VESA driver. Make initfs generated by code
This commit is contained in:
parent
a4ede1d23d
commit
e110ab81b8
21 changed files with 430 additions and 306 deletions
|
@ -6,7 +6,6 @@ version = "0.1.0"
|
|||
bitflags = "*"
|
||||
hole_list_allocator = { path = "../../alloc/hole_list_allocator" }
|
||||
io = { path = "../../drivers/io" }
|
||||
ransid = { git = "https://github.com/redox-os/ransid.git", branch = "new_api" }
|
||||
spin = "*"
|
||||
|
||||
[dependencies.x86]
|
||||
|
|
|
@ -1,31 +1,14 @@
|
|||
use core::fmt::{self, Write};
|
||||
use spin::Mutex;
|
||||
|
||||
use device::display;
|
||||
use device::serial::COM1;
|
||||
|
||||
pub static CONSOLE: Mutex<Console> = Mutex::new(Console::new());
|
||||
pub static CONSOLE: Mutex<Console> = Mutex::new(Console);
|
||||
|
||||
pub struct Console;
|
||||
|
||||
impl Console {
|
||||
const fn new() -> Self {
|
||||
Console
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Console {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
|
||||
if let Some(ref mut console) = *display::CONSOLE.lock() {
|
||||
if let Some(ref mut display) = *display::DISPLAY.lock() {
|
||||
console.write(s.as_bytes(), |event| {
|
||||
display.event(event);
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
COM1.lock().write_str(s)
|
||||
}
|
||||
COM1.lock().write_str(s)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,245 +0,0 @@
|
|||
use core::{cmp, slice};
|
||||
use ransid::{Console, Event};
|
||||
use spin::Mutex;
|
||||
|
||||
use memory::Frame;
|
||||
use paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress, entry};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[allow(unused_assignments)]
|
||||
#[inline(always)]
|
||||
#[cold]
|
||||
unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) {
|
||||
asm!("cld
|
||||
rep movsq"
|
||||
:
|
||||
: "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len)
|
||||
: "cc", "memory"
|
||||
: "intel", "volatile");
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[allow(unused_assignments)]
|
||||
#[inline(always)]
|
||||
#[cold]
|
||||
unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) {
|
||||
asm!("cld
|
||||
rep stosd"
|
||||
:
|
||||
: "{rdi}"(dst as usize), "{eax}"(src), "{rcx}"(len)
|
||||
: "cc", "memory"
|
||||
: "intel", "volatile");
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[allow(unused_assignments)]
|
||||
#[inline(always)]
|
||||
#[cold]
|
||||
unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) {
|
||||
asm!("cld
|
||||
rep stosq"
|
||||
:
|
||||
: "{rdi}"(dst as usize), "{rax}"(src), "{rcx}"(len)
|
||||
: "cc", "memory"
|
||||
: "intel", "volatile");
|
||||
}
|
||||
|
||||
/// The info of the VBE mode
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
#[repr(packed)]
|
||||
pub struct VBEModeInfo {
|
||||
attributes: u16,
|
||||
win_a: u8,
|
||||
win_b: u8,
|
||||
granularity: u16,
|
||||
winsize: u16,
|
||||
segment_a: u16,
|
||||
segment_b: u16,
|
||||
winfuncptr: u32,
|
||||
bytesperscanline: u16,
|
||||
pub xresolution: u16,
|
||||
pub yresolution: u16,
|
||||
xcharsize: u8,
|
||||
ycharsize: u8,
|
||||
numberofplanes: u8,
|
||||
bitsperpixel: u8,
|
||||
numberofbanks: u8,
|
||||
memorymodel: u8,
|
||||
banksize: u8,
|
||||
numberofimagepages: u8,
|
||||
unused: u8,
|
||||
redmasksize: u8,
|
||||
redfieldposition: u8,
|
||||
greenmasksize: u8,
|
||||
greenfieldposition: u8,
|
||||
bluemasksize: u8,
|
||||
bluefieldposition: u8,
|
||||
rsvdmasksize: u8,
|
||||
rsvdfieldposition: u8,
|
||||
directcolormodeinfo: u8,
|
||||
physbaseptr: u32,
|
||||
offscreenmemoryoffset: u32,
|
||||
offscreenmemsize: u16,
|
||||
}
|
||||
|
||||
pub static CONSOLE: Mutex<Option<Console>> = Mutex::new(None);
|
||||
|
||||
pub static DISPLAY: Mutex<Option<Display>> = Mutex::new(None);
|
||||
|
||||
static FONT: &'static [u8] = include_bytes!("../../../../res/unifont.font");
|
||||
|
||||
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||
active_table.identity_map(Frame::containing_address(PhysicalAddress::new(0x5200)), entry::PRESENT | entry::NO_EXECUTE);
|
||||
|
||||
let mode_info = &*(0x5200 as *const VBEModeInfo);
|
||||
if mode_info.physbaseptr > 0 {
|
||||
let width = mode_info.xresolution as usize;
|
||||
let height = mode_info.yresolution as usize;
|
||||
let onscreen = mode_info.physbaseptr as usize + ::KERNEL_OFFSET;
|
||||
let size = width * height;
|
||||
|
||||
{
|
||||
let start_page = Page::containing_address(VirtualAddress::new(onscreen));
|
||||
let end_page = Page::containing_address(VirtualAddress::new(onscreen + size * 4 - 1));
|
||||
for page in Page::range_inclusive(start_page, end_page) {
|
||||
let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get() - ::KERNEL_OFFSET));
|
||||
active_table.map_to(page, frame, /*actually sets PAT for write combining*/ entry::HUGE_PAGE | entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE);
|
||||
}
|
||||
}
|
||||
|
||||
fast_set64(onscreen as *mut u64, 0, size/2);
|
||||
|
||||
let offscreen = ::allocator::__rust_allocate(size * 4, 4096);
|
||||
fast_set64(offscreen as *mut u64, 0, size/2);
|
||||
|
||||
*DISPLAY.lock() = Some(Display::new(width, height,
|
||||
slice::from_raw_parts_mut(onscreen as *mut u32, size),
|
||||
slice::from_raw_parts_mut(offscreen as *mut u32, size)
|
||||
));
|
||||
*CONSOLE.lock() = Some(Console::new(width/8, height/16));
|
||||
}
|
||||
|
||||
active_table.unmap(Page::containing_address(VirtualAddress::new(0x5200)));
|
||||
}
|
||||
|
||||
/// A display
|
||||
pub struct Display {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub onscreen: &'static mut [u32],
|
||||
pub offscreen: &'static mut [u32],
|
||||
}
|
||||
|
||||
impl Display {
|
||||
fn new(width: usize, height: usize, onscreen: &'static mut [u32], offscreen: &'static mut [u32]) -> Display {
|
||||
Display {
|
||||
width: width,
|
||||
height: height,
|
||||
onscreen: onscreen,
|
||||
offscreen: offscreen,
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a rectangle
|
||||
fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
|
||||
let start_y = cmp::min(self.height - 1, y);
|
||||
let end_y = cmp::min(self.height, y + h);
|
||||
|
||||
let start_x = cmp::min(self.width - 1, x);
|
||||
let len = cmp::min(self.width, x + w) - start_x;
|
||||
|
||||
let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
|
||||
let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
|
||||
|
||||
let stride = self.width * 4;
|
||||
|
||||
let offset = y * stride + start_x * 4;
|
||||
offscreen_ptr += offset;
|
||||
onscreen_ptr += offset;
|
||||
|
||||
let mut rows = end_y - start_y;
|
||||
while rows > 0 {
|
||||
unsafe {
|
||||
fast_set(offscreen_ptr as *mut u32, color, len);
|
||||
fast_set(onscreen_ptr as *mut u32, color, len);
|
||||
}
|
||||
offscreen_ptr += stride;
|
||||
onscreen_ptr += stride;
|
||||
rows -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a character
|
||||
fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
|
||||
if x + 8 <= self.width && y + 16 <= self.height {
|
||||
let mut font_i = 16 * (character as usize);
|
||||
let font_end = font_i + 16;
|
||||
if font_end <= FONT.len() {
|
||||
let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
|
||||
let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
|
||||
|
||||
let stride = self.width * 4;
|
||||
|
||||
let offset = y * stride + x * 4;
|
||||
offscreen_ptr += offset;
|
||||
onscreen_ptr += offset;
|
||||
|
||||
while font_i < font_end {
|
||||
let mut row_data = FONT[font_i];
|
||||
let mut col = 8;
|
||||
while col > 0 {
|
||||
col -= 1;
|
||||
if row_data & 1 == 1 {
|
||||
unsafe {
|
||||
*((offscreen_ptr + col * 4) as *mut u32) = color;
|
||||
}
|
||||
}
|
||||
row_data = row_data >> 1;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
fast_copy64(onscreen_ptr as *mut u64, offscreen_ptr as *const u64, 4);
|
||||
}
|
||||
|
||||
offscreen_ptr += stride;
|
||||
onscreen_ptr += stride;
|
||||
font_i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Scroll display
|
||||
pub fn scroll(&mut self, rows: usize, color: u32) {
|
||||
let data = (color as u64) << 32 | color as u64;
|
||||
|
||||
let width = self.width/2;
|
||||
let height = self.height;
|
||||
if rows > 0 && rows < height {
|
||||
let off1 = rows * width;
|
||||
let off2 = height * width - off1;
|
||||
unsafe {
|
||||
let data_ptr = self.offscreen.as_mut_ptr() as *mut u64;
|
||||
fast_copy64(data_ptr, data_ptr.offset(off1 as isize), off2);
|
||||
fast_set64(data_ptr.offset(off2 as isize), data, off1);
|
||||
|
||||
fast_copy64(self.onscreen.as_mut_ptr() as *mut u64, data_ptr, off1 + off2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle ransid event
|
||||
pub fn event(&mut self, event: Event) {
|
||||
match event {
|
||||
Event::Char { x, y, c, color, .. } => {
|
||||
self.char(x * 8, y * 16, c, color.data);
|
||||
},
|
||||
Event::Rect { x, y, w, h, color } => {
|
||||
self.rect(x * 8, y * 16, w * 8, h * 16, color.data);
|
||||
},
|
||||
Event::Scroll { rows, color } => {
|
||||
self.scroll(rows * 16, color.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
use paging::ActivePageTable;
|
||||
|
||||
pub mod display;
|
||||
pub mod serial;
|
||||
|
||||
pub unsafe fn init(active_table: &mut ActivePageTable){
|
||||
pub unsafe fn init(){
|
||||
serial::init();
|
||||
display::init(active_table);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ extern crate hole_list_allocator as allocator;
|
|||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate io;
|
||||
extern crate ransid;
|
||||
extern crate spin;
|
||||
pub extern crate x86;
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ pub unsafe extern fn kstart() -> ! {
|
|||
}
|
||||
|
||||
// Initialize devices
|
||||
device::init(&mut active_table);
|
||||
device::init();
|
||||
|
||||
// Send kernel page table to APs
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ pub unsafe extern fn kstart() -> ! {
|
|||
}
|
||||
|
||||
/// Entry to rust for an AP
|
||||
pub unsafe extern fn kstart_ap(cpu_id: usize, page_table: usize, stack_start: usize, stack_end: usize) -> ! {
|
||||
pub unsafe extern fn kstart_ap(cpu_id: usize, _page_table: usize, stack_start: usize, stack_end: usize) -> ! {
|
||||
{
|
||||
assert_eq!(BSS_TEST_ZERO, 0);
|
||||
assert_eq!(DATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue