The Pedigree Project 0.1
Xhci.h
1/* Copyright (c) 2026, Pedigree Developers. SPDX-License-Identifier: ISC */
2#ifndef XHCI_H
3#define XHCI_H
4#include "pedigree/kernel/machine/IrqHandler.h"
5#include "pedigree/kernel/process/OperationBarrier.h"
6#include "pedigree/kernel/process/Semaphore.h"
7#include "pedigree/kernel/utilities/RequestQueue.h"
8
9#include "CallbackDelivery.h"
10#include "PortChangeRequest.h"
11#include "TransferCompletion.h"
12#include "XhciRing.h"
13#include "modules/system/usb/UsbHub.h"
14class IoBase;
15class Thread;
16class Xhci : public UsbHub, public IrqHandler, public RequestQueue {
17 public:
18 explicit Xhci(Device* device);
19 ~Xhci() override;
20 bool initialiseController();
21 void getName(String& name) override {
22 name.assign("xHCI");
23 }
24 bool controllerAssignsAddresses() const override {
25 return true;
26 }
27 bool supportsHubDevices() const override {
28 return false;
29 }
30 bool prepareDevice(uint8_t address, const UsbEndpoint& endpoint) override;
31 bool addressDevice(uint8_t address, const UsbEndpoint& endpoint) override;
32 bool resetEndpoint(const UsbEndpoint& endpoint) override;
33 uintptr_t createTransaction(UsbEndpoint endpoint) override;
34 void addTransferToTransaction(uintptr_t transaction, bool toggle, UsbPid pid, uintptr_t buffer,
35 size_t bytes) override;
36 bool doAsync(uintptr_t transaction, void (*callback)(uintptr_t, ssize_t) = nullptr,
37 uintptr_t parameter = 0) override;
38 void cancelAsyncAndDrain(uintptr_t transaction, void (*callback)(uintptr_t, ssize_t),
39 uintptr_t parameter) override;
40 bool addInterruptInHandler(UsbEndpoint endpoint, uintptr_t buffer, uint16_t bytes,
41 void (*callback)(uintptr_t, ssize_t), UsbInterruptInHandle& handle,
42 uintptr_t parameter = 0) override;
43 bool portReset(uint8_t port, bool errorResponse = false) override;
44 IrqDisposition irq(irq_id_t) override;
45
46 protected:
47 void releaseDeviceAddress(uint8_t address) override;
48 bool cancelInterruptInAndDrain(const UsbInterruptInToken&, void (*)(uintptr_t, ssize_t),
49 uintptr_t, bool producerAlreadyStopped) override;
53 size_t currentRootPortGeneration(size_t port) const override;
54 void replaySuppressedConnectionChange(size_t port) override;
55 uint64_t executeRequest(uint64_t port, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
56 uint64_t generation) override;
57 void cancelRequest(const Request& request) override;
58
59 private:
60 struct Transaction;
61 struct Endpoint {
62 XhciHw::Ring ring;
63 Transaction* active = nullptr;
64 UsbEndpoint description;
65 Atomic<bool> needsReset{false};
66 uint64_t retiredAddresses[20]{};
67 size_t retiredCount = 0;
68 };
69 struct Slot {
70 Slot() : output("xHCI device context") {}
71 MemoryRegion output;
72 Endpoint* endpoints[32]{};
73 uint8_t logical = 0;
74 uint8_t port = 0;
75 uint8_t speedId = 0;
76 uint8_t contextEntries = 1;
77 size_t generation = 0;
78 };
79 struct Transaction {
80 Transaction() : bounce("xHCI transfer") {}
81 MemoryRegion bounce;
82 physical_uintptr_t pages[16]{};
83 UsbEndpoint description;
85 Endpoint* endpoint = nullptr;
86 uint8_t slot = 0, dci = 0;
87 uintptr_t id = 0, client = 0;
88 size_t bytes = 0, generation = 0;
89 uint64_t setup = 0;
90 bool input = false, setupPresent = false, statusPresent = false, bad = false;
91 bool submitted = false, cancelling = false, periodic = false, captured = false;
92 bool shortSeen = false;
93 size_t actual = 0, trbCount = 0;
94 uint64_t trbAddresses[20]{};
95 size_t trbOffsets[20]{}, trbLengths[20]{};
96 uint8_t trbTypes[20]{};
97 void (*callback)(uintptr_t, ssize_t) = nullptr;
98 uintptr_t parameter = 0;
99 };
100 struct Delivery {
101 Xhci* controller;
102 uintptr_t transaction;
103 size_t generation;
104 bool rearm;
105 };
106 struct Port {
107 uint8_t major = 0, slotType = 0;
108 UsbSpeed speeds[16]{};
109 bool validSpeed[16]{};
110 Atomic<bool> changePending{false};
111 uint32_t resetChanges = 0;
112 };
113 uint32_t read(size_t offset) const;
114 void write(size_t offset, uint32_t value);
115 void write64(size_t offset, uint64_t value);
116 bool wait(size_t offset, uint32_t mask, uint32_t expected, size_t milliseconds);
117 bool parseCapabilities(uint32_t hcc);
118 bool command(XhciHw::Trb trb, uint8_t* returnedSlot = nullptr);
119 bool collectEventsLocked(bool fromInterrupt);
120 bool transferEventLocked(const XhciHw::Trb& event);
121 void notifyPortLocked(size_t port);
122 bool halt();
123 void failLocked();
124 void shutdown();
125 Endpoint* ensureEndpoint(uint8_t slot, const UsbEndpoint& description);
126 uint8_t findSlot(const UsbEndpoint& endpoint) const;
127 uint32_t* inputContext(size_t index);
128 uint32_t* outputContext(uint8_t slot, size_t index);
129 bool resetEndpointHardware(uint8_t slot, uint8_t dci, bool stop);
130 bool submitLocked(Transaction& transaction);
131 static bool decodeCompletion(Transaction&, size_t index, uint8_t code, size_t residual,
132 bool& complete, size_t& actual);
133 static bool completionRegressions();
134 bool accept(uintptr_t transaction, void (*callback)(uintptr_t, ssize_t), uintptr_t parameter,
135 UsbInterruptInHandle* handle);
136 void finishLocked(Transaction& transaction, ssize_t result, bool natural);
137 void enqueueDeliveryLocked(UsbHcd::CallbackDeliveryQueue::Record* delivery);
138 static void afterDelivery(void* context);
139 static void destroyDelivery(void* context);
140 static int deliveryWorker(void* context);
141 void freeTransactionLocked(uintptr_t transaction);
142 void cancelTransfer(uintptr_t transaction, size_t generation, bool recurring,
143 void (*callback)(uintptr_t, ssize_t), uintptr_t parameter);
144 Device* m_Pci;
145 IoBase* m_Registers = nullptr;
146 size_t m_Op = 0, m_Runtime = 0, m_Doorbells = 0, m_ContextSize = 32;
147 size_t m_PortCount = 0, m_SlotCount = 0;
148 irq_id_t m_Irq = 0;
149 bool m_HardwareOwned = false;
150 Atomic<bool> m_Online{false}, m_Stopping{false}, m_Failed{false}, m_PortsClosing{false};
151 bool m_Shutdown = false, m_DeliveryStopping = false, m_PolledInterrupt = false;
152 bool m_ObservedInterruptCompletion = false;
153 Mutex m_Lock, m_CommandLock, m_ConfigurationLock, m_CancelLock;
154 OperationBarrier m_Submissions, m_Cancellations, m_Transfers;
155 XhciHw::Ring m_Commands;
156 MemoryRegion m_Events, m_Erst, m_Dcbaa, m_Input, m_ScratchPointers;
157 MemoryRegion* m_Scratch[32]{};
158 size_t m_EventHead = 0, m_EventWraps = 0;
159 bool m_EventCycle = true;
160 uint64_t m_CommandAddress = 0;
161 uint8_t m_CommandCode = 0, m_CommandSlot = 0;
162 Semaphore m_CommandDone{0, false};
163 Slot m_Slots[XhciHw::MaxSlots + 1];
164 uint8_t m_Addresses[128]{}, m_PortSlots[XhciHw::MaxPorts]{};
165 Port m_Ports[XhciHw::MaxPorts];
166 UsbHcd::PortChangeRequest m_PortChanges[XhciHw::MaxPorts];
167 Transaction* m_Transactions[XhciHw::MaxTransactions]{};
170 Semaphore m_DeliveryReady{0, false};
171 Thread* m_DeliveryThread = nullptr;
172};
173#endif
Abstrace base class for hardware I/O capabilities.
Definition IoBase.h:32
Definition List.h:61
Special memory entity in the kernel's virtual address space.
Definition Mutex.h:56
Definition Xhci.h:16
void addTransferToTransaction(uintptr_t transaction, bool toggle, UsbPid pid, uintptr_t buffer, size_t bytes) override
Adds a new transfer to an existent transaction.
IrqDisposition irq(irq_id_t) override
Definition XhciEvent.cc:98
bool cancelInterruptInAndDrain(const UsbInterruptInToken &, void(*)(uintptr_t, ssize_t), uintptr_t, bool producerAlreadyStopped) override
void replaySuppressedConnectionChange(size_t port) override
Definition XhciEvent.cc:122
bool portReset(uint8_t port, bool errorResponse=false) override
Gets a UsbDevice from a given vendor:product pair.
Definition XhciEvent.cc:127
uint64_t executeRequest(uint64_t port, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t generation) override
Definition XhciEvent.cc:162
bool doAsync(uintptr_t transaction, void(*callback)(uintptr_t, ssize_t)=nullptr, uintptr_t parameter=0) override
uintptr_t createTransaction(UsbEndpoint endpoint) override
Creates a new transaction with the given endpoint data.
bool inInterruptCallbackContext() const override
Definition Xhci.h:50
void cancelRequest(const Request &request) override
Definition XhciEvent.cc:187
void releaseDeviceAddress(uint8_t address) override
void cancelAsyncAndDrain(uintptr_t transaction, void(*callback)(uintptr_t, ssize_t), uintptr_t parameter) override
size_t currentRootPortGeneration(size_t port) const override
Definition XhciEvent.cc:119
void getName(String &name) override
Definition Xhci.h:21
bool addInterruptInHandler(UsbEndpoint endpoint, uintptr_t buffer, uint16_t bytes, void(*callback)(uintptr_t, ssize_t), UsbInterruptInHandle &handle, uintptr_t parameter=0) override
Adds an owned recurring interrupt-IN transaction.
IrqDisposition
Definition IrqHandler.h:31