Compare commits

..

No commits in common. "d0452a35103d14fa0e2b74e2104cb06561e492d3" and "b30a79c7fe3b33103256063dcff479b84c17ced8" have entirely different histories.

26 changed files with 244 additions and 1060 deletions

View File

@ -306,8 +306,20 @@ memset32:
movw $GDT_DATA32, %dx
movw %dx, %es
movl %ecx, %edx
andl $3, %ecx
rep stosb %es:(%edi)
movl %edx, %ecx
shrl $2, %ecx
movb %al, %ah
movw %ax, %dx
shll $16, %eax
movw %dx, %ax
rep stosl %es:(%edi)
ljmpl $GDT_CODE16, $.memset32_pmode16
.code16
@ -358,8 +370,14 @@ memcpy32:
movw %dx, %ds
movw %dx, %es
movl %ecx, %edx
andl $3, %ecx
rep movsb %ds:(%esi), %es:(%edi)
movl %edx, %ecx
shrl $2, %ecx
rep movsl %ds:(%esi), %es:(%edi)
ljmpl $GDT_CODE16, $.memcpy32_pmode16
.code16

View File

@ -96,12 +96,10 @@ set(KERNEL_SOURCES
kernel/Timer/PIT.cpp
kernel/Timer/RTC.cpp
kernel/Timer/Timer.cpp
kernel/USB/Controller.cpp
kernel/USB/Device.cpp
kernel/USB/HID/HIDDriver.cpp
kernel/USB/HID/Keyboard.cpp
kernel/USB/HID/Mouse.cpp
kernel/USB/Hub/HubDriver.cpp
kernel/USB/MassStorage/MassStorageDriver.cpp
kernel/USB/MassStorage/SCSIDevice.cpp
kernel/USB/USBManager.cpp

View File

@ -65,7 +65,6 @@
#define DEBUG_XHCI 0
#define DEBUG_USB 0
#define DEBUG_USB_HID 0
#define DEBUG_USB_HUB 0
#define DEBUG_USB_KEYBOARD 0
#define DEBUG_USB_MOUSE 0
#define DEBUG_USB_MASS_STORAGE 0

View File

@ -28,7 +28,7 @@ namespace Kernel
virtual BAN::ErrorOr<void> fsync_impl() final override { return BAN::Error::from_errno(EINVAL); }
};
class BlockDevice : public Device, public BAN::Weakable<BlockDevice>
class BlockDevice : public Device
{
public:
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) = 0;

View File

@ -97,8 +97,6 @@ namespace Kernel::PCI
BAN::ErrorOr<void> reserve_interrupts(uint8_t count);
void enable_interrupt(uint8_t index, Interruptable&);
InterruptMechanism interrupt_mechanism() const { return m_interrupt_mechanism; }
BAN::ErrorOr<BAN::UniqPtr<BarRegion>> allocate_bar_region(uint8_t bar_num);
void enable_bus_mastering();

View File

@ -13,8 +13,9 @@ namespace Kernel
const BAN::GUID& partition_type() const { return m_type; }
const BAN::GUID& partition_guid() const { return m_guid; }
const BAN::RefPtr<BlockDevice> device() const { return m_device; }
virtual blksize_t blksize() const override { return m_block_size; }
virtual blksize_t blksize() const override { return m_device->blksize(); }
BAN::ErrorOr<void> read_sectors(uint64_t first_block, size_t block_count, BAN::ByteSpan buffer) { return read_blocks(first_block, block_count, buffer); }
BAN::ErrorOr<void> write_sectors(uint64_t first_block, size_t block_count, BAN::ConstByteSpan buffer) { return write_blocks(first_block, block_count, buffer); }
@ -31,8 +32,7 @@ namespace Kernel
Partition(BAN::RefPtr<BlockDevice>, const BAN::GUID&, const BAN::GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t, BAN::StringView);
private:
mutable BAN::WeakPtr<BlockDevice> m_device;
const uint64_t m_block_size;
BAN::RefPtr<BlockDevice> m_device;
const BAN::GUID m_type;
const BAN::GUID m_guid;
const BAN::String m_guid_string;

View File

@ -2,7 +2,6 @@
#include <BAN/CircularQueue.h>
#include <BAN/Errors.h>
#include <BAN/Optional.h>
#include <kernel/Interruptable.h>
#include <kernel/Terminal/TTY.h>
@ -14,12 +13,12 @@ namespace Kernel
public:
static void initialize();
static bool has_devices();
static void putchar_any(uint8_t);
static void putchar_any(char);
static void initialize_devices();
void putchar(uint8_t);
BAN::Optional<uint8_t> getchar();
void putchar(char);
char getchar();
bool is_valid() const { return m_port != 0; }

View File

@ -30,7 +30,7 @@ namespace Kernel
void reset_ansi();
void handle_ansi_csi(uint8_t ch);
void handle_ansi_csi_color(uint8_t ch);
void handle_ansi_csi_color();
void putchar_at(uint32_t codepoint, uint32_t x, uint32_t y);
void render_from_buffer(uint32_t x, uint32_t y);
void set_cursor_position(uint32_t x, uint32_t y);

View File

@ -1,26 +1,10 @@
#pragma once
#include <BAN/Array.h>
#include <kernel/Lock/SpinLock.h>
namespace Kernel
{
class USBController
{
// NOTE: Tier 0 == Root Hub
public:
USBController();
uint8_t current_hub_init_tier() const;
void register_hub_to_init(uint8_t tier);
void mark_hub_init_done(uint8_t tier);
private:
mutable SpinLock m_hub_init_lock;
uint8_t m_current_hub_init_tier { 0 };
BAN::Array<uint32_t, 7> m_hubs_to_init_per_tier;
};
}

View File

@ -4,8 +4,8 @@
#include <BAN/NoCopyMove.h>
#include <kernel/Memory/DMARegion.h>
#include <kernel/USB/Controller.h>
#include <kernel/USB/USBManager.h>
#include <kernel/USB/Controller.h>
namespace Kernel
{
@ -55,41 +55,21 @@ namespace Kernel
BAN::Vector<ConfigurationDescriptor> configurations;
};
struct HubInfo
{
uint8_t number_of_ports;
bool multi_tt;
uint8_t tt_think_time;
};
public:
USBDevice(USBController& controller, USB::SpeedClass speed_class, uint8_t depth)
: m_controller(controller)
, m_speed_class(speed_class)
, m_depth(depth)
USBDevice(USB::SpeedClass speed_class)
: m_speed_class(speed_class)
{}
virtual ~USBDevice() = default;
// Class drivers have to be destroyed before derived class destructor is called
void destroy() { m_class_drivers.clear(); }
BAN::ErrorOr<void> initialize();
const BAN::Vector<ConfigurationDescriptor>& configurations() { return m_descriptor.configurations; }
virtual BAN::ErrorOr<uint8_t> initialize_device_on_hub_port(uint8_t port_id, USB::SpeedClass) = 0;
virtual void deinitialize_device_slot(uint8_t slot_id) = 0;
virtual BAN::ErrorOr<void> configure_endpoint(const USBEndpointDescriptor&, const HubInfo& = {}) = 0;
virtual BAN::ErrorOr<void> initialize_endpoint(const USBEndpointDescriptor&) = 0;
virtual BAN::ErrorOr<size_t> send_request(const USBDeviceRequest&, paddr_t buffer) = 0;
virtual void send_data_buffer(uint8_t endpoint_id, paddr_t buffer, size_t buffer_len) = 0;
USB::SpeedClass speed_class() const { return m_speed_class; }
uint8_t depth() const { return m_depth; }
bool can_start_hub_init() const { return m_controller.current_hub_init_tier() >= m_depth + 1; }
void register_hub_to_init() { m_controller.register_hub_to_init(m_depth + 1); };
void mark_hub_init_done() { m_controller.mark_hub_init_done(m_depth + 1); };
static USB::SpeedClass determine_speed_class(uint64_t bits_per_second);
protected:
void handle_stall(uint8_t endpoint_id);
@ -99,12 +79,8 @@ namespace Kernel
private:
BAN::ErrorOr<ConfigurationDescriptor> parse_configuration(size_t index);
private:
USBController& m_controller;
protected:
const USB::SpeedClass m_speed_class;
const uint8_t m_depth;
private:
DeviceDescriptor m_descriptor;

View File

