xref: /haiku/src/add-ons/kernel/busses/usb/ehci.h (revision f84c53e4acb4c8a9e4dadd4ce165ca3a126114b1)
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 									EHCI(pci_info *info, Stack *stack);
55 									~EHCI();
56 
57 		status_t					Start();
58 
59 virtual	status_t					StartDebugTransfer(Transfer *transfer);
60 virtual	status_t					CheckDebugTransfer(Transfer *transfer);
61 		void						LinkAsyncDebugQueueHead(ehci_qh *queueHead);
62 		void						LinkPeriodicDebugQueueHead(
63 										ehci_qh *queueHead, Pipe *pipe);
64 virtual	void						CancelDebugTransfer(Transfer *transfer);
65 		void						CleanupDebugTransfer(Transfer *transfer);
66 
67 virtual	status_t					SubmitTransfer(Transfer *transfer);
68 		status_t					SubmitIsochronous(Transfer *transfer);
69 
70 virtual	status_t					CancelQueuedTransfers(Pipe *pipe, bool force);
71 		status_t					CancelQueuedIsochronousTransfers(Pipe *pipe, bool force);
72 
73 virtual	status_t					NotifyPipeChange(Pipe *pipe,
74 										usb_change change);
75 
76 static	status_t					AddTo(Stack *stack);
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 		status_t					FillQueueWithData(Transfer *transfer,
148 										ehci_qh *queueHead,
149 										ehci_qtd **dataDescriptor,
150 										bool *directionIn);
151 
152 		bool						LockIsochronous();
153 		void						UnlockIsochronous();
154 
155 		// Descriptor functions
156 		ehci_qtd *					CreateDescriptor(
157 										size_t bufferSizeToAllocate,
158 										uint8 pid);
159 		status_t					CreateDescriptorChain(Pipe *pipe,
160 										ehci_qtd **firstDescriptor,
161 										ehci_qtd **lastDescriptor,
162 										ehci_qtd *strayDescriptor,
163 										size_t bufferSizeToAllocate,
164 										uint8 pid);
165 		ehci_itd*					CreateItdDescriptor();
166 		ehci_sitd*					CreateSitdDescriptor();
167 
168 		void						FreeDescriptor(ehci_qtd *descriptor);
169 		void						FreeDescriptorChain(ehci_qtd *topDescriptor);
170 		void						FreeDescriptor(ehci_itd *descriptor);
171 		void						FreeDescriptor(ehci_sitd *descriptor);
172 		void						FreeIsochronousData(
173 										isochronous_transfer_data *data);
174 
175 		void						LinkDescriptors(ehci_qtd *first,
176 										ehci_qtd *last, ehci_qtd *alt);
177 
178 		size_t						WriteDescriptorChain(
179 										ehci_qtd *topDescriptor,
180 										iovec *vector, size_t vectorCount);
181 		size_t						ReadDescriptorChain(ehci_qtd *topDescriptor,
182 										iovec *vector, size_t vectorCount,
183 										bool *nextDataToggle);
184 		size_t						ReadActualLength(ehci_qtd *topDescriptor,
185 										bool *nextDataToggle);
186 		size_t						WriteIsochronousDescriptorChain(
187 										isochronous_transfer_data *transfer,
188 										uint32 packetCount,
189 										iovec *vector);
190 		size_t						ReadIsochronousDescriptorChain(
191 										isochronous_transfer_data *transfer);
192 
193 		// Operational register functions
194 inline	void						WriteOpReg(uint32 reg, uint32 value);
195 inline	uint32						ReadOpReg(uint32 reg);
196 
197 		// Capability register functions
198 inline	uint8						ReadCapReg8(uint32 reg);
199 inline	uint16						ReadCapReg16(uint32 reg);
200 inline	uint32						ReadCapReg32(uint32 reg);
201 
202 static	pci_module_info *			sPCIModule;
203 static	pci_x86_module_info *		sPCIx86Module;
204 
205 		uint8 *						fCapabilityRegisters;
206 		uint8 *						fOperationalRegisters;
207 		area_id						fRegisterArea;
208 		pci_info *					fPCIInfo;
209 		Stack *						fStack;
210 		uint32						fEnabledInterrupts;
211 		uint32						fThreshold;
212 
213 		// Periodic transfer framelist and interrupt entries
214 		area_id						fPeriodicFrameListArea;
215 		uint32 *					fPeriodicFrameList;
216 		interrupt_entry *			fInterruptEntries;
217 		ehci_itd **					fItdEntries;
218 		ehci_sitd **				fSitdEntries;
219 
220 		// Async transfer queue management
221 		ehci_qh *					fAsyncQueueHead;
222 		sem_id						fAsyncAdvanceSem;
223 
224 		// Maintain a linked list of transfers
225 		transfer_data *				fFirstTransfer;
226 		transfer_data *				fLastTransfer;
227 		sem_id						fFinishTransfersSem;
228 		thread_id					fFinishThread;
229 		Pipe *						fProcessingPipe;
230 
231 		ehci_qh *					fFreeListHead;
232 		sem_id						fCleanupSem;
233 		thread_id					fCleanupThread;
234 		bool						fStopThreads;
235 		int32						fNextStartingFrame;
236 
237 		// fFrameBandwidth[n] holds the available bandwidth
238 		// of the nth frame in microseconds
239 		uint16 *					fFrameBandwidth;
240 
241 		// Maintain a linked list of isochronous transfers
242 		isochronous_transfer_data *	fFirstIsochronousTransfer;
243 		isochronous_transfer_data *	fLastIsochronousTransfer;
244 		sem_id						fFinishIsochronousTransfersSem;
245 		thread_id					fFinishIsochronousThread;
246 		mutex						fIsochronousLock;
247 
248 		// Root Hub
249 		EHCIRootHub *				fRootHub;
250 		uint8						fRootHubAddress;
251 
252 		// Port management
253 		uint8						fPortCount;
254 		uint16						fPortResetChange;
255 		uint16						fPortSuspendChange;
256 
257 		// Interrupt polling
258 		thread_id					fInterruptPollThread;
259 		uint8						fIRQ;
260 		bool						fUseMSI;
261 };
262 
263 
264 class EHCIRootHub : public Hub {
265 public:
266 									EHCIRootHub(Object *rootObject,
267 										int8 deviceAddress);
268 
269 static	status_t					ProcessTransfer(EHCI *ehci,
270 										Transfer *transfer);
271 };
272 
273 
274 #endif // !EHCI_H
275