2 * Copyright 2006, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
11 #include "usb_private.h"
12 #include "ehci_hardware.h"
16 struct pci_module_info
;
17 struct pci_x86_module_info
;
22 typedef struct transfer_data
{
25 ehci_qtd
* data_descriptor
;
32 // This structure is used to create a list of
33 // descriptors per isochronous transfer
34 typedef struct isochronous_transfer_data
{
36 // The next field is used to keep track
37 // of every isochronous descriptor as they are NOT
38 // linked to each other in a queue like in every other
40 ehci_itd
** descriptors
;
41 uint16 last_to_process
;
44 isochronous_transfer_data
* link
;
49 } isochronous_transfer_data
;
52 class EHCI
: public BusManager
{
54 EHCI(pci_info
*info
, Stack
*stack
);
59 virtual status_t
StartDebugTransfer(Transfer
*transfer
);
60 virtual status_t
CheckDebugTransfer(Transfer
*transfer
);
61 void LinkAsyncDebugQueueHead(ehci_qh
*queueHead
);
62 void LinkPeriodicDebugQueueHead(
63 ehci_qh
*queueHead
, Pipe
*pipe
);
64 virtual void CancelDebugTransfer(Transfer
*transfer
);
65 void CleanupDebugTransfer(Transfer
*transfer
);
67 virtual status_t
SubmitTransfer(Transfer
*transfer
);
68 status_t
SubmitIsochronous(Transfer
*transfer
);
70 virtual status_t
CancelQueuedTransfers(Pipe
*pipe
, bool force
);
71 status_t
CancelQueuedIsochronousTransfers(Pipe
*pipe
, bool force
);
73 virtual status_t
NotifyPipeChange(Pipe
*pipe
,
76 static status_t
AddTo(Stack
*stack
);
78 // Port operations for root hub
79 uint8
PortCount() { return fPortCount
; };
80 status_t
GetPortStatus(uint8 index
, usb_port_status
*status
);
81 status_t
SetPortFeature(uint8 index
, uint16 feature
);
82 status_t
ClearPortFeature(uint8 index
, uint16 feature
);
84 status_t
ResetPort(uint8 index
);
85 status_t
SuspendPort(uint8 index
);
87 virtual const char * TypeName() const { return "ehci"; };
91 status_t
ControllerReset();
92 status_t
LightReset();
94 // Interrupt functions
95 static int32
InterruptHandler(void *data
);
97 static int32
InterruptPollThread(void *data
);
99 // Transfer management
100 status_t
AddPendingTransfer(Transfer
*transfer
,
102 ehci_qtd
*dataDescriptor
,
104 status_t
AddPendingIsochronousTransfer(
106 ehci_itd
**isoRequest
, uint32 lastIndex
,
107 bool directionIn
, addr_t bufferPhy
,
108 void *bufferLog
, size_t bufferSize
);
109 status_t
CancelAllPendingTransfers();
112 static int32
FinishThread(void *data
);
113 void FinishTransfers();
114 static int32
CleanupThread(void *data
);
117 // Isochronous transfer functions
118 static int32
FinishIsochronousThread(void *data
);
119 void FinishIsochronousTransfers();
120 isochronous_transfer_data
* FindIsochronousTransfer(ehci_itd
*itd
);
121 void LinkITDescriptors(ehci_itd
*itd
,
123 void LinkSITDescriptors(ehci_sitd
*sitd
,
125 void UnlinkITDescriptors(ehci_itd
*itd
,
127 void UnlinkSITDescriptors(ehci_sitd
*sitd
,
130 // Queue Head functions
131 ehci_qh
* CreateQueueHead();
132 status_t
InitQueueHead(ehci_qh
*queueHead
,
134 void FreeQueueHead(ehci_qh
*queueHead
);
136 status_t
LinkQueueHead(ehci_qh
*queueHead
);
137 status_t
LinkInterruptQueueHead(ehci_qh
*queueHead
,
139 status_t
UnlinkQueueHead(ehci_qh
*queueHead
,
143 status_t
FillQueueWithRequest(Transfer
*transfer
,
145 ehci_qtd
**dataDescriptor
,
147 status_t
FillQueueWithData(Transfer
*transfer
,
149 ehci_qtd
**dataDescriptor
,
152 bool LockIsochronous();
153 void UnlockIsochronous();
155 // Descriptor functions
156 ehci_qtd
* CreateDescriptor(
157 size_t bufferSizeToAllocate
,
159 status_t
CreateDescriptorChain(Pipe
*pipe
,
160 ehci_qtd
**firstDescriptor
,
161 ehci_qtd
**lastDescriptor
,
162 ehci_qtd
*strayDescriptor
,
163 size_t bufferSizeToAllocate
,
165 ehci_itd
* CreateItdDescriptor();
166 ehci_sitd
* CreateSitdDescriptor();
168 void FreeDescriptor(ehci_qtd
*descriptor
);
169 void FreeDescriptorChain(ehci_qtd
*topDescriptor
);
170 void FreeDescriptor(ehci_itd
*descriptor
);
171 void FreeDescriptor(ehci_sitd
*descriptor
);
172 void FreeIsochronousData(
173 isochronous_transfer_data
*data
);
175 void LinkDescriptors(ehci_qtd
*first
,
176 ehci_qtd
*last
, ehci_qtd
*alt
);
178 size_t WriteDescriptorChain(
179 ehci_qtd
*topDescriptor
,
180 iovec
*vector
, size_t vectorCount
);
181 size_t ReadDescriptorChain(ehci_qtd
*topDescriptor
,
182 iovec
*vector
, size_t vectorCount
,
183 bool *nextDataToggle
);
184 size_t ReadActualLength(ehci_qtd
*topDescriptor
,
185 bool *nextDataToggle
);
186 size_t WriteIsochronousDescriptorChain(
187 isochronous_transfer_data
*transfer
,
190 size_t ReadIsochronousDescriptorChain(
191 isochronous_transfer_data
*transfer
);
193 // Operational register functions
194 inline void WriteOpReg(uint32 reg
, uint32 value
);
195 inline uint32
ReadOpReg(uint32 reg
);
197 // Capability register functions
198 inline uint8
ReadCapReg8(uint32 reg
);
199 inline uint16
ReadCapReg16(uint32 reg
);
200 inline uint32
ReadCapReg32(uint32 reg
);
202 static pci_module_info
* sPCIModule
;
203 static pci_x86_module_info
* sPCIx86Module
;
205 uint8
* fCapabilityRegisters
;
206 uint8
* fOperationalRegisters
;
207 area_id fRegisterArea
;
210 uint32 fEnabledInterrupts
;
213 // Periodic transfer framelist and interrupt entries
214 area_id fPeriodicFrameListArea
;
215 uint32
* fPeriodicFrameList
;
216 interrupt_entry
* fInterruptEntries
;
217 ehci_itd
** fItdEntries
;
218 ehci_sitd
** fSitdEntries
;
220 // Async transfer queue management
221 ehci_qh
* fAsyncQueueHead
;
222 sem_id fAsyncAdvanceSem
;
224 // Maintain a linked list of transfers
225 transfer_data
* fFirstTransfer
;
226 transfer_data
* fLastTransfer
;
227 sem_id fFinishTransfersSem
;
228 thread_id fFinishThread
;
229 Pipe
* fProcessingPipe
;
231 ehci_qh
* fFreeListHead
;
233 thread_id fCleanupThread
;
235 int32 fNextStartingFrame
;
237 // fFrameBandwidth[n] holds the available bandwidth
238 // of the nth frame in microseconds
239 uint16
* fFrameBandwidth
;
241 // Maintain a linked list of isochronous transfers
242 isochronous_transfer_data
* fFirstIsochronousTransfer
;
243 isochronous_transfer_data
* fLastIsochronousTransfer
;
244 sem_id fFinishIsochronousTransfersSem
;
245 thread_id fFinishIsochronousThread
;
246 mutex fIsochronousLock
;
249 EHCIRootHub
* fRootHub
;
250 uint8 fRootHubAddress
;
254 uint16 fPortResetChange
;
255 uint16 fPortSuspendChange
;
258 thread_id fInterruptPollThread
;
264 class EHCIRootHub
: public Hub
{
266 EHCIRootHub(Object
*rootObject
,
269 static status_t
ProcessTransfer(EHCI
*ehci
,