@ -1,95 +0,0 @@
#pragma once
#include <stdint.h>
namespace Kernel::USBHub
{
struct HubDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bNbrPorts;
uint16_t wHubCharacteristics;
uint8_t bPowerOnGood;
uint8_t bHubContrCurrent;
uint8_t bitmaps[];
} __attribute__((packed));
static_assert(sizeof(HubDescriptor) == 7);
struct PortStatus
{
union
{
uint16_t raw;
struct {
uint16_t connection : 1; // bit 0
uint16_t enable : 1; // bit 1
uint16_t : 1;
uint16_t over_current : 1; // bit 3
uint16_t reset : 1; // bit 4
};
struct {
uint16_t : 2;
uint16_t suspend : 1; // bit 2
uint16_t : 5;
uint16_t power : 1; // bit 8
uint16_t low_speed : 1; // bit 9
uint16_t high_speed : 1; // bit 10
} usb2;
struct {
uint16_t : 5;
uint16_t link_state : 4; // bit 5-8
uint16_t power : 1; // bit 9
uint16_t speed : 3; // bit 10-12
} usb3;
} wPortStatus;
union
{
uint16_t raw;
struct {
uint16_t connection : 1; // bit 0
uint16_t : 2;
uint16_t over_current : 1; // bit 3
uint16_t reset : 1; // bit 4
};
struct {
uint16_t : 1;
uint16_t enable : 1; // bit 1
uint16_t suspend : 1; // bit 2
} usb2;
struct {
uint16_t : 5;
uint16_t bh_reset : 1; // bit 5
uint16_t link_state : 1; // bit 6
uint16_t config_error : 1; // bit 7
} usb3;
} wPortChanged;
};
static_assert(sizeof(PortStatus) == 4);
enum HubSelector
{
C_HUB_LOCAL_POWER = 0,
C_HUB_OVER_CURRENT = 1,
PORT_CONNECTION = 0,
PORT_ENABLE = 1,
PORT_SUSPEND = 2,
PORT_OVER_CURRENT = 3,
PORT_RESET = 4,
PORT_LINK_STATE = 5,
PORT_POWER = 8,
PORT_LOW_SPEED = 9,
C_PORT_CONNECTION = 16,
C_PORT_ENABLE = 17,
C_PORT_SUSPEND = 18,
C_PORT_OVER_CURRENT = 19,
C_PORT_RESET = 20,
PORT_TEST = 21,
PORT_INDICATOR = 22,
C_PORT_LINK_STATE = 25,
C_PORT_CONFIG_ERROR = 26,
C_BH_PORT_RESET = 29,
};
}

View File

@ -1,57 +0,0 @@
#pragma once
#include <kernel/Process.h>
#include <kernel/USB/Device.h>
namespace Kernel
{
class USBHubDriver final : public USBClassDriver
{
public:
BAN::ErrorOr<void> initialize() override;
void handle_stall(uint8_t endpoint_id) override;
void handle_input_data(size_t byte_count, uint8_t endpoint_id) override;
private:
USBHubDriver(USBDevice&, const USBDevice::DeviceDescriptor&);
~USBHubDriver();
void port_updater_task();
BAN::ErrorOr<void> clear_port_feature(uint8_t port, uint8_t feature);
BAN::ErrorOr<void> set_port_feature(uint8_t port, uint8_t feature);
private:
USBDevice& m_device;
const USBDevice::DeviceDescriptor& m_descriptor;
BAN::UniqPtr<DMARegion> m_data_region;
uint8_t m_endpoint_id { 0 };
uint8_t m_port_count { 0 };
BAN::Atomic<uint32_t> m_changed_ports { 0 };
ThreadBlocker m_changed_port_blocker;
BAN::Atomic<Process*> m_port_updater { nullptr };
struct PortInfo
{
uint8_t slot { 0 };
bool failed { false };
};
BAN::Vector<PortInfo> m_ports;
BAN::Atomic<bool> m_running { true };
bool m_is_usb2 { false };
bool m_is_usb3 { false };
bool m_is_multi_tt { false };
bool m_is_init_done { false };
friend class BAN::UniqPtr<USBHubDriver>;
};
}

View File

@ -5,7 +5,6 @@
#include <kernel/Lock/Mutex.h>
#include <kernel/Memory/DMARegion.h>
#include <kernel/ThreadBlocker.h>
#include <kernel/USB/Definitions.h>
#include <kernel/USB/USBManager.h>
#include <kernel/USB/XHCI/Definitions.h>
@ -24,7 +23,19 @@ namespace Kernel
{
uint8_t revision_major { 0 };
uint8_t revision_minor { 0 };
uint8_t slot_type { 0 };
uint8_t slot_id { 0 };
uint64_t speed_id_to_speed[0x10] {
0,
12'000'000,
1'500'000,
480'000'000,
5'000'000'000,
10'000'000'000,
5'000'000'000,
10'000'000'000,
};
};
public:
@ -46,8 +57,7 @@ namespace Kernel
void port_updater_task();
BAN::ErrorOr<uint8_t> initialize_device(uint32_t route_string, uint8_t depth, USB::SpeedClass speed_class, XHCIDevice* parent_hub, uint8_t parent_port_id);
void deinitialize_slot(uint8_t slot_id);
BAN::ErrorOr<void> initialize_slot(int port_index);
BAN::ErrorOr<XHCI::TRB> send_command(const XHCI::TRB&);
void advance_command_enqueue();
@ -64,22 +74,16 @@ namespace Kernel
const volatile XHCI::TRB& current_event_trb();
uint8_t speed_class_to_id(USB::SpeedClass speed_class) const;
USB::SpeedClass speed_id_to_class(uint8_t) const;
private:
static constexpr uint32_t m_command_ring_trb_count = 256;
static constexpr uint32_t m_event_ring_trb_count = 252;
Mutex m_mutex;
BAN::Atomic<Process*> m_port_updater { nullptr };
Process* m_port_updater { nullptr };
ThreadBlocker m_port_thread_blocker;
BAN::Atomic<bool> m_port_changed { false };
bool m_running { true };
bool m_ports_initialized { false };
PCI::Device& m_pci_device;
BAN::UniqPtr<PCI::BarRegion> m_configuration_bar;
BAN::UniqPtr<DMARegion> m_dcbaa_region;

View File

@ -30,23 +30,10 @@ namespace Kernel
void(XHCIDevice::*callback)(XHCI::TRB);
};
struct Info
{
XHCIDevice* parent_hub;
uint8_t parent_port_id;
USB::SpeedClass speed_class;
uint8_t slot_id;
uint32_t route_string;
uint8_t depth;
};
public:
static BAN::ErrorOr<BAN::UniqPtr<XHCIDevice>> create(XHCIController&, const Info& info);
static BAN::ErrorOr<BAN::UniqPtr<XHCIDevice>> create(XHCIController&, uint32_t port_id, uint32_t slot_id);
BAN::ErrorOr<uint8_t> initialize_device_on_hub_port(uint8_t port_id, USB::SpeedClass) override;
void deinitialize_device_slot(uint8_t slot_id) override;
BAN::ErrorOr<void> configure_endpoint(const USBEndpointDescriptor&, const HubInfo&) override;
BAN::ErrorOr<void> initialize_endpoint(const USBEndpointDescriptor&) override;
BAN::ErrorOr<size_t> send_request(const USBDeviceRequest&, paddr_t buffer) override;
void send_data_buffer(uint8_t endpoint_id, paddr_t buffer, size_t buffer_size) override;
@ -56,22 +43,22 @@ namespace Kernel
BAN::ErrorOr<void> initialize_control_endpoint() override;
private:
XHCIDevice(XHCIController& controller, const Info& info);
XHCIDevice(XHCIController& controller, uint32_t port_id, uint32_t slot_id);
~XHCIDevice();
BAN::ErrorOr<void> update_actual_max_packet_size();
bool is_multi_tt() const;
void on_interrupt_or_bulk_endpoint_event(XHCI::TRB);
void advance_endpoint_enqueue(Endpoint&, bool chain);
static uint64_t calculate_port_bits_per_second(XHCIController&, uint32_t port_id);
private:
static constexpr uint32_t m_transfer_ring_trb_count = PAGE_SIZE / sizeof(XHCI::TRB);
XHCIController& m_controller;
Info m_info;
const uint32_t m_port_id;
const uint32_t m_slot_id;
Mutex m_mutex;

View File

@ -16,7 +16,6 @@ namespace Kernel
Partition::Partition(BAN::RefPtr<BlockDevice> device, const BAN::GUID& type, const BAN::GUID& guid, uint64_t first_block, uint64_t last_block, uint64_t attr, const char* label, uint32_t index, BAN::StringView name_prefix)
: BlockDevice(0660, 0, 0)
, m_device(device)
, m_block_size(device->blksize())
, m_type(type)
, m_guid(guid)
, m_guid_string(MUST(guid.to_string()))
@ -31,42 +30,30 @@ namespace Kernel
BAN::ErrorOr<void> Partition::read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan buffer)
{
auto device = m_device.lock();
if (!device)
return BAN::Error::from_errno(ENODEV);
ASSERT(buffer.size() >= block_count * device->blksize());
ASSERT(buffer.size() >= block_count * m_device->blksize());
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
if (first_block + block_count > blocks_in_partition)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
TRY(device->read_blocks(m_first_block + first_block, block_count, buffer));
TRY(m_device->read_blocks(m_first_block + first_block, block_count, buffer));
return {};
}
BAN::ErrorOr<void> Partition::write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan buffer)
{
auto device = m_device.lock();
if (!device)
return BAN::Error::from_errno(ENODEV);
ASSERT(buffer.size() >= block_count * device->blksize());
ASSERT(buffer.size() >= block_count * m_device->blksize());
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
if (first_block + block_count > blocks_in_partition)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
TRY(device->write_blocks(m_first_block + first_block, block_count, buffer));
TRY(m_device->write_blocks(m_first_block + first_block, block_count, buffer));
return {};
}
BAN::ErrorOr<void> Partition::sync_blocks(uint64_t block, size_t block_count)
{
auto device = m_device.lock();
if (!device)
return BAN::Error::from_errno(ENODEV);
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
if (block + block_count > blocks_in_partition)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
TRY(device->sync_blocks(m_first_block + block, block_count));
TRY(m_device->sync_blocks(m_first_block + block, block_count));
return {};
}
@ -74,16 +61,12 @@ namespace Kernel
{
ASSERT(offset >= 0);
auto device = m_device.lock();
if (!device)
return BAN::Error::from_errno(ENODEV);
if (offset % device->blksize() || buffer.size() % device->blksize())
if (offset % m_device->blksize() || buffer.size() % m_device->blksize())
return BAN::Error::from_errno(ENOTSUP);
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
uint32_t first_block = offset / device->blksize();
uint32_t block_count = buffer.size() / device->blksize();
uint32_t first_block = offset / m_device->blksize();
uint32_t block_count = buffer.size() / m_device->blksize();
if (first_block >= blocks_in_partition)
return 0;
@ -91,7 +74,7 @@ namespace Kernel
block_count = blocks_in_partition - first_block;
TRY(read_blocks(first_block, block_count, buffer));
return block_count * device->blksize();
return block_count * m_device->blksize();
}
}

