xref: /haiku/src/add-ons/kernel/busses/usb/uhci.h (revision e5d65858f2361fe0552495b61620c84dcee6bc00)
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_module_info;
26 class UHCIRootHub;
27 class DebugTransfer;
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 
52 		usb_id						USBID() { return 0; };
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, Stack *stack);
97 									~UHCI();
98 
99 		status_t					Start();
100 virtual	status_t					SubmitTransfer(Transfer *transfer);
101 		status_t					StartDebugTransfer(DebugTransfer *transfer);
102 		status_t					CheckDebugTransfer(DebugTransfer *transfer,
103 										bool &_stillPending);
104 		void						CancelDebugTransfer(
105 										DebugTransfer *transfer);
106 virtual	status_t					CancelQueuedTransfers(Pipe *pipe, bool force);
107 		status_t					CancelQueuedIsochronousTransfers(Pipe *pipe, bool force);
108 		status_t					SubmitRequest(Transfer *transfer);
109 		status_t					SubmitIsochronous(Transfer *transfer);
110 
111 static	status_t					AddTo(Stack *stack);
112 
113 		// Port operations
114 		status_t					GetPortStatus(uint8 index, usb_port_status *status);
115 		status_t					SetPortFeature(uint8 index, uint16 feature);
116 		status_t					ClearPortFeature(uint8 index, uint16 feature);
117 
118 		status_t					ResetPort(uint8 index);
119 
120 virtual	const char *				TypeName() const { return "uhci"; };
121 
122 private:
123 		// Controller resets
124 		void						GlobalReset();
125 		status_t					ControllerReset();
126 
127 		// Interrupt functions
128 static	int32						InterruptHandler(void *data);
129 		int32						Interrupt();
130 
131 		// Transfer functions
132 		status_t					AddPendingTransfer(Transfer *transfer,
133 										Queue *queue,
134 										uhci_qh *transferQueue,
135 										uhci_td *firstDescriptor,
136 										uhci_td *dataDescriptor,
137 										bool directionIn);
138 		status_t					AddPendingIsochronousTransfer(
139 										Transfer *transfer,
140 										uhci_td **isoRequest,
141 										bool directionIn);
142 
143 static	int32						FinishThread(void *data);
144 		void						FinishTransfers();
145 
146 		void						AddToFreeList(transfer_data *transfer);
147 static	int32						CleanupThread(void *data);
148 		void						Cleanup();
149 
150 		status_t					CreateFilledTransfer(Transfer *transfer,
151 										uhci_td **_firstDescriptor,
152 										uhci_qh **_transferQueue);
153 
154 		// Isochronous transfer functions
155 static int32						FinishIsochronousThread(void *data);
156 		void						FinishIsochronousTransfers();
157 		isochronous_transfer_data *	FindIsochronousTransfer(uhci_td *descriptor);
158 
159 		status_t					LinkIsochronousDescriptor(
160 										uhci_td *descriptor,
161 										uint16 frame);
162 		uhci_td *					UnlinkIsochronousDescriptor(uint16 frame);
163 
164 		// Transfer queue functions
165 		uhci_qh *					CreateTransferQueue(uhci_td *descriptor);
166 		void						FreeTransferQueue(uhci_qh *queueHead);
167 
168 		bool						LockIsochronous();
169 		void						UnlockIsochronous();
170 
171 		// Descriptor functions
172 		uhci_td *					CreateDescriptor(Pipe *pipe,
173 										uint8 direction,
174 										size_t bufferSizeToAllocate);
175 		status_t					CreateDescriptorChain(Pipe *pipe,
176 										uhci_td **firstDescriptor,
177 										uhci_td **lastDescriptor,
178 										uint8 direction,
179 										size_t bufferSizeToAllocate);
180 
181 		void						FreeDescriptor(uhci_td *descriptor);
182 		void						FreeDescriptorChain(uhci_td *topDescriptor);
183 
184 		void						LinkDescriptors(uhci_td *first,
185 										uhci_td *second);
186 
187 		size_t						WriteDescriptorChain(uhci_td *topDescriptor,
188 										iovec *vector, size_t vectorCount);
189 		size_t						ReadDescriptorChain(uhci_td *topDescriptor,
190 										iovec *vector, size_t vectorCount,
191 										uint8 *lastDataToggle);
192 		size_t						ReadActualLength(uhci_td *topDescriptor,
193 										uint8 *lastDataToggle);
194 		void						WriteIsochronousDescriptorChain(
195 										uhci_td **isoRequest,
196 										uint32 packetCount,
197 										iovec *vector);
198 		void						ReadIsochronousDescriptorChain(
199 										isochronous_transfer_data *transfer,
200 										iovec *vector);
201 
202 		// Register functions
203 inline	void						WriteReg8(uint32 reg, uint8 value);
204 inline	void						WriteReg16(uint32 reg, uint16 value);
205 inline	void						WriteReg32(uint32 reg, uint32 value);
206 inline	uint8						ReadReg8(uint32 reg);
207 inline	uint16						ReadReg16(uint32 reg);
208 inline	uint32						ReadReg32(uint32 reg);
209 
210 static	pci_module_info *			sPCIModule;
211 
212 		uint32						fRegisterBase;
213 		pci_info *					fPCIInfo;
214 		Stack *						fStack;
215 		uint32						fEnabledInterrupts;
216 
217 		// Frame list memory
218 		area_id						fFrameArea;
219 		uint32 *					fFrameList;
220 
221 		// fFrameBandwidth[n] holds the available bandwidth
222 		// of the nth frame in microseconds
223 		uint16 *					fFrameBandwidth;
224 
225 		// fFirstIsochronousTransfer[n] and fLastIsochronousDescriptor[n]
226 		// keeps track of the first and last isochronous transfer descriptor
227 		// in the nth frame
228 		uhci_td **					fFirstIsochronousDescriptor;
229 		uhci_td **					fLastIsochronousDescriptor;
230 
231 		// Queues
232 		int32						fQueueCount;
233 		Queue **					fQueues;
234 
235 		// Maintain a linked list of transfers
236 		transfer_data *				fFirstTransfer;
237 		transfer_data *				fLastTransfer;
238 		sem_id						fFinishTransfersSem;
239 		thread_id					fFinishThread;
240 		bool						fStopThreads;
241 		Pipe *						fProcessingPipe;
242 
243 		transfer_data *				fFreeList;
244 		thread_id					fCleanupThread;
245 		sem_id						fCleanupSem;
246 		int32						fCleanupCount;
247 
248 		// Maintain a linked list of isochronous transfers
249 		isochronous_transfer_data *	fFirstIsochronousTransfer;
250 		isochronous_transfer_data *	fLastIsochronousTransfer;
251 		sem_id						fFinishIsochronousTransfersSem;
252 		thread_id					fFinishIsochronousThread;
253 		mutex						fIsochronousLock;
254 
255 		// Root hub
256 		UHCIRootHub *				fRootHub;
257 		uint8						fRootHubAddress;
258 		uint8						fPortResetChange;
259 };
260 
261 
262 class UHCIRootHub : public Hub {
263 public:
264 									UHCIRootHub(Object *rootObject,
265 										int8 deviceAddress);
266 
267 static	status_t					ProcessTransfer(UHCI *uhci,
268 										Transfer *transfer);
269 };
270 
271 
272 #endif
273