xref: /haiku/src/add-ons/kernel/busses/usb/ehci.h (revision 9f3bdf3d039430b5172c424def20ce5d9f7367d4)
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 										generic_io_vec *vector, size_t vectorCount,
182 										bool physical);
183 		size_t						ReadDescriptorChain(ehci_qtd *topDescriptor,
184 										generic_io_vec *vector, size_t vectorCount,
185 										bool physical, bool *nextDataToggle);
186 		size_t						ReadActualLength(ehci_qtd *topDescriptor,
187 										bool *nextDataToggle);
188 		size_t						WriteIsochronousDescriptorChain(
189 										isochronous_transfer_data *transfer);
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 		uint8 *						fCapabilityRegisters;
203 		uint8 *						fOperationalRegisters;
204 		area_id						fRegisterArea;
205 		pci_info *					fPCIInfo;
206 		pci_device_module_info*		fPci;
207 		pci_device*					fDevice;
208 		Stack *						fStack;
209 		uint32						fEnabledInterrupts;
210 		uint32						fThreshold;
211 
212 		// Periodic transfer framelist and interrupt entries
213 		area_id						fPeriodicFrameListArea;
214 		uint32 *					fPeriodicFrameList;
215 		interrupt_entry *			fInterruptEntries;
216 		ehci_itd **					fItdEntries;
217 		ehci_sitd **				fSitdEntries;
218 
219 		// Async transfer queue management
220 		ehci_qh *					fAsyncQueueHead;
221 		sem_id						fAsyncAdvanceSem;
222 
223 		// Maintain a linked list of transfers
224 		transfer_data *				fFirstTransfer;
225 		transfer_data *				fLastTransfer;
226 		sem_id						fFinishTransfersSem;
227 		thread_id					fFinishThread;
228 		Pipe *						fProcessingPipe;
229 
230 		ehci_qh *					fFreeListHead;
231 		sem_id						fCleanupSem;
232 		thread_id					fCleanupThread;
233 		bool						fStopThreads;
234 		int32						fNextStartingFrame;
235 
236 		// fFrameBandwidth[n] holds the available bandwidth
237 		// of the nth frame in microseconds
238 		uint16 *					fFrameBandwidth;
239 
240 		// Maintain a linked list of isochronous transfers
241 		isochronous_transfer_data *	fFirstIsochronousTransfer;
242 		isochronous_transfer_data *	fLastIsochronousTransfer;
243 		sem_id						fFinishIsochronousTransfersSem;
244 		thread_id					fFinishIsochronousThread;
245 		mutex						fIsochronousLock;
246 
247 		// Root Hub
248 		EHCIRootHub *				fRootHub;
249 		uint8						fRootHubAddress;
250 
251 		// Port management
252 		uint8						fPortCount;
253 		uint16						fPortResetChange;
254 		uint16						fPortSuspendChange;
255 
256 		// Interrupt polling
257 		thread_id					fInterruptPollThread;
258 		uint32						fIRQ;
259 		bool						fUseMSI;
260 };
261 
262 
263 class EHCIRootHub : public Hub {
264 public:
265 									EHCIRootHub(Object *rootObject,
266 										int8 deviceAddress);
267 
268 static	status_t					ProcessTransfer(EHCI *ehci,
269 										Transfer *transfer);
270 };
271 
272 
273 #endif // !EHCI_H
274