diff options
author | Liav A <liavalb@gmail.com> | 2021-03-26 13:51:31 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-03-27 16:40:16 +0100 |
commit | 531037db7ecff1b340cdfd3a8c8f8c689585e4af (patch) | |
tree | 17e7b8114ce68756cb5aba68cd716dcd4bfcc2b1 /Kernel | |
parent | 4bb8986752815385bcdfa2fd2dcf8fd1c8c88b3b (diff) | |
download | serenity-531037db7ecff1b340cdfd3a8c8f8c689585e4af.zip |
Kernel: Remove support for CHS addressing
An article about IDE limits states that:
"Hard drives over 8.4 GB are supposed to report their geometry as
16383/16/63. This in effect means that the `geometry' is obsolete, and
the total disk size can no longer be computed from the geometry, but is
found in the LBA capacity field returned by the IDENTIFY command.
Hard drives over 137.4 GB are supposed to report an LBA capacity of
0xfffffff = 268435455 sectors (137438952960 bytes). Now the actual disk
size is found in the new 48-capacity field."
(https://tldp.org/HOWTO/Large-Disk-HOWTO-4.html) which is the main
reason to not support CHS as harddrives with less than 8.4 GB capacity
are completely obsolete.
Another good reason is that virtually any harddrive in the last 20 years
or so, supports LBA mode. Therefore, it's probably OK to just ignore CHS
as it's unlikely to encounter a harddrive that doesn't support LBA.
This is somewhat simplifying the IDE initialization and access code.
Also, we should use the ATAIdentifyBlock structure if possible,
so now we do it instead of using macros to calculate offsets.
With the usage of the ATAIdentifyBlock structure, we now use the
48-bit LBA max count if the drive indicates it supports 48-bit LBA mode.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Storage/IDEChannel.cpp | 50 | ||||
-rw-r--r-- | Kernel/Storage/PATADiskDevice.h | 3 |
2 files changed, 18 insertions, 35 deletions
diff --git a/Kernel/Storage/IDEChannel.cpp b/Kernel/Storage/IDEChannel.cpp index 1f3dea0712..86e2b04eb3 100644 --- a/Kernel/Storage/IDEChannel.cpp +++ b/Kernel/Storage/IDEChannel.cpp @@ -370,7 +370,6 @@ UNMAP_AFTER_INIT void IDEChannel::detect_disks() ByteBuffer bbuf = ByteBuffer::create_uninitialized(512); u8* b = bbuf.data(); u16* w = (u16*)wbuf.data(); - const u16* wbufbase = (u16*)wbuf.data(); for (u32 i = 0; i < 256; ++i) { u16 data = m_io_group.io_base().offset(ATA_REG_DATA).in<u16>(); @@ -383,17 +382,20 @@ UNMAP_AFTER_INIT void IDEChannel::detect_disks() for (u32 i = 93; i > 54 && bbuf[i] == ' '; --i) bbuf[i] = 0; - u16 cyls = wbufbase[ATA_IDENT_CYLINDERS / sizeof(u16)]; - u16 heads = wbufbase[ATA_IDENT_HEADS / sizeof(u16)]; - u16 spt = wbufbase[ATA_IDENT_SECTORS / sizeof(u16)]; - u16 capabilities = wbufbase[ATA_IDENT_CAPABILITIES / sizeof(u16)]; - if (cyls == 0 || heads == 0 || spt == 0) + volatile ATAIdentifyBlock& identify_block = (volatile ATAIdentifyBlock&)(*wbuf.data()); + + u16 capabilities = identify_block.capabilites[0]; + + // If the drive is so old that it doesn't support LBA, ignore it. + if (!(capabilities & ATA_CAP_LBA)) continue; - u64 max_addressable_block = cyls * heads * spt; - if (capabilities & ATA_CAP_LBA) - max_addressable_block = (wbufbase[(ATA_IDENT_MAX_LBA + 2) / sizeof(u16)] << 16) | wbufbase[ATA_IDENT_MAX_LBA / sizeof(u16)]; - dbgln("IDEChannel: {} {} {} device found: Name={}, Capacity={}, C/H/Spt={}/{}/{}, Capabilities=0x{:04x}", channel_type_string(), channel_string(i), interface_type == PATADiskDevice::InterfaceType::ATA ? "ATA" : "ATAPI", ((char*)bbuf.data() + 54), max_addressable_block * 512, cyls, heads, spt, capabilities); + u64 max_addressable_block = identify_block.max_28_bit_addressable_logical_sector; + // if we support 48-bit LBA, use that value instead. + if (identify_block.commands_and_feature_sets_supported[1] & (1 << 10)) + max_addressable_block = identify_block.user_addressable_logical_sectors_count; + + dbgln("IDEChannel: {} {} {} device found: Name={}, Capacity={}, Capabilities=0x{:04x}", channel_type_string(), channel_string(i), interface_type == PATADiskDevice::InterfaceType::ATA ? "ATA" : "ATAPI", ((char*)bbuf.data() + 54), max_addressable_block * 512, capabilities); if (i == 0) { m_master = PATADiskDevice::create(m_parent_controller, *this, PATADiskDevice::DriveType::Master, interface_type, capabilities, max_addressable_block); } else { @@ -406,29 +408,19 @@ void IDEChannel::ata_access(Direction direction, bool slave_request, u64 lba, u8 { LBAMode lba_mode; u8 head = 0; - u8 sector = 0; - u16 cylinder = 0; + VERIFY(capabilities & ATA_CAP_LBA); if (lba >= 0x10000000) { - VERIFY(capabilities & ATA_CAP_LBA); lba_mode = LBAMode::FortyEightBit; head = 0; - } else if (capabilities & ATA_CAP_LBA) { + } else { lba_mode = LBAMode::TwentyEightBit; head = (lba & 0xF000000) >> 24; - } else { - lba_mode = LBAMode::None; - sector = (lba % 63) + 1; - cylinder = (lba + 1 - sector) / (16 * 63); - head = (lba + 1 - sector) % (16 * 63) / (63); } wait_until_not_busy(); - if (lba_mode == LBAMode::None) - m_io_group.io_base().offset(ATA_REG_HDDEVSEL).out<u8>(0xA0 | (static_cast<u8>(slave_request) << 4) | head); - else - m_io_group.io_base().offset(ATA_REG_HDDEVSEL).out<u8>(0xE0 | (static_cast<u8>(slave_request) << 4) | head); + m_io_group.io_base().offset(ATA_REG_HDDEVSEL).out<u8>(0xE0 | (static_cast<u8>(slave_request) << 4) | head); if (lba_mode == LBAMode::FortyEightBit) { m_io_group.io_base().offset(ATA_REG_SECCOUNT1).out<u8>(0); @@ -438,15 +430,9 @@ void IDEChannel::ata_access(Direction direction, bool slave_request, u64 lba, u8 } m_io_group.io_base().offset(ATA_REG_SECCOUNT0).out<u8>(block_count); - if (lba_mode == LBAMode::FortyEightBit || lba_mode == LBAMode::TwentyEightBit) { - m_io_group.io_base().offset(ATA_REG_LBA0).out<u8>((lba & 0x000000FF) >> 0); - m_io_group.io_base().offset(ATA_REG_LBA1).out<u8>((lba & 0x0000FF00) >> 8); - m_io_group.io_base().offset(ATA_REG_LBA2).out<u8>((lba & 0x00FF0000) >> 16); - } else { - m_io_group.io_base().offset(ATA_REG_LBA0).out<u8>(sector); - m_io_group.io_base().offset(ATA_REG_LBA1).out<u8>((cylinder >> 0) & 0xFF); - m_io_group.io_base().offset(ATA_REG_LBA2).out<u8>((cylinder >> 8) & 0xFF); - } + m_io_group.io_base().offset(ATA_REG_LBA0).out<u8>((lba & 0x000000FF) >> 0); + m_io_group.io_base().offset(ATA_REG_LBA1).out<u8>((lba & 0x0000FF00) >> 8); + m_io_group.io_base().offset(ATA_REG_LBA2).out<u8>((lba & 0x00FF0000) >> 16); for (;;) { auto status = m_io_group.control_base().in<u8>(); diff --git a/Kernel/Storage/PATADiskDevice.h b/Kernel/Storage/PATADiskDevice.h index f843ab14de..55c394dd00 100644 --- a/Kernel/Storage/PATADiskDevice.h +++ b/Kernel/Storage/PATADiskDevice.h @@ -76,9 +76,6 @@ private: bool is_slave() const; Lock m_lock { "IDEDiskDevice" }; - u16 m_cylinders { 0 }; - u16 m_heads { 0 }; - u16 m_sectors_per_track { 0 }; u16 m_capabilities { 0 }; IDEChannel& m_channel; DriveType m_drive_type { DriveType::Master }; |