The Pedigree Project 0.1
Uhci.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <config.h>
21#if X86_COMMON
22
23#ifndef UHCI_H
24#define UHCI_H
25
26#include "pedigree/kernel/Spinlock.h"
27#include "pedigree/kernel/compiler.h"
28#include "pedigree/kernel/machine/IrqHandler.h"
29#include "pedigree/kernel/machine/TimerHandler.h"
30#include "pedigree/kernel/machine/types.h"
31#include "pedigree/kernel/process/Mutex.h"
32#include "pedigree/kernel/process/OperationBarrier.h"
33#include "pedigree/kernel/process/Semaphore.h"
34#include "pedigree/kernel/processor/MemoryRegion.h"
35#include "pedigree/kernel/processor/state_forward.h"
36#include "pedigree/kernel/processor/types.h"
37#include "pedigree/kernel/utilities/ExtensibleBitmap.h"
38#include "pedigree/kernel/utilities/List.h"
39#include "pedigree/kernel/utilities/RequestQueue.h"
40#include "pedigree/kernel/utilities/String.h"
41#include "pedigree/kernel/utilities/new"
42
43#include "CallbackDelivery.h"
44#include "PortChangeRequest.h"
45#include "TransferCompletion.h"
46#include "modules/system/usb/Usb.h"
47#include "modules/system/usb/UsbHub.h"
48
49class Device;
50class IoBase;
51class Thread;
52
54class Uhci : public UsbHub, public IrqHandler, public RequestQueue, public TimerHandler {
55 public:
56 Uhci(Device* pDev);
57 virtual ~Uhci();
58 bool initialised() const {
59 return m_Initialised;
60 }
61
62 struct TD {
63 uint32_t bNextInvalid : 1;
64 uint32_t bNextQH : 1;
65 uint32_t bNextDepth : 1;
66 uint32_t res0 : 1;
67 uint32_t pNext : 28;
68 uint32_t nActLen : 11;
69 uint32_t res1 : 5;
70 uint32_t nStatus : 8;
71 uint32_t bIoc : 1;
72 uint32_t bIsochronus : 1;
73 uint32_t bLoSpeed : 1;
74 uint32_t nErr : 2;
75 uint32_t bSpd : 1;
76 uint32_t res2 : 2;
77 uint32_t nPid : 8;
78 uint32_t nAddress : 7;
79 uint32_t nEndpoint : 4;
80 uint32_t bDataToggle : 1;
81 uint32_t res3 : 1;
82 uint32_t nMaxLen : 11;
83 uint32_t pBuff;
84
85 // Custom TD fields
86 uint16_t nBufferSize;
87 bool bShortTransferTD;
88
89 size_t id;
90
91 // Possible values for status
92 enum StatusCodes {
93 Timeout = 0x4,
94 Nak = 0x8,
95 Babble = 0x10,
96 Stall = 0x40,
97 };
98
99 inline UsbError getError() {
100 if (nStatus & Stall)
101 return ::Stall;
102 else if (nStatus & Nak)
103 return NakNyet;
104 else if (nStatus & Babble)
105 return ::Babble;
106 else if (nStatus & Timeout)
107 return ::Timeout;
108 else
109 return TransactionError;
110 }
111 } PACKED ALIGN(16);
112
113 struct QH {
114 uint32_t bNextInvalid : 1;
115 uint32_t bNextQH : 1;
116 uint32_t res0 : 2;
117 uint32_t pNext : 28;
118 uint32_t bElemInvalid : 1;
119 uint32_t bElemQH : 1;
120 uint32_t res1 : 2;
121 uint32_t pElem : 28;
122
123 struct MetaData {
124 Uhci* pOwner;
125 void (*pPeriodicCallback)(uintptr_t, ssize_t);
126 uintptr_t pPeriodicParam;
127 size_t periodicGeneration;
128 size_t periodicInterval;
129 size_t periodicBusTime;
130 bool periodicPending;
131
132 UsbEndpoint endpointInfo;
133
134 bool bPeriodic;
135 bool bBuildFailed;
136 TD* pFirstTD;
137 TD* pLastTD;
138 size_t nTotalBytes;
139
140 QH* pPrev;
141 QH* pNext;
142
143 List<TD*> tdList;
144 List<TD*> completedTdList;
145
146 bool bIgnore;
149
150 size_t id;
151 }* pMetaData;
152 } PACKED ALIGN(16);
153
154 virtual void getName(String& str) {
155 str.assign("UHCI", 5);
156 }
157
158 virtual void addTransferToTransaction(uintptr_t pTransaction, bool bToggle, UsbPid pid,
159 uintptr_t pBuffer, size_t nBytes);
160 virtual uintptr_t createTransaction(UsbEndpoint endpointInfo);
161
162 MUST_USE_RESULT virtual bool doAsync(uintptr_t pTransaction,
163 void (*pCallback)(uintptr_t, ssize_t) = 0,
164 uintptr_t pParam = 0);
165 MUST_USE_RESULT virtual bool addInterruptInHandler(UsbEndpoint endpointInfo, uintptr_t pBuffer,
166 uint16_t nBytes,
167 void (*pCallback)(uintptr_t, ssize_t),
168 UsbInterruptInHandle& handle,
169 uintptr_t pParam = 0);
170
172 IrqDisposition irq(irq_id_t number) override;
173
174 void doDequeue();
175
177 void timer(uint64_t delta);
178
179 virtual bool portReset(uint8_t nPort, bool bErrorResponse = false);
180
181 protected:
182 virtual void cancelAsyncAndDrain(uintptr_t pTransaction, void (*pCallback)(uintptr_t, ssize_t),
183 uintptr_t pParam);
185 void (*callback)(uintptr_t, ssize_t),
186 uintptr_t parameter,
187 bool producerAlreadyStopped) override;
191 size_t currentRootPortGeneration(size_t port) const override;
192 void replaySuppressedConnectionChange(size_t port) override;
193
194 virtual uint64_t executeRequest(uint64_t p1 = 0, uint64_t p2 = 0, uint64_t p3 = 0,
195 uint64_t p4 = 0, uint64_t p5 = 0, uint64_t p6 = 0,
196 uint64_t p7 = 0, uint64_t p8 = 0);
197 void cancelRequest(const Request& request) override;
198
199 private:
200 bool doAsyncOwned(uintptr_t transaction, void (*callback)(uintptr_t, ssize_t),
201 uintptr_t parameter, UsbInterruptInHandle* interruptHandle,
202 size_t interruptGeneration);
203
205 static void enqueueCompletedTransfer(void* context);
206 static void rearmPeriodicCompletion(void* context);
207 static void destroyPeriodicCompletion(void* context);
208
211
213 void detachQueueHeadLocked(QH* pQH);
214
216 void reclaimQueueHeadLocked(QH* pQH);
217
219 void stop();
220
222 void start();
223
226 bool setLegacySupportControl(uint16_t control);
227
229 void modifyPortControl(size_t portRegister, uint16_t clearMask, uint16_t setMask);
230
231 enum UhciConstants {
232 UHCI_CMD = 0x00, // Command register
233 UHCI_STS = 0x02, // Status register
234 UHCI_INTR = 0x04, // Intrerrupt Enable register
235 UHCI_FRMN = 0x06, // Frame Number register
236 UHCI_FRLP = 0x08, // Frame List Pointer register
237 UHCI_PORTSC = 0x10, // Port Status/Control registers
238
239 UHCI_CMD_GRES = 0x04, // Global Reset bit
240 UHCI_CMD_HCRES = 0x02, // Host Controller Reset bit
241 UHCI_CMD_RUN = 0x01, // Run bit
242
243 UHCI_STS_HALT = 0x20, // Controller is halted
244 UHCI_STS_ERR = 0x02, // UHCI Error
245 UHCI_STS_INT = 0x01, // On Completition Interrupt bit
246
247 UHCI_PORTSC_PRES = 0x200, // Port Reset bit
248 UHCI_PORTSC_LOSPEED = 0x100, // Port has Low Speed Device attached bit
249 UHCI_PORTSC_EDCH = 0x8, // Port Enable/Disable Change bit
250 UHCI_PORTSC_ENABLE = 0x4, // Port Enable bit
251 UHCI_PORTSC_CSCH = 0x2, // Port Connect Status Change bit
252 UHCI_PORTSC_CONN = 0x1, // Port Connected bit
253 };
254
255 IoBase* m_pBase;
256 bool m_HardwareOwned = false;
257 bool m_Initialised = false;
264 OperationBarrier m_CallbackOperations;
265 irq_id_t m_IrqId;
266 bool m_TimerRegistered;
267 Atomic<bool> m_InterruptsClosing;
268
269 uint8_t m_nPorts;
270 UsbHcd::PortChangeRequest m_PortChanges[UsbHcd::UhciRootPortCount];
271 Atomic<bool> m_PortChangesClosing;
272 Spinlock m_PortChangeLock;
273
274 Mutex m_Mutex;
275
280 Mutex m_AsyncQueueListChangeLock;
281
282 uint32_t* m_pFrameList;
283 uintptr_t m_pFrameListPhys;
284
285 TD* m_pTDList;
286 uintptr_t m_pTDListPhys;
287 ExtensibleBitmap m_TDBitmap;
288
289 QH* m_pAsyncQH;
290 QH* m_pPeriodicQH;
291
292 QH* m_pQHList;
293 uintptr_t m_pQHListPhys;
294 ExtensibleBitmap m_QHBitmap;
295
296 MemoryRegion m_UhciMR;
297
301
305
308 List<QH*> m_PeriodicSchedule;
309
312
315
321 Thread* m_pDequeueThread;
322
325
326 Uhci(const Uhci&);
327 void operator=(const Uhci&);
328};
329
330#endif
331
332#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 Uhci.h:54
static void enqueueCompletedTransfer(void *context)
Definition Uhci.cc:359
Mutex m_IrqProcessingLock
Definition Uhci.h:277
IrqDisposition irq(irq_id_t number) override
IRQ handler.
Definition Uhci.cc:735
size_t currentRootPortGeneration(size_t port) const override
Definition Uhci.cc:1617
virtual uint64_t executeRequest(uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)
Definition Uhci.cc:1485
QH * m_pCurrentAsyncQueueHead
Definition Uhci.h:304
virtual void getName(String &str)
Definition Uhci.h:154
void replaySuppressedConnectionChange(size_t port) override
Definition Uhci.cc:1590
virtual void cancelAsyncAndDrain(uintptr_t pTransaction, void(*pCallback)(uintptr_t, ssize_t), uintptr_t pParam)
Definition Uhci.cc:1230
bool setLegacySupportControl(uint16_t control)
Definition Uhci.cc:1641
virtual MUST_USE_RESULT bool doAsync(uintptr_t pTransaction, void(*pCallback)(uintptr_t, ssize_t)=0, uintptr_t pParam=0)
Definition Uhci.cc:1115
List< QH * > m_AsyncSchedule
List of QHs in the active asynchronous schedule.
Definition Uhci.h:307
Semaphore m_DequeueCount
Semaphore for the dequeue list.
Definition Uhci.h:314
virtual bool portReset(uint8_t nPort, bool bErrorResponse=false)
Gets a UsbDevice from a given vendor:product pair.
Definition Uhci.cc:1414
OperationBarrier m_SubmissionOperations
Definition Uhci.h:259
void cancelRequest(const Request &request) override
Definition Uhci.cc:1521
void rebuildPeriodicScheduleLocked()
Definition Uhci.cc:407
virtual MUST_USE_RESULT bool addInterruptInHandler(UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes, void(*pCallback)(uintptr_t, ssize_t), UsbInterruptInHandle &handle, uintptr_t pParam=0)
Adds an owned recurring interrupt-IN transaction.
Definition Uhci.cc:1346
void detachQueueHeadLocked(QH *pQH)
Definition Uhci.cc:370
void stop()
Stops the controller or panics before DMA ownership can be transferred.
Definition Uhci.cc:1621
void modifyPortControl(size_t portRegister, uint16_t clearMask, uint16_t setMask)
Serialises control RMWs with scanning without echoing W1C status bits.
Definition Uhci.cc:1404
MUST_USE_RESULT bool cancelInterruptInAndDrain(const UsbInterruptInToken &token, void(*callback)(uintptr_t, ssize_t), uintptr_t parameter, bool producerAlreadyStopped) override
Definition Uhci.cc:1297
List< QH * > m_DequeueList
List of QHs ready for dequeue.
Definition Uhci.h:311
virtual uintptr_t createTransaction(UsbEndpoint endpointInfo)
Creates a new transaction with the given endpoint data.
Definition Uhci.cc:1073
uint64_t m_nPortCheckTicks
The time passed since last port check.
Definition Uhci.h:324
void timer(uint64_t delta)
Timer callback to handle port status changes.
Definition Uhci.cc:1527
virtual void addTransferToTransaction(uintptr_t pTransaction, bool bToggle, UsbPid pid, uintptr_t pBuffer, size_t nBytes)
Adds a new transfer to an existent transaction.
Definition Uhci.cc:979
UsbHcd::CallbackDeliveryQueue m_CompletionDeliveries
Definition Uhci.h:279
QH * m_pCurrentAsyncQueueTail
Definition Uhci.h:300
OperationBarrier m_DequeueOperations
Definition Uhci.h:320
bool inInterruptCallbackContext() const override
Definition Uhci.h:188
OperationBarrier m_TransferOperations
Definition Uhci.h:263
void reclaimQueueHeadLocked(QH *pQH)
Definition Uhci.cc:473
OperationBarrier m_CancelOperations
Definition Uhci.h:261
void start()
Starts the controller or panics instead of leaving work silently stuck.
Definition Uhci.cc:1631
IrqDisposition
Definition IrqHandler.h:31
UsbHcd::TransferCompletion completion
Definition Uhci.h:148