View File

@ -204,9 +204,6 @@ namespace Kernel
StorageDevice::~StorageDevice()
{
for (auto& partition : m_partitions)
if (partition)
DevFileSystem::get().remove_device(partition);
}
void StorageDevice::add_disk_cache()

View File

@ -107,38 +107,41 @@ namespace Kernel
while (*ptr)
putchar(*ptr++);
if (auto ch = getchar(); !ch.has_value() || ch.value() != '\033')
if (getchar() != '\033')
return false;
if (auto ch = getchar(); !ch.has_value() || ch.value() != '[')
if (getchar() != '[')
return false;
auto read_number =
[&](uint8_t end) -> BAN::Optional<uint32_t>
[&](char end)
{
uint32_t number = 0;
while (true)
{
const auto ch = getchar();
if (!ch.has_value())
return {};
if (ch.value() == end)
return number;
if (!isdigit(ch.value()))
return {};
number = (number * 10) + (ch.value() - '0');
char c = getchar();
if (c == end)
break;
if (!isdigit(c))
return UINT32_MAX;
number = (number * 10) + (c - '0');
}
return number;
};
const auto height = read_number(';');
if (!height.has_value())
m_height = read_number(';');
if (m_height == UINT32_MAX)
{
m_port = 0;
return false;
}
const auto width = read_number('R');
if (!width.has_value())
m_width = read_number('R');
if (m_width == UINT32_MAX)
{
m_port = 0;
return false;
}
m_height = height.value();
m_width = width.value();
return true;
}
@ -147,26 +150,25 @@ namespace Kernel
return s_has_devices;
}
void Serial::putchar(uint8_t ch)
void Serial::putchar(char c)
{
while (!(IO::inb(m_port + 5) & 0x20))
continue;
IO::outb(m_port, ch);
IO::outb(m_port, c);
}
BAN::Optional<uint8_t> Serial::getchar()
char Serial::getchar()
{
for (size_t i = 0; i < 10'000'000; i++)
if (IO::inb(m_port + 5) & 0x01)
return IO::inb(m_port);
return {};
while (!(IO::inb(m_port + 5) & 0x01))
continue;
return IO::inb(m_port);
}
void Serial::putchar_any(uint8_t ch)
void Serial::putchar_any(char c)
{
for (auto& device : s_serial_drivers)
if (device.is_valid())
return device.putchar(ch);
device.putchar(c);
}
SerialTTY::SerialTTY(Serial serial)

View File

