OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 23, 2024 5:50 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Confusion with port sizes and LBA instructions for ATA
PostPosted: Fri Jun 12, 2020 11:10 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
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:
Quote:
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:
Quote:
Feature Set
This 28-bit command is for all ATA devices.


Following the ATA in PIO mode wiki article, as well as the above mappings, my struct is defined like this:
Code:
#[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,
}

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.


Top
 Profile  
 
 Post subject: Re: Confusion with port sizes and LBA instructions for ATA
PostPosted: Sat Jun 13, 2020 1:20 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5143
The data port is 16 bits. All other ports are 8 bits.

The registers you access using the 8-bit ports may be either 8 bits or 16 bits. If the drive doesn't support the LBA48 feature, all of those registers are 8 bits. If it does support the LBA48 feature, five of those registers are extended to 16 bits: features, sector count, LBA low, LBA mid, and LBA high. Each time you write a byte to a 16-bit register, the low 8 bits of the register are moved to the high 8 bits, and the value you wrote is placed in the low 8 bits. This means that you must write the high byte before you write the low byte when you want to write all 16 bits of the register, but it also means that you may skip writing the high byte for commands that only use the low 8 bits.

The LBA field is mapped to those registers differently depending on whether the command is LBA28 or LBA48. For LBA28, only the low byte of each register is used, and the high byte is ignored. Bits 0-7 are mapped to LBA low, bits 8-15 are mapped to LBA mid, bits 16-23 are mapped to LBA high, and bits 24-27 are mapped to the low four bits of the device register. For LBA48, bits 0-23 are mapped the same way as LBA28, and bits 24-47 are mapped to the high byte of each of the three LBA registers. Bits 24-31 are mapped to LBA low, bits 32-39 are mapped to LBA mid, and bits 40-47 are mapped to LBA high.


Top
 Profile  
 
 Post subject: Re: Confusion with port sizes and LBA instructions for ATA
PostPosted: Sat Jun 13, 2020 11:55 am 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
Got it. Thanks! (Perhaps that should be documented in the article itself... There doesn't seem to be an explanation to port sizes and mappings, and so I wouldn't be surprised if many people get it wrong the first few times.)
Edit: Also, the wiki article says:
Quote:
(Notes: A sector count of 0 means 65536 sectors = 32MB. Try not to send bytes to the same IO port twice in a row. Doing so is much slower than doing two outb() commands to different IO ports. The important thing is that the high byte of the sector count, features and LBA bytes 4, 5, & 6 go to their respective ports before the low bytes.)

Does this work the same way when reading data back? For example, the GET NATIVE MAX ADDRESS EXT command (command 78h, feature 0001h) returns the native maximum LBA in the LBA field. To reconstruct that LBA, would I read the LBA field lo, mid, and hi bytes twice, then merge the first lo, mid, and hi into bits 24-31, 32-39, and 40-47, then the rest into bits 0-7, 8-15, and 16-23?


Top
 Profile  
 
 Post subject: Re: Confusion with port sizes and LBA instructions for ATA
PostPosted: Sat Jun 13, 2020 8:15 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5143
Ethin wrote:
Does this work the same way when reading data back?

No. Reads are controlled by HOB (bit 7) in the device control register. When HOB is clear, you'll read the low byte. When HOB is set, you'll read the high byte. You can set and clear HOB by writing to the device control register, but writing to any other register will also clear HOB.

In the GET NATIVE MAX ADDRESS EXT example, you'd read the LBA low/mid/high registers once with HOB clear and once with HOB set.


Top
 Profile  
 
 Post subject: Re: Confusion with port sizes and LBA instructions for ATA
PostPosted: Sat Jun 13, 2020 11:36 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
Octocontrabass wrote:
Ethin wrote:
Does this work the same way when reading data back?

No. Reads are controlled by HOB (bit 7) in the device control register. When HOB is clear, you'll read the low byte. When HOB is set, you'll read the high byte. You can set and clear HOB by writing to the device control register, but writing to any other register will also clear HOB.

In the GET NATIVE MAX ADDRESS EXT example, you'd read the LBA low/mid/high registers once with HOB clear and once with HOB set.

Aha. So I'd set HOB, read, then clear it and read again? Like what's the order I do that in?


Top
 Profile  
 
 Post subject: Re: Confusion with port sizes and LBA instructions for ATA
PostPosted: Sun Jun 14, 2020 12:28 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5143
Whatever order you want.

I'd aim for the fewest port accesses: read the low bytes, set HOB, and read the high bytes. That way there's no need to explicitly clear HOB, since it will be cleared by the writes for the next command.


Top
 Profile  
 
 Post subject: Re: Confusion with port sizes and LBA instructions for ATA
PostPosted: Sun Jun 14, 2020 12:04 pm 
Offline
Member
Member

Joined: Sun Jun 23, 2019 5:36 pm
Posts: 618
Location: North Dakota, United States
Alright. Thanks!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], SemrushBot [Bot] and 104 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group