1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 10:57:35 +00:00

Kernel: Move IO delay code to x86 architecture subdirectory

Many code patterns and hardware procedures rely on reliable delay in the
microseconds granularity, and since they are using such delays which are
valid cases, but should not rely on x86 specific code, we allow to
determine in compile time the proper platform-specific code to use to
invoke such delays.
This commit is contained in:
Liav A 2022-09-02 11:23:32 +03:00 committed by Linus Groh
parent cac72259d0
commit 84fbab6803
19 changed files with 96 additions and 54 deletions

View file

@ -8,6 +8,7 @@
#include <AK/BuiltinWrappers.h>
#include <AK/OwnPtr.h>
#include <AK/Types.h>
#include <Kernel/Arch/Delay.h>
#include <Kernel/Bus/PCI/API.h>
#include <Kernel/CommandLine.h>
#include <Kernel/Library/LockRefPtr.h>
@ -42,7 +43,7 @@ bool AHCIController::reset()
return false;
if (!(hba().control_regs.ghc & 1))
break;
IO::delay(1000);
microseconds_delay(1000);
retry++;
}
// Note: Turn on AHCI HBA and Global HBA Interrupts.

View file

@ -8,6 +8,7 @@
// please look at Documentation/Kernel/AHCILocking.md
#include <AK/Atomic.h>
#include <Kernel/Arch/Delay.h>
#include <Kernel/Locking/Spinlock.h>
#include <Kernel/Memory/MemoryManager.h>
#include <Kernel/Memory/ScatterGatherList.h>
@ -552,7 +553,7 @@ bool AHCIPort::spin_until_ready() const
size_t spin = 0;
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Spinning until ready.", representative_port_index());
while ((m_port_registers.tfd & (ATA_SR_BSY | ATA_SR_DRQ)) && spin <= 100) {
IO::delay(1000);
microseconds_delay(1000);
spin++;
}
if (spin == 100) {
@ -719,7 +720,7 @@ bool AHCIPort::identify_device()
success = true;
break;
}
IO::delay(1000); // delay with 1 milliseconds
microseconds_delay(1000); // delay with 1 milliseconds
time_elapsed++;
}
@ -739,7 +740,7 @@ void AHCIPort::wait_until_condition_met_or_timeout(size_t delay_in_microseconds,
while (retry < retries) {
if (condition_being_met())
break;
IO::delay(delay_in_microseconds);
microseconds_delay(delay_in_microseconds);
retry++;
}
}
@ -852,7 +853,7 @@ bool AHCIPort::initiate_sata_reset()
full_memory_barrier();
set_interface_state(AHCI::DeviceDetectionInitialization::PerformInterfaceInitializationSequence);
// The AHCI specification says to wait now a 1 millisecond
IO::delay(1000);
microseconds_delay(1000);
full_memory_barrier();
set_interface_state(AHCI::DeviceDetectionInitialization::NoActionRequested);
full_memory_barrier();

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Arch/x86/IO.h>
#include <Kernel/Arch/Delay.h>
#include <Kernel/Storage/ATA/ATADiskDevice.h>
#include <Kernel/Storage/ATA/ATAPort.h>
#include <Kernel/Storage/ATA/Definitions.h>
@ -499,7 +499,7 @@ ErrorOr<void> ATAPort::execute_polled_command(TransactionDirection direction, LB
break;
}
IO::delay(1000);
microseconds_delay(1000);
milliseconds_elapsed++;
}
if (milliseconds_elapsed > completion_timeout_in_milliseconds) {

View file

@ -7,6 +7,7 @@
#include <AK/ByteBuffer.h>
#include <AK/Singleton.h>
#include <AK/StringView.h>
#include <Kernel/Arch/Delay.h>
#include <Kernel/Arch/x86/IO.h>
#include <Kernel/Bus/PCI/API.h>
#include <Kernel/Memory/MemoryManager.h>
@ -44,13 +45,13 @@ StringView IDEChannel::channel_type_string() const
bool IDEChannel::select_device_and_wait_until_not_busy(DeviceType device_type, size_t milliseconds_timeout)
{
IO::delay(20);
microseconds_delay(20);
u8 slave = device_type == DeviceType::Slave;
m_io_group.io_base().offset(ATA_REG_HDDEVSEL).out<u8>(0xA0 | (slave << 4)); // First, we need to select the drive itself
IO::delay(20);
microseconds_delay(20);
size_t time_elapsed = 0;
while (m_io_group.control_base().in<u8>() & ATA_SR_BSY && time_elapsed <= milliseconds_timeout) {
IO::delay(1000);
microseconds_delay(1000);
time_elapsed++;
}
return time_elapsed <= milliseconds_timeout;
@ -63,10 +64,10 @@ ErrorOr<void> IDEChannel::port_phy_reset()
// reset the channel
u8 device_control = m_io_group.control_base().in<u8>();
// Wait 30 milliseconds
IO::delay(30000);
microseconds_delay(30000);
m_io_group.control_base().out<u8>(device_control | (1 << 2));
// Wait 30 milliseconds
IO::delay(30000);
microseconds_delay(30000);
m_io_group.control_base().out<u8>(device_control);
// Wait up to 30 seconds before failing
if (!select_device_and_wait_until_not_busy(DeviceType::Master, 30000)) {
@ -220,7 +221,7 @@ ErrorOr<void> IDEChannel::wait_if_busy_until_timeout(size_t timeout_in_milliseco
{
size_t time_elapsed = 0;
while (m_io_group.control_base().in<u8>() & ATA_SR_BSY && time_elapsed <= timeout_in_milliseconds) {
IO::delay(1000);
microseconds_delay(1000);
time_elapsed++;
}
if (time_elapsed <= timeout_in_milliseconds)
@ -249,7 +250,7 @@ ErrorOr<void> IDEChannel::load_taskfile_into_registers(ATAPort::TaskFile const&
// Note: Preserve the selected drive, always use LBA addressing
auto driver_register = ((m_io_group.io_base().offset(ATA_REG_HDDEVSEL).in<u8>() & (1 << 4)) | (head | (1 << 5) | (1 << 6)));
m_io_group.io_base().offset(ATA_REG_HDDEVSEL).out<u8>(driver_register);
IO::delay(50);
microseconds_delay(50);
if (lba_mode == LBAMode::FortyEightBit) {
m_io_group.io_base().offset(ATA_REG_SECCOUNT1).out<u8>((task_file.count >> 8) & 0xFF);
@ -272,7 +273,7 @@ ErrorOr<void> IDEChannel::load_taskfile_into_registers(ATAPort::TaskFile const&
auto status = m_io_group.control_base().in<u8>();
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY))
break;
IO::delay(1000);
microseconds_delay(1000);
time_elapsed++;
}
m_io_group.io_base().offset(ATA_REG_COMMAND).out<u8>(task_file.command);
@ -284,9 +285,9 @@ ErrorOr<void> IDEChannel::device_select(size_t device_index)
VERIFY(m_lock.is_locked());
if (device_index > 1)
return Error::from_errno(EINVAL);
IO::delay(20);
microseconds_delay(20);
m_io_group.io_base().offset(ATA_REG_HDDEVSEL).out<u8>(0xA0 | ((device_index) << 4));
IO::delay(20);
microseconds_delay(20);
return {};
}