KarxOS/src/ata.rs

88 lines
2.1 KiB
Rust

// ATA Driver!
use alloc::{string::String, vec::Vec};
use core::hint::spin_loop;
use lazy_static::lazy_static;
use spin::Mutex;
use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly};
// Commands to send to the drives
#[repr(u16)]
enum Command {
Read = 0x20,
Write = 0x30,
Identify = 0xEC,
}
#[allow(dead_code)]
#[repr(usize)]
enum Status {
ERR = 0,
IDX,
CORR,
DRQ,
SRV,
DF,
RDY,
BSY,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Bus {
id: u8,
irq: u8,
data_register: Port<u16>,
error_register: PortReadOnly<u8>,
features_register: PortWriteOnly<u8>,
sector_count_register: Port<u8>,
lba0_register: Port<u8>,
lba1_register: Port<u8>,
lba2_register: Port<u8>,
drive_register: Port<u8>,
status_register: PortReadOnly<u8>,
command_register: PortWriteOnly<u8>,
alternate_status_register: PortReadOnly<u8>,
control_register: PortWriteOnly<u8>,
drive_blockless_register: PortReadOnly<u8>
}
#[allow(dead_code)]
impl Bus {
pub fn new(id: u8, io_base: u16, ctrl_base: u16, irq: u8) -> Self {
Bus {
id, irq,
data_register: Port::new(io_base),
error_register: PortReadOnly::new(io_base + 1),
features_register: PortWriteOnly::new(io_base + 1),
sector_count_register: Port::new(io_base + 2),
lba0_register: Port::new(io_base + 3),
lba1_register: Port::new(io_base + 4),
lba2_register: Port::new(io_base + 5),
drive_register: Port::new(io_base + 6),
status_register: PortReadOnly::new(io_base + 7),
command_register: PortWriteOnly::new(io_base + 7),
alternate_status_register: PortReadOnly::new(ctrl_base),
control_register: PortWriteOnly::new(ctrl_base),
drive_blockless_register: PortReadOnly::new(ctrl_base + 1),
}
}
}
lazy_static! {
pub static ref BUSES: Mutex<Vec<Bus>> = Mutex::new(Vec::new());
}
pub fn init() {
let mut buses = BUSES.lock();
buses.push(Bus::new(0, 0x1f0, 0x3f6, 14));
buses.push(Bus::new(1, 0x170, 0x376, 15));
}