@ -110,11 +110,12 @@ namespace Kernel
m_state = State::Normal;
}
void VirtualTTY::handle_ansi_csi_color(uint8_t ch)
void VirtualTTY::handle_ansi_csi_color()
{
ASSERT(m_write_lock.current_processor_has_lock());
switch (ch)
switch (m_ansi_state.nums[0])
{
case -1:
case 0:
m_foreground = TerminalColor::BRIGHT_WHITE;
m_background = TerminalColor::BLACK;
@ -164,25 +165,18 @@ namespace Kernel
void VirtualTTY::handle_ansi_csi(uint8_t ch)
{
constexpr size_t max_ansi_args = sizeof(m_ansi_state.nums) / sizeof(*m_ansi_state.nums);
ASSERT(m_write_lock.current_processor_has_lock());
switch (ch)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
if ((size_t)m_ansi_state.index >= max_ansi_args)
dwarnln("Only {} arguments supported with ANSI codes", max_ansi_args);
else
{
int32_t& val = m_ansi_state.nums[m_ansi_state.index];
val = (val == -1) ? (ch - '0') : (val * 10 + ch - '0');
}
int32_t& val = m_ansi_state.nums[m_ansi_state.index];
val = (val == -1) ? (ch - '0') : (val * 10 + ch - '0');
return;
}
case ';':
m_ansi_state.index = BAN::Math::min<size_t>(m_ansi_state.index + 1, max_ansi_args);
m_ansi_state.index++;
return;
case 'A': // Cursor Up
if (m_ansi_state.nums[0] == -1)
@ -314,9 +308,7 @@ namespace Kernel
dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character f");
return;
case 'm':
handle_ansi_csi_color(BAN::Math::max(m_ansi_state.nums[0], 0));
for (int i = 1; i < m_ansi_state.index; i++)
handle_ansi_csi_color(BAN::Math::max(m_ansi_state.nums[i], 0));
handle_ansi_csi_color();
return reset_ansi();
case 's':
m_saved_row = m_row;

View File

@ -1,40 +0,0 @@
#include <kernel/USB/Controller.h>
namespace Kernel
{
USBController::USBController()
{
for (auto& count : m_hubs_to_init_per_tier)
count = 0;
m_hubs_to_init_per_tier[0] = 1;
}
uint8_t USBController::current_hub_init_tier() const
{
SpinLockGuard _(m_hub_init_lock);
return m_current_hub_init_tier;
}
void USBController::register_hub_to_init(uint8_t tier)
{
ASSERT(tier >= 1);
ASSERT(tier <= m_hubs_to_init_per_tier.size());
SpinLockGuard _(m_hub_init_lock);
m_hubs_to_init_per_tier[tier]++;
if (tier < m_current_hub_init_tier)
m_current_hub_init_tier = tier;
}
void USBController::mark_hub_init_done(uint8_t tier)
{
ASSERT(tier < m_hubs_to_init_per_tier.size());
SpinLockGuard _(m_hub_init_lock);
m_hubs_to_init_per_tier[tier]--;
if (tier == m_current_hub_init_tier && m_hubs_to_init_per_tier[tier] == 0)
m_current_hub_init_tier++;
}
}

View File

@ -1,7 +1,6 @@
#include <kernel/Memory/DMARegion.h>
#include <kernel/USB/Device.h>
#include <kernel/USB/HID/HIDDriver.h>
#include <kernel/USB/Hub/HubDriver.h>
#include <kernel/USB/MassStorage/MassStorageDriver.h>
#define USB_DUMP_DESCRIPTORS 0
@ -108,26 +107,8 @@ namespace Kernel
dprintln_if(DEBUG_USB, "Found CommunicationAndCDCControl device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::Hub:
{
if (auto ret = BAN::UniqPtr<USBHubDriver>::create(*this, m_descriptor); !ret.is_error())
TRY(m_class_drivers.push_back(ret.release_value()));
else
{
dwarnln("Failed to create USB Hub: {}", ret.error());
return ret.release_error();
}
if (auto ret = m_class_drivers[0]->initialize(); ret.is_error())
{
dwarnln("Failed to initialize USB Hub: {}", ret.error());
m_class_drivers.clear();
return ret.release_error();
}
dprintln_if(DEBUG_USB, "Successfully initialized USB hub");
return {};
}
dprintln_if(DEBUG_USB, "Found Hub device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::BillboardDeviceClass:
dprintln_if(DEBUG_USB, "Found BillboardDeviceClass device");
return BAN::Error::from_errno(ENOTSUP);
@ -165,10 +146,6 @@ namespace Kernel
for (const auto& interface : configuration.interfaces)
{
// FIXME: support alternate settings
if (interface.descriptor.bAlternateSetting != 0)
continue;
switch (static_cast<USB::InterfaceBaseClass>(interface.descriptor.bInterfaceClass))
{
case USB::InterfaceBaseClass::Audio:
@ -363,4 +340,15 @@ namespace Kernel
driver->handle_input_data(byte_count, endpoint_id);
}
USB::SpeedClass USBDevice::determine_speed_class(uint64_t bits_per_second)
{
if (bits_per_second <= 1'500'000)
return USB::SpeedClass::LowSpeed;
if (bits_per_second <= 12'000'000)
return USB::SpeedClass::FullSpeed;
else if (bits_per_second <= 480'000'000)
return USB::SpeedClass::HighSpeed;
return USB::SpeedClass::SuperSpeed;
}
}

View File

@ -194,7 +194,7 @@ namespace Kernel
if ((desc.bmAttributes & 0x03) != 0x03)
continue;
TRY(m_device.configure_endpoint(desc));
TRY(m_device.initialize_endpoint(desc));
m_data_buffer = TRY(DMARegion::create(desc.wMaxPacketSize & 0x07FF));
m_data_endpoint_id = (desc.bEndpointAddress & 0x0F) * 2 + !!(desc.bEndpointAddress & 0x80);

View File

@ -1,451 +0,0 @@
#include <BAN/ScopeGuard.h>
#include <kernel/USB/Hub/Definitions.h>
#include <kernel/USB/Hub/HubDriver.h>
#include <kernel/Timer/Timer.h>
namespace Kernel
{
USBHubDriver::USBHubDriver(USBDevice& device, const USBDevice::DeviceDescriptor& desciptor)
: m_device(device)
, m_descriptor(desciptor)
{}
USBHubDriver::~USBHubDriver()
{
m_running = false;
m_changed_port_blocker.unblock();
while (m_port_updater)
continue;
for (const auto info : m_ports)
{
if (info.slot == 0)
continue;
m_device.deinitialize_device_slot(info.slot);
}
}
BAN::ErrorOr<void> USBHubDriver::initialize()
{
#if DEBUG_USB_HUB
switch (m_device.speed_class())
{
case USB::SpeedClass::LowSpeed:
dprintln("configuring low speed hub");
break;
case USB::SpeedClass::FullSpeed:
dprintln("configuring full speed hub");
break;
case USB::SpeedClass::HighSpeed:
dprintln("configuring high speed hub");
break;
case USB::SpeedClass::SuperSpeed:
dprintln("configuring super speed hub");
break;
}
#endif
m_data_region = TRY(DMARegion::create(PAGE_SIZE));
if (m_descriptor.configurations.empty())
{
dwarnln("USB hub does not have any configurations");
return BAN::Error::from_errno(EFAULT);
}
const auto& configuration = m_descriptor.configurations[0];
{
dprintln_if(DEBUG_USB_HUB, "setting configuration");
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Standard | USB::RequestType::Device;
request.bRequest = USB::SET_CONFIGURATION;
request.wValue = configuration.desciptor.bConfigurationValue;
request.wIndex = 0;
request.wLength = 0;
TRY(m_device.send_request(request, 0));
dprintln_if(DEBUG_USB_HUB, " -> done");
}
if (configuration.interfaces.empty())
{
dwarnln("USB hub does not have any interfaces");
return BAN::Error::from_errno(EFAULT);
}
const auto* interface = &configuration.interfaces[0];
// High speed hubs may have alternate multi tt interface
if (m_device.speed_class() == USB::SpeedClass::HighSpeed)
{
for (size_t i = 0; i < configuration.interfaces.size(); i++)
{
if (configuration.interfaces[i].descriptor.bInterfaceProtocol != 2)
continue;
interface = &configuration.interfaces[i];
break;
}
if (interface->descriptor.bAlternateSetting != 0)
{
dprintln_if(DEBUG_USB_HUB, "enabling multi tt interface");
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Standard | USB::RequestType::Interface;
request.bRequest = USB::SET_INTERFACE;
request.wValue = interface->descriptor.bAlternateSetting;
request.wIndex = interface->descriptor.iInterface;
request.wLength = 0;
TRY(m_device.send_request(request, 0));
dprintln_if(DEBUG_USB_HUB, " -> done");
}
m_is_multi_tt = (interface->descriptor.bInterfaceProtocol == 2);
}
if (interface->endpoints.size() != 1)
{
dwarnln("USB hub has {} endpoints", interface->endpoints.size());
return BAN::Error::from_errno(EFAULT);
}
const auto& endpoint = interface->endpoints[0];
m_is_usb3 = (m_device.speed_class() == USB::SpeedClass::SuperSpeed);
m_is_usb2 = !m_is_usb3;
ASSERT(m_is_usb2 ^ m_is_usb3);
// Set multi tt to false until we know tt think time
dprintln_if(DEBUG_USB_HUB, "configuring endpoint with 4 ports");
TRY(m_device.configure_endpoint(endpoint.descriptor, {
.number_of_ports = m_port_count,
.multi_tt = false,
.tt_think_time = 0
}));
dprintln_if(DEBUG_USB_HUB, " -> done");
// USB 3 devices use route_string and hub depth for routing packets
if (m_is_usb3)
{
dprintln_if(DEBUG_USB_HUB, "setting hub depth");
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Device;
request.bRequest = 12; // SET_HUB_DEPTH
request.wValue = m_device.depth();
request.wIndex = 0;
request.wLength = 0;
TRY(m_device.send_request(request, 0));
dprintln_if(DEBUG_USB_HUB, " -> done");
}
uint8_t tt_think_time = 0;
// Hub descriptor has to be requested after device is configured
{
dprintln_if(DEBUG_USB_HUB, "getting hub descriptor");
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Class | USB::RequestType::Device;
request.bRequest = USB::Request::GET_DESCRIPTOR;
request.wValue = m_is_usb3 ? 0x2A00 : 0x2900;
request.wIndex = 0;
request.wLength = 8;
if (TRY(m_device.send_request(request, m_data_region->paddr())) < 8)
{
dwarnln("USB hub did not respond with full hub descriptor");
return BAN::Error::from_errno(EFAULT);
}
dprintln_if(DEBUG_USB_HUB, " -> done");
const auto& hub_descriptor = *reinterpret_cast<USBHub::HubDescriptor*>(m_data_region->vaddr());
m_port_count = hub_descriptor.bNbrPorts;
if (m_device.speed_class() == USB::SpeedClass::HighSpeed)
tt_think_time = (hub_descriptor.wHubCharacteristics >> 5) & 0x03;
}
if (m_port_count > 31)
{
dwarnln("USB hubs only support up to 31 ports");
m_port_count = 31;
}
TRY(m_ports.resize(m_port_count));
dprintln_if(DEBUG_USB_HUB, "re-configuring endpoint with {} ports", m_port_count);
TRY(m_device.configure_endpoint(endpoint.descriptor, {
.number_of_ports = m_port_count,
.multi_tt = m_is_multi_tt,
.tt_think_time = tt_think_time
}));
dprintln_if(DEBUG_USB_HUB, " -> done");
m_endpoint_id = (endpoint.descriptor.bEndpointAddress & 0x0F) * 2 + !!(endpoint.descriptor.bEndpointAddress & 0x80);
m_device.send_data_buffer(m_endpoint_id, m_data_region->paddr() + sizeof(USBHub::PortStatus), m_port_count / 8 + 1);
// Reset all ports in powered off state
for (size_t port_id = 1; port_id <= m_port_count; port_id++)
{
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Class | USB::RequestType::Other;
request.bRequest = USB::Request::GET_STATUS;
request.wValue = 0;
request.wIndex = port_id;
request.wLength = sizeof(USBHub::PortStatus);
auto result = m_device.send_request(request, m_data_region->paddr());
if (result.is_error() || result.value() != sizeof(USBHub::PortStatus))
{
dwarnln("Failed to get port {} status");
continue;
}
const auto& port_status = *reinterpret_cast<volatile USBHub::PortStatus*>(m_data_region->vaddr());
const bool is_powered =
(m_is_usb3 && port_status.wPortStatus.usb3.power) ||
(m_is_usb2 && port_status.wPortStatus.usb2.power);
if (!is_powered)
if (auto ret = set_port_feature(port_id, USBHub::PORT_POWER); ret.is_error())
dwarnln("Failed to power on USB hub port {}: {}", port_id, ret.error());
dprintln_if(DEBUG_USB_HUB, "port {}, status {4H}, changed {4H}",
port_id,
*(uint16_t*)(m_data_region->vaddr() + 0),
*(uint16_t*)(m_data_region->vaddr() + 2)
);
m_changed_ports |= 1u << port_id;
}
m_port_updater = Process::create_kernel([](void* data) { reinterpret_cast<USBHubDriver*>(data)->port_updater_task(); }, this);
if (m_port_updater == nullptr)
return BAN::Error::from_errno(ENOMEM);
return {};
}
BAN::ErrorOr<void> USBHubDriver::clear_port_feature(uint8_t port, uint8_t feature)
{
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Other;
request.bRequest = USB::Request::CLEAR_FEATURE;
request.wValue = feature;
request.wIndex = port;
request.wLength = 0;
TRY(m_device.send_request(request, 0));
return {};
}
BAN::ErrorOr<void> USBHubDriver::set_port_feature(uint8_t port, uint8_t feature)
{
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Other;
request.bRequest = USB::Request::SET_FEATURE;
request.wValue = feature;
request.wIndex = port;
request.wLength = 0;
TRY(m_device.send_request(request, 0));
return {};
}
void USBHubDriver::port_updater_task()
{
m_device.register_hub_to_init();
while (m_running && !m_device.can_start_hub_init())
Processor::yield();
uint64_t last_port_update_ms = SystemTimer::get().ms_since_boot();
while (m_running)
{
uint8_t changed_port = 0xFF;
{
const auto temp = m_changed_ports.exchange(0);
if (temp == 0)
{
// If there has been no changed ports in 100ms, this hub has initialized its devices
if (!m_is_init_done && SystemTimer::get().ms_since_boot() - last_port_update_ms >= 100)
{
m_device.mark_hub_init_done();
m_is_init_done = true;
}
m_changed_port_blocker.block_with_timeout_ms(100);
continue;
}
last_port_update_ms = SystemTimer::get().ms_since_boot();
for (size_t i = 0; i <= m_ports.size(); i++)
{
if (!(temp & (1u << i)))
continue;
changed_port = i;
break;
}
m_changed_ports |= temp & ~(1u << changed_port);
}
if (changed_port == 0)
{
dprintln_if(DEBUG_USB_HUB, "TODO: USB Hub changed");
continue;
}
{
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Class | USB::RequestType::Other;
request.bRequest = USB::Request::GET_STATUS;
request.wValue = 0;
request.wIndex = changed_port;
request.wLength = sizeof(USBHub::PortStatus);
auto result = m_device.send_request(request, m_data_region->paddr());
if (result.is_error() || result.value() != sizeof(USBHub::PortStatus))
{
dwarnln("Failed to get port {} status", changed_port);
continue;
}
}
const USBHub::PortStatus port_status {
.wPortStatus = { .raw = reinterpret_cast<volatile USBHub::PortStatus*>(m_data_region->vaddr())->wPortStatus.raw },
.wPortChanged = { .raw = reinterpret_cast<volatile USBHub::PortStatus*>(m_data_region->vaddr())->wPortChanged.raw },
};
if (port_status.wPortChanged.connection)
{
(void)clear_port_feature(changed_port, USBHub::C_PORT_CONNECTION);
if (port_status.wPortStatus.connection)
{
// USB 2 devices have to be reset to enter enabled state
if (auto ret = set_port_feature(changed_port, USBHub::PORT_RESET); ret.is_error())
dwarnln("Failed to reset USB hub port {}: {}", changed_port, ret.error());
}
else
{
// Cleanup port on disconnection
auto& port_info = m_ports[changed_port - 1];
if (port_info.slot != 0)
m_device.deinitialize_device_slot(port_info.slot);
port_info = {};
}
}
if (port_status.wPortChanged.reset)
{
// If this is USB3 device and the port is not in enabled state don't
// clear reset changed so hub will trigger another port changed interrupt
if (!port_status.wPortStatus.connection || !m_is_usb3 || port_status.wPortStatus.enable)
(void)clear_port_feature(changed_port, USBHub::C_PORT_RESET);
}
if (port_status.wPortChanged.over_current)
{
(void)clear_port_feature(changed_port, USBHub::C_PORT_OVER_CURRENT);
dwarnln_if(DEBUG_USB_HUB, "TODO: USB hub port over current change");
}
if (m_is_usb2)
{
if (port_status.wPortChanged.usb2.enable)
(void)clear_port_feature(changed_port, USBHub::C_PORT_ENABLE);
if (port_status.wPortChanged.usb2.suspend)
{
(void)clear_port_feature(changed_port, USBHub::C_PORT_SUSPEND);
dwarnln_if(DEBUG_USB_HUB, "TODO: USB hub port suspend change");
}
}
else if (m_is_usb3)
{
if (port_status.wPortChanged.usb3.link_state)
(void)clear_port_feature(changed_port, USBHub::C_PORT_LINK_STATE);
if (port_status.wPortChanged.usb3.bh_reset)
{
(void)clear_port_feature(changed_port, USBHub::C_BH_PORT_RESET);
dwarnln_if(DEBUG_USB_HUB, "TODO: USB hub bh port reset change");
}
if (port_status.wPortChanged.usb3.config_error)
{
(void)clear_port_feature(changed_port, USBHub::C_PORT_CONFIG_ERROR);
dwarnln_if(DEBUG_USB_HUB, "TODO: USB hub port config error chage");
}
}
else
{
ASSERT_NOT_REACHED();
}
// Initialize new devices that have not failed initialization
if (port_status.wPortStatus.enable && !m_ports[changed_port - 1].slot && !m_ports[changed_port - 1].failed)
{
USB::SpeedClass speed_class;
if (m_is_usb3)
speed_class = USB::SpeedClass::SuperSpeed;
else if (port_status.wPortStatus.usb2.low_speed)
speed_class = USB::SpeedClass::LowSpeed;
else if (port_status.wPortStatus.usb2.high_speed)
speed_class = USB::SpeedClass::HighSpeed;
else
speed_class = USB::SpeedClass::FullSpeed;
#if DEBUG_USB_HUB
const char* speed_str = "<invalid>";
switch (speed_class)
{
case USB::SpeedClass::LowSpeed: speed_str = "low"; break;
case USB::SpeedClass::FullSpeed: speed_str = "full"; break;
case USB::SpeedClass::HighSpeed: speed_str = "high"; break;
case USB::SpeedClass::SuperSpeed: speed_str = "super"; break;
}
dprintln("Initializing {} speed device on hub port {}", speed_str, changed_port);
#endif
auto result = m_device.initialize_device_on_hub_port(changed_port, speed_class);
if (!result.is_error())
m_ports[changed_port - 1].slot = result.value();
else
{
m_ports[changed_port - 1].failed = true;
dwarnln("Failed to initialize USB hub port {}: {}", changed_port, result.error());
}
}
}
m_port_updater = nullptr;
}
void USBHubDriver::handle_stall(uint8_t endpoint_id)
{
(void)endpoint_id;
dwarnln("TODO: USB hub handle stall");
}
void USBHubDriver::handle_input_data(size_t byte_count, uint8_t endpoint_id)
{
if (endpoint_id != m_endpoint_id)
return;
BAN::ScopeGuard query_changes([&] {
m_device.send_data_buffer(m_endpoint_id, m_data_region->paddr() + sizeof(USBHub::PortStatus), m_port_count / 8 + 1);
});
if (m_ports.size() / 8 + 1 < byte_count)
byte_count = m_ports.size() / 8 + 1;
uint32_t new_ports = 0;
const auto* bitmap = reinterpret_cast<const uint8_t*>(m_data_region->vaddr() + sizeof(USBHub::PortStatus));
for (size_t i = 0; i < byte_count; i++)
new_ports |= static_cast<uint32_t>(bitmap[i]) << (i * 8);
if (new_ports)
{
m_changed_ports |= new_ports;
m_changed_port_blocker.unblock();
}
}
}

View File

@ -20,11 +20,7 @@ namespace Kernel
{ }
USBMassStorageDriver::~USBMassStorageDriver()
{
for (auto& device : m_storage_devices)
if (device)
DevFileSystem::get().remove_device(device);
}
{ }
BAN::ErrorOr<void> USBMassStorageDriver::initialize()
{
@ -78,8 +74,8 @@ namespace Kernel
return BAN::Error::from_errno(EFAULT);
}
TRY(m_device.configure_endpoint(m_interface.endpoints[bulk_in_index].descriptor));
TRY(m_device.configure_endpoint(m_interface.endpoints[bulk_out_index].descriptor));
TRY(m_device.initialize_endpoint(m_interface.endpoints[bulk_in_index].descriptor));
TRY(m_device.initialize_endpoint(m_interface.endpoints[bulk_out_index].descriptor));
{
const auto& desc = m_interface.endpoints[bulk_in_index].descriptor;

View File

@ -16,9 +16,8 @@ namespace Kernel
XHCIController::~XHCIController()
{
m_running = false;
while (m_port_updater)
Processor::yield();
if (m_port_updater)
m_port_updater->exit(0, SIGKILL);
for (auto paddr : m_scratchpad_buffers)
if (paddr)
@ -149,8 +148,6 @@ namespace Kernel
ASSERT(m_ports.size() == max_ports);
bool overrides_speed_ids = false;
{
uint16_t ext_offset = capabilities.hccparams1.xhci_extended_capabilities_pointer;
if (ext_offset == 0)
@ -162,11 +159,11 @@ namespace Kernel
vaddr_t ext_addr = m_configuration_bar->vaddr() + ext_offset * 4;
while (true)
{
const auto& ext_cap = *reinterpret_cast<volatile XHCI::ExtendedCap*>(ext_addr);
auto& ext_cap = *reinterpret_cast<volatile XHCI::ExtendedCap*>(ext_addr);
if (ext_cap.capability_id == XHCI::ExtendedCapabilityID::SupportedProtocol)
{
const auto& protocol = reinterpret_cast<const volatile XHCI::SupportedPrococolCap&>(ext_cap);
auto& protocol = reinterpret_cast<volatile XHCI::SupportedPrococolCap&>(ext_cap);
const uint32_t target_name_string {
('U' << 0) |
@ -186,20 +183,21 @@ namespace Kernel
return BAN::Error::from_errno(EFAULT);
}
if (protocol.protocol_slot_type != 0)
{
dwarnln("Invalid slot type specified in SupportedProtocols");
return BAN::Error::from_errno(EFAULT);
}
if (protocol.protocol_speed_id_count != 0)
overrides_speed_ids = true;
for (size_t i = 0; i < protocol.compatible_port_count; i++)
{
auto& port = m_ports[protocol.compatible_port_offset + i - 1];
port.revision_major = protocol.major_revision;
port.revision_minor = protocol.minor_revision;
port.slot_type = protocol.protocol_slot_type;
for (size_t j = 0; j < protocol.protocol_speed_id_count; j++)
{
uint32_t speed_info = reinterpret_cast<const volatile uint32_t*>(ext_addr + sizeof(XHCI::SupportedPrococolCap))[j];
uint32_t port_speed = speed_info >> 16;
for (size_t exp = 0; exp < ((speed_info >> 4) & 0x03); exp++)
port_speed *= 1000;
port.speed_id_to_speed[speed_info & 0x0F] = port_speed;
}
}
}
@ -209,9 +207,6 @@ namespace Kernel
}
}
if (overrides_speed_ids)
dwarnln("xHCI overrides default speed ids, USB may not work");
// set max slots enabled
auto& operational = operational_regs();
operational.config.max_device_slots_enabled = capabilities.hcsparams1.max_slots;
@ -219,30 +214,6 @@ namespace Kernel
return {};
}
uint8_t XHCIController::speed_class_to_id(USB::SpeedClass speed_class) const
{
switch (speed_class)
{
case USB::SpeedClass::LowSpeed: return 2;
case USB::SpeedClass::FullSpeed: return 1;
case USB::SpeedClass::HighSpeed: return 3;
case USB::SpeedClass::SuperSpeed: return 4;
}
ASSERT_NOT_REACHED();
}
USB::SpeedClass XHCIController::speed_id_to_class(uint8_t speed_id) const
{
switch (speed_id)
{
case 2: return USB::SpeedClass::LowSpeed;
case 1: return USB::SpeedClass::FullSpeed;
case 3: return USB::SpeedClass::HighSpeed;
case 4: return USB::SpeedClass::SuperSpeed;
}
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<void> XHCIController::initialize_primary_interrupter()
{
TRY(m_pci_device.reserve_interrupts(1));
@ -307,28 +278,17 @@ namespace Kernel
// attached ports
m_port_changed = true;
uint64_t last_port_update = SystemTimer::get().ms_since_boot();
while (m_running)
while (true)
{
{
bool expected { true };
while (!m_port_changed.compare_exchange(expected, false))
{
// If there has been no port activity in 100 ms, mark root hub as initialized
if (!m_ports_initialized && SystemTimer::get().ms_since_boot() - last_port_update >= 100)
{
mark_hub_init_done(0);
m_ports_initialized = true;
}
m_port_thread_blocker.block_with_timeout_ms(100);
expected = true;
}
}
last_port_update = SystemTimer::get().ms_since_boot();;
for (size_t i = 0; i < m_ports.size(); i++)
{
auto& my_port = m_ports[i];
@ -348,9 +308,10 @@ namespace Kernel
if (!(op_port.portsc & XHCI::PORTSC::CCS))
{
// if device detached, clear the port
if (my_port.slot_id != 0)
{
deinitialize_slot(my_port.slot_id);
m_slots[my_port.slot_id - 1].clear();
my_port.slot_id = 0;
}
continue;
@ -375,12 +336,7 @@ namespace Kernel
continue;
}
const uint8_t speed_id = (op_port.portsc >> XHCI::PORTSC::PORT_SPEED_SHIFT) & XHCI::PORTSC::PORT_SPEED_MASK;
if (auto temp = speed_class_to_id(speed_id_to_class(speed_id)); temp != speed_id)
dwarnln("FIXME: Using incorrect speed id, {} instead of {}", temp, speed_id);
if (auto ret = initialize_device(i + 1, 0, speed_id_to_class(speed_id), nullptr, 0); !ret.is_error())
my_port.slot_id = ret.value();
else
if (auto ret = initialize_slot(i); ret.is_error())
{
dwarnln("Could not initialize USB {H}.{H} device: {}",
my_port.revision_major,
@ -390,45 +346,26 @@ namespace Kernel
}
}
}
m_port_updater = nullptr;
}
BAN::ErrorOr<uint8_t> XHCIController::initialize_device(uint32_t route_string, uint8_t depth, USB::SpeedClass speed_class, XHCIDevice* parent_hub, uint8_t parent_port_id)
BAN::ErrorOr<void> XHCIController::initialize_slot(int port_index)
{
auto& my_port = m_ports[port_index];
XHCI::TRB enable_slot { .enable_slot_command {} };
enable_slot.enable_slot_command.trb_type = XHCI::TRBType::EnableSlotCommand;
// 7.2.2.1.4: The Protocol Slot Type field of a USB3 or USB2 xHCI Supported Protocol Capability shall be set to 0.
enable_slot.enable_slot_command.slot_type = 0;
enable_slot.enable_slot_command.slot_type = my_port.slot_type;
auto result = TRY(send_command(enable_slot));
const uint8_t slot_id = result.command_completion_event.slot_id;
uint8_t slot_id = result.command_completion_event.slot_id;
if (slot_id == 0 || slot_id > capability_regs().hcsparams1.max_slots)
{
dwarnln("EnableSlotCommand returned an invalid slot {}", slot_id);
dwarnln("EnableSlot gave an invalid slot {}", slot_id);
return BAN::Error::from_errno(EFAULT);
}
dprintln_if(DEBUG_XHCI, "allocated slot {} for port {}", slot_id, port_index + 1);
#if DEBUG_XHCI
const auto& root_port = m_ports[(route_string & 0x0F) - 1];
dprintln("Initializing USB {H}.{H} device on slot {}",
root_port.revision_major,
root_port.revision_minor,
slot_id
);
#endif
const XHCIDevice::Info info {
.parent_hub = parent_hub,
.parent_port_id = parent_port_id,
.speed_class = speed_class,
.slot_id = slot_id,
.route_string = route_string,
.depth = depth
};
m_slots[slot_id - 1] = TRY(XHCIDevice::create(*this, info));
m_slots[slot_id - 1] = TRY(XHCIDevice::create(*this, port_index + 1, slot_id));
if (auto ret = m_slots[slot_id - 1]->initialize(); ret.is_error())
{
dwarnln("Could not initialize device on slot {}: {}", slot_id, ret.error());
@ -436,23 +373,11 @@ namespace Kernel
return ret.release_error();
}
#if DEBUG_XHCI
dprintln("USB {H}.{H} device on slot {} initialized",
root_port.revision_major,
root_port.revision_minor,
slot_id
);
#endif
my_port.slot_id = slot_id;
return slot_id;
}
dprintln_if(DEBUG_XHCI, "device on slot {} initialized", slot_id);
void XHCIController::deinitialize_slot(uint8_t slot_id)
{
ASSERT(0 < slot_id && slot_id <= m_slots.size());
ASSERT(m_slots[slot_id - 1]);
m_slots[slot_id - 1]->destroy();
m_slots[slot_id - 1].clear();
return {};
}
BAN::ErrorOr<void> XHCIController::reset_controller()
@ -539,8 +464,7 @@ namespace Kernel
void XHCIController::handle_irq()
{
auto& primary_interrupter = runtime_regs().irs[0];
if (m_pci_device.interrupt_mechanism() != PCI::Device::InterruptMechanism::MSI && m_pci_device.interrupt_mechanism() != PCI::Device::InterruptMechanism::MSIX)
primary_interrupter.iman = primary_interrupter.iman | XHCI::IMAN::InterruptPending | XHCI::IMAN::InterruptEnable;
primary_interrupter.iman = primary_interrupter.iman | XHCI::IMAN::InterruptPending | XHCI::IMAN::InterruptEnable;
auto& operational = operational_regs();
if (!(operational.usbsts & XHCI::USBSTS::EventInterrupt))

View File

@ -8,33 +8,42 @@
namespace Kernel
{
BAN::ErrorOr<BAN::UniqPtr<XHCIDevice>> XHCIDevice::create(XHCIController& controller, const Info& info)
BAN::ErrorOr<BAN::UniqPtr<XHCIDevice>> XHCIDevice::create(XHCIController& controller, uint32_t port_id, uint32_t slot_id)
{
return TRY(BAN::UniqPtr<XHCIDevice>::create(controller, info));
return TRY(BAN::UniqPtr<XHCIDevice>::create(controller, port_id, slot_id));
}
XHCIDevice::XHCIDevice(XHCIController& controller, const Info& info)
: USBDevice(controller, info.speed_class, info.depth)
uint64_t XHCIDevice::calculate_port_bits_per_second(XHCIController& controller, uint32_t port_id)
{
const uint32_t portsc = controller.operational_regs().ports[port_id - 1].portsc;
const uint32_t speed_id = (portsc >> XHCI::PORTSC::PORT_SPEED_SHIFT) & XHCI::PORTSC::PORT_SPEED_MASK;
return controller.port(port_id).speed_id_to_speed[speed_id];
}
XHCIDevice::XHCIDevice(XHCIController& controller, uint32_t port_id, uint32_t slot_id)
: USBDevice(determine_speed_class(calculate_port_bits_per_second(controller, port_id)))
, m_controller(controller)
, m_info(info)
, m_port_id(port_id)
, m_slot_id(slot_id)
{}
XHCIDevice::~XHCIDevice()
{
XHCI::TRB disable_slot { .disable_slot_command {} };
disable_slot.disable_slot_command.trb_type = XHCI::TRBType::DisableSlotCommand;
disable_slot.disable_slot_command.slot_id = m_info.slot_id;
disable_slot.disable_slot_command.slot_id = m_slot_id;
if (auto ret = m_controller.send_command(disable_slot); ret.is_error())
dwarnln("Could not disable slot {}: {}", m_info.slot_id, ret.error());
dwarnln("Could not disable slot {}: {}", m_slot_id, ret.error());
else
dprintln_if(DEBUG_XHCI, "Slot {} disabled", m_info.slot_id);
dprintln_if(DEBUG_XHCI, "Slot {} disabled", m_slot_id);
}
BAN::ErrorOr<void> XHCIDevice::initialize_control_endpoint()
{
const uint32_t context_size = m_controller.context_size_set() ? 64 : 32;
bool is_ls_or_fs_device_on_hs_hub = false;
const uint32_t portsc = m_controller.operational_regs().ports[m_port_id - 1].portsc;
const uint32_t speed_id = (portsc >> XHCI::PORTSC::PORT_SPEED_SHIFT) & XHCI::PORTSC::PORT_SPEED_MASK;
m_endpoints[0].max_packet_size = 0;
switch (m_speed_class)
@ -42,7 +51,6 @@ namespace Kernel
case USB::SpeedClass::LowSpeed:
case USB::SpeedClass::FullSpeed:
m_endpoints[0].max_packet_size = 8;
is_ls_or_fs_device_on_hs_hub = m_info.parent_hub && (m_info.parent_hub->speed_class() == USB::SpeedClass::HighSpeed);
break;
case USB::SpeedClass::HighSpeed:
m_endpoints[0].max_packet_size = 64;
@ -67,32 +75,25 @@ namespace Kernel
auto& slot_context = *reinterpret_cast<XHCI::SlotContext*> (m_input_context->vaddr() + 1 * context_size);
auto& endpoint0_context = *reinterpret_cast<XHCI::EndpointContext*> (m_input_context->vaddr() + 2 * context_size);
input_control_context.add_context_flags = (1 << 1) | (1 << 0);
memset(&input_control_context, 0, context_size);
input_control_context.add_context_flags = 0b11;
slot_context.route_string = m_info.route_string >> 4;
slot_context.root_hub_port_number = m_info.route_string & 0x0F;
memset(&slot_context, 0, context_size);
slot_context.route_string = 0;
slot_context.root_hub_port_number = m_port_id;
slot_context.context_entries = 1;
slot_context.interrupter_target = 0;
slot_context.speed = m_controller.speed_class_to_id(m_info.speed_class);
if (is_ls_or_fs_device_on_hs_hub)
{
slot_context.parent_hub_slot_id = m_info.parent_hub->m_info.slot_id;
slot_context.parent_port_number = m_info.parent_port_id;
slot_context.multi_tt = m_info.parent_hub->is_multi_tt();
}
slot_context.speed = speed_id;
// FIXME: 4.5.2 hub
memset(&endpoint0_context, 0, context_size);
endpoint0_context.endpoint_type = XHCI::EndpointType::Control;
endpoint0_context.max_packet_size = m_endpoints[0].max_packet_size;
endpoint0_context.max_burst_size = 0; // FIXME: SuperSpeed
endpoint0_context.interval = 0;
endpoint0_context.tr_dequeue_pointer = m_endpoints[0].transfer_ring->paddr() | 1;
endpoint0_context.max_primary_streams = 0;
endpoint0_context.error_count = 3;
endpoint0_context.tr_dequeue_pointer = m_endpoints[0].transfer_ring->paddr() | 1;
}
m_controller.dcbaa_reg(m_info.slot_id) = m_output_context->paddr();
dprintln_if(DEBUG_XHCI, "Addressing device on slot {}", m_info.slot_id);
m_controller.dcbaa_reg(m_slot_id) = m_output_context->paddr();
for (int i = 0; i < 2; i++)
{
@ -101,7 +102,7 @@ namespace Kernel
address_device.address_device_command.input_context_pointer = m_input_context->paddr();
// NOTE: some legacy devices require sending request with BSR=1 before actual BSR=0
address_device.address_device_command.block_set_address_request = (i == 0);
address_device.address_device_command.slot_id = m_info.slot_id;
address_device.address_device_command.slot_id = m_slot_id;
TRY(m_controller.send_command(address_device));
}
@ -122,14 +123,12 @@ namespace Kernel
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Standard | USB::RequestType::Device;
request.bRequest = USB::Request::GET_DESCRIPTOR;
request.wValue = USB::DescriptorType::DEVICE << 8;
request.wValue = 0x0100;
request.wIndex = 0;
request.wLength = 8;
TRY(send_request(request, kmalloc_paddr_of((vaddr_t)buffer.data()).value()));
dprintln_if(DEBUG_XHCI, "Got device descriptor");
const bool is_usb3 = (m_speed_class == USB::SpeedClass::SuperSpeed);
const bool is_usb3 = m_controller.port(m_port_id).revision_major == 3;
const uint32_t new_max_packet_size = is_usb3 ? 1u << buffer.back() : buffer.back();
if (m_endpoints[0].max_packet_size == new_max_packet_size)
@ -141,38 +140,39 @@ namespace Kernel
{
auto& input_control_context = *reinterpret_cast<XHCI::InputControlContext*>(m_input_context->vaddr() + 0 * context_size);
auto& slot_context = *reinterpret_cast<XHCI::SlotContext*> (m_input_context->vaddr() + 1 * context_size);
auto& endpoint0_context = *reinterpret_cast<XHCI::EndpointContext*> (m_input_context->vaddr() + 2 * context_size);
memset(&input_control_context, 0, context_size);
input_control_context.add_context_flags = (1 << 1);
input_control_context.add_context_flags = 0b11;
// Only update max packet size. Other fields should be fine from initial configuration
endpoint0_context.max_packet_size = new_max_packet_size;
memset(&slot_context, 0, context_size);
slot_context.max_exit_latency = 0; // FIXME:
slot_context.interrupter_target = 0;
memset(&endpoint0_context, 0, context_size);
endpoint0_context.endpoint_type = XHCI::EndpointType::Control;
endpoint0_context.max_packet_size = m_endpoints[0].max_packet_size;
endpoint0_context.error_count = 3;
endpoint0_context.tr_dequeue_pointer = m_endpoints[0].transfer_ring->paddr() | 1;
}
XHCI::TRB evaluate_context { .address_device_command = {} };
evaluate_context.address_device_command.trb_type = XHCI::TRBType::EvaluateContextCommand;
evaluate_context.address_device_command.input_context_pointer = m_input_context->paddr();
evaluate_context.address_device_command.block_set_address_request = 0;
evaluate_context.address_device_command.slot_id = m_info.slot_id;
evaluate_context.address_device_command.slot_id = m_slot_id;
TRY(m_controller.send_command(evaluate_context));
dprintln_if(DEBUG_XHCI, "Updated max packet size to {}", new_max_packet_size);
dprintln_if(DEBUG_XHCI, "successfully updated max packet size to {}", m_endpoints[0].max_packet_size);
return {};
}
bool XHCIDevice::is_multi_tt() const
{
const uint32_t context_size = m_controller.context_size_set() ? 64 : 32;
const auto& slot_context = *reinterpret_cast<const XHCI::SlotContext*>(m_input_context->vaddr() + context_size);
return slot_context.multi_tt;
}
// 6.2.3.6 Interval
static uint32_t determine_interval(const USBEndpointDescriptor& endpoint_descriptor, USB::SpeedClass speed_class)
{
const auto ep_type = static_cast<USB::EndpointType>(endpoint_descriptor.bmAttributes & 0x03);
auto ep_type = static_cast<USB::EndpointType>(endpoint_descriptor.bDescriptorType & 0x03);
switch (speed_class)
{
@ -202,31 +202,18 @@ namespace Kernel
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<uint8_t> XHCIDevice::initialize_device_on_hub_port(uint8_t port_id, USB::SpeedClass speed_class)
{
if (m_info.depth + 1 > 5)
{
dwarnln("Invalid USB hub on depth {}", m_info.depth);
return BAN::Error::from_errno(EFAULT);
}
uint32_t route_string = m_info.route_string;
route_string |= static_cast<uint32_t>(port_id) << ((m_info.depth + 1) * 4);
return m_controller.initialize_device(route_string, m_info.depth + 1, speed_class, this, port_id);
}
void XHCIDevice::deinitialize_device_slot(uint8_t slot_id)
{
m_controller.deinitialize_slot(slot_id);
}
BAN::ErrorOr<void> XHCIDevice::configure_endpoint(const USBEndpointDescriptor& endpoint_descriptor, const HubInfo& hub_info)
BAN::ErrorOr<void> XHCIDevice::initialize_endpoint(const USBEndpointDescriptor& endpoint_descriptor)
{
const bool is_control { (endpoint_descriptor.bmAttributes & 0x03) == 0x00 };
const bool is_isoch { (endpoint_descriptor.bmAttributes & 0x03) == 0x01 };
const bool is_bulk { (endpoint_descriptor.bmAttributes & 0x03) == 0x02 };
const bool is_interrupt { (endpoint_descriptor.bmAttributes & 0x03) == 0x03 };
(void)is_control;
(void)is_isoch;
(void)is_bulk;
(void)is_interrupt;
XHCI::EndpointType endpoint_type;
switch ((endpoint_descriptor.bEndpointAddress & 0x80) | (endpoint_descriptor.bmAttributes & 0x03))
{
@ -251,29 +238,20 @@ namespace Kernel
const uint32_t average_trb_length = (is_control) ? 8 : max_esit_payload;
const uint32_t error_count = (is_isoch) ? 0 : 3;
auto& endpoint = m_endpoints[endpoint_id - 1];
ASSERT(!endpoint.transfer_ring);
uint32_t last_valid_endpoint_id = endpoint_id;
for (size_t i = endpoint_id; i < m_endpoints.size(); i++)
if (m_endpoints[i].transfer_ring)
last_valid_endpoint_id = i + 1;
auto& endpoint = m_endpoints[endpoint_id - 1];
LockGuard _(endpoint.mutex);
if (!endpoint.transfer_ring)
{
endpoint.transfer_ring = TRY(DMARegion::create(m_transfer_ring_trb_count * sizeof(XHCI::TRB)));
endpoint.max_packet_size = max_packet_size;
endpoint.dequeue_index = 0;
endpoint.enqueue_index = 0;
endpoint.cycle_bit = 1;
endpoint.callback = (is_interrupt || is_bulk) ? &XHCIDevice::on_interrupt_or_bulk_endpoint_event : nullptr;
}
else
{
endpoint.dequeue_index = 0;
endpoint.enqueue_index = 0;
endpoint.cycle_bit = 1;
}
endpoint.transfer_ring = TRY(DMARegion::create(m_transfer_ring_trb_count * sizeof(XHCI::TRB)));
endpoint.max_packet_size = max_packet_size;
endpoint.dequeue_index = 0;
endpoint.enqueue_index = 0;
endpoint.cycle_bit = 1;
endpoint.callback = (is_interrupt || is_bulk) ? &XHCIDevice::on_interrupt_or_bulk_endpoint_event : nullptr;
memset(reinterpret_cast<void*>(endpoint.transfer_ring->vaddr()), 0, endpoint.transfer_ring->size());
@ -285,16 +263,11 @@ namespace Kernel
auto& endpoint_context = *reinterpret_cast<XHCI::EndpointContext*> (m_input_context->vaddr() + (endpoint_id + 1) * context_size);
memset(&input_control_context, 0, context_size);
input_control_context.add_context_flags = (1u << endpoint_id) | (1 << 0);
input_control_context.add_context_flags = (1u << endpoint_id) | 1;
memset(&slot_context, 0, context_size);
slot_context.context_entries = last_valid_endpoint_id;
slot_context.hub = (hub_info.number_of_ports > 0);
slot_context.number_of_ports = hub_info.number_of_ports;
if (m_speed_class == USB::SpeedClass::HighSpeed)
{
slot_context.multi_tt = hub_info.multi_tt;
slot_context.tt_think_time = hub_info.tt_think_time;
}
// FIXME: 4.5.2 hub
memset(&endpoint_context, 0, context_size);
endpoint_context.endpoint_type = endpoint_type;
@ -313,7 +286,7 @@ namespace Kernel
configure_endpoint.configure_endpoint_command.trb_type = XHCI::TRBType::ConfigureEndpointCommand;
configure_endpoint.configure_endpoint_command.input_context_pointer = m_input_context->paddr();
configure_endpoint.configure_endpoint_command.deconfigure = 0;
configure_endpoint.configure_endpoint_command.slot_id = m_info.slot_id;
configure_endpoint.configure_endpoint_command.slot_id = m_slot_id;
TRY(m_controller.send_command(configure_endpoint));
return {};
@ -395,9 +368,17 @@ namespace Kernel
BAN::ErrorOr<size_t> XHCIDevice::send_request(const USBDeviceRequest& request, paddr_t buffer_paddr)
{
ASSERT(request.wLength == 0 || buffer_paddr);
// FIXME: This is more or less generic USB code
const uint8_t transfer_type =
auto& endpoint = m_endpoints[0];
// minus 3: Setup, Status, Link (this is probably too generous and will result in STALL)
if (request.wLength > (m_transfer_ring_trb_count - 3) * endpoint.max_packet_size)
return BAN::Error::from_errno((ENOBUFS));
LockGuard _(endpoint.mutex);
uint8_t transfer_type =
[&request]() -> uint8_t
{
if (request.wLength == 0)
@ -407,12 +388,6 @@ namespace Kernel
return 2;
}();
const bool status_stage_dir = !((request.wLength > 0) && (request.bmRequestType & USB::RequestType::DeviceToHost));
auto& endpoint = m_endpoints[0];
LockGuard _(endpoint.mutex);
auto* transfer_trb_arr = reinterpret_cast<volatile XHCI::TRB*>(endpoint.transfer_ring->vaddr());
{
@ -435,23 +410,32 @@ namespace Kernel
advance_endpoint_enqueue(endpoint, false);
}
if (request.wLength)
const uint32_t td_packet_count = BAN::Math::div_round_up<uint32_t>(request.wLength, endpoint.max_packet_size);
uint32_t packets_transferred = 1;
uint32_t bytes_handled = 0;
while (bytes_handled < request.wLength)
{
const uint32_t to_handle = BAN::Math::min<uint32_t>(endpoint.max_packet_size, request.wLength - bytes_handled);
auto& trb = transfer_trb_arr[endpoint.enqueue_index];
memset(const_cast<XHCI::TRB*>(&trb), 0, sizeof(XHCI::TRB));
trb.data_stage.trb_type = XHCI::TRBType::DataStage;
trb.data_stage.direction = !!(request.bmRequestType & USB::RequestType::DeviceToHost);
trb.data_stage.trb_transfer_length = request.wLength;
trb.data_stage.td_size = 0;
trb.data_stage.chain_bit = 0;
trb.data_stage.direction = 1;
trb.data_stage.trb_transfer_length = to_handle;
trb.data_stage.td_size = BAN::Math::min<uint32_t>(td_packet_count - packets_transferred, 31);
trb.data_stage.chain_bit = (bytes_handled + to_handle < request.wLength);
trb.data_stage.interrupt_on_completion = 0;
trb.data_stage.interrupt_on_short_packet = 0;
trb.data_stage.interrupt_on_short_packet = 1;
trb.data_stage.immediate_data = 0;
trb.data_stage.data_buffer_pointer = buffer_paddr;
trb.data_stage.data_buffer_pointer = buffer_paddr + bytes_handled;
trb.data_stage.cycle_bit = endpoint.cycle_bit;
advance_endpoint_enqueue(endpoint, false);
bytes_handled += to_handle;
packets_transferred++;
advance_endpoint_enqueue(endpoint, trb.data_stage.chain_bit);
}
{
@ -459,10 +443,10 @@ namespace Kernel
memset(const_cast<XHCI::TRB*>(&trb), 0, sizeof(XHCI::TRB));
trb.status_stage.trb_type = XHCI::TRBType::StatusStage;
trb.status_stage.direction = status_stage_dir;
trb.status_stage.direction = 0;
trb.status_stage.chain_bit = 0;
trb.status_stage.interrupt_on_completion = 1;
trb.status_stage.cycle_bit = endpoint.cycle_bit;
trb.data_stage.cycle_bit = endpoint.cycle_bit;
advance_endpoint_enqueue(endpoint, false);
}
@ -475,7 +459,7 @@ namespace Kernel
endpoint.transfer_count = request.wLength;
m_controller.doorbell_reg(m_info.slot_id) = 1;
m_controller.doorbell_reg(m_slot_id) = 1;
const uint64_t timeout_ms = SystemTimer::get().ms_since_boot() + 1000;
while ((__atomic_load_n(&completion_trb.raw.dword2, __ATOMIC_SEQ_CST) >> 24) == 0)
@ -498,7 +482,7 @@ namespace Kernel
ASSERT(endpoint_id != 0);
auto& endpoint = m_endpoints[endpoint_id - 1];
ASSERT(buffer_len <= (1 << 16));
ASSERT(buffer_len <= endpoint.max_packet_size);
auto& trb = *reinterpret_cast<volatile XHCI::TRB*>(endpoint.transfer_ring->vaddr() + endpoint.enqueue_index * sizeof(XHCI::TRB));
memset(const_cast<XHCI::TRB*>(&trb), 0, sizeof(XHCI::TRB));
@ -512,7 +496,7 @@ namespace Kernel
trb.normal.interrupt_on_short_packet = 1;
advance_endpoint_enqueue(endpoint, false);
m_controller.doorbell_reg(m_info.slot_id) = endpoint_id;
m_controller.doorbell_reg(m_slot_id) = endpoint_id;
}
void XHCIDevice::advance_endpoint_enqueue(Endpoint& endpoint, bool chain)

View File

@ -228,13 +228,11 @@ static void init2(void*)
dprintln("USBManager initialized");
}
if (!cmdline.disable_acpi)
{
if (auto ret = ACPI::ACPI::get().enter_acpi_mode(InterruptController::get().is_using_apic()); ret.is_error())
dprintln("Failed to enter ACPI mode: {}", ret.error());
if (auto ret = ACPI::ACPI::get().initialize_acpi_devices(); ret.is_error())
dwarnln("Could not initialize ACPI devices: {}", ret.error());
}
if (!cmdline.disable_acpi && ACPI::ACPI::get().enter_acpi_mode(InterruptController::get().is_using_apic()).is_error())
dprintln("Failed to enter ACPI mode");
if (auto ret = ACPI::ACPI::get().initialize_acpi_devices(); ret.is_error())
dwarnln("Could not initialize ACPI devices: {}", ret.error());
DevFileSystem::get().initialize_device_updater();