xref: /haiku/src/add-ons/kernel/busses/usb/xhci.h (revision cb837539f5d245cedff238f8894c0ae326c2eaf5)
1 /*
2  * Copyright 2011-2019, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Augustin Cavalier <waddlesplash>
7  *		Michael Lotz <mmlr@mlotz.ch>
8  *		Jian Chiang <j.jian.chiang@gmail.com>
9  *		Jérôme Duval <jerome.duval@gmail.com>
10  */
11 #ifndef XHCI_H
12 #define XHCI_H
13 
14 
15 #include "usb_private.h"
16 #include "xhci_hardware.h"
17 
18 
19 struct pci_info;
20 struct pci_module_info;
21 struct pci_x86_module_info;
22 struct xhci_td;
23 struct xhci_device;
24 struct xhci_endpoint;
25 class XHCIRootHub;
26 
27 
28 #define XHCI_ENDPOINT_RING_SIZE	(XHCI_MAX_TRANSFERS * 2 + 1)
29 
30 
31 typedef struct xhci_td {
32 	xhci_trb*	trbs;
33 	phys_addr_t	trb_addr;
34 	uint32		trb_count;
35 	uint32		trb_used;
36 
37 	void**		buffers;
38 	phys_addr_t* buffer_addrs;
39 	size_t		buffer_size;
40 	uint32		buffer_count;
41 
42 	Transfer*	transfer;
43 	uint8		trb_completion_code;
44 	int32		td_transferred;
45 	int32		trb_left;
46 
47 	xhci_td*	next;
48 } xhci_td;
49 
50 
51 typedef struct xhci_endpoint {
52 	mutex 			lock;
53 
54 	xhci_device*	device;
55 	uint8			id;
56 
57 	uint16			max_burst_payload;
58 
59 	xhci_td*		td_head;
60 	uint8			used;
61 	uint8			current;
62 
63 	xhci_trb*		trbs; // [XHCI_ENDPOINT_RING_SIZE]
64 	phys_addr_t 	trb_addr;
65 } xhci_endpoint;
66 
67 
68 typedef struct xhci_device {
69 	uint8 slot;
70 	uint8 address;
71 	area_id trb_area;
72 	phys_addr_t trb_addr;
73 	struct xhci_trb *trbs; // [XHCI_MAX_ENDPOINTS - 1][XHCI_ENDPOINT_RING_SIZE]
74 
75 	area_id input_ctx_area;
76 	phys_addr_t input_ctx_addr;
77 	struct xhci_input_device_ctx *input_ctx;
78 
79 	area_id device_ctx_area;
80 	phys_addr_t device_ctx_addr;
81 	struct xhci_device_ctx *device_ctx;
82 
83 	xhci_endpoint endpoints[XHCI_MAX_ENDPOINTS - 1];
84 } xhci_device;
85 
86 
87 class XHCI : public BusManager {
88 public:
89 	static	status_t			AddTo(Stack *stack);
90 
91 								XHCI(pci_info *info, Stack *stack);
92 								~XHCI();
93 
94 	virtual	const char *		TypeName() const { return "xhci"; }
95 
96 			status_t			Start();
97 	virtual	status_t			SubmitTransfer(Transfer *transfer);
98 			status_t			SubmitControlRequest(Transfer *transfer);
99 			status_t			SubmitNormalRequest(Transfer *transfer);
100 	virtual	status_t			CancelQueuedTransfers(Pipe *pipe, bool force);
101 
102 	virtual	status_t			StartDebugTransfer(Transfer *transfer);
103 	virtual	status_t			CheckDebugTransfer(Transfer *transfer);
104 	virtual	void				CancelDebugTransfer(Transfer *transfer);
105 
106 	virtual	status_t			NotifyPipeChange(Pipe *pipe,
107 									usb_change change);
108 
109 	virtual	Device *			AllocateDevice(Hub *parent,
110 									int8 hubAddress, uint8 hubPort,
111 									usb_speed speed);
112 	virtual	void				FreeDevice(Device *device);
113 
114 			// Port operations for root hub
115 			uint8				PortCount() const { return fPortCount; }
116 			status_t			GetPortStatus(uint8 index,
117 									usb_port_status *status);
118 			status_t			SetPortFeature(uint8 index, uint16 feature);
119 			status_t			ClearPortFeature(uint8 index, uint16 feature);
120 
121 			status_t			GetPortSpeed(uint8 index, usb_speed *speed);
122 
123 private:
124 			// Controller resets
125 			status_t			ControllerReset();
126 			status_t			ControllerHalt();
127 
128 			// Interrupt functions
129 	static	int32				InterruptHandler(void *data);
130 			int32				Interrupt();
131 
132 			// Endpoint management
133 			status_t			ConfigureEndpoint(xhci_endpoint* ep, uint8 slot,
134 									uint8 number, uint8 type, bool directionIn,
135 									uint16 interval, uint16 maxPacketSize,
136 									usb_speed speed, uint8 maxBurst,
137 									uint16 bytesPerInterval);
138 			status_t			_InsertEndpointForPipe(Pipe *pipe);
139 			status_t			_RemoveEndpointForPipe(Pipe *pipe);
140 
141 			// Event management
142 	static	int32				EventThread(void *data);
143 			void				CompleteEvents();
144 			void				ProcessEvents();
145 
146 			// Transfer management
147 	static	int32				FinishThread(void *data);
148 			void				FinishTransfers();
149 
150 			// Descriptor management
151 			xhci_td *			CreateDescriptor(uint32 trbCount,
152 									uint32 bufferCount, size_t bufferSize);
153 			void				FreeDescriptor(xhci_td *descriptor);
154 
155 			size_t				WriteDescriptor(xhci_td *descriptor,
156 									iovec *vector, size_t vectorCount);
157 			size_t				ReadDescriptor(xhci_td *descriptor,
158 									iovec *vector, size_t vectorCount);
159 
160 			status_t			_LinkDescriptorForPipe(xhci_td *descriptor,
161 									xhci_endpoint *endpoint);
162 			status_t			_UnlinkDescriptorForPipe(xhci_td *descriptor,
163 									xhci_endpoint *endpoint);
164 
165 			// Command
166 			void				DumpRing(xhci_trb *trb, uint32 size);
167 			void				QueueCommand(xhci_trb *trb);
168 			void				HandleCmdComplete(xhci_trb *trb);
169 			void				HandleTransferComplete(xhci_trb *trb);
170 			status_t			DoCommand(xhci_trb *trb);
171 
172 			// Doorbell
173 			void				Ring(uint8 slot, uint8 endpoint);
174 
175 			// Commands
176 			status_t			Noop();
177 			status_t			EnableSlot(uint8 *slot);
178 			status_t			DisableSlot(uint8 slot);
179 			status_t			SetAddress(uint64 inputContext, bool bsr,
180 									uint8 slot);
181 			status_t			ConfigureEndpoint(uint64 inputContext,
182 									bool deconfigure, uint8 slot);
183 			status_t			EvaluateContext(uint64 inputContext,
184 									uint8 slot);
185 			status_t			ResetEndpoint(bool preserve, uint8 endpoint,
186 									uint8 slot);
187 			status_t			StopEndpoint(bool suspend, uint8 endpoint,
188 									uint8 slot);
189 			status_t			SetTRDequeue(uint64 dequeue, uint16 stream,
190 									uint8 endpoint, uint8 slot);
191 			status_t			ResetDevice(uint8 slot);
192 
193 			// Operational register functions
194 	inline	void				WriteOpReg(uint32 reg, uint32 value);
195 	inline	uint32				ReadOpReg(uint32 reg);
196 	inline	status_t			WaitOpBits(uint32 reg, uint32 mask, uint32 expected);
197 
198 			// Capability register functions
199 	inline	uint32				ReadCapReg32(uint32 reg);
200 	inline	void				WriteCapReg32(uint32 reg, uint32 value);
201 
202 			// Runtime register functions
203 	inline	uint32				ReadRunReg32(uint32 reg);
204 	inline	void				WriteRunReg32(uint32 reg, uint32 value);
205 
206 			// Doorbell register functions
207 	inline	uint32				ReadDoorReg32(uint32 reg);
208 	inline	void				WriteDoorReg32(uint32 reg, uint32 value);
209 
210 			// Context functions
211 	inline	addr_t				_OffsetContextAddr(addr_t p);
212 	inline	uint32				_ReadContext(uint32* p);
213 	inline	void				_WriteContext(uint32* p, uint32 value);
214 	inline	uint64				_ReadContext(uint64* p);
215 	inline	void				_WriteContext(uint64* p, uint64 value);
216 
217 			void				_SwitchIntelPorts();
218 
219 private:
220 	static	pci_module_info *	sPCIModule;
221 	static	pci_x86_module_info *sPCIx86Module;
222 
223 			area_id				fRegisterArea;
224 			uint8 *				fRegisters;
225 			uint32				fCapabilityRegisterOffset;
226 			uint32				fOperationalRegisterOffset;
227 			uint32				fRuntimeRegisterOffset;
228 			uint32				fDoorbellRegisterOffset;
229 
230 			pci_info *			fPCIInfo;
231 			Stack *				fStack;
232 			uint8				fIRQ;
233 			bool				fUseMSI;
234 
235 			area_id				fErstArea;
236 			xhci_erst_element *	fErst;
237 			xhci_trb *			fEventRing;
238 			xhci_trb *			fCmdRing;
239 			uint64				fCmdAddr;
240 			uint32				fCmdResult[2];
241 
242 			area_id				fDcbaArea;
243 			struct xhci_device_context_array * fDcba;
244 
245 			spinlock			fSpinlock;
246 
247 			sem_id				fCmdCompSem;
248 			bool				fStopThreads;
249 
250 			// Root Hub
251 			XHCIRootHub *		fRootHub;
252 			uint8				fRootHubAddress;
253 
254 			// Port management
255 			uint8				fPortCount;
256 			uint8				fSlotCount;
257 			usb_speed			fPortSpeeds[XHCI_MAX_PORTS];
258 			uint8				fPortSlots[XHCI_MAX_PORTS];
259 
260 			// Scratchpad
261 			uint32				fScratchpadCount;
262 			area_id				fScratchpadArea[XHCI_MAX_SCRATCHPADS];
263 			void *				fScratchpad[XHCI_MAX_SCRATCHPADS];
264 
265 			// Devices
266 			struct xhci_device	fDevices[XHCI_MAX_DEVICES];
267 			int32				fContextSizeShift; // 0/1 for 32/64 bytes
268 
269 			// Transfers
270 			mutex				fFinishedLock;
271 			xhci_td	*			fFinishedHead;
272 			sem_id				fFinishTransfersSem;
273 			thread_id			fFinishThread;
274 
275 			// Events
276 			sem_id				fEventSem;
277 			thread_id			fEventThread;
278 			mutex				fEventLock;
279 			uint16				fEventIdx;
280 			uint16				fCmdIdx;
281 			uint8				fEventCcs;
282 			uint8				fCmdCcs;
283 
284 			uint32				fExitLatMax;
285 };
286 
287 
288 class XHCIRootHub : public Hub {
289 public:
290 									XHCIRootHub(Object *rootObject,
291 										int8 deviceAddress);
292 
293 static	status_t					ProcessTransfer(XHCI *ehci,
294 										Transfer *transfer);
295 };
296 
297 
298 #endif // !XHCI_H
299