xref: /haiku/src/add-ons/kernel/busses/usb/uhci.h (revision 56430ad8002b8fd1ac69b590e9cc130de6d9e852)
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 struct pci_x86_module_info;
27 
28 class UHCIRootHub;
29 
30 
31 class Queue {
32 public:
33 									Queue(Stack *stack);
34 									~Queue();
35 
36 		bool						Lock();
37 		void						Unlock();
38 
39 		status_t					InitCheck();
40 
41 		status_t					LinkTo(Queue *other);
42 		status_t					TerminateByStrayDescriptor();
43 
44 		status_t					AppendTransfer(uhci_qh *transfer,
45 										bool lock = true);
46 		status_t					RemoveTransfer(uhci_qh *transfer,
47 										bool lock = true);
48 
49 		uint32						PhysicalAddress();
50 
51 		void						PrintToStream();
52 
53 		usb_id						USBID() { return 0; };
54 		const char *				TypeName() { return "uhci"; };
55 
56 private:
57 		status_t					fStatus;
58 		Stack *						fStack;
59 		uhci_qh *					fQueueHead;
60 		uhci_td *					fStrayDescriptor;
61 		uhci_qh *					fQueueTop;
62 		mutex						fLock;
63 };
64 
65 
66 typedef struct transfer_data {
67 	Transfer *		transfer;
68 	Queue *			queue;
69 	uhci_qh *		transfer_queue;
70 	uhci_td *		first_descriptor;
71 	uhci_td *		data_descriptor;
72 	bool			incoming;
73 	bool			canceled;
74 	uint16			free_after_frame;
75 	transfer_data *	link;
76 } transfer_data;
77 
78 
79 // This structure is used to create a list of
80 // descriptors per isochronous transfer
81 typedef struct isochronous_transfer_data {
82 	Transfer *					transfer;
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
86 	// transfer type
87 	uhci_td **					descriptors;
88 	uint16						last_to_process;
89 	bool						incoming;
90 	bool						is_active;
91 	isochronous_transfer_data *	link;
92 } isochronous_transfer_data;
93 
94 
95 class UHCI : public BusManager {
96 public:
97 									UHCI(pci_info *info, Stack *stack);
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 static	status_t					AddTo(Stack *stack);
113 
114 		// Port operations
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);
118 
119 		status_t					ResetPort(uint8 index);
120 
121 virtual	const char *				TypeName() const { return "uhci"; };
122 
123 private:
124 		// Controller resets
125 		void						GlobalReset();
126 		status_t					ControllerReset();
127 
128 		// Interrupt functions
129 static	int32						InterruptHandler(void *data);
130 		int32						Interrupt();
131 
132 		// Transfer functions
133 		status_t					AddPendingTransfer(Transfer *transfer,
134 										Queue *queue,
135 										uhci_qh *transferQueue,
136 										uhci_td *firstDescriptor,
137 										uhci_td *dataDescriptor,
138 										bool directionIn);
139 		status_t					AddPendingIsochronousTransfer(
140 										Transfer *transfer,
141 										uhci_td **isoRequest,
142 										bool directionIn);
143 
144 static	int32						FinishThread(void *data);
145 		void						FinishTransfers();
146 
147 		void						AddToFreeList(transfer_data *transfer);
148 static	int32						CleanupThread(void *data);
149 		void						Cleanup();
150 
151 		status_t					CreateFilledTransfer(Transfer *transfer,
152 										uhci_td **_firstDescriptor,
153 										uhci_qh **_transferQueue);
154 
155 		// Isochronous transfer functions
156 static int32						FinishIsochronousThread(void *data);
157 		void						FinishIsochronousTransfers();
158 		isochronous_transfer_data *	FindIsochronousTransfer(uhci_td *descriptor);
159 
160 		status_t					LinkIsochronousDescriptor(
161 										uhci_td *descriptor,
162 										uint16 frame);
163 		uhci_td *					UnlinkIsochronousDescriptor(uint16 frame);
164 
165 		// Transfer queue functions
166 		uhci_qh *					CreateTransferQueue(uhci_td *descriptor);
167 		void						FreeTransferQueue(uhci_qh *queueHead);
168 
169 		bool						LockIsochronous();
170 		void						UnlockIsochronous();
171 
172 		// Descriptor functions
173 		uhci_td *					CreateDescriptor(Pipe *pipe,
174 										uint8 direction,
175 										size_t bufferSizeToAllocate);
176 		status_t					CreateDescriptorChain(Pipe *pipe,
177 										uhci_td **firstDescriptor,
178 										uhci_td **lastDescriptor,
179 										uint8 direction,
180 										size_t bufferSizeToAllocate);
181 
182 		void						FreeDescriptor(uhci_td *descriptor);
183 		void						FreeDescriptorChain(uhci_td *topDescriptor);
184 
185 		void						LinkDescriptors(uhci_td *first,
186 										uhci_td *second);
187 
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,
197 										uint32 packetCount,
198 										iovec *vector);
199 		void						ReadIsochronousDescriptorChain(
200 										isochronous_transfer_data *transfer,
201 										iovec *vector);
202 
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);
210 
211 static	pci_module_info *			sPCIModule;
212 static	pci_x86_module_info *		sPCIx86Module;
213 
214 		uint32						fRegisterBase;
215 		pci_info *					fPCIInfo;
216 		Stack *						fStack;
217 		uint32						fEnabledInterrupts;
218 
219 		// Frame list memory
220 		area_id						fFrameArea;
221 		uint32 *					fFrameList;
222 
223 		// fFrameBandwidth[n] holds the available bandwidth
224 		// of the nth frame in microseconds
225 		uint16 *					fFrameBandwidth;
226 
227 		// fFirstIsochronousTransfer[n] and fLastIsochronousDescriptor[n]
228 		// keeps track of the first and last isochronous transfer descriptor
229 		// in the nth frame
230 		uhci_td **					fFirstIsochronousDescriptor;
231 		uhci_td **					fLastIsochronousDescriptor;
232 
233 		// Queues
234 		int32						fQueueCount;
235 		Queue **					fQueues;
236 
237 		// Maintain a linked list of transfers
238 		transfer_data *				fFirstTransfer;
239 		transfer_data *				fLastTransfer;
240 		sem_id						fFinishTransfersSem;
241 		thread_id					fFinishThread;
242 		bool						fStopThreads;
243 		Pipe *						fProcessingPipe;
244 
245 		transfer_data *				fFreeList;
246 		thread_id					fCleanupThread;
247 		sem_id						fCleanupSem;
248 		int32						fCleanupCount;
249 
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;
256 
257 		// Root hub
258 		UHCIRootHub *				fRootHub;
259 		uint8						fRootHubAddress;
260 		uint8						fPortResetChange;
261 
262 		uint8						fIRQ;
263 		bool						fUseMSI;
264 };
265 
266 
267 class UHCIRootHub : public Hub {
268 public:
269 									UHCIRootHub(Object *rootObject,
270 										int8 deviceAddress);
271 
272 static	status_t					ProcessTransfer(UHCI *uhci,
273 										Transfer *transfer);
274 };
275 
276 
277 #endif
278