diff options
| -rw-r--r-- | Makefile | 21 | ||||
| -rw-r--r-- | src/arch/x86_64/asm/io_port.s | 16 | ||||
| -rw-r--r-- | src/arch/x86_64/io_port.rs | 41 | ||||
| -rw-r--r-- | src/lib.rs | 4 | ||||
| -rw-r--r-- | src/machine/cgascr.rs | 51 |
5 files changed, 96 insertions, 37 deletions
@@ -10,29 +10,34 @@ # TODO replace hardcoded values with variables # TODO there can be more options of grub-mkrescue # TODO put the startup.s elsewhere (I don't like it in the root dir) +# TODO maybe put the bootdisk.iso in the build dir too .. # verbose for testing; VERBOSE=@ to turn off.. VERBOSE=@ BUILD = build ARCH = x86_64 -ASM_SOURCES = $(shell find ./src -name "*.s") -ASM_OBJECTS = $(patsubst %.s,_%.o, $(notdir $(ASM_SOURCES))) ASM = nasm ASMOBJFORMAT = elf64 +LINKER_SCRIPT = ./src/arch/$(ARCH)/linker.ld +CARGO_XBUILD_FLAGS = + +# ---------- No need to edit below this line -------------- +# ---------- If you have to, something is wrong ----------- +ASM_SOURCES = $(shell find ./src -name "*.s") +ASM_OBJECTS = $(patsubst %.s,_%.o, $(notdir $(ASM_SOURCES))) # I don't like this style... but what can I do? ASMOBJ_PREFIXED = $(addprefix $(BUILD)/,$(ASM_OBJECTS)) # Setting directories to look for missing source files VPATH = $(sort $(dir $(ASM_SOURCES))) -LINKER_SCRIPT = ./src/arch/$(ARCH)/linker.ld -# include --release flag to build optimized code -CARGO_XBUILD_FLAG = -ifneq ($(CARGO_XBUILD_FLAG), --release) - RUST_BUILD = debug -else + +# the logic here is so cursed +ifeq (--release, $(findstring NT-5.1,$(CARGO_XBUILD_FLAGS))) RUST_BUILD = release +else + RUST_BUILD = debug endif RUST_OBJECT = target/$(ARCH)-rustubs/$(RUST_BUILD)/librustubs.a diff --git a/src/arch/x86_64/asm/io_port.s b/src/arch/x86_64/asm/io_port.s index 9ddc4e6..3aec69d 100644 --- a/src/arch/x86_64/asm/io_port.s +++ b/src/arch/x86_64/asm/io_port.s @@ -11,10 +11,10 @@ ; EXPORTED FUNCTIONS -[GLOBAL outb] -[GLOBAL outw] -[GLOBAL inb] -[GLOBAL inw] +[GLOBAL _outb] +[GLOBAL _outw] +[GLOBAL _inb] +[GLOBAL _inw] ; FUNCTION IMPLEMENTATIONS @@ -24,7 +24,7 @@ ; ; C prototype: void outb (int port, int value); -outb: +_outb: push rbp mov rbp, rsp mov rdx, rdi @@ -37,7 +37,7 @@ outb: ; ; C prototype: void outw (int port, int value); -outw: +_outw: push rbp mov rbp, rsp mov rdx, rdi @@ -50,7 +50,7 @@ outw: ; ; C prototype: unsigned char inb (int port); -inb: +_inb: push rbp mov rbp, rsp mov rdx, rdi @@ -62,7 +62,7 @@ inb: ; ; C prototype: unsigned short inw (int port); -inw: +_inw: push rbp mov rbp, rsp mov rdx, rdi diff --git a/src/arch/x86_64/io_port.rs b/src/arch/x86_64/io_port.rs index 9c24c98..4f629b8 100644 --- a/src/arch/x86_64/io_port.rs +++ b/src/arch/x86_64/io_port.rs @@ -1,13 +1,36 @@ - extern "C" { - fn inb(port:u32) -> u32; - fn inw(port:u32) -> u32; - fn outb(port:u32, val:u32); - fn outw(port:u32, val:u32); + fn _inb(port:u16) -> u8; + fn _inw(port:u16) -> u16; + fn _outb(port:u16, val:u8); + fn _outw(port:u16, val:u16); +} + +// The port addr is 16-bit wide. +// wrappers for in/out[b,w] +// Also I don't feel necessary to have a IO_Port Class give how +// trivial it is +// TODO perhaps use inline asm, because the code is short + +pub fn inw(p:u16) -> u16 { + unsafe{ + _inw(p) + } } -// TODO -// pub struct IO_Port { -// addr: u32, -// } +pub fn inb(p:u16) -> u8 { + unsafe{ + _inb(p) + } +} +pub fn outb(p:u16, val:u8){ + unsafe{ + _outb(p,val); + } +} + +pub fn outw(p:u16, val:u16){ + unsafe{ + _outw(p,val) + } +} @@ -3,7 +3,6 @@ mod arch; mod machine; use core::panic::PanicInfo; -use core::{mem, ptr}; use machine::cgascr::CGAScreen; #[panic_handler] @@ -18,6 +17,7 @@ pub extern "C" fn _entry() -> ! { // scr.show(0,79,'X',0x0f); // scr.show(24,0,'X',0x0f); // scr.show(24,79,'X',0x0f); - scr.test(); + // scr.test(); + scr.setpos(10, 10); loop {} } diff --git a/src/machine/cgascr.rs b/src/machine/cgascr.rs index 091c50d..2748e67 100644 --- a/src/machine/cgascr.rs +++ b/src/machine/cgascr.rs @@ -1,4 +1,8 @@ -const vga_buffer:*mut u8 = 0xb8000 as *mut u8; +use crate::arch::x86_64::io_port::*; + +const CGA_BUFFER_START:*mut u8 = 0xb8000 as *mut u8; +const IR_PORT:u16 = 0x3d4; +const DR_PORT:u16 = 0x3d5; #[allow(dead_code)] pub struct CGAScreen{ @@ -13,7 +17,7 @@ impl CGAScreen{ } - fn get_index(&self,row:u32, col:u32) -> u32{ + fn cal_offset(&self,row:u32, col:u32) -> u32{ col + row*self.max_cows } @@ -21,21 +25,48 @@ impl CGAScreen{ // the memory by address. // and since it's unsafe, it shouldn't be public pub fn show(&self, row:u32, col:u32, c:char, attr:u8){ - let index = self.get_index(row, col); + let index = self.cal_offset(row, col); unsafe{ - *vga_buffer.offset(index as isize * 2) = c as u8; - *vga_buffer.offset(index as isize * 2 + 1) = attr; + *CGA_BUFFER_START.offset(index as isize * 2) = c as u8; + *CGA_BUFFER_START.offset(index as isize * 2 + 1) = attr; } } - pub fn putchar(&self, ch:char){ - - } + // pub fn putchar(&self, ch:char){ + // + // } - pub fn setpos(){} - pub fn getpos(){} + pub fn setpos(&self, row:u32, col:u32){ + // io ports for instruction register and data register + let offset = self.cal_offset(row,col); + + // set lower byte + outb(IR_PORT, 15 as u8); + outb(DR_PORT, offset as u8); + // set higher byte + outb(IR_PORT, 14 as u8); + outb(DR_PORT, (offset >> 8) as u8); + + } + + pub fn getoffset() -> u32 { + // read higher byte + outb(IR_PORT, 14 as u8); + let mut offset = inb(DR_PORT); + offset = offset << 8; + // read lower byte + outb(IR_PORT, 15 as u8); + offset += inb(DR_PORT); + offset as u32 + } + + pub fn getpos(&self, row:& mut u32, cow:& mut u32){ + let offset = Self::getoffset(); + *row = offset % self.max_cows; + *cow = offset / self.max_cows; + } // Sanity Check of the cgascreen |
