Confusion with port sizes and LBA instructions for ATA
Posted: Fri Jun 12, 2020 11:10 am
So, I've done some major restructuring with my kernel, and I'm changing the port mappings to use actual readable names instead of direct out() function calls. However, I'm confused on what types to assign to the ports (I'm putting them all in a struct). The ACS-4 standard says:
I initialize this using the port offsets in the ATA PIO Mode article. But I'm kinda confused on the port sizes for these ports, aswell as the instructions for reading and writing 28-bit LBAs. The wiki article says to write LBA lo, LBA mid, and LBA hi, as bits 7:0, 15:8, and 24:16, respectively. But what about bits 31:25? I know that bits 31:29 are ignored, but bits 28:25 are not.
Following the ATA in PIO mode wiki article, as well as the above mappings, my struct is defined like this:7.1.3 Feature Set
The feature set subclause for each command lists the feature set (see clause 4) along with a statement that indicates if the command uses 28-bit field formatting or 48-bit field formatting. If a command uses 28-bit formatting, then:
a) the FEATURE field, COUNT field, DEVICE field, ERROR field, STATUS field, and COMMAND field are each eight bits in length; and
b) the LBA field is 28 bits in length.
If a command uses 48-bit formatting, then:
a) the DEVICE field, ERROR field, STATUS field, and COMMAND field are each eight bits in length;
b) the FEATURE field and COUNT field are 16 bits in length; and
c) the LBA field is 48 bits in length.
EXAMPLE - A feature set subclause reads:Feature Set
This 28-bit command is for all ATA devices.
Code: Select all
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, partialEq, Ord, PartialOrd, Hash)]
pub enum Drive {
Master,
Slave,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct AtaDevice {
master_data: Port<u16>,
master_error28: PortReadOnly<u8>,
master_error48: PortReadOnly<u16>,
master_features28: PortWriteOnly<u8>,
master_features48: PortWriteOnly<u16>,
master_count28: Port<u8>,
master_count48: Port<u16>,
master_lba28_lo: Port<u8>,
master_lba28_mid: Port<u8>,
master_lba28_hi: Port<u8>,
master_lba48_lo: Port<u16>,
master_lba48_mid: Port<u16>,
master_lba48_hi: Port<u16>,
master_drive: Port<u8>,
master_status: PortReadOnly<u8>,
master_command: PortWriteOnly<u8>,
master_alt_status: PortReadOnly<u8>,
master_dev_ctl: PortWriteOnly<u8>,
master_drive_addr: PortReadOnly<u8>,
slave_data: Port<u16>,
slave_error28: PortReadOnly<u8>,
slave_error48: PortReadOnly<u16>,
slave_features28: PortWriteOnly<u8>,
slave_features48: PortWriteOnly<u16>,
slave_count28: Port<u8>,
slave_count48: Port<u16>,
slave_lba28_lo: Port<u8>,
slave_lba28_mid: Port<u8>,
slave_lba28_hi: Port<u8>,
slave_lba48_lo: Port<u16>,
slave_lba48_mid: Port<u16>,
slave_lba48_hi: Port<u16>,
slave_drive: Port<u8>,
slave_status: PortReadOnly<u8>,
slave_command: PortWriteOnly<u8>,
slave_alt_status: PortReadOnly<u8>,
slave_dev_ctl: PortWriteOnly<u8>,
slave_drive_addr: PortReadOnly<u8>,
drive: Drive,
}