summaryrefslogtreecommitdiff
path: root/Kernel/Storage/IDEChannel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Storage/IDEChannel.cpp')
-rw-r--r--Kernel/Storage/IDEChannel.cpp87
1 files changed, 41 insertions, 46 deletions
diff --git a/Kernel/Storage/IDEChannel.cpp b/Kernel/Storage/IDEChannel.cpp
index 6127124b9a..e7dc66846c 100644
--- a/Kernel/Storage/IDEChannel.cpp
+++ b/Kernel/Storage/IDEChannel.cpp
@@ -292,8 +292,6 @@ void IDEChannel::handle_irq(const RegisterState&)
return;
}
- bool received_all_irqs = m_current_request_uses_dma || m_current_request_block_index + 1 >= m_current_request->block_count();
-
if (status & ATA_SR_ERR) {
print_ide_status(status);
m_device_error = m_io_group.io_base().offset(ATA_REG_ERROR).in<u8>();
@@ -302,45 +300,44 @@ void IDEChannel::handle_irq(const RegisterState&)
complete_current_request(AsyncDeviceRequest::Failure);
return;
}
-
m_device_error = 0;
- if (received_all_irqs) {
+ if (m_current_request_uses_dma) {
complete_current_request(AsyncDeviceRequest::Success);
- } else {
- ASSERT(!m_current_request_uses_dma);
-
- // Now schedule reading/writing the buffer as soon as we leave the irq handler.
- // This is important so that we can safely access the buffers, which could
- // trigger page faults
- Processor::deferred_call_queue([this]() {
- if (m_current_request->request_type() == AsyncBlockDeviceRequest::Read) {
- dbgln("IDEChannel: Read block {}/{}", m_current_request_block_index, m_current_request->block_count());
- if (ata_do_read_sector()) {
- if (++m_current_request_block_index >= m_current_request->block_count()) {
- complete_current_request(AsyncDeviceRequest::Success);
- return;
- }
- // Wait for the next block
- enable_irq();
+ return;
+ }
+
+ // Now schedule reading/writing the buffer as soon as we leave the irq handler.
+ // This is important so that we can safely access the buffers, which could
+ // trigger page faults
+ Processor::deferred_call_queue([this]() {
+ ScopedSpinLock lock(m_request_lock);
+ if (m_current_request->request_type() == AsyncBlockDeviceRequest::Read) {
+ dbgln<PATA_DEBUG>("IDEChannel: Read block {}/{}", m_current_request_block_index, m_current_request->block_count());
+ if (ata_do_read_sector()) {
+ if (++m_current_request_block_index >= m_current_request->block_count()) {
+ complete_current_request(AsyncDeviceRequest::Success);
+ return;
}
- } else {
- if (!m_current_request_flushing_cache) {
- dbgln("IDEChannel: Wrote block {}/{}", m_current_request_block_index, m_current_request->block_count());
- if (++m_current_request_block_index >= m_current_request->block_count()) {
- // We read the last block, flush cache
- ASSERT(!m_current_request_flushing_cache);
- m_current_request_flushing_cache = true;
- m_io_group.io_base().offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_CACHE_FLUSH);
- } else {
- // Read next block
- ata_do_write_sector();
- }
+ // Wait for the next block
+ enable_irq();
+ }
+ } else {
+ if (!m_current_request_flushing_cache) {
+ dbgln<PATA_DEBUG>("IDEChannel: Wrote block {}/{}", m_current_request_block_index, m_current_request->block_count());
+ if (++m_current_request_block_index >= m_current_request->block_count()) {
+ // We read the last block, flush cache
+ ASSERT(!m_current_request_flushing_cache);
+ m_current_request_flushing_cache = true;
+ m_io_group.io_base().offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_CACHE_FLUSH);
} else {
- complete_current_request(AsyncDeviceRequest::Success);
+ // Read next block
+ ata_do_write_sector();
}
+ } else {
+ complete_current_request(AsyncDeviceRequest::Success);
}
- });
- }
+ }
+ });
}
static void io_delay()
@@ -351,7 +348,7 @@ static void io_delay()
void IDEChannel::wait_until_not_busy()
{
- while (m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY)
+ while (m_io_group.control_base().in<u8>() & ATA_SR_BSY)
;
}
@@ -379,10 +376,10 @@ void IDEChannel::detect_disks()
m_io_group.io_base().offset(ATA_REG_COMMAND).out<u8>(ATA_CMD_IDENTIFY); // Send the ATA_IDENTIFY command
// Wait for the BSY flag to be reset
- while (m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY)
+ while (m_io_group.control_base().in<u8>() & ATA_SR_BSY)
;
- if (m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>() == 0x00) {
+ if (m_io_group.control_base().in<u8>() == 0x00) {
dbgln<PATA_DEBUG>("IDEChannel: No {} {} disk detected!", channel_type_string().to_lowercase(), channel_string(i));
continue;
}
@@ -391,7 +388,7 @@ void IDEChannel::detect_disks()
PATADiskDevice::InterfaceType interface_type = PATADiskDevice::InterfaceType::ATA;
for (;;) {
- u8 status = m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>();
+ u8 status = m_io_group.control_base().in<u8>();
if (status & ATA_SR_ERR) {
dbgln<PATA_DEBUG>("IDEChannel: {} {} device is not ATA. Will check for ATAPI.", channel_type_string(), channel_string(i));
check_for_atapi = true;
@@ -499,7 +496,7 @@ void IDEChannel::ata_access(Direction direction, bool slave_request, u32 lba, u8
}
for (;;) {
- auto status = m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>();
+ auto status = m_io_group.control_base().in<u8>();
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY))
break;
}
@@ -515,7 +512,6 @@ void IDEChannel::ata_access(Direction direction, bool slave_request, u32 lba, u8
else
m_io_group.io_base().offset(ATA_REG_COMMAND).out<u8>(direction == Direction::Read ? ATA_CMD_READ_PIO_EXT : ATA_CMD_WRITE_PIO_EXT);
}
-
enable_irq();
}
@@ -550,6 +546,7 @@ void IDEChannel::ata_read_sectors_with_dma(bool slave_request, u16 capabilities)
bool IDEChannel::ata_do_read_sector()
{
+ dbgln<PATA_DEBUG>("IDEChannel::ata_do_read_sector");
auto& request = *m_current_request;
auto out_buffer = request.buffer().offset(m_current_request_block_index * 512);
ssize_t nwritten = request.write_to_buffer_buffered<512>(out_buffer, 512, [&](u8* buffer, size_t buffer_bytes) {
@@ -576,7 +573,6 @@ void IDEChannel::ata_read_sectors(bool slave_request, u16 capabilities)
dbgln<PATA_DEBUG>("IDEChannel: Reading {} sector(s) @ LBA {}", request.block_count(), lba);
ata_access(Direction::Read, slave_request, lba, request.block_count(), capabilities, false);
- ata_do_read_sector();
}
void IDEChannel::ata_write_sectors_with_dma(bool slave_request, u16 capabilities)
@@ -615,10 +611,10 @@ void IDEChannel::ata_do_write_sector()
auto& request = *m_current_request;
io_delay();
- while ((m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>() & ATA_SR_BSY) || !(m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>() & ATA_SR_DRQ))
+ while ((m_io_group.control_base().in<u8>() & ATA_SR_BSY) || !(m_io_group.control_base().in<u8>() & ATA_SR_DRQ))
;
- u8 status = m_io_group.io_base().offset(ATA_REG_STATUS).in<u8>();
+ u8 status = m_io_group.control_base().in<u8>();
ASSERT(status & ATA_SR_DRQ);
auto in_buffer = request.buffer().offset(m_current_request_block_index * 512);
@@ -642,8 +638,7 @@ void IDEChannel::ata_write_sectors(bool slave_request, u16 capabilities)
u32 count = request.block_count();
dbgln<PATA_DEBUG>("IDEChannel: Writing {} sector(s) @ LBA {}", count, start_sector);
- ata_access(Direction::Write, slave_request, start_sector, request.block_count(), capabilities, true);
+ ata_access(Direction::Write, slave_request, start_sector, request.block_count(), capabilities, false);
ata_do_write_sector();
}
-
}