x86-64: better IoPort interface

This commit is contained in:
Mark Poliakov 2023-08-31 09:21:24 +03:00
parent 67fe71bfc4
commit 9c419115e7
4 changed files with 88 additions and 18 deletions

View File

@ -10,7 +10,15 @@ pub struct IoPort<T> {
_pd: PhantomData<T>, _pd: PhantomData<T>,
} }
impl IoPort<u8> { /// Common interface for reading and writing I/O ports
pub trait IoPortAccess<T> {
/// Reads a value from the port
fn read(&self) -> T;
/// Writes a value to the port
fn write(&self, value: T);
}
impl<T> IoPort<T> {
/// Constructs a new I/O port interface /// Constructs a new I/O port interface
pub const fn new(address: u16) -> Self { pub const fn new(address: u16) -> Self {
Self { Self {
@ -18,20 +26,76 @@ impl IoPort<u8> {
_pd: PhantomData, _pd: PhantomData,
} }
} }
}
/// Writes a byte into the port impl IoPortAccess<u8> for IoPort<u8> {
pub fn write(&self, value: u8) { fn write(&self, value: u8) {
unsafe { 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 fn read(&self) -> u8 {
pub fn read(&self) -> u8 { unsafe { inb(self.address) }
let value: u8;
unsafe {
core::arch::asm!("inb %dx, %al", in("dx") self.address, out("al") value, options(att_syntax));
}
value
} }
} }
impl IoPortAccess<u16> for IoPort<u16> {
fn write(&self, value: u16) {
unsafe {
outw(self.address, value);
}
}
fn read(&self) -> u16 {
unsafe { inw(self.address) }
}
}
impl IoPortAccess<u32> for IoPort<u32> {
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));
}

View File

@ -40,7 +40,7 @@ use crate::{
use self::{ use self::{
apic::ioapic::IoApic, apic::ioapic::IoApic,
intrinsics::IoPort, intrinsics::{IoPort, IoPortAccess},
peripherals::{hpet::Hpet, ps2::PS2Controller}, peripherals::{hpet::Hpet, ps2::PS2Controller},
smp::CPU_COUNT, smp::CPU_COUNT,
}; };
@ -494,10 +494,10 @@ impl X86_64 {
unsafe fn disable_8259() { unsafe fn disable_8259() {
infoln!("Disabling i8259 PIC"); infoln!("Disabling i8259 PIC");
// TODO should I make a module for 8259 if I don't even use it? // 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_cmd = IoPort::<u8>::new(0x20);
let pic_master_data = IoPort::new(0x21); let pic_master_data = IoPort::<u8>::new(0x21);
let pic_slave_cmd = IoPort::new(0xA0); let pic_slave_cmd = IoPort::<u8>::new(0xA0);
let pic_slave_data = IoPort::new(0xA1); let pic_slave_data = IoPort::<u8>::new(0xA1);
// Remap PIC IRQ vectors to 32.. // Remap PIC IRQ vectors to 32..
pic_master_cmd.write(0x11); pic_master_cmd.write(0x11);

View File

@ -8,7 +8,10 @@ use device_api::{
use crate::{ use crate::{
arch::{ arch::{
x86_64::{intrinsics::IoPort, IrqNumber}, x86_64::{
intrinsics::{IoPort, IoPortAccess},
IrqNumber,
},
Architecture, ARCHITECTURE, Architecture, ARCHITECTURE,
}, },
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,

View File

@ -3,7 +3,10 @@ use abi::error::Error;
use device_api::{serial::SerialDevice, Device}; use device_api::{serial::SerialDevice, Device};
use crate::{ use crate::{
arch::x86_64::{intrinsics::IoPort, IrqNumber}, arch::x86_64::{
intrinsics::{IoPort, IoPortAccess},
IrqNumber,
},
debug::DebugSink, debug::DebugSink,
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,
}; };