1 /*
2 * Copyright 2004-2011, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 * Niels S. Reedijk
8 * Salvatore Benedetto <salvatore.benedetto@gmail.com>
9 */
10 #ifndef UHCI_H
11 #define UHCI_H
12
13 #include "usb_private.h"
14 #include "uhci_hardware.h"
15 #include <lock.h>
16
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
23
24 struct pci_info;
25 struct pci_device_module_info;
26 struct pci_device;
27 class UHCIRootHub;
28
29
30 class Queue {
31 public:
32 Queue(Stack *stack);
33 ~Queue();
34
35 bool Lock();
36 void Unlock();
37
38 status_t InitCheck();
39
40 status_t LinkTo(Queue *other);
41 status_t TerminateByStrayDescriptor();
42
43 status_t AppendTransfer(uhci_qh *transfer,
44 bool lock = true);
45 status_t RemoveTransfer(uhci_qh *transfer,
46 bool lock = true);
47
48 uint32 PhysicalAddress();
49
50 void PrintToStream();
51
USBID()52 usb_id USBID() { return 0; };
TypeName()53 const char * TypeName() { return "uhci"; };
54
55 private:
56 status_t fStatus;
57 Stack * fStack;
58 uhci_qh * fQueueHead;
59 uhci_td * fStrayDescriptor;
60 uhci_qh * fQueueTop;
61 mutex fLock;
62 };
63
64
65 typedef struct transfer_data {
66 Transfer * transfer;
67 Queue * queue;
68 uhci_qh * transfer_queue;
69 uhci_td * first_descriptor;
70 uhci_td * data_descriptor;
71 bool incoming;
72 bool canceled;
73 uint16 free_after_frame;
74 transfer_data * link;
75 } transfer_data;
76
77
78 // This structure is used to create a list of
79 // descriptors per isochronous transfer
80 typedef struct isochronous_transfer_data {
81 Transfer * transfer;
82 // The next field is used to keep track
83 // of every isochronous descriptor as they are NOT
84 // linked to each other in a queue like in every other
85 // transfer type
86 uhci_td ** descriptors;
87 uint16 last_to_process;
88 bool incoming;
89 bool is_active;
90 isochronous_transfer_data * link;
91 } isochronous_transfer_data;
92
93
94 class UHCI : public BusManager {
95 public:
96 UHCI(pci_info *info, pci_device_module_info* pci,
97 pci_device* device, Stack *stack, device_node* node);
98 ~UHCI();
99
100 status_t Start();
101 virtual status_t SubmitTransfer(Transfer *transfer);
102
103 virtual status_t StartDebugTransfer(Transfer *transfer);
104 virtual status_t CheckDebugTransfer(Transfer *transfer);
105 virtual void CancelDebugTransfer(Transfer *transfer);
106
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);
111
112 // Port operations
113 status_t GetPortStatus(uint8 index, usb_port_status *status);
114 status_t SetPortFeature(uint8 index, uint16 feature);
115 status_t ClearPortFeature(uint8 index, uint16 feature);
116
117 status_t ResetPort(uint8 index);
118
TypeName()119 virtual const char * TypeName() const { return "uhci"; };
120
121 private:
122 // Controller resets
123 void GlobalReset();
124 status_t ControllerReset();
125
126 // Interrupt functions
127 static int32 InterruptHandler(void *data);
128 int32 Interrupt();
129
130 // Transfer functions
131 status_t AddPendingTransfer(Transfer *transfer,
132 Queue *queue,
133 uhci_qh *transferQueue,
134 uhci_td *firstDescriptor,
135 uhci_td *dataDescriptor,
136 bool directionIn);
137 status_t AddPendingIsochronousTransfer(
138 Transfer *transfer,
139 uhci_td **isoRequest,
140 bool directionIn);
141
142 static int32 FinishThread(void *data);
143 void FinishTransfers();
144
145 void AddToFreeList(transfer_data *transfer);
146 static int32 CleanupThread(void *data);
147 void Cleanup();
148
149 status_t CreateFilledTransfer(Transfer *transfer,
150 uhci_td **_firstDescriptor,
151 uhci_qh **_transferQueue);
152
153 // Isochronous transfer functions
154 static int32 FinishIsochronousThread(void *data);
155 void FinishIsochronousTransfers();
156 isochronous_transfer_data * FindIsochronousTransfer(uhci_td *descriptor);
157
158 status_t LinkIsochronousDescriptor(
159 uhci_td *descriptor,
160 uint16 frame);
161 uhci_td * UnlinkIsochronousDescriptor(uint16 frame);
162
163 // Transfer queue functions
164 uhci_qh * CreateTransferQueue(uhci_td *descriptor);
165 void FreeTransferQueue(uhci_qh *queueHead);
166
167 bool LockIsochronous();
168 void UnlockIsochronous();
169
170 // Descriptor functions
171 uhci_td * CreateDescriptor(Pipe *pipe,
172 uint8 direction,
173 size_t bufferSizeToAllocate);
174 status_t CreateDescriptorChain(Pipe *pipe,
175 uhci_td **firstDescriptor,
176 uhci_td **lastDescriptor,
177 uint8 direction,
178 size_t bufferSizeToAllocate);
179
180 void FreeDescriptor(uhci_td *descriptor);
181 void FreeDescriptorChain(uhci_td *topDescriptor);
182
183 void LinkDescriptors(uhci_td *first,
184 uhci_td *second);
185
186 size_t WriteDescriptorChain(uhci_td *topDescriptor,
187 generic_io_vec *vector, size_t vectorCount, bool physical);
188 size_t ReadDescriptorChain(uhci_td *topDescriptor,
189 generic_io_vec *vector, size_t vectorCount, bool physical,
190 uint8 *lastDataToggle);
191 size_t ReadActualLength(uhci_td *topDescriptor,
192 uint8 *lastDataToggle);
193 void WriteIsochronousDescriptorChain(
194 uhci_td **isoRequest,
195 uint32 packetCount,
196 generic_io_vec *vector);
197 void ReadIsochronousDescriptorChain(
198 isochronous_transfer_data *transfer,
199 generic_io_vec *vector);
200
201 // Register functions
202 inline void WriteReg8(uint32 reg, uint8 value);
203 inline void WriteReg16(uint32 reg, uint16 value);
204 inline void WriteReg32(uint32 reg, uint32 value);
205 inline uint8 ReadReg8(uint32 reg);
206 inline uint16 ReadReg16(uint32 reg);
207 inline uint32 ReadReg32(uint32 reg);
208
209 uint32 fRegisterBase;
210 pci_info * fPCIInfo;
211 pci_device_module_info* fPci;
212 pci_device* fDevice;
213 Stack * fStack;
214 uint32 fEnabledInterrupts;
215
216 // Frame list memory
217 area_id fFrameArea;
218 uint32 * fFrameList;
219
220 // fFrameBandwidth[n] holds the available bandwidth
221 // of the nth frame in microseconds
222 uint16 * fFrameBandwidth;
223
224 // fFirstIsochronousTransfer[n] and fLastIsochronousDescriptor[n]
225 // keeps track of the first and last isochronous transfer descriptor
226 // in the nth frame
227 uhci_td ** fFirstIsochronousDescriptor;
228 uhci_td ** fLastIsochronousDescriptor;
229
230 // Queues
231 int32 fQueueCount;
232 Queue ** fQueues;
233
234 // Maintain a linked list of transfers
235 transfer_data * fFirstTransfer;
236 transfer_data * fLastTransfer;
237 sem_id fFinishTransfersSem;
238 thread_id fFinishThread;
239 bool fStopThreads;
240 Pipe * fProcessingPipe;
241
242 transfer_data * fFreeList;
243 thread_id fCleanupThread;
244 sem_id fCleanupSem;
245 int32 fCleanupCount;
246
247 // Maintain a linked list of isochronous transfers
248 isochronous_transfer_data * fFirstIsochronousTransfer;
249 isochronous_transfer_data * fLastIsochronousTransfer;
250 sem_id fFinishIsochronousTransfersSem;
251 thread_id fFinishIsochronousThread;
252 mutex fIsochronousLock;
253
254 // Root hub
255 UHCIRootHub * fRootHub;
256 uint8 fRootHubAddress;
257 uint8 fPortResetChange;
258
259 uint32 fIRQ;
260 bool fUseMSI;
261 };
262
263
264 class UHCIRootHub : public Hub {
265 public:
266 UHCIRootHub(Object *rootObject,
267 int8 deviceAddress);
268
269 static status_t ProcessTransfer(UHCI *uhci,
270 Transfer *transfer);
271 };
272
273
274 #endif
275