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