From 777888aae2a4bfcf051e0a84c2bf8b9a06990796 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Wed, 17 Aug 2022 15:10:00 +0300 Subject: [PATCH] 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. --- ableos/src/devices/pci/ide.rs | 69 +++++++++++++++++++++++------------ ableos/src/scratchpad.rs | 3 +- qrcode-rust/src/bits.rs | 33 +++++------------ qrcode-rust/src/optimize.rs | 3 +- 4 files changed, 57 insertions(+), 51 deletions(-) diff --git a/ableos/src/devices/pci/ide.rs b/ableos/src/devices/pci/ide.rs index 63e59c2a..81576729 100644 --- a/ableos/src/devices/pci/ide.rs +++ b/ableos/src/devices/pci/ide.rs @@ -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, TryFromIntError> { + buffer: &mut Vec, + ) -> 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, diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs index 3d9f7394..dbe877a5 100644 --- a/ableos/src/scratchpad.rs +++ b/ableos/src/scratchpad.rs @@ -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:?}"); } } diff --git a/qrcode-rust/src/bits.rs b/qrcode-rust/src/bits.rs index 1273626f..9cc951cc 100644 --- a/qrcode-rust/src/bits.rs +++ b/qrcode-rust/src/bits.rs @@ -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] diff --git a/qrcode-rust/src/optimize.rs b/qrcode-rust/src/optimize.rs index 7a59c11e..1d3af2cf 100644 --- a/qrcode-rust/src/optimize.rs +++ b/qrcode-rust/src/optimize.rs @@ -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;