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