diff --git a/src/drivers/atapi/mod.rs b/src/drivers/atapi/mod.rs index efbc50d..21a717c 100644 --- a/src/drivers/atapi/mod.rs +++ b/src/drivers/atapi/mod.rs @@ -1,3 +1,7 @@ +use crate::serial_println; +use crate::println; + +use lazy_static::lazy_static; use x86_64::instructions::port::Port; const CD_SECTOR_SIZE: usize = 2048; @@ -18,6 +22,10 @@ const ATA_DF: u8 = 1 << 5; const ATA_RDY: u8 = 1 << 6; const ATA_BSY: u8 = 1 << 7; +// DCR bits +const ATA_INTERRUPT_DISABLE: u8 = 1 << 1; +const ATA_SRST: u8 = 1 << 2; + // ATAPI signature const ATAPI_SIG_SC: u8 = 0x01; const ATAPI_SIG_LBA_LO: u8 = 0x01; @@ -31,7 +39,37 @@ static ATAPI_SIG: [u8; 4] = [ ATAPI_SIG_LBA_HI ]; +lazy_static! { + static ref DRIVE: Option = { + 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 { + base_port: u16, + // IO ports data: Port, features: Port, // write @@ -49,8 +87,47 @@ struct ATABus { } impl ATABus { - pub fn new(port: u16) -> Self { + fn discover_atapi_drive() -> Option { + 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 { + base_port: port, + data: Port::new(port), features: Port::new(port + 1), // write error: Port::new(port + 1), // read @@ -76,7 +153,6 @@ impl ATABus { } fn is_atapi(&mut self) -> bool { - let mut sig: [u8; 4] = [0, 0, 0, 0]; unsafe { sig[0] = self.sector_count.read(); @@ -114,4 +190,5 @@ impl ATABus { } } } -} \ No newline at end of file +} + diff --git a/src/lib.rs b/src/lib.rs index cb0a140..6a8d1dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,7 @@ pub fn init(boot_info: &BootInformation) { println!("Starting init"); memory::init(boot_info); memory::gdt::init_gdt(); + drivers::atapi::init(); interrupts::init_idt(); vga::change_color(ColorCode::new(Color::LightGreen, Color::Black)); }