2 * Copyright 2004-2011, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
8 * Salvatore Benedetto <salvatore.benedetto@gmail.com>
13 #include "usb_private.h"
14 #include "uhci_hardware.h"
17 #define UHCI_INTERRUPT_QUEUE 0
18 #define UHCI_LOW_SPEED_CONTROL_QUEUE 1
19 #define UHCI_FULL_SPEED_CONTROL_QUEUE 2
20 #define UHCI_BULK_QUEUE 3
21 #define UHCI_BANDWIDTH_RECLAMATION_QUEUE 4
22 #define UHCI_DEBUG_QUEUE 4
25 struct pci_module_info
;
26 struct pci_x86_module_info
;
41 status_t
LinkTo(Queue
*other
);
42 status_t
TerminateByStrayDescriptor();
44 status_t
AppendTransfer(uhci_qh
*transfer
,
46 status_t
RemoveTransfer(uhci_qh
*transfer
,
49 uint32
PhysicalAddress();
53 usb_id
USBID() { return 0; };
54 const char * TypeName() { return "uhci"; };
60 uhci_td
* fStrayDescriptor
;
66 typedef struct transfer_data
{
69 uhci_qh
* transfer_queue
;
70 uhci_td
* first_descriptor
;
71 uhci_td
* data_descriptor
;
74 uint16 free_after_frame
;
79 // This structure is used to create a list of
80 // descriptors per isochronous transfer
81 typedef struct isochronous_transfer_data
{
83 // The next field is used to keep track
84 // of every isochronous descriptor as they are NOT
85 // linked to each other in a queue like in every other
87 uhci_td
** descriptors
;
88 uint16 last_to_process
;
91 isochronous_transfer_data
* link
;
92 } isochronous_transfer_data
;
95 class UHCI
: public BusManager
{
97 UHCI(pci_info
*info
, Stack
*stack
);
101 virtual status_t
SubmitTransfer(Transfer
*transfer
);
103 virtual status_t
StartDebugTransfer(Transfer
*transfer
);
104 virtual status_t
CheckDebugTransfer(Transfer
*transfer
);
105 virtual void CancelDebugTransfer(Transfer
*transfer
);
107 virtual status_t
CancelQueuedTransfers(Pipe
*pipe
, bool force
);
108 status_t
CancelQueuedIsochronousTransfers(Pipe
*pipe
, bool force
);
109 status_t
SubmitRequest(Transfer
*transfer
);
110 status_t
SubmitIsochronous(Transfer
*transfer
);
112 static status_t
AddTo(Stack
*stack
);
115 status_t
GetPortStatus(uint8 index
, usb_port_status
*status
);
116 status_t
SetPortFeature(uint8 index
, uint16 feature
);
117 status_t
ClearPortFeature(uint8 index
, uint16 feature
);
119 status_t
ResetPort(uint8 index
);
121 virtual const char * TypeName() const { return "uhci"; };
126 status_t
ControllerReset();
128 // Interrupt functions
129 static int32
InterruptHandler(void *data
);
132 // Transfer functions
133 status_t
AddPendingTransfer(Transfer
*transfer
,
135 uhci_qh
*transferQueue
,
136 uhci_td
*firstDescriptor
,
137 uhci_td
*dataDescriptor
,
139 status_t
AddPendingIsochronousTransfer(
141 uhci_td
**isoRequest
,
144 static int32
FinishThread(void *data
);
145 void FinishTransfers();
147 void AddToFreeList(transfer_data
*transfer
);
148 static int32
CleanupThread(void *data
);
151 status_t
CreateFilledTransfer(Transfer
*transfer
,
152 uhci_td
**_firstDescriptor
,
153 uhci_qh
**_transferQueue
);
155 // Isochronous transfer functions
156 static int32
FinishIsochronousThread(void *data
);
157 void FinishIsochronousTransfers();
158 isochronous_transfer_data
* FindIsochronousTransfer(uhci_td
*descriptor
);
160 status_t
LinkIsochronousDescriptor(
163 uhci_td
* UnlinkIsochronousDescriptor(uint16 frame
);
165 // Transfer queue functions
166 uhci_qh
* CreateTransferQueue(uhci_td
*descriptor
);
167 void FreeTransferQueue(uhci_qh
*queueHead
);
169 bool LockIsochronous();
170 void UnlockIsochronous();
172 // Descriptor functions
173 uhci_td
* CreateDescriptor(Pipe
*pipe
,
175 size_t bufferSizeToAllocate
);
176 status_t
CreateDescriptorChain(Pipe
*pipe
,
177 uhci_td
**firstDescriptor
,
178 uhci_td
**lastDescriptor
,
180 size_t bufferSizeToAllocate
);
182 void FreeDescriptor(uhci_td
*descriptor
);
183 void FreeDescriptorChain(uhci_td
*topDescriptor
);
185 void LinkDescriptors(uhci_td
*first
,
188 size_t WriteDescriptorChain(uhci_td
*topDescriptor
,
189 iovec
*vector
, size_t vectorCount
);
190 size_t ReadDescriptorChain(uhci_td
*topDescriptor
,
191 iovec
*vector
, size_t vectorCount
,
192 uint8
*lastDataToggle
);
193 size_t ReadActualLength(uhci_td
*topDescriptor
,
194 uint8
*lastDataToggle
);
195 void WriteIsochronousDescriptorChain(
196 uhci_td
**isoRequest
,
199 void ReadIsochronousDescriptorChain(
200 isochronous_transfer_data
*transfer
,
203 // Register functions
204 inline void WriteReg8(uint32 reg
, uint8 value
);
205 inline void WriteReg16(uint32 reg
, uint16 value
);
206 inline void WriteReg32(uint32 reg
, uint32 value
);
207 inline uint8
ReadReg8(uint32 reg
);
208 inline uint16
ReadReg16(uint32 reg
);
209 inline uint32
ReadReg32(uint32 reg
);
211 static pci_module_info
* sPCIModule
;
212 static pci_x86_module_info
* sPCIx86Module
;
214 uint32 fRegisterBase
;
217 uint32 fEnabledInterrupts
;
223 // fFrameBandwidth[n] holds the available bandwidth
224 // of the nth frame in microseconds
225 uint16
* fFrameBandwidth
;
227 // fFirstIsochronousTransfer[n] and fLastIsochronousDescriptor[n]
228 // keeps track of the first and last isochronous transfer descriptor
230 uhci_td
** fFirstIsochronousDescriptor
;
231 uhci_td
** fLastIsochronousDescriptor
;
237 // Maintain a linked list of transfers
238 transfer_data
* fFirstTransfer
;
239 transfer_data
* fLastTransfer
;
240 sem_id fFinishTransfersSem
;
241 thread_id fFinishThread
;
243 Pipe
* fProcessingPipe
;
245 transfer_data
* fFreeList
;
246 thread_id fCleanupThread
;
250 // Maintain a linked list of isochronous transfers
251 isochronous_transfer_data
* fFirstIsochronousTransfer
;
252 isochronous_transfer_data
* fLastIsochronousTransfer
;
253 sem_id fFinishIsochronousTransfersSem
;
254 thread_id fFinishIsochronousThread
;
255 mutex fIsochronousLock
;
258 UHCIRootHub
* fRootHub
;
259 uint8 fRootHubAddress
;
260 uint8 fPortResetChange
;
267 class UHCIRootHub
: public Hub
{
269 UHCIRootHub(Object
*rootObject
,
272 static status_t
ProcessTransfer(UHCI
*uhci
,