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