summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Storage/IDEChannel.cpp50
-rw-r--r--Kernel/Storage/PATADiskDevice.h3
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 };