diff --git a/ableos/src/devices/pci/piix.rs b/ableos/src/devices/pci/piix.rs index 606c58d6..693fbcc8 100644 --- a/ableos/src/devices/pci/piix.rs +++ b/ableos/src/devices/pci/piix.rs @@ -6,6 +6,7 @@ use core::num::TryFromIntError; +use x86_64::instructions::interrupts; use x86_64::structures::paging::{FrameAllocator, FrameDeallocator}; // FIXME: platform agnostic paging stuff use x86_64::structures::paging::{mapper::MapToError, Mapper, Page, PhysFrame, Size4KiB}; @@ -34,6 +35,9 @@ const PRIMARY_COMMAND: u16 = 0x01F0; /// Secondary command block offset const SECONDARY_COMMAND: u16 = 0x0170; +/// Data register offset +const DATA_OFFSET: u16 = 0; + /// Drive/Head register offset const DRIVE_HEAD_OFFSET: u16 = 6; @@ -80,6 +84,7 @@ impl Piix { unsafe { select_drive(drive, channel); + // FIXME: clear sector count and lba0, lba1, lba2 registers let status = ata_send_command(CMD_IDENTIFY, channel); if status == 0 { continue; // If status = 0, no device @@ -105,6 +110,49 @@ impl Piix { break; } } + + // Read identification space of device + let addr = if channel.secondary() { + SECONDARY_COMMAND + } else { + PRIMARY_COMMAND + } + DATA_OFFSET; + let mut buffer = [0_u8; 512]; + read_dword_buffer(addr, buffer.as_mut_ptr() as *mut _, 128); + // for (i, byte) in buffer.iter().enumerate() { + // if byte.is_ascii() { + // trace!("byte {i}: {byte:b}, ascii: {}", *byte as char); + // } else { + // trace!("byte {i}: {byte:b}"); + // } + // } + + if buffer[99] & 1 != 1 { + // FIXME: PIO mode support + error!("IDE drive {channel:?}/{drive:?} does not support DMA"); + continue; + } + + if (buffer[167] >> 2) & 1 != 1 { + // FIXME: 24-bit LBA and CHS support + error!("IDE drive {channel:?}/{drive:?} does not support 48-bit LBA"); + } + + let size = buffer[200] as u64 + | (buffer[201] as u64) << 8 + | (buffer[202] as u64) << 16 + | (buffer[203] as u64) << 24 + | (buffer[204] as u64) << 32 + | (buffer[205] as u64) << 40 + | (buffer[206] as u64) << 48 + | (buffer[207] as u64) << 54; + trace!("IDE drive {channel:?}/{drive:?} has {size} sectors"); + + ide_devices.push(IdeDevice { + channel, + drive, + size, + }); } } } @@ -332,13 +380,24 @@ unsafe fn ata_delay(channel: Channel) { } } +unsafe fn read_dword_buffer(port: u16, buffer: *mut u32, mut count: u32) { + // FIXME: this assumes x86-64 + interrupts::without_interrupts(|| { + asm!(" + cld + repne + insd", + in("di") buffer, + in("dx") port, + inout("cx") count, + ) + }); +} + struct IdeDevice { pub channel: Channel, pub drive: Drive, - pub signature: u16, - pub capabilities: u16, - pub command_sets: u32, - pub size: u64, + pub size: u64, // in sectors } #[derive(Copy, Clone, Debug)]