diff --git a/src/arch/x86_64/intrinsics.rs b/src/arch/x86_64/intrinsics.rs index c359d00e..fe8ef909 100644 --- a/src/arch/x86_64/intrinsics.rs +++ b/src/arch/x86_64/intrinsics.rs @@ -10,7 +10,15 @@ pub struct IoPort { _pd: PhantomData, } -impl IoPort { +/// Common interface for reading and writing I/O ports +pub trait IoPortAccess { + /// Reads a value from the port + fn read(&self) -> T; + /// Writes a value to the port + fn write(&self, value: T); +} + +impl IoPort { /// Constructs a new I/O port interface pub const fn new(address: u16) -> Self { Self { @@ -18,20 +26,76 @@ impl IoPort { _pd: PhantomData, } } +} - /// Writes a byte into the port - pub fn write(&self, value: u8) { +impl IoPortAccess for IoPort { + fn write(&self, value: u8) { unsafe { - core::arch::asm!("outb %al, %dx", in("al") value, in("dx") self.address, options(att_syntax)); + outb(self.address, value); } } - /// Reads a byte from the port - pub fn read(&self) -> u8 { - let value: u8; - unsafe { - core::arch::asm!("inb %dx, %al", in("dx") self.address, out("al") value, options(att_syntax)); - } - value + fn read(&self) -> u8 { + unsafe { inb(self.address) } } } + +impl IoPortAccess for IoPort { + fn write(&self, value: u16) { + unsafe { + outw(self.address, value); + } + } + + fn read(&self) -> u16 { + unsafe { inw(self.address) } + } +} + +impl IoPortAccess for IoPort { + fn write(&self, value: u32) { + unsafe { + outl(self.address, value); + } + } + + fn read(&self) -> u32 { + unsafe { inl(self.address) } + } +} + +#[inline] +pub unsafe fn inb(port: u16) -> u8 { + let value: u8; + core::arch::asm!("inb %dx, %al", in("dx") port, out("al") value, options(att_syntax)); + value +} + +#[inline] +pub unsafe fn inw(port: u16) -> u16 { + let value: u16; + core::arch::asm!("inb %dx, %ax", in("dx") port, out("ax") value, options(att_syntax)); + value +} + +#[inline] +pub unsafe fn inl(port: u16) -> u32 { + let value: u32; + core::arch::asm!("inb %dx, %eax", in("dx") port, out("eax") value, options(att_syntax)); + value +} + +#[inline] +pub unsafe fn outb(port: u16, value: u8) { + core::arch::asm!("outb %al, %dx", in("dx") port, in("al") value, options(att_syntax)); +} + +#[inline] +pub unsafe fn outw(port: u16, value: u16) { + core::arch::asm!("outw %ax, %dx", in("dx") port, in("ax") value, options(att_syntax)); +} + +#[inline] +pub unsafe fn outl(port: u16, value: u32) { + core::arch::asm!("outl %eax, %dx", in("dx") port, in("eax") value, options(att_syntax)); +} diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 0f7ffc80..4cb15ecc 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -40,7 +40,7 @@ use crate::{ use self::{ apic::ioapic::IoApic, - intrinsics::IoPort, + intrinsics::{IoPort, IoPortAccess}, peripherals::{hpet::Hpet, ps2::PS2Controller}, smp::CPU_COUNT, }; @@ -494,10 +494,10 @@ impl X86_64 { unsafe fn disable_8259() { infoln!("Disabling i8259 PIC"); // TODO should I make a module for 8259 if I don't even use it? - let pic_master_cmd = IoPort::new(0x20); - let pic_master_data = IoPort::new(0x21); - let pic_slave_cmd = IoPort::new(0xA0); - let pic_slave_data = IoPort::new(0xA1); + let pic_master_cmd = IoPort::::new(0x20); + let pic_master_data = IoPort::::new(0x21); + let pic_slave_cmd = IoPort::::new(0xA0); + let pic_slave_data = IoPort::::new(0xA1); // Remap PIC IRQ vectors to 32.. pic_master_cmd.write(0x11); diff --git a/src/arch/x86_64/peripherals/ps2/mod.rs b/src/arch/x86_64/peripherals/ps2/mod.rs index 0db12770..8e50b1a5 100644 --- a/src/arch/x86_64/peripherals/ps2/mod.rs +++ b/src/arch/x86_64/peripherals/ps2/mod.rs @@ -8,7 +8,10 @@ use device_api::{ use crate::{ arch::{ - x86_64::{intrinsics::IoPort, IrqNumber}, + x86_64::{ + intrinsics::{IoPort, IoPortAccess}, + IrqNumber, + }, Architecture, ARCHITECTURE, }, sync::IrqSafeSpinlock, diff --git a/src/arch/x86_64/peripherals/serial.rs b/src/arch/x86_64/peripherals/serial.rs index 61764dc1..f8b87635 100644 --- a/src/arch/x86_64/peripherals/serial.rs +++ b/src/arch/x86_64/peripherals/serial.rs @@ -3,7 +3,10 @@ use abi::error::Error; use device_api::{serial::SerialDevice, Device}; use crate::{ - arch::x86_64::{intrinsics::IoPort, IrqNumber}, + arch::x86_64::{ + intrinsics::{IoPort, IoPortAccess}, + IrqNumber, + }, debug::DebugSink, sync::IrqSafeSpinlock, };