From 50970fa2cc89c79c20ed272ca35c71b6c18fa011 Mon Sep 17 00:00:00 2001 From: fekhesk Date: Thu, 27 Oct 2022 01:00:01 -0700 Subject: [PATCH] need to figure out a better way for memory mapping --- Cargo.toml | 6 +- serial.log | 32 ++++ src/boot/mod.rs | 67 ++++++++- src/internals/cpu.rs | 142 ++++++++++++++++++ .../interrupts.rs} | 0 src/internals/mod.rs | 4 +- src/lib.rs | 135 ++++++++++++++--- src/macros/mod.rs | 16 ++ src/memory/mod.rs | 63 +++++++- src/serial/mod.rs | 5 +- src/serial/ps2/mod.rs | 70 --------- src/serial/ps2controller.rs | 3 - src/serial/terminal.rs | 27 ++-- 13 files changed, 457 insertions(+), 113 deletions(-) create mode 100644 src/internals/cpu.rs rename src/{serial/ps2keyboard.rs => internals/interrupts.rs} (100%) delete mode 100644 src/serial/ps2/mod.rs delete mode 100644 src/serial/ps2controller.rs diff --git a/Cargo.toml b/Cargo.toml index 1561936..f7dd3b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,12 +11,14 @@ spin = "0.9.1" x86_64 = "0.14.10" rlibc = "1.0" multiboot2 = { version = "0.14.0", optional = true } +acpi = { version = "4.1.1", optional = true } linked_list_allocator = { version = "0.9.0", optional = true } [dependencies.lazy_static] version = "1.4.0" features = ["spin_no_std"] [features] -default = ["f_multiboot2", "f_ll_alloc"] -f_multiboot2 = ["dep:multiboot2"] +default = ["f_multiboot2", "f_ll_alloc", "f_debug_verbose"] +f_debug_verbose = [] +f_multiboot2 = ["dep:multiboot2", "dep:acpi"] f_ll_alloc = ["dep:linked_list_allocator"] \ No newline at end of file diff --git a/serial.log b/serial.log index ef292d9..c5b92ba 100644 --- a/serial.log +++ b/serial.log @@ -7,6 +7,12 @@ BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1 WARNING: no console will be available to OS error: no suitable video mode found. using serial port 0 as console +debug: setup GDT +debug: GDT loaded +debug: CS set +debug: SS set +debug: TSS loaded +debug: IDT loaded @@ -16,3 +22,29 @@ initialising mapper...[OK] initialising frame allocator...[OK] initialising heap...[OK] testing heap...[OK] +checking for apic compatibility...[OK] +disabling PIC...[OK] +initialising apic...[debug] read_phys_memory32: addr fee000f0 not mapped +[debug] allocated frame: PhysFrame[4KiB](0x1c000) +[debug] mapped page: Page[4KiB](0xfee00000) +[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfee00000))) +[OK] +setting up apic interrupts...[debug] write_phys_memory32: addr fec00000 not mapped +[debug] allocated frame: PhysFrame[4KiB](0x1f000) +[debug] mapped page: Page[4KiB](0xfec00000) +[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfec00000))) +[OK] +[debug] keyboard interrupt +---KERNEL FUCKY WUKKY UWU--- +double fault! +stack frame: InterruptStackFrame { + instruction_pointer: VirtAddr( + 0x120ef1, + ), + code_segment: 8, + cpu_flags: 0x200002, + stack_pointer: VirtAddr( + 0x140c00, + ), + stack_segment: 16, +} diff --git a/src/boot/mod.rs b/src/boot/mod.rs index 3491cce..d8ec989 100644 --- a/src/boot/mod.rs +++ b/src/boot/mod.rs @@ -1,8 +1,12 @@ +use alloc::sync::Arc; use core::marker::PhantomData; -use crate::KernelArgs; +use acpi::{AcpiHandler, PhysicalMapping}; +use crate::{debug, KernelArgs}; #[cfg(feature = "f_multiboot2")] use multiboot2::{load, MemoryMapTag, BootInformation}; +use x86_64::structures::paging::{FrameAllocator, OffsetPageTable}; +use crate::memory::BootInfoFrameAllocator; pub struct KernelInfo { kernel_start: u64, @@ -51,4 +55,65 @@ impl KernelInfo { pub fn safe_memory_start(&self) -> u64 { self.safe_mem_start } + + pub fn acpi_get_ioapic_addr(&self, mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator) -> u64 { + #[cfg(feature = "f_multiboot2")] + { + let acpi_tag = self.boot_info.rsdp_v1_tag().expect("no acpi tag"); + let rsdp = acpi_tag; + let rsdp = unsafe { &*rsdp }; + let rsdt = rsdp.rsdt_address(); + #[derive(Clone)] + struct Handler<'a> { + mem_mapper: Arc<&'a mut OffsetPageTable<'a>>, + frame_allocator: Arc<&'a mut BootInfoFrameAllocator>, + } + impl<'a> AcpiHandler for Handler<'a> { + unsafe fn map_physical_region(&self, physical_address: usize, size: usize) -> PhysicalMapping { + let frame_allocator = self.frame_allocator.clone(); + debug!("read_phys_memory32: addr {:x} not mapped", physical_address); + // map the page + let frame = frame_allocator.allocate_frame().unwrap(); + debug!("allocated frame: {:?}", frame); + let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; + let page = x86_64::structures::paging::Page::containing_address(initaladdr); + debug!("mapped page: {:?}", page); + let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; + debug!("map_to_result: {:?}", map_to_result); + if map_to_result.is_err() { + panic!("Failed to map page"); + } + let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; + if let Some(addr) = addr { + let addr = addr.as_u64() as *const u32; + unsafe { *addr } + } else { + panic!("Failed to map page"); + } + } + + fn unmap_physical_region(region: &PhysicalMapping) { + todo!() + } + } + let rsdt = acpi::AcpiTables::from_rsdt(rsdt).expect("failed to get acpi tables"); + let mut ioapic_addr = 0; + for entry in rsdt.entries() { + let entry = unsafe { &*entry }; + if entry.signature() == *b"APIC" { + let apic = entry.as_apic(); + let apic = unsafe { &*apic }; + for entry in apic.entries() { + let entry = unsafe { &*entry }; + if entry.signature() == *b"IOAP" { + let ioapic = entry.as_ioapic(); + let ioapic = unsafe { &*ioapic }; + ioapic_addr = ioapic.address(); + } + } + } + } + ioapic_addr + } + } } \ No newline at end of file diff --git a/src/internals/cpu.rs b/src/internals/cpu.rs new file mode 100644 index 0000000..8fdd444 --- /dev/null +++ b/src/internals/cpu.rs @@ -0,0 +1,142 @@ +use core::arch::asm; +use x86_64::{PhysAddr, VirtAddr}; +use x86_64::structures::idt::InterruptStackFrame; +use x86_64::structures::paging::OffsetPageTable; +use crate::{debug, print, println}; +use crate::memory::{BootInfoFrameAllocator, read_phys_memory32, write_phys_memory32}; +use crate::serial::{command, read}; + +// todo! maybe abstract this into different sections for different parts of cpu func? + +pub fn check_apic_compat() -> bool { + unsafe { + let mut eax: u32; + let mut edx: u32; + asm!("cpuid", + in("eax") 1, + lateout("eax") eax, + lateout("edx") edx, + ); + edx & (1 << 9) != 0 + } +} + +pub fn set_apic_base(apic: usize) { + const IA32_APIC_BASE_MSR_ENABLE: u32 = 0x800; + let mut edx = 0u32; + let mut eax = (apic & 0xfffff0000) as u32 | IA32_APIC_BASE_MSR_ENABLE; + unsafe { + asm!("wrmsr", + in("ecx") 0x1b, + in("eax") eax, + in("edx") edx, + ); + } +} + +pub fn get_apic_base() -> usize { + let mut edx = 0u32; + let mut eax = 0u32; + unsafe { + asm!("rdmsr", + in("ecx") 0x1b, + lateout("eax") eax, + lateout("edx") edx, + ); + } + ((edx as usize) << 32) | (eax as usize) +} + +pub fn enable_apic(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator) { + // PIC should be disabled by now + // now enable local apic + // 1. set bit 8 of spurious interrupt vector register + let sivr_addr = 0xfee000f0; + let sivr = read_phys_memory32(mem_mapper, frame_alloc, sivr_addr); + write_phys_memory32(mem_mapper, frame_alloc, sivr_addr, sivr | (1 << 8)); +} + +pub fn apic_read_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32) -> u32 { + write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg); + read_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10) +} + +pub fn apic_write_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32, val: u32) { + write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg); + write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10, val); +} + +pub fn disable_pic() { + command(0x20, 0x11); + command(0xa0, 0x11); + + command(0x21, 0xe0); + command(0xa1, 0xe8); + + command(0x21, 0x04); + command(0xa1, 0x02); + + command(0x21, 0x01); + command(0xa1, 0x01); + + command(0x21, 0xff); + command(0xa1, 0xff); +} + +pub fn ioapic_set_irq(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, irq: u8, apic_id: u64, vector:u8) { + let lo_index: u32 = (0x10 + irq*2 ) as u32; + let hi_index: u32 = (0x10 + irq*2 + 1) as u32; + + let mut high = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, hi_index); + // set apic id + high &= !(0xff000000); + high |= (apic_id as u32) << 24; + apic_write_io(mem_mapper, frame_alloc, ioapicaddr, hi_index, high); + + let mut low = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, lo_index); + + // unmask + low &= !(1 << 16); + // set to physical delivery + low &= !(1 << 11); + // set to fixed delivery + low &= !(0x700); + // set vector + low &= !(0xff); + low |= vector as u32; + + apic_write_io(mem_mapper, frame_alloc, ioapicaddr, lo_index, low); +} + +pub fn apic_eoi() { + unsafe { + asm!("mov eax, 0", + "mov ecx, 0xb0", + "wrmsr", + in("ecx") 0x80b, + in("eax") 0, + ); + } +} + +// todo! in the future this will be removed, it is only for testing basic apic functionality +pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) { + debug!("keyboard interrupt"); + unsafe { asm!("iretq"); } + let scancode = read(0x60); + + print!("ksc: {},", scancode); + + // reset keyboard controller + let mut a = read(0x61); + a |= 0x82; + command(0x61, a); + a &= 0x7f; + command(0x61, a); +} + +// todo! we should abstract this away +pub fn setup_apic_interrupts(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize) { + // set keyboard irq to interrupt 40 + ioapic_set_irq(mem_mapper, frame_alloc, ioapicaddr, 1, 0, 40); +} \ No newline at end of file diff --git a/src/serial/ps2keyboard.rs b/src/internals/interrupts.rs similarity index 100% rename from src/serial/ps2keyboard.rs rename to src/internals/interrupts.rs diff --git a/src/internals/mod.rs b/src/internals/mod.rs index 4050443..9ef5c0f 100644 --- a/src/internals/mod.rs +++ b/src/internals/mod.rs @@ -1,8 +1,8 @@ pub mod errors; +pub mod interrupts; +pub mod cpu; pub mod WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood { - use core::arch::asm; - use core::marker::PhantomData; #[derive(Clone, Copy)] pub struct Point { diff --git a/src/lib.rs b/src/lib.rs index 6e43a50..35409fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,12 +12,16 @@ extern crate alloc; use alloc::rc::Rc; use alloc::vec; +use core::arch::asm; use lazy_static::lazy_static; use core::panic::PanicInfo; use multiboot2::MemoryAreaType; use spin::Mutex; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; +use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor}; +use x86_64::structures::tss::TaskStateSegment; use x86_64::{PhysAddr, VirtAddr}; +use x86_64::registers::segmentation::{CS, Segment, SS}; use x86_64::structures::paging::Translate; use crate::boot::KernelInfo; use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*; @@ -32,11 +36,16 @@ mod memory; mod macros; lazy_static! { + static ref GDT: Mutex = { + let mut gdt = GlobalDescriptorTable::new(); + Mutex::new(gdt) + }; static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(internals::errors::breakpoint_exception); idt.double_fault.set_handler_fn(internals::errors::double_fault); idt.page_fault.set_handler_fn(internals::errors::page_fault); + idt[40].set_handler_fn(internals::cpu::keyboard_irq); idt }; } @@ -93,6 +102,60 @@ pub extern fn kernel_main(args: KernelArgs) -> ! { println!("using serial port {} as console", i); } + // temporarily disable interrupts + x86_64::instructions::interrupts::disable(); + println!("debug: setup GDT"); + // load TSS + static mut tss: TaskStateSegment = TaskStateSegment::new(); + { + unsafe { + tss.interrupt_stack_table[0] = { + const STACK_SIZE: usize = 4096 * 5; + static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; + let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); + let stack_end = stack_start + STACK_SIZE; + stack_end + }; + // set word at offset 102 to 0x68 and last two bytes of the tss to 0xffff + // this is a hack to make the tss valid + let tss_ptr = &tss as *const TaskStateSegment as *mut u8; + unsafe { + *tss_ptr.add(102) = 0x68; + *tss_ptr.add(104) = 0xff; + *tss_ptr.add(105) = 0xff; + } + } + let kcs = GDT.lock().add_entry(Descriptor::kernel_code_segment()); + let kds = GDT.lock().add_entry(Descriptor::kernel_data_segment()); + let tsss = unsafe { GDT.lock().add_entry(Descriptor::tss_segment(&tss)) }; + // load GDT + unsafe { + GDT.lock().load_unsafe(); + } + println!("debug: GDT loaded"); + // set code segment to kernel code segment + unsafe { + CS::set_reg(kcs); + } + println!("debug: CS set"); + // set data segment to kernel data segment + unsafe { + SS::set_reg(kds); + } + println!("debug: SS set"); + // load TSS + unsafe { + x86_64::instructions::tables::load_tss(tsss); + } + println!("debug: TSS loaded"); + + // load IDT + IDT.load(); + println!("debug: IDT loaded"); + // enable interrupts + x86_64::instructions::interrupts::enable(); + } + println!(); println!(); @@ -100,28 +163,58 @@ pub extern fn kernel_main(args: KernelArgs) -> ! { println!("welcome to wukkOS!"); println!("(c) 2022 Real Microsoft, LLC"); let kern_info = Mutex::new(KernelInfo::init_from_kernel_args(args)); - print!("initialising mapper..."); - let mut mapper = unsafe { memory::init(VirtAddr::new(0)) }; - println!("[OK]"); - print!("initialising frame allocator..."); - let mut frame_allocator = unsafe { memory::BootInfoFrameAllocator::init(kern_info) }; - println!("[OK]"); - print!("initialising heap..."); - memory::allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap init failed"); - println!("[OK]"); - print!("testing heap..."); - let reference_counted = Rc::new(vec![1, 2, 3]); - let cloned = reference_counted.clone(); - let test_1 = Rc::strong_count(&reference_counted) == 2; - drop(cloned); - let test_2 = Rc::strong_count(&reference_counted) == 1; - if test_1 && test_2 { + // memory stuff + let mut mapper = None; + let mut frame_allocator = None; + { + print!("initialising mapper..."); + mapper = Some(unsafe { memory::init(VirtAddr::new(0)) }); + println!("[OK]"); + print!("initialising frame allocator..."); + frame_allocator = Some(unsafe { memory::BootInfoFrameAllocator::init(kern_info) }); + println!("[OK]"); + print!("initialising heap..."); + memory::allocator::init_heap(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()).expect("heap init failed"); println!("[OK]"); - } else { - println!("[FAIL]"); - } - drop(reference_counted); - loop {} + print!("testing heap..."); + let reference_counted = Rc::new(vec![1, 2, 3]); + let cloned = reference_counted.clone(); + let test_1 = Rc::strong_count(&reference_counted) == 2; + drop(cloned); + let test_2 = Rc::strong_count(&reference_counted) == 1; + if test_1 && test_2 { + println!("[OK]"); + } else { + println!("[FAIL]"); + } + drop(reference_counted); + } + + // apic stuff + { + print!("checking for apic compatibility..."); + let apic_compatible = unsafe { internals::cpu::check_apic_compat() }; + if apic_compatible { + println!("[OK]"); + } else { + println!("[FAIL]"); + panic!("apic required at the moment"); + } + print!("disabling PIC..."); + unsafe { internals::cpu::disable_pic() }; + println!("[OK]"); + print!("initialising apic..."); + unsafe { internals::cpu::enable_apic(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) }; + println!("[OK]"); + print!("setting up apic interrupts..."); + unsafe { internals::cpu::setup_apic_interrupts(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) }; + println!("[OK]"); + // enable interrupts + x86_64::instructions::interrupts::enable(); + } + + loop { + } } \ No newline at end of file diff --git a/src/macros/mod.rs b/src/macros/mod.rs index 390ce73..11c85f3 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -12,8 +12,24 @@ macro_rules! println { ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); } +#[macro_export] +macro_rules! debug { + ($($arg:tt)*) => ($crate::macros::_debug(format_args!($($arg)*))); +} + #[doc(hidden)] pub fn _print(args: fmt::Arguments) { use core::fmt::Write; ST.writer.lock().write_fmt(args).unwrap(); +} + +#[doc(hidden)] +pub fn _debug(args: fmt::Arguments) { + use core::fmt::Write; + #[cfg(feature = "f_debug_verbose")] + { + ST.log("[debug] "); + ST.writer.lock().write_fmt(args).unwrap(); + ST.logln(""); + } } \ No newline at end of file diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 95eca8e..9b2a305 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,6 +1,8 @@ pub mod allocator; -use x86_64::structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB}; +use alloc::boxed::Box; +use alloc::sync::Arc; +use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate}; use x86_64::{PhysAddr, VirtAddr}; pub struct Locked { @@ -40,6 +42,7 @@ unsafe fn active_level_4_table(phys_mem_offset: VirtAddr) -> &'static mut PageTa use multiboot2::{MemoryMapTag, BootInformation}; use spin::Mutex; use crate::boot::KernelInfo; +use crate::{debug, print, println}; pub struct BootInfoFrameAllocator { kern_info: Mutex, @@ -81,4 +84,62 @@ unsafe impl FrameAllocator for BootInfoFrameAllocator { frame } } +} + +pub fn read_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32) -> u32 { + let initaladdr = VirtAddr::new(addr as u64); + let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; + if let Some(addr) = addr { + let addr = addr.as_u64() as *const u32; + unsafe { *addr } + } else { + debug!("read_phys_memory32: addr {:x} not mapped", initaladdr.as_u64()); + // map the page + let frame = frame_allocator.allocate_frame().unwrap(); + debug!("allocated frame: {:?}", frame); + let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; + let page = x86_64::structures::paging::Page::containing_address(initaladdr); + debug!("mapped page: {:?}", page); + let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; + debug!("map_to_result: {:?}", map_to_result); + if map_to_result.is_err() { + panic!("Failed to map page"); + } + let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; + if let Some(addr) = addr { + let addr = addr.as_u64() as *const u32; + unsafe { *addr } + } else { + panic!("Failed to map page"); + } + } +} + +pub fn write_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32, value: u32) { + let initaladdr = VirtAddr::new(addr as u64); + let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; + if let Some(addr) = addr { + let addr = addr.as_u64() as *mut u32; + unsafe { *addr = value }; + } else { + debug!("write_phys_memory32: addr {:x} not mapped", initaladdr.as_u64()); + // map the page + let frame = frame_allocator.allocate_frame().unwrap(); + debug!("allocated frame: {:?}", frame); + let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE; + let page = x86_64::structures::paging::Page::containing_address(initaladdr); + debug!("mapped page: {:?}", page); + let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) }; + debug!("map_to_result: {:?}", map_to_result); + if map_to_result.is_err() { + panic!("Failed to map page"); + } + let addr = unsafe { mem_mapper.translate_addr(initaladdr) }; + if let Some(addr) = addr { + let addr = addr.as_u64() as *mut u32; + unsafe { *addr = value }; + } else { + panic!("Failed to map page"); + } + } } \ No newline at end of file diff --git a/src/serial/mod.rs b/src/serial/mod.rs index bb07bdc..a2628a4 100644 --- a/src/serial/mod.rs +++ b/src/serial/mod.rs @@ -4,7 +4,6 @@ use core::arch::asm; use core::borrow::{Borrow, BorrowMut}; use core::ops::Deref; -pub mod ps2; pub mod terminal_helpers; pub mod terminal; @@ -60,14 +59,14 @@ pub struct SerialPorts { } #[cfg(any(target_arch="x86", target_arch="x86_64"))] -fn command(port: u16, data: u8) { +pub fn command(port: u16, data: u8) { unsafe { asm!("out dx, al", in("al") data, in("dx") port); } } #[cfg(any(target_arch="x86", target_arch="x86_64"))] -fn read(port: u16) -> u8 { +pub fn read(port: u16) -> u8 { let mut data: u8; unsafe { asm!("in al, dx", out("al") data, in("dx") port); diff --git a/src/serial/ps2/mod.rs b/src/serial/ps2/mod.rs deleted file mode 100644 index f187b81..0000000 --- a/src/serial/ps2/mod.rs +++ /dev/null @@ -1,70 +0,0 @@ -use super::*; -use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::{KernelError, ErrorKind, ErrorLevel}; - -pub enum PS2Type { - AncientKeyboard, - Keyboard, - Mouse, - FiveButtonMouse, - ScrollWheelMouse, - Unknown, -} - -enum Messages { - MSGDisableScanning = 0xF5, - MSGIdentify = 0xF2, - MSGACK = 0xFA, -} - -pub fn probePort(port : Port) -> Result { - let mut response : u8; - response = port.transrecv(Messages::MSGDisableScanning as u8); - // check for ACK - if response != Messages::MSGACK as u8 { - return Err(KernelError::new(ErrorKind::HardwareFuckUp, ErrorLevel::Warning, "Did not receive ACK", port.base.to_string())); - } - response = port.transrecv(Messages::MSGIdentify as u8); - // check for ACK - if response != Messages::MSGACK as u8 { - return Err(KernelError::new(ErrorKind::HardwareFuckUp, ErrorLevel::MinorFuckUp, "Did not receive ACK after asking port to identify", port.base.to_string())); - } - // read the response with a timeout of x cpu cycles, this can be quite low as it will only matter on slow machines - response = port.receive(0xFFFF); - // if there's no response, it's a really old keyboard (IBM or whoever, why did you have to do this??)\ - if response == 0 { - return Ok(PS2Type::AncientKeyboard); - } else { - // switch on the response - match response { - 0x00 => { // standard mouse - return Ok(PS2Type::Mouse); - }, - 0x03 => { // mouse with scroll wheel - return Ok(PS2Type::ScrollWheelMouse); - }, - 0x04 => { // 5 button mouse - return Ok(PS2Type::FiveButtonMouse); - }, - 0xAB => { // some type of keyboard, we'll need to read another byte to be sure - response = port.receive(0xFFFF); - match response { - 0x41 => { // some keyboard idfk - return Ok(PS2Type::Keyboard); - }, - 0xC1 => { // same as above - return Ok(PS2Type::Keyboard); - }, - 0x83 => { // keyboard after taking normal pills - return Ok(PS2Type::Keyboard); - }, - _ => { // what? - return Ok(PS2Type::Unknown); - } - } - }, - _ => { // some other device idk - return Ok(PS2Type::Unknown); - } - } - } -} \ No newline at end of file diff --git a/src/serial/ps2controller.rs b/src/serial/ps2controller.rs deleted file mode 100644 index ca3f6bf..0000000 --- a/src/serial/ps2controller.rs +++ /dev/null @@ -1,3 +0,0 @@ -static DATA_PORT: u16 = 0x60; -static COMMAND_PORT: u16 = 0x64; - diff --git a/src/serial/terminal.rs b/src/serial/terminal.rs index 0246bc2..6edab88 100644 --- a/src/serial/terminal.rs +++ b/src/serial/terminal.rs @@ -2,6 +2,7 @@ use core::fmt; use core::ops::Deref; use lazy_static::lazy_static; use spin::Mutex; +use x86_64::instructions::interrupts::without_interrupts; use crate::serial::Port; pub struct SerialTerminal { @@ -32,24 +33,30 @@ impl SerialTerminal { } pub fn log(&self, message: &str) { - if let Some(port) = self.port.lock().deref() { - port.transmit_string(message); - } + without_interrupts(|| { + if let Some(port) = self.port.lock().deref() { + port.transmit_string(message); + } + }); } pub fn logln(&self, message: &str) { - if let Some(port) = self.port.lock().deref() { - port.transmit_string(message); - port.transmit_string("\r\n"); - } + without_interrupts(|| { + if let Some(port) = self.port.lock().deref() { + port.transmit_string(message); + port.transmit_string("\r\n"); + } + }); } } impl fmt::Write for SerialTerminalWriter { fn write_str(&mut self, s: &str) -> fmt::Result { - if let Some(port) = self.port.lock().deref() { - port.transmit_string(s); - } + without_interrupts(|| { + if let Some(port) = self.port.lock().deref() { + port.transmit_string(s); + } + }); Ok(()) } } \ No newline at end of file