diff --git a/Kernel/Arch/Delay.h b/Kernel/Arch/Delay.h new file mode 100644 index 0000000000..5b9f0be551 --- /dev/null +++ b/Kernel/Arch/Delay.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Kernel { + +void microseconds_delay(u32 microseconds); + +} diff --git a/Kernel/Arch/x86/common/Delay.cpp b/Kernel/Arch/x86/common/Delay.cpp new file mode 100644 index 0000000000..444d6604c0 --- /dev/null +++ b/Kernel/Arch/x86/common/Delay.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace Kernel { + +void microseconds_delay(u32 microseconds) +{ + IO::delay(microseconds); +} + +} diff --git a/Kernel/Bus/USB/UHCI/UHCIController.cpp b/Kernel/Bus/USB/UHCI/UHCIController.cpp index ba80a1ee4e..7fed7817b7 100644 --- a/Kernel/Bus/USB/UHCI/UHCIController.cpp +++ b/Kernel/Bus/USB/UHCI/UHCIController.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -633,7 +634,7 @@ void UHCIController::reset_port(u8 port) // Wait at least 50 ms for the port to reset. // This is T DRSTR in the USB 2.0 Specification Page 186 Table 7-13. constexpr u16 reset_delay = 50 * 1000; - IO::delay(reset_delay); + microseconds_delay(reset_delay); port_data &= ~UHCI_PORTSC_PORT_RESET; if (port == 0) @@ -644,7 +645,7 @@ void UHCIController::reset_port(u8 port) // Wait 10 ms for the port to recover. // This is T RSTRCY in the USB 2.0 Specification Page 188 Table 7-14. constexpr u16 reset_recovery_delay = 10 * 1000; - IO::delay(reset_recovery_delay); + microseconds_delay(reset_recovery_delay); port_data = port == 0 ? read_portsc1() : read_portsc2(); port_data |= UHCI_PORTSC_PORT_ENABLED; diff --git a/Kernel/Bus/USB/USBHub.cpp b/Kernel/Bus/USB/USBHub.cpp index bbb3d5bdcf..c2df5b8f4c 100644 --- a/Kernel/Bus/USB/USBHub.cpp +++ b/Kernel/Bus/USB/USBHub.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -83,7 +84,7 @@ ErrorOr Hub::enumerate_and_power_on_hub() } // Wait for the ports to power up. power_on_to_power_good_time is in units of 2 ms and we want in us, so multiply by 2000. - IO::delay(descriptor.power_on_to_power_good_time * 2000); + microseconds_delay(descriptor.power_on_to_power_good_time * 2000); memcpy(&m_hub_descriptor, &descriptor, sizeof(USBHubDescriptor)); @@ -171,7 +172,7 @@ void Hub::check_for_port_updates() // FIXME: Timeout while (debounce_timer < debounce_interval) { - IO::delay(debounce_disconnect_check_interval); + microseconds_delay(debounce_disconnect_check_interval); debounce_timer += debounce_disconnect_check_interval; if (auto result = get_port_status(port_number, port_status); result.is_error()) { @@ -203,7 +204,7 @@ void Hub::check_for_port_updates() // Wait at least 10 ms for the port to reset. // This is T DRST in the USB 2.0 Specification Page 186 Table 7-13. constexpr u16 reset_delay = 10 * 1000; - IO::delay(reset_delay); + microseconds_delay(reset_delay); if (auto result = get_port_status(port_number, port_status); result.is_error()) { dbgln("USB Hub: Error occurred when getting status while resetting port {}: {}.", port_number, result.error()); @@ -224,7 +225,7 @@ void Hub::check_for_port_updates() // Wait 10 ms for the port to recover. // This is T RSTRCY in the USB 2.0 Specification Page 188 Table 7-14. constexpr u16 reset_recovery_delay = 10 * 1000; - IO::delay(reset_recovery_delay); + microseconds_delay(reset_recovery_delay); dbgln_if(USB_DEBUG, "USB Hub: Reset complete!"); diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 20b53634a9..d783aeb52f 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -333,6 +333,7 @@ if ("${SERENITY_ARCH}" STREQUAL "i686" OR "${SERENITY_ARCH}" STREQUAL "x86_64") ${KERNEL_SOURCES} Arch/Processor.cpp + Arch/x86/common/Delay.cpp Arch/x86/common/I8042Reboot.cpp Arch/x86/common/ScopedCritical.cpp Arch/x86/common/SmapDisabler.cpp diff --git a/Kernel/Devices/Audio/AC97.cpp b/Kernel/Devices/Audio/AC97.cpp index bf617e000c..7b7346979a 100644 --- a/Kernel/Devices/Audio/AC97.cpp +++ b/Kernel/Devices/Audio/AC97.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -291,7 +292,7 @@ void AC97::AC97Channel::reset() control_register.out(AudioControlRegisterFlag::ResetRegisters); while ((control_register.in() & AudioControlRegisterFlag::ResetRegisters) > 0) - IO::delay(50); + microseconds_delay(50); m_dma_running.with([](auto& dma_running) { dma_running = false; diff --git a/Kernel/Devices/HID/I8042Controller.cpp b/Kernel/Devices/HID/I8042Controller.cpp index d4cd636a29..bf48056068 100644 --- a/Kernel/Devices/HID/I8042Controller.cpp +++ b/Kernel/Devices/HID/I8042Controller.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -71,7 +72,7 @@ UNMAP_AFTER_INIT bool I8042Controller::check_existence_via_probing(Badge I8042Controller::drain_output_buffer() return {}; IO::in8(I8042Port::Buffer); - IO::delay(100); + microseconds_delay(100); } return Error::from_errno(EBUSY); } @@ -332,14 +333,14 @@ ErrorOr I8042Controller::prepare_for_input(HIDDevice::Type device) for (int attempt = 0; attempt < 1000; attempt++) { u8 status = IO::in8(I8042Port::Status); if (!(status & I8042StatusFlag::OutputBuffer)) { - IO::delay(1000); + microseconds_delay(1000); continue; } if (device == HIDDevice::Type::Unknown) return {}; if ((status & I8042StatusFlag::SecondPS2PortOutputBuffer) == second_port_flag) return {}; - IO::delay(1000); + microseconds_delay(1000); } return Error::from_errno(EBUSY); } @@ -351,7 +352,7 @@ ErrorOr I8042Controller::prepare_for_output() u8 status = IO::in8(I8042Port::Status); if (!(status & I8042StatusFlag::InputBuffer)) return {}; - IO::delay(1000); + microseconds_delay(1000); } return Error::from_errno(EBUSY); } diff --git a/Kernel/Graphics/GraphicsManagement.cpp b/Kernel/Graphics/GraphicsManagement.cpp index 025a3370f8..4411ec4563 100644 --- a/Kernel/Graphics/GraphicsManagement.cpp +++ b/Kernel/Graphics/GraphicsManagement.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -46,7 +47,7 @@ void GraphicsManagement::disable_vga_emulation_access_permanently() IO::out8(0x3c4, 1); u8 sr1 = IO::in8(0x3c5); IO::out8(0x3c5, sr1 | 1 << 5); - IO::delay(1000); + microseconds_delay(1000); m_vga_access_is_disabled = true; } diff --git a/Kernel/Graphics/Intel/NativeDisplayConnector.cpp b/Kernel/Graphics/Intel/NativeDisplayConnector.cpp index b0710b3ea9..4ce94adf0c 100644 --- a/Kernel/Graphics/Intel/NativeDisplayConnector.cpp +++ b/Kernel/Graphics/Intel/NativeDisplayConnector.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include #include @@ -371,7 +371,7 @@ bool IntelNativeDisplayConnector::gmbus_wait_for(IntelGraphics::GMBusStatus desi default: VERIFY_NOT_REACHED(); } - IO::delay(1000); + microseconds_delay(1000); milliseconds_passed++; } } @@ -544,7 +544,7 @@ void IntelNativeDisplayConnector::set_display_timings(Graphics::Modesetting cons dbgln_if(INTEL_GRAPHICS_DEBUG, "sourceSize - {}, {}", (modesetting.vertical.active - 1), (modesetting.horizontal.active - 1)); write_to_register(IntelGraphics::RegisterIndex::PipeASource, (modesetting.vertical.active - 1) | (modesetting.horizontal.active - 1) << 16); - IO::delay(200); + microseconds_delay(200); } bool IntelNativeDisplayConnector::wait_for_enabled_pipe_a(size_t milliseconds_timeout) const @@ -553,7 +553,7 @@ bool IntelNativeDisplayConnector::wait_for_enabled_pipe_a(size_t milliseconds_ti while (current_time < milliseconds_timeout) { if (pipe_a_enabled()) return true; - IO::delay(1000); + microseconds_delay(1000); current_time++; } return false; @@ -564,7 +564,7 @@ bool IntelNativeDisplayConnector::wait_for_disabled_pipe_a(size_t milliseconds_t while (current_time < milliseconds_timeout) { if (!pipe_a_enabled()) return true; - IO::delay(1000); + microseconds_delay(1000); current_time++; } return false; @@ -576,7 +576,7 @@ bool IntelNativeDisplayConnector::wait_for_disabled_pipe_b(size_t milliseconds_t while (current_time < milliseconds_timeout) { if (!pipe_b_enabled()) return true; - IO::delay(1000); + microseconds_delay(1000); current_time++; } return false; @@ -662,14 +662,14 @@ void IntelNativeDisplayConnector::enable_dpll_without_vga(IntelGraphics::PLLSett set_dpll_registers(settings); - IO::delay(200); + microseconds_delay(200); write_to_register(IntelGraphics::RegisterIndex::DPLLControlA, (6 << 9) | (settings.p1) << 16 | (1 << 26) | (1 << 28) | (1 << 31)); write_to_register(IntelGraphics::RegisterIndex::DPLLMultiplierA, (dac_multiplier - 1) | ((dac_multiplier - 1) << 8)); // The specification says we should wait (at least) about 150 microseconds // after enabling the DPLL to allow the clock to stabilize - IO::delay(200); + microseconds_delay(200); VERIFY(read_from_register(IntelGraphics::RegisterIndex::DPLLControlA) & (1 << 31)); } diff --git a/Kernel/Interrupts/APIC.cpp b/Kernel/Interrupts/APIC.cpp index f75963f829..c5f0b97403 100644 --- a/Kernel/Interrupts/APIC.cpp +++ b/Kernel/Interrupts/APIC.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -186,7 +186,7 @@ void APIC::set_siv(u32 offset, u8 interrupt) void APIC::wait_for_pending_icr() { while ((read_register(APIC_REG_ICR_LOW) & APIC_ICR_DELIVERY_PENDING) != 0) { - IO::delay(200); + microseconds_delay(200); } } @@ -409,13 +409,13 @@ UNMAP_AFTER_INIT void APIC::do_boot_aps() // INIT write_icr({ 0, 0, ICRReg::INIT, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf }); - IO::delay(10 * 1000); + microseconds_delay(10 * 1000); for (int i = 0; i < 2; i++) { // SIPI write_icr({ 0x08, 0, ICRReg::StartUp, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf }); // start execution at P8000 - IO::delay(200); + microseconds_delay(200); } // Now wait until the ap_cpu_init_pending variable dropped to 0, which means all APs are initialized and no longer need these special mappings @@ -423,7 +423,7 @@ UNMAP_AFTER_INIT void APIC::do_boot_aps() dbgln_if(APIC_DEBUG, "APIC: Waiting for {} AP(s) to finish initialization...", aps_to_enable); do { // Wait a little bit - IO::delay(200); + microseconds_delay(200); } while (m_apic_ap_count.load(AK::MemoryOrder::memory_order_consume) != aps_to_enable); } @@ -537,7 +537,7 @@ UNMAP_AFTER_INIT void APIC::init_finished(u32 cpu) // we don't want APs to trigger IPIs (e.g. through MM) while the BSP // is unable to process them while (!m_apic_ap_continue.load(AK::MemoryOrder::memory_order_consume)) { - IO::delay(200); + microseconds_delay(200); } dbgln_if(APIC_DEBUG, "APIC: CPU #{} continues, all others are initialized", cpu); diff --git a/Kernel/RTC.cpp b/Kernel/RTC.cpp index 7929869b38..d773af8a8f 100644 --- a/Kernel/RTC.cpp +++ b/Kernel/RTC.cpp @@ -4,8 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include -#include +#include #include #include @@ -43,7 +44,7 @@ static bool try_to_read_registers(unsigned& year, unsigned& month, unsigned& day update_in_progress_ended_successfully = true; break; } - IO::delay(1000); + microseconds_delay(1000); time_passed_in_milliseconds++; } diff --git a/Kernel/Storage/ATA/AHCI/Controller.cpp b/Kernel/Storage/ATA/AHCI/Controller.cpp index 6b375ecdeb..d05f1c8e91 100644 --- a/Kernel/Storage/ATA/AHCI/Controller.cpp +++ b/Kernel/Storage/ATA/AHCI/Controller.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -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. diff --git a/Kernel/Storage/ATA/AHCI/Port.cpp b/Kernel/Storage/ATA/AHCI/Port.cpp index aff473adc8..776d1d125e 100644 --- a/Kernel/Storage/ATA/AHCI/Port.cpp +++ b/Kernel/Storage/ATA/AHCI/Port.cpp @@ -8,6 +8,7 @@ // please look at Documentation/Kernel/AHCILocking.md #include +#include #include #include #include @@ -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(); diff --git a/Kernel/Storage/ATA/ATAPort.cpp b/Kernel/Storage/ATA/ATAPort.cpp index 7f89a9d64c..99e0838f21 100644 --- a/Kernel/Storage/ATA/ATAPort.cpp +++ b/Kernel/Storage/ATA/ATAPort.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include #include @@ -499,7 +499,7 @@ ErrorOr ATAPort::execute_polled_command(TransactionDirection direction, LB break; } - IO::delay(1000); + microseconds_delay(1000); milliseconds_elapsed++; } if (milliseconds_elapsed > completion_timeout_in_milliseconds) { diff --git a/Kernel/Storage/ATA/GenericIDE/Channel.cpp b/Kernel/Storage/ATA/GenericIDE/Channel.cpp index c89ef74d6f..feda770ba2 100644 --- a/Kernel/Storage/ATA/GenericIDE/Channel.cpp +++ b/Kernel/Storage/ATA/GenericIDE/Channel.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -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(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() & 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 IDEChannel::port_phy_reset() // reset the channel u8 device_control = m_io_group.control_base().in(); // Wait 30 milliseconds - IO::delay(30000); + microseconds_delay(30000); m_io_group.control_base().out(device_control | (1 << 2)); // Wait 30 milliseconds - IO::delay(30000); + microseconds_delay(30000); m_io_group.control_base().out(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 IDEChannel::wait_if_busy_until_timeout(size_t timeout_in_milliseco { size_t time_elapsed = 0; while (m_io_group.control_base().in() & 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 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() & (1 << 4)) | (head | (1 << 5) | (1 << 6))); m_io_group.io_base().offset(ATA_REG_HDDEVSEL).out(driver_register); - IO::delay(50); + microseconds_delay(50); if (lba_mode == LBAMode::FortyEightBit) { m_io_group.io_base().offset(ATA_REG_SECCOUNT1).out((task_file.count >> 8) & 0xFF); @@ -272,7 +273,7 @@ ErrorOr IDEChannel::load_taskfile_into_registers(ATAPort::TaskFile const& auto status = m_io_group.control_base().in(); 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(task_file.command); @@ -284,9 +285,9 @@ ErrorOr 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(0xA0 | ((device_index) << 4)); - IO::delay(20); + microseconds_delay(20); return {}; } diff --git a/Kernel/Storage/NVMe/NVMeController.cpp b/Kernel/Storage/NVMe/NVMeController.cpp index 95d2c434da..dab462ddb7 100644 --- a/Kernel/Storage/NVMe/NVMeController.cpp +++ b/Kernel/Storage/NVMe/NVMeController.cpp @@ -7,9 +7,8 @@ #include #include +#include #include -#include -#include #include #include #include @@ -77,7 +76,7 @@ bool NVMeController::wait_for_ready(bool expected_ready_bit_value) u32 expected_rdy = expected_ready_bit_value ? 1 : 0; while (((m_controller_regs->csts >> CSTS_RDY_BIT) & 0x1) != expected_rdy) { - IO::delay(one_ms_io_delay); + microseconds_delay(one_ms_io_delay); if (--wait_iterations == 0) { if (((m_controller_regs->csts >> CSTS_RDY_BIT) & 0x1) != expected_rdy) { diff --git a/Kernel/Storage/NVMe/NVMePollQueue.cpp b/Kernel/Storage/NVMe/NVMePollQueue.cpp index 086c042a51..91664a4640 100644 --- a/Kernel/Storage/NVMe/NVMePollQueue.cpp +++ b/Kernel/Storage/NVMe/NVMePollQueue.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include #include @@ -20,7 +20,7 @@ void NVMePollQueue::submit_sqe(NVMeSubmission& sub) NVMeQueue::submit_sqe(sub); SpinlockLocker lock_cq(m_cq_lock); while (!process_cq()) { - IO::delay(1); + microseconds_delay(1); } } diff --git a/Kernel/Storage/NVMe/NVMeQueue.cpp b/Kernel/Storage/NVMe/NVMeQueue.cpp index 46cd951ab7..09ae9f767d 100644 --- a/Kernel/Storage/NVMe/NVMeQueue.cpp +++ b/Kernel/Storage/NVMe/NVMeQueue.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include #include @@ -126,7 +126,7 @@ u16 NVMeQueue::submit_sync_sqe(NVMeSubmission& sub) index = m_qdepth - 1; } cqe_cid = m_cqe_array[index].command_id; - IO::delay(1); + microseconds_delay(1); } while (cid != cqe_cid); auto status = CQ_STATUS_FIELD(m_cqe_array[m_cq_head].status); diff --git a/Kernel/TTY/VirtualConsole.cpp b/Kernel/TTY/VirtualConsole.cpp index 707a1814ad..cc20a57584 100644 --- a/Kernel/TTY/VirtualConsole.cpp +++ b/Kernel/TTY/VirtualConsole.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -327,7 +328,7 @@ void VirtualConsole::beep() if (!kernel_command_line().is_pc_speaker_enabled()) return; PCSpeaker::tone_on(440); - IO::delay(10000); + microseconds_delay(10000); PCSpeaker::tone_off(); }