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