mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
Kernel/USB: Prevent system crash via correct UHCI inititilisation
It seems that not setting the framelist address register was causing the entire system to lock up as it generated an insane interrupt storm in the IRQ handler for the UHCI controller. We now allocate a 4KiB aligned page via `MemoryManager::allocate_supervisor_physical_page()` and set every value to 1. In effect, this creates a framelist with each entry being a "TERMINATE" entry in which the controller stalls until its' 1mS time slice is up. Some more registers have also been set for consistency, though it seems like this don't need to be set explicitly in software.
This commit is contained in:
parent
33d73c600c
commit
375d269b21
Notes:
sideshowbarker
2024-07-19 00:00:59 +09:00
Author: https://github.com/Quaker762 Commit: https://github.com/SerenityOS/serenity/commit/375d269b213 Pull-request: https://github.com/SerenityOS/serenity/pull/4019 Reviewed-by: https://github.com/Lubrsi Reviewed-by: https://github.com/awesomekling
2 changed files with 20 additions and 1 deletions
|
@ -25,8 +25,10 @@
|
|||
*/
|
||||
|
||||
#include <Kernel/Devices/USB/UHCIController.h>
|
||||
#include <Kernel/StdLib.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
|
||||
#define UHCI_ENABLED 0
|
||||
#define UHCI_ENABLED 1
|
||||
|
||||
namespace Kernel::USB {
|
||||
|
||||
|
@ -46,6 +48,11 @@ static constexpr u16 UHCI_USBSTS_RESUME_RECEIVED = 0x0004;
|
|||
static constexpr u16 UHCI_USBSTS_USB_ERROR_INTERRUPT = 0x0002;
|
||||
static constexpr u16 UHCI_USBSTS_USB_INTERRUPT = 0x0001;
|
||||
|
||||
static constexpr u8 UHCI_USBINTR_TIMEOUT_CRC_ENABLE = 0x01;
|
||||
static constexpr u8 UHCI_USBINTR_RESUME_INTR_ENABLE = 0x02;
|
||||
static constexpr u8 UHCI_USBINTR_IOC_ENABLE = 0x04;
|
||||
static constexpr u8 UHCI_USBINTR_SHORT_PACKET_INTR_ENABLE = 0x08;
|
||||
|
||||
void UHCIController::detect()
|
||||
{
|
||||
#if !UHCI_ENABLED
|
||||
|
@ -90,6 +97,17 @@ void UHCIController::reset()
|
|||
break;
|
||||
}
|
||||
|
||||
// Let's allocate the physical page for the Frame List (which is 4KiB aligned)
|
||||
m_framelist = MemoryManager::the().allocate_supervisor_physical_page()->paddr();
|
||||
klog() << "UHCI: Allocated framelist at physical address " << m_framelist;
|
||||
memset(reinterpret_cast<u32*>(low_physical_to_virtual(m_framelist.as_ptr())), 1, 1024); // All frames are TERMINATE frames
|
||||
|
||||
write_sofmod(64); // 1mS frame time
|
||||
write_flbaseadd(m_framelist.get()); // Frame list (physical) address
|
||||
write_frnum(0); // Set the initial frame number
|
||||
|
||||
// Enable all interrupt types
|
||||
write_frnum(UHCI_USBINTR_TIMEOUT_CRC_ENABLE | UHCI_USBINTR_RESUME_INTR_ENABLE | UHCI_USBINTR_IOC_ENABLE | UHCI_USBINTR_SHORT_PACKET_INTR_ENABLE);
|
||||
klog() << "UHCI: Reset completed!";
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ private:
|
|||
virtual void handle_irq(const RegisterState&) override;
|
||||
|
||||
IOAddress m_io_base;
|
||||
PhysicalAddress m_framelist;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue