IDE device discovery

master
TheOddGarlic 2022-08-12 12:19:08 +03:00
parent e9d58c67ad
commit 54140d153f
1 changed files with 63 additions and 4 deletions

View File

@ -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)]