1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 12:17:35 +00:00

Kernel/USB: Implement UHCI Data structures

Implemented both Queue Heads and Transfer Descriptors. These
are required to actually perform USB transactions. The UHCI
driver sets up a pool of these that can be allocated when we
need them. It seems some drivers have these statically
allocated, so it might be worth looking into that, but
for now, the simple way seems to be to allocate them on
the fly as we need them, and then release them.
This commit is contained in:
Jesse Buhagiar 2020-11-12 00:27:22 +11:00 committed by Andreas Kling
parent 375d269b21
commit a5f895d251
3 changed files with 529 additions and 12 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Jesse Buhagiar <jooster669@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,14 +27,19 @@
#pragma once
#include <AK/NonnullOwnPtr.h>
#include <Kernel/Devices/USB/UHCIDescriptorTypes.h>
#include <Kernel/IO.h>
#include <Kernel/PCI/Device.h>
#include <Kernel/VM/ContiguousVMObject.h>
namespace Kernel::USB {
class UHCIController final : public PCI::Device {
public:
static void detect();
static UHCIController& the();
virtual ~UHCIController() override;
void reset();
@ -49,8 +55,6 @@ private:
u16 read_frnum() { return m_io_base.offset(0x6).in<u16>(); }
u32 read_flbaseadd() { return m_io_base.offset(0x8).in<u32>(); }
u8 read_sofmod() { return m_io_base.offset(0xc).in<u8>(); }
u16 read_portsc1() { return m_io_base.offset(0x10).in<u16>(); }
u16 read_portsc2() { return m_io_base.offset(0x12).in<u16>(); }
void write_usbcmd(u16 value) { m_io_base.offset(0).out(value); }
void write_usbsts(u16 value) { m_io_base.offset(0x2).out(value); }
@ -58,13 +62,33 @@ private:
void write_frnum(u16 value) { m_io_base.offset(0x6).out(value); }
void write_flbaseadd(u32 value) { m_io_base.offset(0x8).out(value); }
void write_sofmod(u8 value) { m_io_base.offset(0xc).out(value); }
void write_portsc1(u16 value) { m_io_base.offset(0x10).out(value); }
void write_portsc2(u16 value) { m_io_base.offset(0x12).out(value); }
virtual void handle_irq(const RegisterState&) override;
void create_structures();
void setup_schedule();
QueueHead* allocate_queue_head() const;
TransferDescriptor* allocate_transfer_descriptor() const;
private:
IOAddress m_io_base;
PhysicalAddress m_framelist;
Vector<QueueHead*> m_free_qh_pool;
Vector<TransferDescriptor*> m_free_td_pool;
Vector<TransferDescriptor*> m_iso_td_list;
Vector<QueueHead*> m_interrupt_qh_list;
QueueHead* m_interrupt_transfer_queue;
QueueHead* m_lowspeed_control_qh;
QueueHead* m_fullspeed_control_qh;
QueueHead* m_bulk_qh;
QueueHead* m_dummy_qh; // Needed for PIIX4 hack
OwnPtr<Region> m_framelist;
OwnPtr<Region> m_qh_pool;
OwnPtr<Region> m_td_pool;
OwnPtr<Region> m_td_buffer_region;
};
}