add drive detection

Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
Julien CLEMENT 2022-12-11 19:17:50 +01:00
parent 1ad893a219
commit 11782b5397
2 changed files with 81 additions and 3 deletions

@ -1,3 +1,7 @@
use crate::serial_println;
use crate::println;
use lazy_static::lazy_static;
use x86_64::instructions::port::Port; use x86_64::instructions::port::Port;
const CD_SECTOR_SIZE: usize = 2048; const CD_SECTOR_SIZE: usize = 2048;
@ -18,6 +22,10 @@ const ATA_DF: u8 = 1 << 5;
const ATA_RDY: u8 = 1 << 6; const ATA_RDY: u8 = 1 << 6;
const ATA_BSY: u8 = 1 << 7; const ATA_BSY: u8 = 1 << 7;
// DCR bits
const ATA_INTERRUPT_DISABLE: u8 = 1 << 1;
const ATA_SRST: u8 = 1 << 2;
// ATAPI signature // ATAPI signature
const ATAPI_SIG_SC: u8 = 0x01; const ATAPI_SIG_SC: u8 = 0x01;
const ATAPI_SIG_LBA_LO: u8 = 0x01; const ATAPI_SIG_LBA_LO: u8 = 0x01;
@ -31,7 +39,37 @@ static ATAPI_SIG: [u8; 4] = [
ATAPI_SIG_LBA_HI ATAPI_SIG_LBA_HI
]; ];
lazy_static! {
static ref DRIVE: Option<ATABus> = {
ATABus::discover_atapi_drive()
};
}
pub fn init() {
println!("Detecting drives");
match DRIVE.as_ref() {
None => println!("No drive detected :("),
Some(drive) => {
let drive_type = match drive.current_drive {
ATA_DRIVE_MASTER => "master",
ATA_DRIVE_SLAVE => "slave",
_ => "bad"
};
let bus = match drive.base_port {
ATA_BUS_PRIMARY => "primary",
ATA_BUS_SECONDARY => "secondary",
_ => "bad"
};
println!("Detected {} drive on {} bus", drive_type, bus);
serial_println!("Detected drive: {:?}", drive);
}
}
}
#[derive(Debug)]
struct ATABus { struct ATABus {
base_port: u16,
// IO ports // IO ports
data: Port<u8>, data: Port<u8>,
features: Port<u8>, // write features: Port<u8>, // write
@ -49,8 +87,47 @@ struct ATABus {
} }
impl ATABus { impl ATABus {
pub fn new(port: u16) -> Self { fn discover_atapi_drive() -> Option<Self> {
let mut primary_bus = ATABus::new(ATA_BUS_PRIMARY);
unsafe {
primary_bus.dcr.write(ATA_SRST);
primary_bus.dcr.write(ATA_INTERRUPT_DISABLE);
}
primary_bus.select_drive(ATA_DRIVE_MASTER);
if primary_bus.is_atapi() {
return Some(primary_bus);
}
primary_bus.select_drive(ATA_DRIVE_SLAVE);
if primary_bus.is_atapi() {
return Some(primary_bus);
}
let mut secondary_bus = ATABus::new(ATA_BUS_SECONDARY);
unsafe {
secondary_bus.dcr.write(ATA_SRST);
primary_bus.dcr.write(ATA_INTERRUPT_DISABLE);
}
secondary_bus.select_drive(ATA_DRIVE_MASTER);
if secondary_bus.is_atapi() {
return Some(secondary_bus);
}
secondary_bus.select_drive(ATA_DRIVE_SLAVE);
if secondary_bus.is_atapi() {
return Some(secondary_bus);
}
None
}
fn new(port: u16) -> Self {
ATABus { ATABus {
base_port: port,
data: Port::new(port), data: Port::new(port),
features: Port::new(port + 1), // write features: Port::new(port + 1), // write
error: Port::new(port + 1), // read error: Port::new(port + 1), // read
@ -76,7 +153,6 @@ impl ATABus {
} }
fn is_atapi(&mut self) -> bool { fn is_atapi(&mut self) -> bool {
let mut sig: [u8; 4] = [0, 0, 0, 0]; let mut sig: [u8; 4] = [0, 0, 0, 0];
unsafe { unsafe {
sig[0] = self.sector_count.read(); sig[0] = self.sector_count.read();
@ -115,3 +191,4 @@ impl ATABus {
} }
} }
} }

@ -40,6 +40,7 @@ pub fn init(boot_info: &BootInformation) {
println!("Starting init"); println!("Starting init");
memory::init(boot_info); memory::init(boot_info);
memory::gdt::init_gdt(); memory::gdt::init_gdt();
drivers::atapi::init();
interrupts::init_idt(); interrupts::init_idt();
vga::change_color(ColorCode::new(Color::LightGreen, Color::Black)); vga::change_color(ColorCode::new(Color::LightGreen, Color::Black));
} }