69 lines
1.6 KiB
Zig
69 lines
1.6 KiB
Zig
//! x86 port I/O and model-specific registers — the low-level primitives the
|
|
//! serial port and the APIC talk to hardware through.
|
|
|
|
pub fn outb(port: u16, value: u8) void {
|
|
asm volatile ("outb %[value], %[port]"
|
|
:
|
|
: [value] "{al}" (value),
|
|
[port] "{dx}" (port),
|
|
);
|
|
}
|
|
|
|
pub fn inb(port: u16) u8 {
|
|
return asm volatile ("inb %[port], %[value]"
|
|
: [value] "={al}" (-> u8),
|
|
: [port] "{dx}" (port),
|
|
);
|
|
}
|
|
|
|
pub fn outw(port: u16, value: u16) void {
|
|
asm volatile ("outw %[value], %[port]"
|
|
:
|
|
: [value] "{ax}" (value),
|
|
[port] "{dx}" (port),
|
|
);
|
|
}
|
|
|
|
pub fn inw(port: u16) u16 {
|
|
return asm volatile ("inw %[port], %[value]"
|
|
: [value] "={ax}" (-> u16),
|
|
: [port] "{dx}" (port),
|
|
);
|
|
}
|
|
|
|
pub fn outl(port: u16, value: u32) void {
|
|
asm volatile ("outl %[value], %[port]"
|
|
:
|
|
: [value] "{eax}" (value),
|
|
[port] "{dx}" (port),
|
|
);
|
|
}
|
|
|
|
pub fn inl(port: u16) u32 {
|
|
return asm volatile ("inl %[port], %[value]"
|
|
: [value] "={eax}" (-> u32),
|
|
: [port] "{dx}" (port),
|
|
);
|
|
}
|
|
|
|
/// Read a model-specific register (returns edx:eax combined).
|
|
pub fn rdmsr(msr: u32) u64 {
|
|
var low: u32 = undefined;
|
|
var high: u32 = undefined;
|
|
asm volatile ("rdmsr"
|
|
: [low] "={eax}" (low),
|
|
[high] "={edx}" (high),
|
|
: [msr] "{ecx}" (msr),
|
|
);
|
|
return (@as(u64, high) << 32) | low;
|
|
}
|
|
|
|
pub fn wrmsr(msr: u32, value: u64) void {
|
|
asm volatile ("wrmsr"
|
|
:
|
|
: [msr] "{ecx}" (msr),
|
|
[low] "{eax}" (@as(u32, @truncate(value))),
|
|
[high] "{edx}" (@as(u32, @truncate(value >> 32))),
|
|
);
|
|
}
|