xref: /haiku/src/add-ons/kernel/busses/usb/uhci.h (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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 
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, 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 
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 										iovec *vector, size_t vectorCount);
188 		size_t						ReadDescriptorChain(uhci_td *topDescriptor,
189 										iovec *vector, size_t vectorCount,
190 										uint8 *lastDataToggle);
191 		size_t						ReadActualLength(uhci_td *topDescriptor,
192 										uint8 *lastDataToggle);
193 		void						WriteIsochronousDescriptorChain(
194 										uhci_td **isoRequest,
195 										uint32 packetCount,
196 										iovec *vector);
197 		void						ReadIsochronousDescriptorChain(
198 										isochronous_transfer_data *transfer,
199 										iovec *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 		uint8						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