xref: /haiku/src/add-ons/kernel/busses/usb/ehci.h (revision 21258e2674226d6aa732321b6f8494841895af5f)
1 /*
2  * Copyright 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  */
8 #ifndef EHCI_H
9 #define EHCI_H
10 
11 #include "usb_private.h"
12 #include "ehci_hardware.h"
13 
14 
15 struct pci_info;
16 struct pci_module_info;
17 struct pci_x86_module_info;
18 
19 class EHCIRootHub;
20 
21 
22 typedef struct transfer_data {
23 	Transfer *		transfer;
24 	ehci_qh *		queue_head;
25 	ehci_qtd *		data_descriptor;
26 	bool			incoming;
27 	bool			canceled;
28 	transfer_data *	link;
29 } transfer_data;
30 
31 
32 // This structure is used to create a list of
33 // descriptors per isochronous transfer
34 typedef struct isochronous_transfer_data {
35 	Transfer *					transfer;
36 	// The next field is used to keep track
37 	// of every isochronous descriptor as they are NOT
38 	// linked to each other in a queue like in every other
39 	// transfer type
40 	ehci_itd **					descriptors;
41 	uint16						last_to_process;
42 	bool						incoming;
43 	bool						is_active;
44 	isochronous_transfer_data *	link;
45 
46 	size_t						buffer_size;
47 	void *						buffer_log;
48 	addr_t						buffer_phy;
49 } isochronous_transfer_data;
50 
51 
52 class EHCI : public BusManager {
53 public:
54 static	status_t					AddTo(Stack *stack);
55 
56 									EHCI(pci_info *info, Stack *stack);
57 									~EHCI();
58 
59 		status_t					Start();
60 
61 virtual	status_t					StartDebugTransfer(Transfer *transfer);
62 virtual	status_t					CheckDebugTransfer(Transfer *transfer);
63 		void						LinkAsyncDebugQueueHead(ehci_qh *queueHead);
64 		void						LinkPeriodicDebugQueueHead(
65 										ehci_qh *queueHead, Pipe *pipe);
66 virtual	void						CancelDebugTransfer(Transfer *transfer);
67 		void						CleanupDebugTransfer(Transfer *transfer);
68 
69 virtual	status_t					SubmitTransfer(Transfer *transfer);
70 		status_t					SubmitIsochronous(Transfer *transfer);
71 
72 virtual	status_t					CancelQueuedTransfers(Pipe *pipe, bool force);
73 		status_t					CancelQueuedIsochronousTransfers(Pipe *pipe, bool force);
74 
75 virtual	status_t					NotifyPipeChange(Pipe *pipe,
76 										usb_change change);
77 
78 		// Port operations for root hub
79 		uint8						PortCount() { return fPortCount; }
80 		status_t					GetPortStatus(uint8 index, usb_port_status *status);
81 		status_t					SetPortFeature(uint8 index, uint16 feature);
82 		status_t					ClearPortFeature(uint8 index, uint16 feature);
83 
84 		status_t					ResetPort(uint8 index);
85 		status_t					SuspendPort(uint8 index);
86 
87 virtual	const char *				TypeName() const { return "ehci"; }
88 
89 private:
90 		// Controller resets
91 		status_t					ControllerReset();
92 		status_t					LightReset();
93 
94 		// Interrupt functions
95 static	int32						InterruptHandler(void *data);
96 		int32						Interrupt();
97 static	int32						InterruptPollThread(void *data);
98 
99 		// Transfer management
100 		status_t					AddPendingTransfer(Transfer *transfer,
101 										ehci_qh *queueHead,
102 										ehci_qtd *dataDescriptor,
103 										bool directionIn);
104 		status_t					AddPendingIsochronousTransfer(
105 										Transfer *transfer,
106 										ehci_itd **isoRequest, uint32 lastIndex,
107 										bool directionIn, addr_t bufferPhy,
108 										void *bufferLog, size_t bufferSize);
109 		status_t					CancelAllPendingTransfers();
110 
111 
112 static	int32						FinishThread(void *data);
113 		void						FinishTransfers();
114 static	int32						CleanupThread(void *data);
115 		void						Cleanup();
116 
117 		// Isochronous transfer functions
118 static int32						FinishIsochronousThread(void *data);
119 		void						FinishIsochronousTransfers();
120 		isochronous_transfer_data *	FindIsochronousTransfer(ehci_itd *itd);
121 		void						LinkITDescriptors(ehci_itd *itd,
122 										ehci_itd **last);
123 		void						LinkSITDescriptors(ehci_sitd *sitd,
124 										ehci_sitd **last);
125 		void						UnlinkITDescriptors(ehci_itd *itd,
126 										ehci_itd **last);
127 		void						UnlinkSITDescriptors(ehci_sitd *sitd,
128 										ehci_sitd **last);
129 
130 		// Queue Head functions
131 		ehci_qh *					CreateQueueHead();
132 		status_t					InitQueueHead(ehci_qh *queueHead,
133 										Pipe *pipe);
134 		void						FreeQueueHead(ehci_qh *queueHead);
135 
136 		status_t					LinkQueueHead(ehci_qh *queueHead);
137 		status_t					LinkInterruptQueueHead(ehci_qh *queueHead,
138 										Pipe *pipe);
139 		status_t					UnlinkQueueHead(ehci_qh *queueHead,
140 										ehci_qh **freeList);
141 
142 		// Queue functions
143 		status_t					FillQueueWithRequest(Transfer *transfer,
144 										ehci_qh *queueHead,
145 										ehci_qtd **dataDescriptor,
146 										bool *directionIn,
147 										bool prepareKernelAccess);
148 		status_t					FillQueueWithData(Transfer *transfer,
149 										ehci_qh *queueHead,
150 										ehci_qtd **dataDescriptor,
151 										bool *directionIn,
152 										bool prepareKernelAccess);
153 
154 		bool						LockIsochronous();
155 		void						UnlockIsochronous();
156 
157 		// Descriptor functions
158 		ehci_qtd *					CreateDescriptor(
159 										size_t bufferSizeToAllocate,
160 										uint8 pid);
161 		status_t					CreateDescriptorChain(Pipe *pipe,
162 										ehci_qtd **firstDescriptor,
163 										ehci_qtd **lastDescriptor,
164 										ehci_qtd *strayDescriptor,
165 										size_t bufferSizeToAllocate,
166 										uint8 pid);
167 		ehci_itd*					CreateItdDescriptor();
168 		ehci_sitd*					CreateSitdDescriptor();
169 
170 		void						FreeDescriptor(ehci_qtd *descriptor);
171 		void						FreeDescriptorChain(ehci_qtd *topDescriptor);
172 		void						FreeDescriptor(ehci_itd *descriptor);
173 		void						FreeDescriptor(ehci_sitd *descriptor);
174 		void						FreeIsochronousData(
175 										isochronous_transfer_data *data);
176 
177 		void						LinkDescriptors(ehci_qtd *first,
178 										ehci_qtd *last, ehci_qtd *alt);
179 
180 		size_t						WriteDescriptorChain(
181 										ehci_qtd *topDescriptor,
182 										iovec *vector, size_t vectorCount);
183 		size_t						ReadDescriptorChain(ehci_qtd *topDescriptor,
184 										iovec *vector, size_t vectorCount,
185 										bool *nextDataToggle);
186 		size_t						ReadActualLength(ehci_qtd *topDescriptor,
187 										bool *nextDataToggle);
188 		size_t						WriteIsochronousDescriptorChain(
189 										isochronous_transfer_data *transfer,
190 										uint32 packetCount,
191 										iovec *vector);
192 		size_t						ReadIsochronousDescriptorChain(
193 										isochronous_transfer_data *transfer);
194 
195 		// Operational register functions
196 inline	void						WriteOpReg(uint32 reg, uint32 value);
197 inline	uint32						ReadOpReg(uint32 reg);
198 
199 		// Capability register functions
200 inline	uint8						ReadCapReg8(uint32 reg);
201 inline	uint16						ReadCapReg16(uint32 reg);
202 inline	uint32						ReadCapReg32(uint32 reg);
203 
204 static	pci_module_info *			sPCIModule;
205 static	pci_x86_module_info *		sPCIx86Module;
206 
207 		uint8 *						fCapabilityRegisters;
208 		uint8 *						fOperationalRegisters;
209 		area_id						fRegisterArea;
210 		pci_info *					fPCIInfo;
211 		Stack *						fStack;
212 		uint32						fEnabledInterrupts;
213 		uint32						fThreshold;
214 
215 		// Periodic transfer framelist and interrupt entries
216 		area_id						fPeriodicFrameListArea;
217 		uint32 *					fPeriodicFrameList;
218 		interrupt_entry *			fInterruptEntries;
219 		ehci_itd **					fItdEntries;
220 		ehci_sitd **				fSitdEntries;
221 
222 		// Async transfer queue management
223 		ehci_qh *					fAsyncQueueHead;
224 		sem_id						fAsyncAdvanceSem;
225 
226 		// Maintain a linked list of transfers
227 		transfer_data *				fFirstTransfer;
228 		transfer_data *				fLastTransfer;
229 		sem_id						fFinishTransfersSem;
230 		thread_id					fFinishThread;
231 		Pipe *						fProcessingPipe;
232 
233 		ehci_qh *					fFreeListHead;
234 		sem_id						fCleanupSem;
235 		thread_id					fCleanupThread;
236 		bool						fStopThreads;
237 		int32						fNextStartingFrame;
238 
239 		// fFrameBandwidth[n] holds the available bandwidth
240 		// of the nth frame in microseconds
241 		uint16 *					fFrameBandwidth;
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 		EHCIRootHub *				fRootHub;
252 		uint8						fRootHubAddress;
253 
254 		// Port management
255 		uint8						fPortCount;
256 		uint16						fPortResetChange;
257 		uint16						fPortSuspendChange;
258 
259 		// Interrupt polling
260 		thread_id					fInterruptPollThread;
261 		uint8						fIRQ;
262 		bool						fUseMSI;
263 };
264 
265 
266 class EHCIRootHub : public Hub {
267 public:
268 									EHCIRootHub(Object *rootObject,
269 										int8 deviceAddress);
270 
271 static	status_t					ProcessTransfer(EHCI *ehci,
272 										Transfer *transfer);
273 };
274 
275 
276 #endif // !EHCI_H
277