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