xref: /haiku/src/add-ons/kernel/busses/usb/ehci.h (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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_device_module_info;
17 struct pci_device;
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, pci_device_module_info* pci,
55 										pci_device* device, Stack *stack, device_node *node);
56 									~EHCI();
57 
58 		status_t					Start();
59 
60 virtual	status_t					StartDebugTransfer(Transfer *transfer);
61 virtual	status_t					CheckDebugTransfer(Transfer *transfer);
62 		void						LinkAsyncDebugQueueHead(ehci_qh *queueHead);
63 		void						LinkPeriodicDebugQueueHead(
64 										ehci_qh *queueHead, Pipe *pipe);
65 virtual	void						CancelDebugTransfer(Transfer *transfer);
66 		void						CleanupDebugTransfer(Transfer *transfer);
67 
68 virtual	status_t					SubmitTransfer(Transfer *transfer);
69 		status_t					SubmitIsochronous(Transfer *transfer);
70 
71 virtual	status_t					CancelQueuedTransfers(Pipe *pipe, bool force);
72 		status_t					CancelQueuedIsochronousTransfers(Pipe *pipe, bool force);
73 
74 virtual	status_t					NotifyPipeChange(Pipe *pipe,
75 										usb_change change);
76 
77 		// Port operations for root hub
78 		uint8						PortCount() { return fPortCount; }
79 		status_t					GetPortStatus(uint8 index, usb_port_status *status);
80 		status_t					SetPortFeature(uint8 index, uint16 feature);
81 		status_t					ClearPortFeature(uint8 index, uint16 feature);
82 
83 		status_t					ResetPort(uint8 index);
84 		status_t					SuspendPort(uint8 index);
85 
86 virtual	const char *				TypeName() const { return "ehci"; }
87 
88 private:
89 		// Controller resets
90 		status_t					ControllerReset();
91 		status_t					LightReset();
92 
93 		// Interrupt functions
94 static	int32						InterruptHandler(void *data);
95 		int32						Interrupt();
96 static	int32						InterruptPollThread(void *data);
97 
98 		// Transfer management
99 		status_t					AddPendingTransfer(Transfer *transfer,
100 										ehci_qh *queueHead,
101 										ehci_qtd *dataDescriptor,
102 										bool directionIn);
103 		status_t					AddPendingIsochronousTransfer(
104 										Transfer *transfer,
105 										ehci_itd **isoRequest, uint32 lastIndex,
106 										bool directionIn, addr_t bufferPhy,
107 										void *bufferLog, size_t bufferSize);
108 		status_t					CancelAllPendingTransfers();
109 
110 
111 static	int32						FinishThread(void *data);
112 		void						FinishTransfers();
113 static	int32						CleanupThread(void *data);
114 		void						Cleanup();
115 
116 		// Isochronous transfer functions
117 static int32						FinishIsochronousThread(void *data);
118 		void						FinishIsochronousTransfers();
119 		isochronous_transfer_data *	FindIsochronousTransfer(ehci_itd *itd);
120 		void						LinkITDescriptors(ehci_itd *itd,
121 										ehci_itd **last);
122 		void						LinkSITDescriptors(ehci_sitd *sitd,
123 										ehci_sitd **last);
124 		void						UnlinkITDescriptors(ehci_itd *itd,
125 										ehci_itd **last);
126 		void						UnlinkSITDescriptors(ehci_sitd *sitd,
127 										ehci_sitd **last);
128 
129 		// Queue Head functions
130 		ehci_qh *					CreateQueueHead();
131 		status_t					InitQueueHead(ehci_qh *queueHead,
132 										Pipe *pipe);
133 		void						FreeQueueHead(ehci_qh *queueHead);
134 
135 		status_t					LinkQueueHead(ehci_qh *queueHead);
136 		status_t					LinkInterruptQueueHead(ehci_qh *queueHead,
137 										Pipe *pipe);
138 		status_t					UnlinkQueueHead(ehci_qh *queueHead,
139 										ehci_qh **freeList);
140 
141 		// Queue functions
142 		status_t					FillQueueWithRequest(Transfer *transfer,
143 										ehci_qh *queueHead,
144 										ehci_qtd **dataDescriptor,
145 										bool *directionIn,
146 										bool prepareKernelAccess);
147 		status_t					FillQueueWithData(Transfer *transfer,
148 										ehci_qh *queueHead,
149 										ehci_qtd **dataDescriptor,
150 										bool *directionIn,
151 										bool prepareKernelAccess);
152 
153 		bool						LockIsochronous();
154 		void						UnlockIsochronous();
155 
156 		// Descriptor functions
157 		ehci_qtd *					CreateDescriptor(
158 										size_t bufferSizeToAllocate,
159 										uint8 pid);
160 		status_t					CreateDescriptorChain(Pipe *pipe,
161 										ehci_qtd **firstDescriptor,
162 										ehci_qtd **lastDescriptor,
163 										ehci_qtd *strayDescriptor,
164 										size_t bufferSizeToAllocate,
165 										uint8 pid);
166 		ehci_itd*					CreateItdDescriptor();
167 		ehci_sitd*					CreateSitdDescriptor();
168 
169 		void						FreeDescriptor(ehci_qtd *descriptor);
170 		void						FreeDescriptorChain(ehci_qtd *topDescriptor);
171 		void						FreeDescriptor(ehci_itd *descriptor);
172 		void						FreeDescriptor(ehci_sitd *descriptor);
173 		void						FreeIsochronousData(
174 										isochronous_transfer_data *data);
175 
176 		void						LinkDescriptors(ehci_qtd *first,
177 										ehci_qtd *last, ehci_qtd *alt);
178 
179 		size_t						WriteDescriptorChain(
180 										ehci_qtd *topDescriptor,
181 										iovec *vector, size_t vectorCount);
182 		size_t						ReadDescriptorChain(ehci_qtd *topDescriptor,
183 										iovec *vector, size_t vectorCount,
184 										bool *nextDataToggle);
185 		size_t						ReadActualLength(ehci_qtd *topDescriptor,
186 										bool *nextDataToggle);
187 		size_t						WriteIsochronousDescriptorChain(
188 										isochronous_transfer_data *transfer,
189 										uint32 packetCount,
190 										iovec *vector);
191 		size_t						ReadIsochronousDescriptorChain(
192 										isochronous_transfer_data *transfer);
193 
194 		// Operational register functions
195 inline	void						WriteOpReg(uint32 reg, uint32 value);
196 inline	uint32						ReadOpReg(uint32 reg);
197 
198 		// Capability register functions
199 inline	uint8						ReadCapReg8(uint32 reg);
200 inline	uint16						ReadCapReg16(uint32 reg);
201 inline	uint32						ReadCapReg32(uint32 reg);
202 
203 		uint8 *						fCapabilityRegisters;
204 		uint8 *						fOperationalRegisters;
205 		area_id						fRegisterArea;
206 		pci_info *					fPCIInfo;
207 		pci_device_module_info*		fPci;
208 		pci_device*					fDevice;
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