IDE: Add LBA28 addressing support
LBA28 is obsolete at this point, but we prefer to use it over LBA48 whenever we can because LBA28 is faster.
This commit is contained in:
parent
f993f6d7b9
commit
9329059510
|
@ -73,6 +73,9 @@ const ALT_STATUS_OFFSET: u16 = 2;
|
|||
/// ATA identification command
|
||||
const CMD_IDENTIFY: u8 = 0xEC;
|
||||
|
||||
/// ATA read using LBA28 DMA command
|
||||
const CMD_READ_DMA: u8 = 0xC8;
|
||||
|
||||
/// ATA read using LBA48 DMA command
|
||||
const CMD_READ_DMA_EXT: u8 = 0x25;
|
||||
|
||||
|
@ -154,10 +157,8 @@ impl PciIde {
|
|||
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");
|
||||
}
|
||||
// FIXME: CHS support
|
||||
let lba48 = (buffer[167] >> 2) & 1 == 1;
|
||||
|
||||
let size = buffer[200] as u64
|
||||
| (buffer[201] as u64) << 8
|
||||
|
@ -173,6 +174,7 @@ impl PciIde {
|
|||
channel,
|
||||
drive,
|
||||
size,
|
||||
lba48_support: lba48,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -260,9 +262,19 @@ impl PciIde {
|
|||
drive: Drive,
|
||||
lba: u64,
|
||||
sector_count: u16,
|
||||
) -> Result<Vec<u8>, TryFromIntError> {
|
||||
buffer: &mut Vec<u8>,
|
||||
) -> Result<(), TryFromIntError> {
|
||||
let lba48_support = self
|
||||
.ide_devices
|
||||
.iter()
|
||||
.find(|d| d.channel == channel && d.drive == drive)
|
||||
.map(|d| d.lba48_support)
|
||||
.unwrap(); // FIXME: make this an error
|
||||
let lba48 = lba > 0xFFFFFFF && lba48_support;
|
||||
|
||||
// FIXME: make this an error
|
||||
assert!(lba < 0xFFFFFFFFFFFF);
|
||||
assert!((lba48 && lba > 0xFFFFFFF) || (!lba48 && lba <= 0xFFFFFFF));
|
||||
|
||||
let byte_count = sector_count * SECTOR_SIZE;
|
||||
|
||||
// prepare PRD table
|
||||
|
@ -285,8 +297,14 @@ impl PciIde {
|
|||
self.set_read(channel);
|
||||
self.clear_bmi_status(channel);
|
||||
select_drive(drive, channel);
|
||||
set_lba(channel, lba, sector_count);
|
||||
ata_send_command(CMD_READ_DMA_EXT, channel);
|
||||
set_lba(channel, lba, sector_count, lba48);
|
||||
|
||||
if lba48 {
|
||||
ata_send_command(CMD_READ_DMA_EXT, channel);
|
||||
} else {
|
||||
ata_send_command(CMD_READ_DMA, channel);
|
||||
}
|
||||
|
||||
self.start(channel);
|
||||
}
|
||||
|
||||
|
@ -309,13 +327,12 @@ impl PciIde {
|
|||
self.clear_bmi_status(channel);
|
||||
}
|
||||
|
||||
let mut buffer = Vec::with_capacity(byte_count as usize);
|
||||
for i in 0..512 {
|
||||
for i in 0..byte_count as u64 {
|
||||
let addr = (BUFFER_START + i) as *mut u8;
|
||||
buffer.push(unsafe { *addr });
|
||||
}
|
||||
|
||||
Ok(buffer)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_info(&self) -> PciDeviceInfo {
|
||||
|
@ -474,30 +491,33 @@ unsafe fn ata_delay(channel: Channel) {
|
|||
}
|
||||
|
||||
/// Set LBA and sector count registers. sector_count of 0 means 65536 sectors
|
||||
unsafe fn set_lba(channel: Channel, lba: u64, sector_count: u16) {
|
||||
// FIXME: CHS and LBA24 support
|
||||
assert!(lba < 0xFFFFFFFFFFFF);
|
||||
|
||||
unsafe fn set_lba(channel: Channel, lba: u64, sector_count: u16, lba48: bool) {
|
||||
let command_block = if channel.secondary() {
|
||||
SECONDARY_COMMAND
|
||||
} else {
|
||||
PRIMARY_COMMAND
|
||||
};
|
||||
|
||||
let mut seccount = Port::new(command_block + SECCOUNT_OFFSET);
|
||||
let mut lba0 = Port::new(command_block + LBA0_OFFSET);
|
||||
let mut lba1 = Port::new(command_block + LBA1_OFFSET);
|
||||
let mut lba2 = Port::new(command_block + LBA2_OFFSET);
|
||||
let mut head = Port::new(command_block + DRIVE_HEAD_OFFSET);
|
||||
let head_value: u8 = head.read();
|
||||
|
||||
let lba_bytes = lba.to_le_bytes();
|
||||
let sector_count_bytes = sector_count.to_le_bytes();
|
||||
|
||||
// write the new LBA & sector count registers
|
||||
// if LBA48 {
|
||||
seccount.write(sector_count_bytes[1]);
|
||||
lba0.write(lba_bytes[3]);
|
||||
lba1.write(lba_bytes[4]);
|
||||
lba2.write(lba_bytes[5]);
|
||||
// }
|
||||
// FIXME: CHS support
|
||||
if lba48 {
|
||||
seccount.write(sector_count_bytes[1]);
|
||||
lba0.write(lba_bytes[3]);
|
||||
lba1.write(lba_bytes[4]);
|
||||
lba2.write(lba_bytes[5]);
|
||||
} else {
|
||||
head.write(head_value | (lba_bytes[3] & 0x0F));
|
||||
}
|
||||
seccount.write(sector_count_bytes[0]);
|
||||
lba0.write(lba_bytes[0]);
|
||||
lba1.write(lba_bytes[1]);
|
||||
|
@ -522,10 +542,11 @@ struct IdeDevice {
|
|||
pub channel: Channel,
|
||||
pub drive: Drive,
|
||||
pub size: u64, // in sectors
|
||||
// FIXME: model
|
||||
pub lba48_support: bool,
|
||||
// FIXME: model
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Channel {
|
||||
Primary,
|
||||
Secondary,
|
||||
|
@ -537,7 +558,7 @@ impl Channel {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Drive {
|
||||
Master,
|
||||
Slave,
|
||||
|
|
|
@ -132,7 +132,8 @@ pub fn scratchpad() {
|
|||
{
|
||||
let mut pci_ide_device = pci_ide_device.lock();
|
||||
if let PciDevice::Ide(device) = &mut *pci_ide_device {
|
||||
let first_sector = device.read(Channel::Primary, Drive::Master, 0, 1).unwrap();
|
||||
let mut first_sector = Vec::with_capacity(512);
|
||||
device.read(Channel::Primary, Drive::Master, 0, 1, &mut first_sector).unwrap();
|
||||
trace!("IDE Primary/Master sector 0: {first_sector:?}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,14 +135,14 @@ fn test_push_number() {
|
|||
assert_eq!(
|
||||
bytes,
|
||||
vec![
|
||||
0b0101_1010, // 90
|
||||
0b0101_1010, // 90
|
||||
0b1001_1010, // 154
|
||||
0b1100_1011, // 203
|
||||
0b0110_1101, // 109
|
||||
0b01_1001_00, // 100
|
||||
0b1100_1011, // 203
|
||||
0b0110_1101, // 109
|
||||
0b01_1001_00, // 100
|
||||
0b0111_1001, // 121
|
||||
0b0111_0001, // 113
|
||||
0b1000_0000, // 128
|
||||
0b0111_0001, // 113
|
||||
0b1000_0000, // 128
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -357,10 +357,7 @@ mod numeric_tests {
|
|||
fn test_iso_18004_2006_example_1() {
|
||||
let mut bits = Bits::new(Version::Normal(1));
|
||||
assert_eq!(bits.push_numeric_data(b"01234567"), Ok(()));
|
||||
assert_eq!(
|
||||
bits.into_bytes(),
|
||||
vec![0b0001_0000, 0b001000_00, 0b00001100, 0b01010110, 0b0110_0001, 0b1000_0000]
|
||||
);
|
||||
assert_eq!(bits.into_bytes(), vec![0b0001_0000, 0b001000_00, 0b00001100, 0b01010110, 0b0110_0001, 0b1000_0000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -389,16 +386,7 @@ mod numeric_tests {
|
|||
assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(()));
|
||||
assert_eq!(
|
||||
bits.into_bytes(),
|
||||
vec![
|
||||
0b0010_0000,
|
||||
0b00000110,
|
||||
0b0010_1011,
|
||||
0b0011_0101,
|
||||
0b0011_0111,
|
||||
0b0000_1010,
|
||||
0b01110101,
|
||||
0b0010_1000,
|
||||
]
|
||||
vec![0b0010_0000, 0b00000110, 0b0010_1011, 0b0011_0101, 0b0011_0111, 0b0000_1010, 0b01110101, 0b0010_1000,]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -465,10 +453,7 @@ mod alphanumeric_tests {
|
|||
fn test_iso_18004_2006_example() {
|
||||
let mut bits = Bits::new(Version::Normal(1));
|
||||
assert_eq!(bits.push_alphanumeric_data(b"AC-42"), Ok(()));
|
||||
assert_eq!(
|
||||
bits.into_bytes(),
|
||||
vec![0b0010_0000, 0b0010_1001, 0b11001110, 0b11100111, 0b0010_0001, 0b0000_0000]
|
||||
);
|
||||
assert_eq!(bits.into_bytes(), vec![0b0010_0000, 0b0010_1001, 0b11001110, 0b11100111, 0b0010_0001, 0b0000_0000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! Find the optimal data mode sequence to encode a piece of data.
|
||||
use crate::types::{Mode, Version};
|
||||
|
||||
|
||||
use core::slice::Iter;
|
||||
|
||||
#[cfg(feature = "bench")]
|
||||
|
@ -155,7 +154,7 @@ impl<'a> Iterator for Parser<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod parse_tests {
|
||||
use alloc::vec::{Vec};
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::optimize::{Parser, Segment};
|
||||
use crate::types::Mode;
|
||||
|
|
Loading…
Reference in a new issue