88 lines
2.1 KiB
Rust
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));
|
|
}
|
|
|