xref: /illumos-gate/usr/src/cmd/bhyve/pci_xhci.c (revision 4c87aefe8930bd07275b8dd2e96ea5f24d93a52e)
1*4c87aefeSPatrick Mooney /*-
2*4c87aefeSPatrick Mooney  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*4c87aefeSPatrick Mooney  *
4*4c87aefeSPatrick Mooney  * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com>
5*4c87aefeSPatrick Mooney  * Copyright 2018 Joyent, Inc.
6*4c87aefeSPatrick Mooney  * All rights reserved.
7*4c87aefeSPatrick Mooney  *
8*4c87aefeSPatrick Mooney  * Redistribution and use in source and binary forms, with or without
9*4c87aefeSPatrick Mooney  * modification, are permitted provided that the following conditions
10*4c87aefeSPatrick Mooney  * are met:
11*4c87aefeSPatrick Mooney  * 1. Redistributions of source code must retain the above copyright
12*4c87aefeSPatrick Mooney  *    notice, this list of conditions and the following disclaimer.
13*4c87aefeSPatrick Mooney  * 2. Redistributions in binary form must reproduce the above copyright
14*4c87aefeSPatrick Mooney  *    notice, this list of conditions and the following disclaimer in the
15*4c87aefeSPatrick Mooney  *    documentation and/or other materials provided with the distribution.
16*4c87aefeSPatrick Mooney  *
17*4c87aefeSPatrick Mooney  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*4c87aefeSPatrick Mooney  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*4c87aefeSPatrick Mooney  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*4c87aefeSPatrick Mooney  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*4c87aefeSPatrick Mooney  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*4c87aefeSPatrick Mooney  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*4c87aefeSPatrick Mooney  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*4c87aefeSPatrick Mooney  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*4c87aefeSPatrick Mooney  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*4c87aefeSPatrick Mooney  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*4c87aefeSPatrick Mooney  * SUCH DAMAGE.
28*4c87aefeSPatrick Mooney  */
29*4c87aefeSPatrick Mooney /*
30*4c87aefeSPatrick Mooney    XHCI options:
31*4c87aefeSPatrick Mooney     -s <n>,xhci,{devices}
32*4c87aefeSPatrick Mooney 
33*4c87aefeSPatrick Mooney    devices:
34*4c87aefeSPatrick Mooney      tablet             USB tablet mouse
35*4c87aefeSPatrick Mooney  */
36*4c87aefeSPatrick Mooney #include <sys/cdefs.h>
37*4c87aefeSPatrick Mooney __FBSDID("$FreeBSD$");
38*4c87aefeSPatrick Mooney 
39*4c87aefeSPatrick Mooney #include <sys/param.h>
40*4c87aefeSPatrick Mooney #include <sys/uio.h>
41*4c87aefeSPatrick Mooney #include <sys/types.h>
42*4c87aefeSPatrick Mooney #include <sys/queue.h>
43*4c87aefeSPatrick Mooney 
44*4c87aefeSPatrick Mooney #include <stdio.h>
45*4c87aefeSPatrick Mooney #include <stdlib.h>
46*4c87aefeSPatrick Mooney #include <stdint.h>
47*4c87aefeSPatrick Mooney #include <string.h>
48*4c87aefeSPatrick Mooney #include <errno.h>
49*4c87aefeSPatrick Mooney #include <pthread.h>
50*4c87aefeSPatrick Mooney #include <unistd.h>
51*4c87aefeSPatrick Mooney 
52*4c87aefeSPatrick Mooney #include <dev/usb/usbdi.h>
53*4c87aefeSPatrick Mooney #include <dev/usb/usb.h>
54*4c87aefeSPatrick Mooney #include <dev/usb/usb_freebsd.h>
55*4c87aefeSPatrick Mooney #include <xhcireg.h>
56*4c87aefeSPatrick Mooney 
57*4c87aefeSPatrick Mooney #include "bhyverun.h"
58*4c87aefeSPatrick Mooney #include "pci_emul.h"
59*4c87aefeSPatrick Mooney #include "pci_xhci.h"
60*4c87aefeSPatrick Mooney #include "usb_emul.h"
61*4c87aefeSPatrick Mooney 
62*4c87aefeSPatrick Mooney 
63*4c87aefeSPatrick Mooney static int xhci_debug = 0;
64*4c87aefeSPatrick Mooney #define	DPRINTF(params) if (xhci_debug) printf params
65*4c87aefeSPatrick Mooney #define	WPRINTF(params) printf params
66*4c87aefeSPatrick Mooney 
67*4c87aefeSPatrick Mooney 
68*4c87aefeSPatrick Mooney #define	XHCI_NAME		"xhci"
69*4c87aefeSPatrick Mooney #define	XHCI_MAX_DEVS		8	/* 4 USB3 + 4 USB2 devs */
70*4c87aefeSPatrick Mooney 
71*4c87aefeSPatrick Mooney #define	XHCI_MAX_SLOTS		64	/* min allowed by Windows drivers */
72*4c87aefeSPatrick Mooney 
73*4c87aefeSPatrick Mooney /*
74*4c87aefeSPatrick Mooney  * XHCI data structures can be up to 64k, but limit paddr_guest2host mapping
75*4c87aefeSPatrick Mooney  * to 4k to avoid going over the guest physical memory barrier.
76*4c87aefeSPatrick Mooney  */
77*4c87aefeSPatrick Mooney #define	XHCI_PADDR_SZ		4096	/* paddr_guest2host max size */
78*4c87aefeSPatrick Mooney 
79*4c87aefeSPatrick Mooney #define	XHCI_ERST_MAX		0	/* max 2^entries event ring seg tbl */
80*4c87aefeSPatrick Mooney 
81*4c87aefeSPatrick Mooney #define	XHCI_CAPLEN		(4*8)	/* offset of op register space */
82*4c87aefeSPatrick Mooney #define	XHCI_HCCPRAMS2		0x1C	/* offset of HCCPARAMS2 register */
83*4c87aefeSPatrick Mooney #define	XHCI_PORTREGS_START	0x400
84*4c87aefeSPatrick Mooney #define	XHCI_DOORBELL_MAX	256
85*4c87aefeSPatrick Mooney 
86*4c87aefeSPatrick Mooney #define	XHCI_STREAMS_MAX	1	/* 4-15 in XHCI spec */
87*4c87aefeSPatrick Mooney 
88*4c87aefeSPatrick Mooney /* caplength and hci-version registers */
89*4c87aefeSPatrick Mooney #define	XHCI_SET_CAPLEN(x)		((x) & 0xFF)
90*4c87aefeSPatrick Mooney #define	XHCI_SET_HCIVERSION(x)		(((x) & 0xFFFF) << 16)
91*4c87aefeSPatrick Mooney #define	XHCI_GET_HCIVERSION(x)		(((x) >> 16) & 0xFFFF)
92*4c87aefeSPatrick Mooney 
93*4c87aefeSPatrick Mooney /* hcsparams1 register */
94*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP1_MAXSLOTS(x)	((x) & 0xFF)
95*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP1_MAXINTR(x)	(((x) & 0x7FF) << 8)
96*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP1_MAXPORTS(x)	(((x) & 0xFF) << 24)
97*4c87aefeSPatrick Mooney 
98*4c87aefeSPatrick Mooney /* hcsparams2 register */
99*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP2_IST(x)		((x) & 0x0F)
100*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP2_ERSTMAX(x)	(((x) & 0x0F) << 4)
101*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP2_MAXSCRATCH_HI(x)	(((x) & 0x1F) << 21)
102*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP2_MAXSCRATCH_LO(x)	(((x) & 0x1F) << 27)
103*4c87aefeSPatrick Mooney 
104*4c87aefeSPatrick Mooney /* hcsparams3 register */
105*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP3_U1EXITLATENCY(x)	((x) & 0xFF)
106*4c87aefeSPatrick Mooney #define	XHCI_SET_HCSP3_U2EXITLATENCY(x)	(((x) & 0xFFFF) << 16)
107*4c87aefeSPatrick Mooney 
108*4c87aefeSPatrick Mooney /* hccparams1 register */
109*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_AC64(x)		((x) & 0x01)
110*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_BNC(x)		(((x) & 0x01) << 1)
111*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_CSZ(x)		(((x) & 0x01) << 2)
112*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_PPC(x)		(((x) & 0x01) << 3)
113*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_PIND(x)		(((x) & 0x01) << 4)
114*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_LHRC(x)		(((x) & 0x01) << 5)
115*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_LTC(x)		(((x) & 0x01) << 6)
116*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_NSS(x)		(((x) & 0x01) << 7)
117*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_PAE(x)		(((x) & 0x01) << 8)
118*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_SPC(x)		(((x) & 0x01) << 9)
119*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_SEC(x)		(((x) & 0x01) << 10)
120*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_CFC(x)		(((x) & 0x01) << 11)
121*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_MAXPSA(x)	(((x) & 0x0F) << 12)
122*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP1_XECP(x)		(((x) & 0xFFFF) << 16)
123*4c87aefeSPatrick Mooney 
124*4c87aefeSPatrick Mooney /* hccparams2 register */
125*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP2_U3C(x)		((x) & 0x01)
126*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP2_CMC(x)		(((x) & 0x01) << 1)
127*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP2_FSC(x)		(((x) & 0x01) << 2)
128*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP2_CTC(x)		(((x) & 0x01) << 3)
129*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP2_LEC(x)		(((x) & 0x01) << 4)
130*4c87aefeSPatrick Mooney #define	XHCI_SET_HCCP2_CIC(x)		(((x) & 0x01) << 5)
131*4c87aefeSPatrick Mooney 
132*4c87aefeSPatrick Mooney /* other registers */
133*4c87aefeSPatrick Mooney #define	XHCI_SET_DOORBELL(x)		((x) & ~0x03)
134*4c87aefeSPatrick Mooney #define	XHCI_SET_RTSOFFSET(x)		((x) & ~0x0F)
135*4c87aefeSPatrick Mooney 
136*4c87aefeSPatrick Mooney /* register masks */
137*4c87aefeSPatrick Mooney #define	XHCI_PS_PLS_MASK		(0xF << 5)	/* port link state */
138*4c87aefeSPatrick Mooney #define	XHCI_PS_SPEED_MASK		(0xF << 10)	/* port speed */
139*4c87aefeSPatrick Mooney #define	XHCI_PS_PIC_MASK		(0x3 << 14)	/* port indicator */
140*4c87aefeSPatrick Mooney 
141*4c87aefeSPatrick Mooney /* port register set */
142*4c87aefeSPatrick Mooney #define	XHCI_PORTREGS_BASE		0x400		/* base offset */
143*4c87aefeSPatrick Mooney #define	XHCI_PORTREGS_PORT0		0x3F0
144*4c87aefeSPatrick Mooney #define	XHCI_PORTREGS_SETSZ		0x10		/* size of a set */
145*4c87aefeSPatrick Mooney 
146*4c87aefeSPatrick Mooney #define	MASK_64_HI(x)			((x) & ~0xFFFFFFFFULL)
147*4c87aefeSPatrick Mooney #define	MASK_64_LO(x)			((x) & 0xFFFFFFFFULL)
148*4c87aefeSPatrick Mooney 
149*4c87aefeSPatrick Mooney #define	FIELD_REPLACE(a,b,m,s)		(((a) & ~((m) << (s))) | \
150*4c87aefeSPatrick Mooney 					(((b) & (m)) << (s)))
151*4c87aefeSPatrick Mooney #define	FIELD_COPY(a,b,m,s)		(((a) & ~((m) << (s))) | \
152*4c87aefeSPatrick Mooney 					(((b) & ((m) << (s)))))
153*4c87aefeSPatrick Mooney 
154*4c87aefeSPatrick Mooney struct pci_xhci_trb_ring {
155*4c87aefeSPatrick Mooney 	uint64_t ringaddr;		/* current dequeue guest address */
156*4c87aefeSPatrick Mooney 	uint32_t ccs;			/* consumer cycle state */
157*4c87aefeSPatrick Mooney };
158*4c87aefeSPatrick Mooney 
159*4c87aefeSPatrick Mooney /* device endpoint transfer/stream rings */
160*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep {
161*4c87aefeSPatrick Mooney 	union {
162*4c87aefeSPatrick Mooney 		struct xhci_trb		*_epu_tr;
163*4c87aefeSPatrick Mooney 		struct xhci_stream_ctx	*_epu_sctx;
164*4c87aefeSPatrick Mooney 	} _ep_trbsctx;
165*4c87aefeSPatrick Mooney #define	ep_tr		_ep_trbsctx._epu_tr
166*4c87aefeSPatrick Mooney #define	ep_sctx		_ep_trbsctx._epu_sctx
167*4c87aefeSPatrick Mooney 
168*4c87aefeSPatrick Mooney 	union {
169*4c87aefeSPatrick Mooney 		struct pci_xhci_trb_ring _epu_trb;
170*4c87aefeSPatrick Mooney 		struct pci_xhci_trb_ring *_epu_sctx_trbs;
171*4c87aefeSPatrick Mooney 	} _ep_trb_rings;
172*4c87aefeSPatrick Mooney #define	ep_ringaddr	_ep_trb_rings._epu_trb.ringaddr
173*4c87aefeSPatrick Mooney #define	ep_ccs		_ep_trb_rings._epu_trb.ccs
174*4c87aefeSPatrick Mooney #define	ep_sctx_trbs	_ep_trb_rings._epu_sctx_trbs
175*4c87aefeSPatrick Mooney 
176*4c87aefeSPatrick Mooney 	struct usb_data_xfer *ep_xfer;	/* transfer chain */
177*4c87aefeSPatrick Mooney };
178*4c87aefeSPatrick Mooney 
179*4c87aefeSPatrick Mooney /* device context base address array: maps slot->device context */
180*4c87aefeSPatrick Mooney struct xhci_dcbaa {
181*4c87aefeSPatrick Mooney 	uint64_t dcba[USB_MAX_DEVICES+1]; /* xhci_dev_ctx ptrs */
182*4c87aefeSPatrick Mooney };
183*4c87aefeSPatrick Mooney 
184*4c87aefeSPatrick Mooney /* port status registers */
185*4c87aefeSPatrick Mooney struct pci_xhci_portregs {
186*4c87aefeSPatrick Mooney 	uint32_t	portsc;		/* port status and control */
187*4c87aefeSPatrick Mooney 	uint32_t	portpmsc;	/* port pwr mgmt status & control */
188*4c87aefeSPatrick Mooney 	uint32_t	portli;		/* port link info */
189*4c87aefeSPatrick Mooney 	uint32_t	porthlpmc;	/* port hardware LPM control */
190*4c87aefeSPatrick Mooney } __packed;
191*4c87aefeSPatrick Mooney #define	XHCI_PS_SPEED_SET(x)	(((x) & 0xF) << 10)
192*4c87aefeSPatrick Mooney 
193*4c87aefeSPatrick Mooney /* xHC operational registers */
194*4c87aefeSPatrick Mooney struct pci_xhci_opregs {
195*4c87aefeSPatrick Mooney 	uint32_t	usbcmd;		/* usb command */
196*4c87aefeSPatrick Mooney 	uint32_t	usbsts;		/* usb status */
197*4c87aefeSPatrick Mooney 	uint32_t	pgsz;		/* page size */
198*4c87aefeSPatrick Mooney 	uint32_t	dnctrl;		/* device notification control */
199*4c87aefeSPatrick Mooney 	uint64_t	crcr;		/* command ring control */
200*4c87aefeSPatrick Mooney 	uint64_t	dcbaap;		/* device ctx base addr array ptr */
201*4c87aefeSPatrick Mooney 	uint32_t	config;		/* configure */
202*4c87aefeSPatrick Mooney 
203*4c87aefeSPatrick Mooney 	/* guest mapped addresses: */
204*4c87aefeSPatrick Mooney 	struct xhci_trb	*cr_p;		/* crcr dequeue */
205*4c87aefeSPatrick Mooney 	struct xhci_dcbaa *dcbaa_p;	/* dev ctx array ptr */
206*4c87aefeSPatrick Mooney };
207*4c87aefeSPatrick Mooney 
208*4c87aefeSPatrick Mooney /* xHC runtime registers */
209*4c87aefeSPatrick Mooney struct pci_xhci_rtsregs {
210*4c87aefeSPatrick Mooney 	uint32_t	mfindex;	/* microframe index */
211*4c87aefeSPatrick Mooney 	struct {			/* interrupter register set */
212*4c87aefeSPatrick Mooney 		uint32_t	iman;	/* interrupter management */
213*4c87aefeSPatrick Mooney 		uint32_t	imod;	/* interrupter moderation */
214*4c87aefeSPatrick Mooney 		uint32_t	erstsz;	/* event ring segment table size */
215*4c87aefeSPatrick Mooney 		uint32_t	rsvd;
216*4c87aefeSPatrick Mooney 		uint64_t	erstba;	/* event ring seg-tbl base addr */
217*4c87aefeSPatrick Mooney 		uint64_t	erdp;	/* event ring dequeue ptr */
218*4c87aefeSPatrick Mooney 	} intrreg __packed;
219*4c87aefeSPatrick Mooney 
220*4c87aefeSPatrick Mooney 	/* guest mapped addresses */
221*4c87aefeSPatrick Mooney 	struct xhci_event_ring_seg *erstba_p;
222*4c87aefeSPatrick Mooney 	struct xhci_trb *erst_p;	/* event ring segment tbl */
223*4c87aefeSPatrick Mooney 	int		er_deq_seg;	/* event ring dequeue segment */
224*4c87aefeSPatrick Mooney 	int		er_enq_idx;	/* event ring enqueue index - xHCI */
225*4c87aefeSPatrick Mooney 	int		er_enq_seg;	/* event ring enqueue segment */
226*4c87aefeSPatrick Mooney 	uint32_t	er_events_cnt;	/* number of events in ER */
227*4c87aefeSPatrick Mooney 	uint32_t	event_pcs;	/* producer cycle state flag */
228*4c87aefeSPatrick Mooney };
229*4c87aefeSPatrick Mooney 
230*4c87aefeSPatrick Mooney 
231*4c87aefeSPatrick Mooney struct pci_xhci_softc;
232*4c87aefeSPatrick Mooney 
233*4c87aefeSPatrick Mooney 
234*4c87aefeSPatrick Mooney /*
235*4c87aefeSPatrick Mooney  * USB device emulation container.
236*4c87aefeSPatrick Mooney  * This is referenced from usb_hci->hci_sc; 1 pci_xhci_dev_emu for each
237*4c87aefeSPatrick Mooney  * emulated device instance.
238*4c87aefeSPatrick Mooney  */
239*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu {
240*4c87aefeSPatrick Mooney 	struct pci_xhci_softc	*xsc;
241*4c87aefeSPatrick Mooney 
242*4c87aefeSPatrick Mooney 	/* XHCI contexts */
243*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
244*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_ep	eps[XHCI_MAX_ENDPOINTS];
245*4c87aefeSPatrick Mooney 	int			dev_slotstate;
246*4c87aefeSPatrick Mooney 
247*4c87aefeSPatrick Mooney 	struct usb_devemu	*dev_ue;	/* USB emulated dev */
248*4c87aefeSPatrick Mooney 	void			*dev_sc;	/* device's softc */
249*4c87aefeSPatrick Mooney 
250*4c87aefeSPatrick Mooney 	struct usb_hci		hci;
251*4c87aefeSPatrick Mooney };
252*4c87aefeSPatrick Mooney 
253*4c87aefeSPatrick Mooney struct pci_xhci_softc {
254*4c87aefeSPatrick Mooney 	struct pci_devinst *xsc_pi;
255*4c87aefeSPatrick Mooney 
256*4c87aefeSPatrick Mooney 	pthread_mutex_t	mtx;
257*4c87aefeSPatrick Mooney 
258*4c87aefeSPatrick Mooney 	uint32_t	caplength;	/* caplen & hciversion */
259*4c87aefeSPatrick Mooney 	uint32_t	hcsparams1;	/* structural parameters 1 */
260*4c87aefeSPatrick Mooney 	uint32_t	hcsparams2;	/* structural parameters 2 */
261*4c87aefeSPatrick Mooney 	uint32_t	hcsparams3;	/* structural parameters 3 */
262*4c87aefeSPatrick Mooney 	uint32_t	hccparams1;	/* capability parameters 1 */
263*4c87aefeSPatrick Mooney 	uint32_t	dboff;		/* doorbell offset */
264*4c87aefeSPatrick Mooney 	uint32_t	rtsoff;		/* runtime register space offset */
265*4c87aefeSPatrick Mooney 	uint32_t	hccparams2;	/* capability parameters 2 */
266*4c87aefeSPatrick Mooney 
267*4c87aefeSPatrick Mooney 	uint32_t	regsend;	/* end of configuration registers */
268*4c87aefeSPatrick Mooney 
269*4c87aefeSPatrick Mooney 	struct pci_xhci_opregs  opregs;
270*4c87aefeSPatrick Mooney 	struct pci_xhci_rtsregs rtsregs;
271*4c87aefeSPatrick Mooney 
272*4c87aefeSPatrick Mooney 	struct pci_xhci_portregs *portregs;
273*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu  **devices; /* XHCI[port] = device */
274*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu  **slots;   /* slots assigned from 1 */
275*4c87aefeSPatrick Mooney 	int		ndevices;
276*4c87aefeSPatrick Mooney 
277*4c87aefeSPatrick Mooney 	int		usb2_port_start;
278*4c87aefeSPatrick Mooney 	int		usb3_port_start;
279*4c87aefeSPatrick Mooney };
280*4c87aefeSPatrick Mooney 
281*4c87aefeSPatrick Mooney 
282*4c87aefeSPatrick Mooney /* portregs and devices arrays are set up to start from idx=1 */
283*4c87aefeSPatrick Mooney #define	XHCI_PORTREG_PTR(x,n)	&(x)->portregs[(n)]
284*4c87aefeSPatrick Mooney #define	XHCI_DEVINST_PTR(x,n)	(x)->devices[(n)]
285*4c87aefeSPatrick Mooney #define	XHCI_SLOTDEV_PTR(x,n)	(x)->slots[(n)]
286*4c87aefeSPatrick Mooney 
287*4c87aefeSPatrick Mooney #define	XHCI_HALTED(sc)		((sc)->opregs.usbsts & XHCI_STS_HCH)
288*4c87aefeSPatrick Mooney 
289*4c87aefeSPatrick Mooney #define	XHCI_GADDR(sc,a)	paddr_guest2host((sc)->xsc_pi->pi_vmctx, \
290*4c87aefeSPatrick Mooney 				    (a),                                 \
291*4c87aefeSPatrick Mooney 				    XHCI_PADDR_SZ - ((a) & (XHCI_PADDR_SZ-1)))
292*4c87aefeSPatrick Mooney 
293*4c87aefeSPatrick Mooney static int xhci_in_use;
294*4c87aefeSPatrick Mooney 
295*4c87aefeSPatrick Mooney /* map USB errors to XHCI */
296*4c87aefeSPatrick Mooney static const int xhci_usb_errors[USB_ERR_MAX] = {
297*4c87aefeSPatrick Mooney 	[USB_ERR_NORMAL_COMPLETION]	= XHCI_TRB_ERROR_SUCCESS,
298*4c87aefeSPatrick Mooney 	[USB_ERR_PENDING_REQUESTS]	= XHCI_TRB_ERROR_RESOURCE,
299*4c87aefeSPatrick Mooney 	[USB_ERR_NOT_STARTED]		= XHCI_TRB_ERROR_ENDP_NOT_ON,
300*4c87aefeSPatrick Mooney 	[USB_ERR_INVAL]			= XHCI_TRB_ERROR_INVALID,
301*4c87aefeSPatrick Mooney 	[USB_ERR_NOMEM]			= XHCI_TRB_ERROR_RESOURCE,
302*4c87aefeSPatrick Mooney 	[USB_ERR_CANCELLED]		= XHCI_TRB_ERROR_STOPPED,
303*4c87aefeSPatrick Mooney 	[USB_ERR_BAD_ADDRESS]		= XHCI_TRB_ERROR_PARAMETER,
304*4c87aefeSPatrick Mooney 	[USB_ERR_BAD_BUFSIZE]		= XHCI_TRB_ERROR_PARAMETER,
305*4c87aefeSPatrick Mooney 	[USB_ERR_BAD_FLAG]		= XHCI_TRB_ERROR_PARAMETER,
306*4c87aefeSPatrick Mooney 	[USB_ERR_NO_CALLBACK]		= XHCI_TRB_ERROR_STALL,
307*4c87aefeSPatrick Mooney 	[USB_ERR_IN_USE]		= XHCI_TRB_ERROR_RESOURCE,
308*4c87aefeSPatrick Mooney 	[USB_ERR_NO_ADDR]		= XHCI_TRB_ERROR_RESOURCE,
309*4c87aefeSPatrick Mooney 	[USB_ERR_NO_PIPE]               = XHCI_TRB_ERROR_RESOURCE,
310*4c87aefeSPatrick Mooney 	[USB_ERR_ZERO_NFRAMES]          = XHCI_TRB_ERROR_UNDEFINED,
311*4c87aefeSPatrick Mooney 	[USB_ERR_ZERO_MAXP]             = XHCI_TRB_ERROR_UNDEFINED,
312*4c87aefeSPatrick Mooney 	[USB_ERR_SET_ADDR_FAILED]       = XHCI_TRB_ERROR_RESOURCE,
313*4c87aefeSPatrick Mooney 	[USB_ERR_NO_POWER]              = XHCI_TRB_ERROR_ENDP_NOT_ON,
314*4c87aefeSPatrick Mooney 	[USB_ERR_TOO_DEEP]              = XHCI_TRB_ERROR_RESOURCE,
315*4c87aefeSPatrick Mooney 	[USB_ERR_IOERROR]               = XHCI_TRB_ERROR_TRB,
316*4c87aefeSPatrick Mooney 	[USB_ERR_NOT_CONFIGURED]        = XHCI_TRB_ERROR_ENDP_NOT_ON,
317*4c87aefeSPatrick Mooney 	[USB_ERR_TIMEOUT]               = XHCI_TRB_ERROR_CMD_ABORTED,
318*4c87aefeSPatrick Mooney 	[USB_ERR_SHORT_XFER]            = XHCI_TRB_ERROR_SHORT_PKT,
319*4c87aefeSPatrick Mooney 	[USB_ERR_STALLED]               = XHCI_TRB_ERROR_STALL,
320*4c87aefeSPatrick Mooney 	[USB_ERR_INTERRUPTED]           = XHCI_TRB_ERROR_CMD_ABORTED,
321*4c87aefeSPatrick Mooney 	[USB_ERR_DMA_LOAD_FAILED]       = XHCI_TRB_ERROR_DATA_BUF,
322*4c87aefeSPatrick Mooney 	[USB_ERR_BAD_CONTEXT]           = XHCI_TRB_ERROR_TRB,
323*4c87aefeSPatrick Mooney 	[USB_ERR_NO_ROOT_HUB]           = XHCI_TRB_ERROR_UNDEFINED,
324*4c87aefeSPatrick Mooney 	[USB_ERR_NO_INTR_THREAD]        = XHCI_TRB_ERROR_UNDEFINED,
325*4c87aefeSPatrick Mooney 	[USB_ERR_NOT_LOCKED]            = XHCI_TRB_ERROR_UNDEFINED,
326*4c87aefeSPatrick Mooney };
327*4c87aefeSPatrick Mooney #define	USB_TO_XHCI_ERR(e)	((e) < USB_ERR_MAX ? xhci_usb_errors[(e)] : \
328*4c87aefeSPatrick Mooney 				XHCI_TRB_ERROR_INVALID)
329*4c87aefeSPatrick Mooney 
330*4c87aefeSPatrick Mooney static int pci_xhci_insert_event(struct pci_xhci_softc *sc,
331*4c87aefeSPatrick Mooney     struct xhci_trb *evtrb, int do_intr);
332*4c87aefeSPatrick Mooney static void pci_xhci_dump_trb(struct xhci_trb *trb);
333*4c87aefeSPatrick Mooney static void pci_xhci_assert_interrupt(struct pci_xhci_softc *sc);
334*4c87aefeSPatrick Mooney static void pci_xhci_reset_slot(struct pci_xhci_softc *sc, int slot);
335*4c87aefeSPatrick Mooney static void pci_xhci_reset_port(struct pci_xhci_softc *sc, int portn, int warm);
336*4c87aefeSPatrick Mooney static void pci_xhci_update_ep_ring(struct pci_xhci_softc *sc,
337*4c87aefeSPatrick Mooney     struct pci_xhci_dev_emu *dev, struct pci_xhci_dev_ep *devep,
338*4c87aefeSPatrick Mooney     struct xhci_endp_ctx *ep_ctx, uint32_t streamid,
339*4c87aefeSPatrick Mooney     uint64_t ringaddr, int ccs);
340*4c87aefeSPatrick Mooney 
341*4c87aefeSPatrick Mooney static void
342*4c87aefeSPatrick Mooney pci_xhci_set_evtrb(struct xhci_trb *evtrb, uint64_t port, uint32_t errcode,
343*4c87aefeSPatrick Mooney     uint32_t evtype)
344*4c87aefeSPatrick Mooney {
345*4c87aefeSPatrick Mooney 	evtrb->qwTrb0 = port << 24;
346*4c87aefeSPatrick Mooney 	evtrb->dwTrb2 = XHCI_TRB_2_ERROR_SET(errcode);
347*4c87aefeSPatrick Mooney 	evtrb->dwTrb3 = XHCI_TRB_3_TYPE_SET(evtype);
348*4c87aefeSPatrick Mooney }
349*4c87aefeSPatrick Mooney 
350*4c87aefeSPatrick Mooney 
351*4c87aefeSPatrick Mooney /* controller reset */
352*4c87aefeSPatrick Mooney static void
353*4c87aefeSPatrick Mooney pci_xhci_reset(struct pci_xhci_softc *sc)
354*4c87aefeSPatrick Mooney {
355*4c87aefeSPatrick Mooney 	int i;
356*4c87aefeSPatrick Mooney 
357*4c87aefeSPatrick Mooney 	sc->rtsregs.er_enq_idx = 0;
358*4c87aefeSPatrick Mooney 	sc->rtsregs.er_events_cnt = 0;
359*4c87aefeSPatrick Mooney 	sc->rtsregs.event_pcs = 1;
360*4c87aefeSPatrick Mooney 
361*4c87aefeSPatrick Mooney 	for (i = 1; i <= XHCI_MAX_SLOTS; i++) {
362*4c87aefeSPatrick Mooney 		pci_xhci_reset_slot(sc, i);
363*4c87aefeSPatrick Mooney 	}
364*4c87aefeSPatrick Mooney }
365*4c87aefeSPatrick Mooney 
366*4c87aefeSPatrick Mooney static uint32_t
367*4c87aefeSPatrick Mooney pci_xhci_usbcmd_write(struct pci_xhci_softc *sc, uint32_t cmd)
368*4c87aefeSPatrick Mooney {
369*4c87aefeSPatrick Mooney 	int do_intr = 0;
370*4c87aefeSPatrick Mooney 	int i;
371*4c87aefeSPatrick Mooney 
372*4c87aefeSPatrick Mooney 	if (cmd & XHCI_CMD_RS) {
373*4c87aefeSPatrick Mooney 		do_intr = (sc->opregs.usbcmd & XHCI_CMD_RS) == 0;
374*4c87aefeSPatrick Mooney 
375*4c87aefeSPatrick Mooney 		sc->opregs.usbcmd |= XHCI_CMD_RS;
376*4c87aefeSPatrick Mooney 		sc->opregs.usbsts &= ~XHCI_STS_HCH;
377*4c87aefeSPatrick Mooney 		sc->opregs.usbsts |= XHCI_STS_PCD;
378*4c87aefeSPatrick Mooney 
379*4c87aefeSPatrick Mooney 		/* Queue port change event on controller run from stop */
380*4c87aefeSPatrick Mooney 		if (do_intr)
381*4c87aefeSPatrick Mooney 			for (i = 1; i <= XHCI_MAX_DEVS; i++) {
382*4c87aefeSPatrick Mooney 				struct pci_xhci_dev_emu *dev;
383*4c87aefeSPatrick Mooney 				struct pci_xhci_portregs *port;
384*4c87aefeSPatrick Mooney 				struct xhci_trb		evtrb;
385*4c87aefeSPatrick Mooney 
386*4c87aefeSPatrick Mooney 				if ((dev = XHCI_DEVINST_PTR(sc, i)) == NULL)
387*4c87aefeSPatrick Mooney 					continue;
388*4c87aefeSPatrick Mooney 
389*4c87aefeSPatrick Mooney 				port = XHCI_PORTREG_PTR(sc, i);
390*4c87aefeSPatrick Mooney 				port->portsc |= XHCI_PS_CSC | XHCI_PS_CCS;
391*4c87aefeSPatrick Mooney 				port->portsc &= ~XHCI_PS_PLS_MASK;
392*4c87aefeSPatrick Mooney 
393*4c87aefeSPatrick Mooney 				/*
394*4c87aefeSPatrick Mooney 				 * XHCI 4.19.3 USB2 RxDetect->Polling,
395*4c87aefeSPatrick Mooney 				 *             USB3 Polling->U0
396*4c87aefeSPatrick Mooney 				 */
397*4c87aefeSPatrick Mooney 				if (dev->dev_ue->ue_usbver == 2)
398*4c87aefeSPatrick Mooney 					port->portsc |=
399*4c87aefeSPatrick Mooney 					    XHCI_PS_PLS_SET(UPS_PORT_LS_POLL);
400*4c87aefeSPatrick Mooney 				else
401*4c87aefeSPatrick Mooney 					port->portsc |=
402*4c87aefeSPatrick Mooney 					    XHCI_PS_PLS_SET(UPS_PORT_LS_U0);
403*4c87aefeSPatrick Mooney 
404*4c87aefeSPatrick Mooney 				pci_xhci_set_evtrb(&evtrb, i,
405*4c87aefeSPatrick Mooney 				    XHCI_TRB_ERROR_SUCCESS,
406*4c87aefeSPatrick Mooney 				    XHCI_TRB_EVENT_PORT_STS_CHANGE);
407*4c87aefeSPatrick Mooney 
408*4c87aefeSPatrick Mooney 				if (pci_xhci_insert_event(sc, &evtrb, 0) !=
409*4c87aefeSPatrick Mooney 				    XHCI_TRB_ERROR_SUCCESS)
410*4c87aefeSPatrick Mooney 					break;
411*4c87aefeSPatrick Mooney 			}
412*4c87aefeSPatrick Mooney 	} else {
413*4c87aefeSPatrick Mooney 		sc->opregs.usbcmd &= ~XHCI_CMD_RS;
414*4c87aefeSPatrick Mooney 		sc->opregs.usbsts |= XHCI_STS_HCH;
415*4c87aefeSPatrick Mooney 		sc->opregs.usbsts &= ~XHCI_STS_PCD;
416*4c87aefeSPatrick Mooney 	}
417*4c87aefeSPatrick Mooney 
418*4c87aefeSPatrick Mooney 	/* start execution of schedule; stop when set to 0 */
419*4c87aefeSPatrick Mooney 	cmd |= sc->opregs.usbcmd & XHCI_CMD_RS;
420*4c87aefeSPatrick Mooney 
421*4c87aefeSPatrick Mooney 	if (cmd & XHCI_CMD_HCRST) {
422*4c87aefeSPatrick Mooney 		/* reset controller */
423*4c87aefeSPatrick Mooney 		pci_xhci_reset(sc);
424*4c87aefeSPatrick Mooney 		cmd &= ~XHCI_CMD_HCRST;
425*4c87aefeSPatrick Mooney 	}
426*4c87aefeSPatrick Mooney 
427*4c87aefeSPatrick Mooney 	cmd &= ~(XHCI_CMD_CSS | XHCI_CMD_CRS);
428*4c87aefeSPatrick Mooney 
429*4c87aefeSPatrick Mooney 	if (do_intr)
430*4c87aefeSPatrick Mooney 		pci_xhci_assert_interrupt(sc);
431*4c87aefeSPatrick Mooney 
432*4c87aefeSPatrick Mooney 	return (cmd);
433*4c87aefeSPatrick Mooney }
434*4c87aefeSPatrick Mooney 
435*4c87aefeSPatrick Mooney static void
436*4c87aefeSPatrick Mooney pci_xhci_portregs_write(struct pci_xhci_softc *sc, uint64_t offset,
437*4c87aefeSPatrick Mooney     uint64_t value)
438*4c87aefeSPatrick Mooney {
439*4c87aefeSPatrick Mooney 	struct xhci_trb		evtrb;
440*4c87aefeSPatrick Mooney 	struct pci_xhci_portregs *p;
441*4c87aefeSPatrick Mooney 	int port;
442*4c87aefeSPatrick Mooney 	uint32_t oldpls, newpls;
443*4c87aefeSPatrick Mooney 
444*4c87aefeSPatrick Mooney 	if (sc->portregs == NULL)
445*4c87aefeSPatrick Mooney 		return;
446*4c87aefeSPatrick Mooney 
447*4c87aefeSPatrick Mooney 	port = (offset - XHCI_PORTREGS_PORT0) / XHCI_PORTREGS_SETSZ;
448*4c87aefeSPatrick Mooney 	offset = (offset - XHCI_PORTREGS_PORT0) % XHCI_PORTREGS_SETSZ;
449*4c87aefeSPatrick Mooney 
450*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: portregs wr offset 0x%lx, port %u: 0x%lx\r\n",
451*4c87aefeSPatrick Mooney 	        offset, port, value));
452*4c87aefeSPatrick Mooney 
453*4c87aefeSPatrick Mooney 	assert(port >= 0);
454*4c87aefeSPatrick Mooney 
455*4c87aefeSPatrick Mooney 	if (port > XHCI_MAX_DEVS) {
456*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: portregs_write port %d > ndevices\r\n",
457*4c87aefeSPatrick Mooney 		    port));
458*4c87aefeSPatrick Mooney 		return;
459*4c87aefeSPatrick Mooney 	}
460*4c87aefeSPatrick Mooney 
461*4c87aefeSPatrick Mooney 	if (XHCI_DEVINST_PTR(sc, port) == NULL) {
462*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: portregs_write to unattached port %d\r\n",
463*4c87aefeSPatrick Mooney 		     port));
464*4c87aefeSPatrick Mooney 	}
465*4c87aefeSPatrick Mooney 
466*4c87aefeSPatrick Mooney 	p = XHCI_PORTREG_PTR(sc, port);
467*4c87aefeSPatrick Mooney 	switch (offset) {
468*4c87aefeSPatrick Mooney 	case 0:
469*4c87aefeSPatrick Mooney 		/* port reset or warm reset */
470*4c87aefeSPatrick Mooney 		if (value & (XHCI_PS_PR | XHCI_PS_WPR)) {
471*4c87aefeSPatrick Mooney 			pci_xhci_reset_port(sc, port, value & XHCI_PS_WPR);
472*4c87aefeSPatrick Mooney 			break;
473*4c87aefeSPatrick Mooney 		}
474*4c87aefeSPatrick Mooney 
475*4c87aefeSPatrick Mooney 		if ((p->portsc & XHCI_PS_PP) == 0) {
476*4c87aefeSPatrick Mooney 			WPRINTF(("pci_xhci: portregs_write to unpowered "
477*4c87aefeSPatrick Mooney 			         "port %d\r\n", port));
478*4c87aefeSPatrick Mooney 			break;
479*4c87aefeSPatrick Mooney 		}
480*4c87aefeSPatrick Mooney 
481*4c87aefeSPatrick Mooney 		/* Port status and control register  */
482*4c87aefeSPatrick Mooney 		oldpls = XHCI_PS_PLS_GET(p->portsc);
483*4c87aefeSPatrick Mooney 		newpls = XHCI_PS_PLS_GET(value);
484*4c87aefeSPatrick Mooney 
485*4c87aefeSPatrick Mooney 		p->portsc &= XHCI_PS_PED | XHCI_PS_PLS_MASK |
486*4c87aefeSPatrick Mooney 		             XHCI_PS_SPEED_MASK | XHCI_PS_PIC_MASK;
487*4c87aefeSPatrick Mooney 
488*4c87aefeSPatrick Mooney 		if (XHCI_DEVINST_PTR(sc, port))
489*4c87aefeSPatrick Mooney 			p->portsc |= XHCI_PS_CCS;
490*4c87aefeSPatrick Mooney 
491*4c87aefeSPatrick Mooney 		p->portsc |= (value &
492*4c87aefeSPatrick Mooney 		              ~(XHCI_PS_OCA |
493*4c87aefeSPatrick Mooney 		                XHCI_PS_PR  |
494*4c87aefeSPatrick Mooney 			        XHCI_PS_PED |
495*4c87aefeSPatrick Mooney 			        XHCI_PS_PLS_MASK   |	/* link state */
496*4c87aefeSPatrick Mooney 			        XHCI_PS_SPEED_MASK |
497*4c87aefeSPatrick Mooney 			        XHCI_PS_PIC_MASK   |	/* port indicator */
498*4c87aefeSPatrick Mooney 			        XHCI_PS_LWS | XHCI_PS_DR | XHCI_PS_WPR));
499*4c87aefeSPatrick Mooney 
500*4c87aefeSPatrick Mooney 		/* clear control bits */
501*4c87aefeSPatrick Mooney 		p->portsc &= ~(value &
502*4c87aefeSPatrick Mooney 		               (XHCI_PS_CSC |
503*4c87aefeSPatrick Mooney 		                XHCI_PS_PEC |
504*4c87aefeSPatrick Mooney 		                XHCI_PS_WRC |
505*4c87aefeSPatrick Mooney 		                XHCI_PS_OCC |
506*4c87aefeSPatrick Mooney 		                XHCI_PS_PRC |
507*4c87aefeSPatrick Mooney 		                XHCI_PS_PLC |
508*4c87aefeSPatrick Mooney 		                XHCI_PS_CEC |
509*4c87aefeSPatrick Mooney 		                XHCI_PS_CAS));
510*4c87aefeSPatrick Mooney 
511*4c87aefeSPatrick Mooney 		/* port disable request; for USB3, don't care */
512*4c87aefeSPatrick Mooney 		if (value & XHCI_PS_PED)
513*4c87aefeSPatrick Mooney 			DPRINTF(("Disable port %d request\r\n", port));
514*4c87aefeSPatrick Mooney 
515*4c87aefeSPatrick Mooney 		if (!(value & XHCI_PS_LWS))
516*4c87aefeSPatrick Mooney 			break;
517*4c87aefeSPatrick Mooney 
518*4c87aefeSPatrick Mooney 		DPRINTF(("Port new PLS: %d\r\n", newpls));
519*4c87aefeSPatrick Mooney 		switch (newpls) {
520*4c87aefeSPatrick Mooney 		case 0: /* U0 */
521*4c87aefeSPatrick Mooney 		case 3: /* U3 */
522*4c87aefeSPatrick Mooney 			if (oldpls != newpls) {
523*4c87aefeSPatrick Mooney 				p->portsc &= ~XHCI_PS_PLS_MASK;
524*4c87aefeSPatrick Mooney 				p->portsc |= XHCI_PS_PLS_SET(newpls) |
525*4c87aefeSPatrick Mooney 				             XHCI_PS_PLC;
526*4c87aefeSPatrick Mooney 
527*4c87aefeSPatrick Mooney 				if (oldpls != 0 && newpls == 0) {
528*4c87aefeSPatrick Mooney 					pci_xhci_set_evtrb(&evtrb, port,
529*4c87aefeSPatrick Mooney 					    XHCI_TRB_ERROR_SUCCESS,
530*4c87aefeSPatrick Mooney 					    XHCI_TRB_EVENT_PORT_STS_CHANGE);
531*4c87aefeSPatrick Mooney 
532*4c87aefeSPatrick Mooney 					pci_xhci_insert_event(sc, &evtrb, 1);
533*4c87aefeSPatrick Mooney 				}
534*4c87aefeSPatrick Mooney 			}
535*4c87aefeSPatrick Mooney 			break;
536*4c87aefeSPatrick Mooney 
537*4c87aefeSPatrick Mooney 		default:
538*4c87aefeSPatrick Mooney 			DPRINTF(("Unhandled change port %d PLS %u\r\n",
539*4c87aefeSPatrick Mooney 			         port, newpls));
540*4c87aefeSPatrick Mooney 			break;
541*4c87aefeSPatrick Mooney 		}
542*4c87aefeSPatrick Mooney 		break;
543*4c87aefeSPatrick Mooney 	case 4:
544*4c87aefeSPatrick Mooney 		/* Port power management status and control register  */
545*4c87aefeSPatrick Mooney 		p->portpmsc = value;
546*4c87aefeSPatrick Mooney 		break;
547*4c87aefeSPatrick Mooney 	case 8:
548*4c87aefeSPatrick Mooney 		/* Port link information register */
549*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci attempted write to PORTLI, port %d\r\n",
550*4c87aefeSPatrick Mooney 		        port));
551*4c87aefeSPatrick Mooney 		break;
552*4c87aefeSPatrick Mooney 	case 12:
553*4c87aefeSPatrick Mooney 		/*
554*4c87aefeSPatrick Mooney 		 * Port hardware LPM control register.
555*4c87aefeSPatrick Mooney 		 * For USB3, this register is reserved.
556*4c87aefeSPatrick Mooney 		 */
557*4c87aefeSPatrick Mooney 		p->porthlpmc = value;
558*4c87aefeSPatrick Mooney 		break;
559*4c87aefeSPatrick Mooney 	}
560*4c87aefeSPatrick Mooney }
561*4c87aefeSPatrick Mooney 
562*4c87aefeSPatrick Mooney struct xhci_dev_ctx *
563*4c87aefeSPatrick Mooney pci_xhci_get_dev_ctx(struct pci_xhci_softc *sc, uint32_t slot)
564*4c87aefeSPatrick Mooney {
565*4c87aefeSPatrick Mooney 	uint64_t devctx_addr;
566*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx *devctx;
567*4c87aefeSPatrick Mooney 
568*4c87aefeSPatrick Mooney 	assert(slot > 0 && slot <= sc->ndevices);
569*4c87aefeSPatrick Mooney 	assert(sc->opregs.dcbaa_p != NULL);
570*4c87aefeSPatrick Mooney 
571*4c87aefeSPatrick Mooney 	devctx_addr = sc->opregs.dcbaa_p->dcba[slot];
572*4c87aefeSPatrick Mooney 
573*4c87aefeSPatrick Mooney 	if (devctx_addr == 0) {
574*4c87aefeSPatrick Mooney 		DPRINTF(("get_dev_ctx devctx_addr == 0\r\n"));
575*4c87aefeSPatrick Mooney 		return (NULL);
576*4c87aefeSPatrick Mooney 	}
577*4c87aefeSPatrick Mooney 
578*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: get dev ctx, slot %u devctx addr %016lx\r\n",
579*4c87aefeSPatrick Mooney 	        slot, devctx_addr));
580*4c87aefeSPatrick Mooney 	devctx = XHCI_GADDR(sc, devctx_addr & ~0x3FUL);
581*4c87aefeSPatrick Mooney 
582*4c87aefeSPatrick Mooney 	return (devctx);
583*4c87aefeSPatrick Mooney }
584*4c87aefeSPatrick Mooney 
585*4c87aefeSPatrick Mooney struct xhci_trb *
586*4c87aefeSPatrick Mooney pci_xhci_trb_next(struct pci_xhci_softc *sc, struct xhci_trb *curtrb,
587*4c87aefeSPatrick Mooney     uint64_t *guestaddr)
588*4c87aefeSPatrick Mooney {
589*4c87aefeSPatrick Mooney 	struct xhci_trb *next;
590*4c87aefeSPatrick Mooney 
591*4c87aefeSPatrick Mooney 	assert(curtrb != NULL);
592*4c87aefeSPatrick Mooney 
593*4c87aefeSPatrick Mooney 	if (XHCI_TRB_3_TYPE_GET(curtrb->dwTrb3) == XHCI_TRB_TYPE_LINK) {
594*4c87aefeSPatrick Mooney 		if (guestaddr)
595*4c87aefeSPatrick Mooney 			*guestaddr = curtrb->qwTrb0 & ~0xFUL;
596*4c87aefeSPatrick Mooney 
597*4c87aefeSPatrick Mooney 		next = XHCI_GADDR(sc, curtrb->qwTrb0 & ~0xFUL);
598*4c87aefeSPatrick Mooney 	} else {
599*4c87aefeSPatrick Mooney 		if (guestaddr)
600*4c87aefeSPatrick Mooney 			*guestaddr += sizeof(struct xhci_trb) & ~0xFUL;
601*4c87aefeSPatrick Mooney 
602*4c87aefeSPatrick Mooney 		next = curtrb + 1;
603*4c87aefeSPatrick Mooney 	}
604*4c87aefeSPatrick Mooney 
605*4c87aefeSPatrick Mooney 	return (next);
606*4c87aefeSPatrick Mooney }
607*4c87aefeSPatrick Mooney 
608*4c87aefeSPatrick Mooney static void
609*4c87aefeSPatrick Mooney pci_xhci_assert_interrupt(struct pci_xhci_softc *sc)
610*4c87aefeSPatrick Mooney {
611*4c87aefeSPatrick Mooney 
612*4c87aefeSPatrick Mooney 	sc->rtsregs.intrreg.erdp |= XHCI_ERDP_LO_BUSY;
613*4c87aefeSPatrick Mooney 	sc->rtsregs.intrreg.iman |= XHCI_IMAN_INTR_PEND;
614*4c87aefeSPatrick Mooney 	sc->opregs.usbsts |= XHCI_STS_EINT;
615*4c87aefeSPatrick Mooney 
616*4c87aefeSPatrick Mooney 	/* only trigger interrupt if permitted */
617*4c87aefeSPatrick Mooney 	if ((sc->opregs.usbcmd & XHCI_CMD_INTE) &&
618*4c87aefeSPatrick Mooney 	    (sc->rtsregs.intrreg.iman & XHCI_IMAN_INTR_ENA)) {
619*4c87aefeSPatrick Mooney 		if (pci_msi_enabled(sc->xsc_pi))
620*4c87aefeSPatrick Mooney 			pci_generate_msi(sc->xsc_pi, 0);
621*4c87aefeSPatrick Mooney 		else
622*4c87aefeSPatrick Mooney 			pci_lintr_assert(sc->xsc_pi);
623*4c87aefeSPatrick Mooney 	}
624*4c87aefeSPatrick Mooney }
625*4c87aefeSPatrick Mooney 
626*4c87aefeSPatrick Mooney static void
627*4c87aefeSPatrick Mooney pci_xhci_deassert_interrupt(struct pci_xhci_softc *sc)
628*4c87aefeSPatrick Mooney {
629*4c87aefeSPatrick Mooney 
630*4c87aefeSPatrick Mooney 	if (!pci_msi_enabled(sc->xsc_pi))
631*4c87aefeSPatrick Mooney 		pci_lintr_assert(sc->xsc_pi);
632*4c87aefeSPatrick Mooney }
633*4c87aefeSPatrick Mooney 
634*4c87aefeSPatrick Mooney static void
635*4c87aefeSPatrick Mooney pci_xhci_init_ep(struct pci_xhci_dev_emu *dev, int epid)
636*4c87aefeSPatrick Mooney {
637*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx    *dev_ctx;
638*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_ep *devep;
639*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx   *ep_ctx;
640*4c87aefeSPatrick Mooney 	uint32_t	pstreams;
641*4c87aefeSPatrick Mooney 	int		i;
642*4c87aefeSPatrick Mooney 
643*4c87aefeSPatrick Mooney 	dev_ctx = dev->dev_ctx;
644*4c87aefeSPatrick Mooney 	ep_ctx = &dev_ctx->ctx_ep[epid];
645*4c87aefeSPatrick Mooney 	devep = &dev->eps[epid];
646*4c87aefeSPatrick Mooney 	pstreams = XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0);
647*4c87aefeSPatrick Mooney 	if (pstreams > 0) {
648*4c87aefeSPatrick Mooney 		DPRINTF(("init_ep %d with pstreams %d\r\n", epid, pstreams));
649*4c87aefeSPatrick Mooney 		assert(devep->ep_sctx_trbs == NULL);
650*4c87aefeSPatrick Mooney 
651*4c87aefeSPatrick Mooney 		devep->ep_sctx = XHCI_GADDR(dev->xsc, ep_ctx->qwEpCtx2 &
652*4c87aefeSPatrick Mooney 		                            XHCI_EPCTX_2_TR_DQ_PTR_MASK);
653*4c87aefeSPatrick Mooney 		devep->ep_sctx_trbs = calloc(pstreams,
654*4c87aefeSPatrick Mooney 		                      sizeof(struct pci_xhci_trb_ring));
655*4c87aefeSPatrick Mooney 		for (i = 0; i < pstreams; i++) {
656*4c87aefeSPatrick Mooney 			devep->ep_sctx_trbs[i].ringaddr =
657*4c87aefeSPatrick Mooney 			                         devep->ep_sctx[i].qwSctx0 &
658*4c87aefeSPatrick Mooney 			                         XHCI_SCTX_0_TR_DQ_PTR_MASK;
659*4c87aefeSPatrick Mooney 			devep->ep_sctx_trbs[i].ccs =
660*4c87aefeSPatrick Mooney 			     XHCI_SCTX_0_DCS_GET(devep->ep_sctx[i].qwSctx0);
661*4c87aefeSPatrick Mooney 		}
662*4c87aefeSPatrick Mooney 	} else {
663*4c87aefeSPatrick Mooney 		DPRINTF(("init_ep %d with no pstreams\r\n", epid));
664*4c87aefeSPatrick Mooney 		devep->ep_ringaddr = ep_ctx->qwEpCtx2 &
665*4c87aefeSPatrick Mooney 		                     XHCI_EPCTX_2_TR_DQ_PTR_MASK;
666*4c87aefeSPatrick Mooney 		devep->ep_ccs = XHCI_EPCTX_2_DCS_GET(ep_ctx->qwEpCtx2);
667*4c87aefeSPatrick Mooney 		devep->ep_tr = XHCI_GADDR(dev->xsc, devep->ep_ringaddr);
668*4c87aefeSPatrick Mooney 		DPRINTF(("init_ep tr DCS %x\r\n", devep->ep_ccs));
669*4c87aefeSPatrick Mooney 	}
670*4c87aefeSPatrick Mooney 
671*4c87aefeSPatrick Mooney 	if (devep->ep_xfer == NULL) {
672*4c87aefeSPatrick Mooney 		devep->ep_xfer = malloc(sizeof(struct usb_data_xfer));
673*4c87aefeSPatrick Mooney 		USB_DATA_XFER_INIT(devep->ep_xfer);
674*4c87aefeSPatrick Mooney 	}
675*4c87aefeSPatrick Mooney }
676*4c87aefeSPatrick Mooney 
677*4c87aefeSPatrick Mooney static void
678*4c87aefeSPatrick Mooney pci_xhci_disable_ep(struct pci_xhci_dev_emu *dev, int epid)
679*4c87aefeSPatrick Mooney {
680*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx    *dev_ctx;
681*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_ep *devep;
682*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx   *ep_ctx;
683*4c87aefeSPatrick Mooney 
684*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci disable_ep %d\r\n", epid));
685*4c87aefeSPatrick Mooney 
686*4c87aefeSPatrick Mooney 	dev_ctx = dev->dev_ctx;
687*4c87aefeSPatrick Mooney 	ep_ctx = &dev_ctx->ctx_ep[epid];
688*4c87aefeSPatrick Mooney 	ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_DISABLED;
689*4c87aefeSPatrick Mooney 
690*4c87aefeSPatrick Mooney 	devep = &dev->eps[epid];
691*4c87aefeSPatrick Mooney 	if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0 &&
692*4c87aefeSPatrick Mooney 	    devep->ep_sctx_trbs != NULL)
693*4c87aefeSPatrick Mooney 			free(devep->ep_sctx_trbs);
694*4c87aefeSPatrick Mooney 
695*4c87aefeSPatrick Mooney 	if (devep->ep_xfer != NULL) {
696*4c87aefeSPatrick Mooney 		free(devep->ep_xfer);
697*4c87aefeSPatrick Mooney 		devep->ep_xfer = NULL;
698*4c87aefeSPatrick Mooney 	}
699*4c87aefeSPatrick Mooney 
700*4c87aefeSPatrick Mooney 	memset(devep, 0, sizeof(struct pci_xhci_dev_ep));
701*4c87aefeSPatrick Mooney }
702*4c87aefeSPatrick Mooney 
703*4c87aefeSPatrick Mooney 
704*4c87aefeSPatrick Mooney /* reset device at slot and data structures related to it */
705*4c87aefeSPatrick Mooney static void
706*4c87aefeSPatrick Mooney pci_xhci_reset_slot(struct pci_xhci_softc *sc, int slot)
707*4c87aefeSPatrick Mooney {
708*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu *dev;
709*4c87aefeSPatrick Mooney 
710*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
711*4c87aefeSPatrick Mooney 
712*4c87aefeSPatrick Mooney 	if (!dev) {
713*4c87aefeSPatrick Mooney 		DPRINTF(("xhci reset unassigned slot (%d)?\r\n", slot));
714*4c87aefeSPatrick Mooney 	} else {
715*4c87aefeSPatrick Mooney 		dev->dev_slotstate = XHCI_ST_DISABLED;
716*4c87aefeSPatrick Mooney 	}
717*4c87aefeSPatrick Mooney 
718*4c87aefeSPatrick Mooney 	/* TODO: reset ring buffer pointers */
719*4c87aefeSPatrick Mooney }
720*4c87aefeSPatrick Mooney 
721*4c87aefeSPatrick Mooney static int
722*4c87aefeSPatrick Mooney pci_xhci_insert_event(struct pci_xhci_softc *sc, struct xhci_trb *evtrb,
723*4c87aefeSPatrick Mooney     int do_intr)
724*4c87aefeSPatrick Mooney {
725*4c87aefeSPatrick Mooney 	struct pci_xhci_rtsregs *rts;
726*4c87aefeSPatrick Mooney 	uint64_t	erdp;
727*4c87aefeSPatrick Mooney 	int		erdp_idx;
728*4c87aefeSPatrick Mooney 	int		err;
729*4c87aefeSPatrick Mooney 	struct xhci_trb *evtrbptr;
730*4c87aefeSPatrick Mooney 
731*4c87aefeSPatrick Mooney 	err = XHCI_TRB_ERROR_SUCCESS;
732*4c87aefeSPatrick Mooney 
733*4c87aefeSPatrick Mooney 	rts = &sc->rtsregs;
734*4c87aefeSPatrick Mooney 
735*4c87aefeSPatrick Mooney 	erdp = rts->intrreg.erdp & ~0xF;
736*4c87aefeSPatrick Mooney 	erdp_idx = (erdp - rts->erstba_p[rts->er_deq_seg].qwEvrsTablePtr) /
737*4c87aefeSPatrick Mooney 	           sizeof(struct xhci_trb);
738*4c87aefeSPatrick Mooney 
739*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: insert event 0[%lx] 2[%x] 3[%x]\r\n"
740*4c87aefeSPatrick Mooney 	         "\terdp idx %d/seg %d, enq idx %d/seg %d, pcs %u\r\n"
741*4c87aefeSPatrick Mooney 	         "\t(erdp=0x%lx, erst=0x%lx, tblsz=%u, do_intr %d)\r\n",
742*4c87aefeSPatrick Mooney 	         evtrb->qwTrb0, evtrb->dwTrb2, evtrb->dwTrb3,
743*4c87aefeSPatrick Mooney 	         erdp_idx, rts->er_deq_seg, rts->er_enq_idx,
744*4c87aefeSPatrick Mooney 	         rts->er_enq_seg,
745*4c87aefeSPatrick Mooney 	         rts->event_pcs, erdp, rts->erstba_p->qwEvrsTablePtr,
746*4c87aefeSPatrick Mooney 	         rts->erstba_p->dwEvrsTableSize, do_intr));
747*4c87aefeSPatrick Mooney 
748*4c87aefeSPatrick Mooney 	evtrbptr = &rts->erst_p[rts->er_enq_idx];
749*4c87aefeSPatrick Mooney 
750*4c87aefeSPatrick Mooney 	/* TODO: multi-segment table */
751*4c87aefeSPatrick Mooney 	if (rts->er_events_cnt >= rts->erstba_p->dwEvrsTableSize) {
752*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci[%d] cannot insert event; ring full\r\n",
753*4c87aefeSPatrick Mooney 		         __LINE__));
754*4c87aefeSPatrick Mooney 		err = XHCI_TRB_ERROR_EV_RING_FULL;
755*4c87aefeSPatrick Mooney 		goto done;
756*4c87aefeSPatrick Mooney 	}
757*4c87aefeSPatrick Mooney 
758*4c87aefeSPatrick Mooney 	if (rts->er_events_cnt == rts->erstba_p->dwEvrsTableSize - 1) {
759*4c87aefeSPatrick Mooney 		struct xhci_trb	errev;
760*4c87aefeSPatrick Mooney 
761*4c87aefeSPatrick Mooney 		if ((evtrbptr->dwTrb3 & 0x1) == (rts->event_pcs & 0x1)) {
762*4c87aefeSPatrick Mooney 
763*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci[%d] insert evt err: ring full\r\n",
764*4c87aefeSPatrick Mooney 			         __LINE__));
765*4c87aefeSPatrick Mooney 
766*4c87aefeSPatrick Mooney 			errev.qwTrb0 = 0;
767*4c87aefeSPatrick Mooney 			errev.dwTrb2 = XHCI_TRB_2_ERROR_SET(
768*4c87aefeSPatrick Mooney 			                    XHCI_TRB_ERROR_EV_RING_FULL);
769*4c87aefeSPatrick Mooney 			errev.dwTrb3 = XHCI_TRB_3_TYPE_SET(
770*4c87aefeSPatrick Mooney 			                    XHCI_TRB_EVENT_HOST_CTRL) |
771*4c87aefeSPatrick Mooney 			               rts->event_pcs;
772*4c87aefeSPatrick Mooney 			rts->er_events_cnt++;
773*4c87aefeSPatrick Mooney 			memcpy(&rts->erst_p[rts->er_enq_idx], &errev,
774*4c87aefeSPatrick Mooney 			       sizeof(struct xhci_trb));
775*4c87aefeSPatrick Mooney 			rts->er_enq_idx = (rts->er_enq_idx + 1) %
776*4c87aefeSPatrick Mooney 			                  rts->erstba_p->dwEvrsTableSize;
777*4c87aefeSPatrick Mooney 			err = XHCI_TRB_ERROR_EV_RING_FULL;
778*4c87aefeSPatrick Mooney 			do_intr = 1;
779*4c87aefeSPatrick Mooney 
780*4c87aefeSPatrick Mooney 			goto done;
781*4c87aefeSPatrick Mooney 		}
782*4c87aefeSPatrick Mooney 	} else {
783*4c87aefeSPatrick Mooney 		rts->er_events_cnt++;
784*4c87aefeSPatrick Mooney 	}
785*4c87aefeSPatrick Mooney 
786*4c87aefeSPatrick Mooney 	evtrb->dwTrb3 &= ~XHCI_TRB_3_CYCLE_BIT;
787*4c87aefeSPatrick Mooney 	evtrb->dwTrb3 |= rts->event_pcs;
788*4c87aefeSPatrick Mooney 
789*4c87aefeSPatrick Mooney 	memcpy(&rts->erst_p[rts->er_enq_idx], evtrb, sizeof(struct xhci_trb));
790*4c87aefeSPatrick Mooney 	rts->er_enq_idx = (rts->er_enq_idx + 1) %
791*4c87aefeSPatrick Mooney 	                  rts->erstba_p->dwEvrsTableSize;
792*4c87aefeSPatrick Mooney 
793*4c87aefeSPatrick Mooney 	if (rts->er_enq_idx == 0)
794*4c87aefeSPatrick Mooney 		rts->event_pcs ^= 1;
795*4c87aefeSPatrick Mooney 
796*4c87aefeSPatrick Mooney done:
797*4c87aefeSPatrick Mooney 	if (do_intr)
798*4c87aefeSPatrick Mooney 		pci_xhci_assert_interrupt(sc);
799*4c87aefeSPatrick Mooney 
800*4c87aefeSPatrick Mooney 	return (err);
801*4c87aefeSPatrick Mooney }
802*4c87aefeSPatrick Mooney 
803*4c87aefeSPatrick Mooney static uint32_t
804*4c87aefeSPatrick Mooney pci_xhci_cmd_enable_slot(struct pci_xhci_softc *sc, uint32_t *slot)
805*4c87aefeSPatrick Mooney {
806*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu *dev;
807*4c87aefeSPatrick Mooney 	uint32_t	cmderr;
808*4c87aefeSPatrick Mooney 	int		i;
809*4c87aefeSPatrick Mooney 
810*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_NO_SLOTS;
811*4c87aefeSPatrick Mooney 	if (sc->portregs != NULL)
812*4c87aefeSPatrick Mooney 		for (i = 1; i <= XHCI_MAX_SLOTS; i++) {
813*4c87aefeSPatrick Mooney 			dev = XHCI_SLOTDEV_PTR(sc, i);
814*4c87aefeSPatrick Mooney 			if (dev && dev->dev_slotstate == XHCI_ST_DISABLED) {
815*4c87aefeSPatrick Mooney 				*slot = i;
816*4c87aefeSPatrick Mooney 				dev->dev_slotstate = XHCI_ST_ENABLED;
817*4c87aefeSPatrick Mooney 				cmderr = XHCI_TRB_ERROR_SUCCESS;
818*4c87aefeSPatrick Mooney 				dev->hci.hci_address = i;
819*4c87aefeSPatrick Mooney 				break;
820*4c87aefeSPatrick Mooney 			}
821*4c87aefeSPatrick Mooney 		}
822*4c87aefeSPatrick Mooney 
823*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci enable slot (error=%d) slot %u\r\n",
824*4c87aefeSPatrick Mooney 		cmderr != XHCI_TRB_ERROR_SUCCESS, *slot));
825*4c87aefeSPatrick Mooney 
826*4c87aefeSPatrick Mooney 	return (cmderr);
827*4c87aefeSPatrick Mooney }
828*4c87aefeSPatrick Mooney 
829*4c87aefeSPatrick Mooney static uint32_t
830*4c87aefeSPatrick Mooney pci_xhci_cmd_disable_slot(struct pci_xhci_softc *sc, uint32_t slot)
831*4c87aefeSPatrick Mooney {
832*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu *dev;
833*4c87aefeSPatrick Mooney 	uint32_t cmderr;
834*4c87aefeSPatrick Mooney 
835*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci disable slot %u\r\n", slot));
836*4c87aefeSPatrick Mooney 
837*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_NO_SLOTS;
838*4c87aefeSPatrick Mooney 	if (sc->portregs == NULL)
839*4c87aefeSPatrick Mooney 		goto done;
840*4c87aefeSPatrick Mooney 
841*4c87aefeSPatrick Mooney 	if (slot > sc->ndevices) {
842*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
843*4c87aefeSPatrick Mooney 		goto done;
844*4c87aefeSPatrick Mooney 	}
845*4c87aefeSPatrick Mooney 
846*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
847*4c87aefeSPatrick Mooney 	if (dev) {
848*4c87aefeSPatrick Mooney 		if (dev->dev_slotstate == XHCI_ST_DISABLED) {
849*4c87aefeSPatrick Mooney 			cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
850*4c87aefeSPatrick Mooney 		} else {
851*4c87aefeSPatrick Mooney 			dev->dev_slotstate = XHCI_ST_DISABLED;
852*4c87aefeSPatrick Mooney 			cmderr = XHCI_TRB_ERROR_SUCCESS;
853*4c87aefeSPatrick Mooney 			/* TODO: reset events and endpoints */
854*4c87aefeSPatrick Mooney 		}
855*4c87aefeSPatrick Mooney 	}
856*4c87aefeSPatrick Mooney 
857*4c87aefeSPatrick Mooney done:
858*4c87aefeSPatrick Mooney 	return (cmderr);
859*4c87aefeSPatrick Mooney }
860*4c87aefeSPatrick Mooney 
861*4c87aefeSPatrick Mooney static uint32_t
862*4c87aefeSPatrick Mooney pci_xhci_cmd_reset_device(struct pci_xhci_softc *sc, uint32_t slot)
863*4c87aefeSPatrick Mooney {
864*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu *dev;
865*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx     *dev_ctx;
866*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx    *ep_ctx;
867*4c87aefeSPatrick Mooney 	uint32_t	cmderr;
868*4c87aefeSPatrick Mooney 	int		i;
869*4c87aefeSPatrick Mooney 
870*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_NO_SLOTS;
871*4c87aefeSPatrick Mooney 	if (sc->portregs == NULL)
872*4c87aefeSPatrick Mooney 		goto done;
873*4c87aefeSPatrick Mooney 
874*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci reset device slot %u\r\n", slot));
875*4c87aefeSPatrick Mooney 
876*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
877*4c87aefeSPatrick Mooney 	if (!dev || dev->dev_slotstate == XHCI_ST_DISABLED)
878*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
879*4c87aefeSPatrick Mooney 	else {
880*4c87aefeSPatrick Mooney 		dev->dev_slotstate = XHCI_ST_DEFAULT;
881*4c87aefeSPatrick Mooney 
882*4c87aefeSPatrick Mooney 		dev->hci.hci_address = 0;
883*4c87aefeSPatrick Mooney 		dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
884*4c87aefeSPatrick Mooney 
885*4c87aefeSPatrick Mooney 		/* slot state */
886*4c87aefeSPatrick Mooney 		dev_ctx->ctx_slot.dwSctx3 = FIELD_REPLACE(
887*4c87aefeSPatrick Mooney 		    dev_ctx->ctx_slot.dwSctx3, XHCI_ST_SLCTX_DEFAULT,
888*4c87aefeSPatrick Mooney 		    0x1F, 27);
889*4c87aefeSPatrick Mooney 
890*4c87aefeSPatrick Mooney 		/* number of contexts */
891*4c87aefeSPatrick Mooney 		dev_ctx->ctx_slot.dwSctx0 = FIELD_REPLACE(
892*4c87aefeSPatrick Mooney 		    dev_ctx->ctx_slot.dwSctx0, 1, 0x1F, 27);
893*4c87aefeSPatrick Mooney 
894*4c87aefeSPatrick Mooney 		/* reset all eps other than ep-0 */
895*4c87aefeSPatrick Mooney 		for (i = 2; i <= 31; i++) {
896*4c87aefeSPatrick Mooney 			ep_ctx = &dev_ctx->ctx_ep[i];
897*4c87aefeSPatrick Mooney 			ep_ctx->dwEpCtx0 = FIELD_REPLACE( ep_ctx->dwEpCtx0,
898*4c87aefeSPatrick Mooney 			    XHCI_ST_EPCTX_DISABLED, 0x7, 0);
899*4c87aefeSPatrick Mooney 		}
900*4c87aefeSPatrick Mooney 
901*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_SUCCESS;
902*4c87aefeSPatrick Mooney 	}
903*4c87aefeSPatrick Mooney 
904*4c87aefeSPatrick Mooney 	pci_xhci_reset_slot(sc, slot);
905*4c87aefeSPatrick Mooney 
906*4c87aefeSPatrick Mooney done:
907*4c87aefeSPatrick Mooney 	return (cmderr);
908*4c87aefeSPatrick Mooney }
909*4c87aefeSPatrick Mooney 
910*4c87aefeSPatrick Mooney static uint32_t
911*4c87aefeSPatrick Mooney pci_xhci_cmd_address_device(struct pci_xhci_softc *sc, uint32_t slot,
912*4c87aefeSPatrick Mooney     struct xhci_trb *trb)
913*4c87aefeSPatrick Mooney {
914*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	*dev;
915*4c87aefeSPatrick Mooney 	struct xhci_input_dev_ctx *input_ctx;
916*4c87aefeSPatrick Mooney 	struct xhci_slot_ctx	*islot_ctx;
917*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
918*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx	*ep0_ctx;
919*4c87aefeSPatrick Mooney 	uint32_t		cmderr;
920*4c87aefeSPatrick Mooney 
921*4c87aefeSPatrick Mooney 	input_ctx = XHCI_GADDR(sc, trb->qwTrb0 & ~0xFUL);
922*4c87aefeSPatrick Mooney 	islot_ctx = &input_ctx->ctx_slot;
923*4c87aefeSPatrick Mooney 	ep0_ctx = &input_ctx->ctx_ep[1];
924*4c87aefeSPatrick Mooney 
925*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_SUCCESS;
926*4c87aefeSPatrick Mooney 
927*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: address device, input ctl: D 0x%08x A 0x%08x,\r\n"
928*4c87aefeSPatrick Mooney 	         "          slot %08x %08x %08x %08x\r\n"
929*4c87aefeSPatrick Mooney 	         "          ep0  %08x %08x %016lx %08x\r\n",
930*4c87aefeSPatrick Mooney 	        input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1,
931*4c87aefeSPatrick Mooney 	        islot_ctx->dwSctx0, islot_ctx->dwSctx1,
932*4c87aefeSPatrick Mooney 	        islot_ctx->dwSctx2, islot_ctx->dwSctx3,
933*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2,
934*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx4));
935*4c87aefeSPatrick Mooney 
936*4c87aefeSPatrick Mooney 	/* when setting address: drop-ctx=0, add-ctx=slot+ep0 */
937*4c87aefeSPatrick Mooney 	if ((input_ctx->ctx_input.dwInCtx0 != 0) ||
938*4c87aefeSPatrick Mooney 	    (input_ctx->ctx_input.dwInCtx1 & 0x03) != 0x03) {
939*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: address device, input ctl invalid\r\n"));
940*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_TRB;
941*4c87aefeSPatrick Mooney 		goto done;
942*4c87aefeSPatrick Mooney 	}
943*4c87aefeSPatrick Mooney 
944*4c87aefeSPatrick Mooney 	/* assign address to slot */
945*4c87aefeSPatrick Mooney 	dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
946*4c87aefeSPatrick Mooney 
947*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: address device, dev ctx\r\n"
948*4c87aefeSPatrick Mooney 	         "          slot %08x %08x %08x %08x\r\n",
949*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1,
950*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3));
951*4c87aefeSPatrick Mooney 
952*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
953*4c87aefeSPatrick Mooney 	assert(dev != NULL);
954*4c87aefeSPatrick Mooney 
955*4c87aefeSPatrick Mooney 	dev->hci.hci_address = slot;
956*4c87aefeSPatrick Mooney 	dev->dev_ctx = dev_ctx;
957*4c87aefeSPatrick Mooney 
958*4c87aefeSPatrick Mooney 	if (dev->dev_ue->ue_reset == NULL ||
959*4c87aefeSPatrick Mooney 	    dev->dev_ue->ue_reset(dev->dev_sc) < 0) {
960*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_ENDP_NOT_ON;
961*4c87aefeSPatrick Mooney 		goto done;
962*4c87aefeSPatrick Mooney 	}
963*4c87aefeSPatrick Mooney 
964*4c87aefeSPatrick Mooney 	memcpy(&dev_ctx->ctx_slot, islot_ctx, sizeof(struct xhci_slot_ctx));
965*4c87aefeSPatrick Mooney 
966*4c87aefeSPatrick Mooney 	dev_ctx->ctx_slot.dwSctx3 =
967*4c87aefeSPatrick Mooney 	    XHCI_SCTX_3_SLOT_STATE_SET(XHCI_ST_SLCTX_ADDRESSED) |
968*4c87aefeSPatrick Mooney 	    XHCI_SCTX_3_DEV_ADDR_SET(slot);
969*4c87aefeSPatrick Mooney 
970*4c87aefeSPatrick Mooney 	memcpy(&dev_ctx->ctx_ep[1], ep0_ctx, sizeof(struct xhci_endp_ctx));
971*4c87aefeSPatrick Mooney 	ep0_ctx = &dev_ctx->ctx_ep[1];
972*4c87aefeSPatrick Mooney 	ep0_ctx->dwEpCtx0 = (ep0_ctx->dwEpCtx0 & ~0x7) |
973*4c87aefeSPatrick Mooney 	    XHCI_EPCTX_0_EPSTATE_SET(XHCI_ST_EPCTX_RUNNING);
974*4c87aefeSPatrick Mooney 
975*4c87aefeSPatrick Mooney 	pci_xhci_init_ep(dev, 1);
976*4c87aefeSPatrick Mooney 
977*4c87aefeSPatrick Mooney 	dev->dev_slotstate = XHCI_ST_ADDRESSED;
978*4c87aefeSPatrick Mooney 
979*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: address device, output ctx\r\n"
980*4c87aefeSPatrick Mooney 	         "          slot %08x %08x %08x %08x\r\n"
981*4c87aefeSPatrick Mooney 	         "          ep0  %08x %08x %016lx %08x\r\n",
982*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1,
983*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3,
984*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2,
985*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx4));
986*4c87aefeSPatrick Mooney 
987*4c87aefeSPatrick Mooney done:
988*4c87aefeSPatrick Mooney 	return (cmderr);
989*4c87aefeSPatrick Mooney }
990*4c87aefeSPatrick Mooney 
991*4c87aefeSPatrick Mooney static uint32_t
992*4c87aefeSPatrick Mooney pci_xhci_cmd_config_ep(struct pci_xhci_softc *sc, uint32_t slot,
993*4c87aefeSPatrick Mooney     struct xhci_trb *trb)
994*4c87aefeSPatrick Mooney {
995*4c87aefeSPatrick Mooney 	struct xhci_input_dev_ctx *input_ctx;
996*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	*dev;
997*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
998*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx	*ep_ctx, *iep_ctx;
999*4c87aefeSPatrick Mooney 	uint32_t	cmderr;
1000*4c87aefeSPatrick Mooney 	int		i;
1001*4c87aefeSPatrick Mooney 
1002*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_SUCCESS;
1003*4c87aefeSPatrick Mooney 
1004*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci config_ep slot %u\r\n", slot));
1005*4c87aefeSPatrick Mooney 
1006*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
1007*4c87aefeSPatrick Mooney 	assert(dev != NULL);
1008*4c87aefeSPatrick Mooney 
1009*4c87aefeSPatrick Mooney 	if ((trb->dwTrb3 & XHCI_TRB_3_DCEP_BIT) != 0) {
1010*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci config_ep - deconfigure ep slot %u\r\n",
1011*4c87aefeSPatrick Mooney 		        slot));
1012*4c87aefeSPatrick Mooney 		if (dev->dev_ue->ue_stop != NULL)
1013*4c87aefeSPatrick Mooney 			dev->dev_ue->ue_stop(dev->dev_sc);
1014*4c87aefeSPatrick Mooney 
1015*4c87aefeSPatrick Mooney 		dev->dev_slotstate = XHCI_ST_ADDRESSED;
1016*4c87aefeSPatrick Mooney 
1017*4c87aefeSPatrick Mooney 		dev->hci.hci_address = 0;
1018*4c87aefeSPatrick Mooney 		dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
1019*4c87aefeSPatrick Mooney 
1020*4c87aefeSPatrick Mooney 		/* number of contexts */
1021*4c87aefeSPatrick Mooney 		dev_ctx->ctx_slot.dwSctx0 = FIELD_REPLACE(
1022*4c87aefeSPatrick Mooney 		    dev_ctx->ctx_slot.dwSctx0, 1, 0x1F, 27);
1023*4c87aefeSPatrick Mooney 
1024*4c87aefeSPatrick Mooney 		/* slot state */
1025*4c87aefeSPatrick Mooney 		dev_ctx->ctx_slot.dwSctx3 = FIELD_REPLACE(
1026*4c87aefeSPatrick Mooney 		    dev_ctx->ctx_slot.dwSctx3, XHCI_ST_SLCTX_ADDRESSED,
1027*4c87aefeSPatrick Mooney 		    0x1F, 27);
1028*4c87aefeSPatrick Mooney 
1029*4c87aefeSPatrick Mooney 		/* disable endpoints */
1030*4c87aefeSPatrick Mooney 		for (i = 2; i < 32; i++)
1031*4c87aefeSPatrick Mooney 			pci_xhci_disable_ep(dev, i);
1032*4c87aefeSPatrick Mooney 
1033*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_SUCCESS;
1034*4c87aefeSPatrick Mooney 
1035*4c87aefeSPatrick Mooney 		goto done;
1036*4c87aefeSPatrick Mooney 	}
1037*4c87aefeSPatrick Mooney 
1038*4c87aefeSPatrick Mooney 	if (dev->dev_slotstate < XHCI_ST_ADDRESSED) {
1039*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: config_ep slotstate x%x != addressed\r\n",
1040*4c87aefeSPatrick Mooney 		        dev->dev_slotstate));
1041*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
1042*4c87aefeSPatrick Mooney 		goto done;
1043*4c87aefeSPatrick Mooney 	}
1044*4c87aefeSPatrick Mooney 
1045*4c87aefeSPatrick Mooney 	/* In addressed/configured state;
1046*4c87aefeSPatrick Mooney 	 * for each drop endpoint ctx flag:
1047*4c87aefeSPatrick Mooney 	 *   ep->state = DISABLED
1048*4c87aefeSPatrick Mooney 	 * for each add endpoint ctx flag:
1049*4c87aefeSPatrick Mooney 	 *   cp(ep-in, ep-out)
1050*4c87aefeSPatrick Mooney 	 *   ep->state = RUNNING
1051*4c87aefeSPatrick Mooney 	 * for each drop+add endpoint flag:
1052*4c87aefeSPatrick Mooney 	 *   reset ep resources
1053*4c87aefeSPatrick Mooney 	 *   cp(ep-in, ep-out)
1054*4c87aefeSPatrick Mooney 	 *   ep->state = RUNNING
1055*4c87aefeSPatrick Mooney 	 * if input->DisabledCtx[2-31] < 30: (at least 1 ep not disabled)
1056*4c87aefeSPatrick Mooney 	 *   slot->state = configured
1057*4c87aefeSPatrick Mooney 	 */
1058*4c87aefeSPatrick Mooney 
1059*4c87aefeSPatrick Mooney 	input_ctx = XHCI_GADDR(sc, trb->qwTrb0 & ~0xFUL);
1060*4c87aefeSPatrick Mooney 	dev_ctx = dev->dev_ctx;
1061*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: config_ep inputctx: D:x%08x A:x%08x 7:x%08x\r\n",
1062*4c87aefeSPatrick Mooney 		input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1,
1063*4c87aefeSPatrick Mooney 	        input_ctx->ctx_input.dwInCtx7));
1064*4c87aefeSPatrick Mooney 
1065*4c87aefeSPatrick Mooney 	for (i = 2; i <= 31; i++) {
1066*4c87aefeSPatrick Mooney 		ep_ctx = &dev_ctx->ctx_ep[i];
1067*4c87aefeSPatrick Mooney 
1068*4c87aefeSPatrick Mooney 		if (input_ctx->ctx_input.dwInCtx0 &
1069*4c87aefeSPatrick Mooney 		    XHCI_INCTX_0_DROP_MASK(i)) {
1070*4c87aefeSPatrick Mooney 			DPRINTF((" config ep - dropping ep %d\r\n", i));
1071*4c87aefeSPatrick Mooney 			pci_xhci_disable_ep(dev, i);
1072*4c87aefeSPatrick Mooney 		}
1073*4c87aefeSPatrick Mooney 
1074*4c87aefeSPatrick Mooney 		if (input_ctx->ctx_input.dwInCtx1 &
1075*4c87aefeSPatrick Mooney 		    XHCI_INCTX_1_ADD_MASK(i)) {
1076*4c87aefeSPatrick Mooney 			iep_ctx = &input_ctx->ctx_ep[i];
1077*4c87aefeSPatrick Mooney 
1078*4c87aefeSPatrick Mooney 			DPRINTF((" enable ep[%d]  %08x %08x %016lx %08x\r\n",
1079*4c87aefeSPatrick Mooney 			   i, iep_ctx->dwEpCtx0, iep_ctx->dwEpCtx1,
1080*4c87aefeSPatrick Mooney 			   iep_ctx->qwEpCtx2, iep_ctx->dwEpCtx4));
1081*4c87aefeSPatrick Mooney 
1082*4c87aefeSPatrick Mooney 			memcpy(ep_ctx, iep_ctx, sizeof(struct xhci_endp_ctx));
1083*4c87aefeSPatrick Mooney 
1084*4c87aefeSPatrick Mooney 			pci_xhci_init_ep(dev, i);
1085*4c87aefeSPatrick Mooney 
1086*4c87aefeSPatrick Mooney 			/* ep state */
1087*4c87aefeSPatrick Mooney 			ep_ctx->dwEpCtx0 = FIELD_REPLACE(
1088*4c87aefeSPatrick Mooney 			    ep_ctx->dwEpCtx0, XHCI_ST_EPCTX_RUNNING, 0x7, 0);
1089*4c87aefeSPatrick Mooney 		}
1090*4c87aefeSPatrick Mooney 	}
1091*4c87aefeSPatrick Mooney 
1092*4c87aefeSPatrick Mooney 	/* slot state to configured */
1093*4c87aefeSPatrick Mooney 	dev_ctx->ctx_slot.dwSctx3 = FIELD_REPLACE(
1094*4c87aefeSPatrick Mooney 	    dev_ctx->ctx_slot.dwSctx3, XHCI_ST_SLCTX_CONFIGURED, 0x1F, 27);
1095*4c87aefeSPatrick Mooney 	dev_ctx->ctx_slot.dwSctx0 = FIELD_COPY(
1096*4c87aefeSPatrick Mooney 	    dev_ctx->ctx_slot.dwSctx0, input_ctx->ctx_slot.dwSctx0, 0x1F, 27);
1097*4c87aefeSPatrick Mooney 	dev->dev_slotstate = XHCI_ST_CONFIGURED;
1098*4c87aefeSPatrick Mooney 
1099*4c87aefeSPatrick Mooney 	DPRINTF(("EP configured; slot %u [0]=0x%08x [1]=0x%08x [2]=0x%08x "
1100*4c87aefeSPatrick Mooney 	         "[3]=0x%08x\r\n",
1101*4c87aefeSPatrick Mooney 	    slot, dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1,
1102*4c87aefeSPatrick Mooney 	    dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3));
1103*4c87aefeSPatrick Mooney 
1104*4c87aefeSPatrick Mooney done:
1105*4c87aefeSPatrick Mooney 	return (cmderr);
1106*4c87aefeSPatrick Mooney }
1107*4c87aefeSPatrick Mooney 
1108*4c87aefeSPatrick Mooney static uint32_t
1109*4c87aefeSPatrick Mooney pci_xhci_cmd_reset_ep(struct pci_xhci_softc *sc, uint32_t slot,
1110*4c87aefeSPatrick Mooney     struct xhci_trb *trb)
1111*4c87aefeSPatrick Mooney {
1112*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	*dev;
1113*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_ep *devep;
1114*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
1115*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx	*ep_ctx;
1116*4c87aefeSPatrick Mooney 	uint32_t	cmderr, epid;
1117*4c87aefeSPatrick Mooney 	uint32_t	type;
1118*4c87aefeSPatrick Mooney 
1119*4c87aefeSPatrick Mooney 	epid = XHCI_TRB_3_EP_GET(trb->dwTrb3);
1120*4c87aefeSPatrick Mooney 
1121*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: reset ep %u: slot %u\r\n", epid, slot));
1122*4c87aefeSPatrick Mooney 
1123*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_SUCCESS;
1124*4c87aefeSPatrick Mooney 
1125*4c87aefeSPatrick Mooney 	type = XHCI_TRB_3_TYPE_GET(trb->dwTrb3);
1126*4c87aefeSPatrick Mooney 
1127*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
1128*4c87aefeSPatrick Mooney 	assert(dev != NULL);
1129*4c87aefeSPatrick Mooney 
1130*4c87aefeSPatrick Mooney 	if (type == XHCI_TRB_TYPE_STOP_EP &&
1131*4c87aefeSPatrick Mooney 	    (trb->dwTrb3 & XHCI_TRB_3_SUSP_EP_BIT) != 0) {
1132*4c87aefeSPatrick Mooney 		/* XXX suspend endpoint for 10ms */
1133*4c87aefeSPatrick Mooney 	}
1134*4c87aefeSPatrick Mooney 
1135*4c87aefeSPatrick Mooney 	if (epid < 1 || epid > 31) {
1136*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: reset ep: invalid epid %u\r\n", epid));
1137*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_TRB;
1138*4c87aefeSPatrick Mooney 		goto done;
1139*4c87aefeSPatrick Mooney 	}
1140*4c87aefeSPatrick Mooney 
1141*4c87aefeSPatrick Mooney 	devep = &dev->eps[epid];
1142*4c87aefeSPatrick Mooney 	if (devep->ep_xfer != NULL)
1143*4c87aefeSPatrick Mooney 		USB_DATA_XFER_RESET(devep->ep_xfer);
1144*4c87aefeSPatrick Mooney 
1145*4c87aefeSPatrick Mooney 	dev_ctx = dev->dev_ctx;
1146*4c87aefeSPatrick Mooney 	assert(dev_ctx != NULL);
1147*4c87aefeSPatrick Mooney 
1148*4c87aefeSPatrick Mooney 	ep_ctx = &dev_ctx->ctx_ep[epid];
1149*4c87aefeSPatrick Mooney 
1150*4c87aefeSPatrick Mooney 	ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_STOPPED;
1151*4c87aefeSPatrick Mooney 
1152*4c87aefeSPatrick Mooney 	if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) == 0)
1153*4c87aefeSPatrick Mooney 		ep_ctx->qwEpCtx2 = devep->ep_ringaddr | devep->ep_ccs;
1154*4c87aefeSPatrick Mooney 
1155*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: reset ep[%u] %08x %08x %016lx %08x\r\n",
1156*4c87aefeSPatrick Mooney 	        epid, ep_ctx->dwEpCtx0, ep_ctx->dwEpCtx1, ep_ctx->qwEpCtx2,
1157*4c87aefeSPatrick Mooney 	        ep_ctx->dwEpCtx4));
1158*4c87aefeSPatrick Mooney 
1159*4c87aefeSPatrick Mooney 	if (type == XHCI_TRB_TYPE_RESET_EP &&
1160*4c87aefeSPatrick Mooney 	    (dev->dev_ue->ue_reset == NULL ||
1161*4c87aefeSPatrick Mooney 	    dev->dev_ue->ue_reset(dev->dev_sc) < 0)) {
1162*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_ENDP_NOT_ON;
1163*4c87aefeSPatrick Mooney 		goto done;
1164*4c87aefeSPatrick Mooney 	}
1165*4c87aefeSPatrick Mooney 
1166*4c87aefeSPatrick Mooney done:
1167*4c87aefeSPatrick Mooney 	return (cmderr);
1168*4c87aefeSPatrick Mooney }
1169*4c87aefeSPatrick Mooney 
1170*4c87aefeSPatrick Mooney 
1171*4c87aefeSPatrick Mooney static uint32_t
1172*4c87aefeSPatrick Mooney pci_xhci_find_stream(struct pci_xhci_softc *sc, struct xhci_endp_ctx *ep,
1173*4c87aefeSPatrick Mooney     uint32_t streamid, struct xhci_stream_ctx **osctx)
1174*4c87aefeSPatrick Mooney {
1175*4c87aefeSPatrick Mooney 	struct xhci_stream_ctx *sctx;
1176*4c87aefeSPatrick Mooney 	uint32_t	maxpstreams;
1177*4c87aefeSPatrick Mooney 
1178*4c87aefeSPatrick Mooney 	maxpstreams = XHCI_EPCTX_0_MAXP_STREAMS_GET(ep->dwEpCtx0);
1179*4c87aefeSPatrick Mooney 	if (maxpstreams == 0)
1180*4c87aefeSPatrick Mooney 		return (XHCI_TRB_ERROR_TRB);
1181*4c87aefeSPatrick Mooney 
1182*4c87aefeSPatrick Mooney 	if (maxpstreams > XHCI_STREAMS_MAX)
1183*4c87aefeSPatrick Mooney 		return (XHCI_TRB_ERROR_INVALID_SID);
1184*4c87aefeSPatrick Mooney 
1185*4c87aefeSPatrick Mooney 	if (XHCI_EPCTX_0_LSA_GET(ep->dwEpCtx0) == 0) {
1186*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: find_stream; LSA bit not set\r\n"));
1187*4c87aefeSPatrick Mooney 		return (XHCI_TRB_ERROR_INVALID_SID);
1188*4c87aefeSPatrick Mooney 	}
1189*4c87aefeSPatrick Mooney 
1190*4c87aefeSPatrick Mooney 	/* only support primary stream */
1191*4c87aefeSPatrick Mooney 	if (streamid > maxpstreams)
1192*4c87aefeSPatrick Mooney 		return (XHCI_TRB_ERROR_STREAM_TYPE);
1193*4c87aefeSPatrick Mooney 
1194*4c87aefeSPatrick Mooney 	sctx = XHCI_GADDR(sc, ep->qwEpCtx2 & ~0xFUL) + streamid;
1195*4c87aefeSPatrick Mooney 	if (!XHCI_SCTX_0_SCT_GET(sctx->qwSctx0))
1196*4c87aefeSPatrick Mooney 		return (XHCI_TRB_ERROR_STREAM_TYPE);
1197*4c87aefeSPatrick Mooney 
1198*4c87aefeSPatrick Mooney 	*osctx = sctx;
1199*4c87aefeSPatrick Mooney 
1200*4c87aefeSPatrick Mooney 	return (XHCI_TRB_ERROR_SUCCESS);
1201*4c87aefeSPatrick Mooney }
1202*4c87aefeSPatrick Mooney 
1203*4c87aefeSPatrick Mooney 
1204*4c87aefeSPatrick Mooney static uint32_t
1205*4c87aefeSPatrick Mooney pci_xhci_cmd_set_tr(struct pci_xhci_softc *sc, uint32_t slot,
1206*4c87aefeSPatrick Mooney     struct xhci_trb *trb)
1207*4c87aefeSPatrick Mooney {
1208*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	*dev;
1209*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_ep	*devep;
1210*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
1211*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx	*ep_ctx;
1212*4c87aefeSPatrick Mooney 	uint32_t	cmderr, epid;
1213*4c87aefeSPatrick Mooney 	uint32_t	streamid;
1214*4c87aefeSPatrick Mooney 
1215*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_SUCCESS;
1216*4c87aefeSPatrick Mooney 
1217*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
1218*4c87aefeSPatrick Mooney 	assert(dev != NULL);
1219*4c87aefeSPatrick Mooney 
1220*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci set_tr: new-tr x%016lx, SCT %u DCS %u\r\n"
1221*4c87aefeSPatrick Mooney 	         "                 stream-id %u, slot %u, epid %u, C %u\r\n",
1222*4c87aefeSPatrick Mooney 	         (trb->qwTrb0 & ~0xF),  (uint32_t)((trb->qwTrb0 >> 1) & 0x7),
1223*4c87aefeSPatrick Mooney 	         (uint32_t)(trb->qwTrb0 & 0x1), (trb->dwTrb2 >> 16) & 0xFFFF,
1224*4c87aefeSPatrick Mooney 	         XHCI_TRB_3_SLOT_GET(trb->dwTrb3),
1225*4c87aefeSPatrick Mooney 	         XHCI_TRB_3_EP_GET(trb->dwTrb3), trb->dwTrb3 & 0x1));
1226*4c87aefeSPatrick Mooney 
1227*4c87aefeSPatrick Mooney 	epid = XHCI_TRB_3_EP_GET(trb->dwTrb3);
1228*4c87aefeSPatrick Mooney 	if (epid < 1 || epid > 31) {
1229*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: set_tr_deq: invalid epid %u\r\n", epid));
1230*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_TRB;
1231*4c87aefeSPatrick Mooney 		goto done;
1232*4c87aefeSPatrick Mooney 	}
1233*4c87aefeSPatrick Mooney 
1234*4c87aefeSPatrick Mooney 	dev_ctx = dev->dev_ctx;
1235*4c87aefeSPatrick Mooney 	assert(dev_ctx != NULL);
1236*4c87aefeSPatrick Mooney 
1237*4c87aefeSPatrick Mooney 	ep_ctx = &dev_ctx->ctx_ep[epid];
1238*4c87aefeSPatrick Mooney 	devep = &dev->eps[epid];
1239*4c87aefeSPatrick Mooney 
1240*4c87aefeSPatrick Mooney 	switch (XHCI_EPCTX_0_EPSTATE_GET(ep_ctx->dwEpCtx0)) {
1241*4c87aefeSPatrick Mooney 	case XHCI_ST_EPCTX_STOPPED:
1242*4c87aefeSPatrick Mooney 	case XHCI_ST_EPCTX_ERROR:
1243*4c87aefeSPatrick Mooney 		break;
1244*4c87aefeSPatrick Mooney 	default:
1245*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci cmd set_tr invalid state %x\r\n",
1246*4c87aefeSPatrick Mooney 		        XHCI_EPCTX_0_EPSTATE_GET(ep_ctx->dwEpCtx0)));
1247*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_CONTEXT_STATE;
1248*4c87aefeSPatrick Mooney 		goto done;
1249*4c87aefeSPatrick Mooney 	}
1250*4c87aefeSPatrick Mooney 
1251*4c87aefeSPatrick Mooney 	streamid = XHCI_TRB_2_STREAM_GET(trb->dwTrb2);
1252*4c87aefeSPatrick Mooney 	if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0) {
1253*4c87aefeSPatrick Mooney 		struct xhci_stream_ctx *sctx;
1254*4c87aefeSPatrick Mooney 
1255*4c87aefeSPatrick Mooney 		sctx = NULL;
1256*4c87aefeSPatrick Mooney 		cmderr = pci_xhci_find_stream(sc, ep_ctx, streamid, &sctx);
1257*4c87aefeSPatrick Mooney 		if (sctx != NULL) {
1258*4c87aefeSPatrick Mooney 			assert(devep->ep_sctx != NULL);
1259*4c87aefeSPatrick Mooney 
1260*4c87aefeSPatrick Mooney 			devep->ep_sctx[streamid].qwSctx0 = trb->qwTrb0;
1261*4c87aefeSPatrick Mooney 			devep->ep_sctx_trbs[streamid].ringaddr =
1262*4c87aefeSPatrick Mooney 			    trb->qwTrb0 & ~0xF;
1263*4c87aefeSPatrick Mooney 			devep->ep_sctx_trbs[streamid].ccs =
1264*4c87aefeSPatrick Mooney 			    XHCI_EPCTX_2_DCS_GET(trb->qwTrb0);
1265*4c87aefeSPatrick Mooney 		}
1266*4c87aefeSPatrick Mooney 	} else {
1267*4c87aefeSPatrick Mooney 		if (streamid != 0) {
1268*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci cmd set_tr streamid %x != 0\r\n",
1269*4c87aefeSPatrick Mooney 			        streamid));
1270*4c87aefeSPatrick Mooney 		}
1271*4c87aefeSPatrick Mooney 		ep_ctx->qwEpCtx2 = trb->qwTrb0 & ~0xFUL;
1272*4c87aefeSPatrick Mooney 		devep->ep_ringaddr = ep_ctx->qwEpCtx2 & ~0xFUL;
1273*4c87aefeSPatrick Mooney 		devep->ep_ccs = trb->qwTrb0 & 0x1;
1274*4c87aefeSPatrick Mooney 		devep->ep_tr = XHCI_GADDR(sc, devep->ep_ringaddr);
1275*4c87aefeSPatrick Mooney 
1276*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci set_tr first TRB:\r\n"));
1277*4c87aefeSPatrick Mooney 		pci_xhci_dump_trb(devep->ep_tr);
1278*4c87aefeSPatrick Mooney 	}
1279*4c87aefeSPatrick Mooney 	ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_STOPPED;
1280*4c87aefeSPatrick Mooney 
1281*4c87aefeSPatrick Mooney done:
1282*4c87aefeSPatrick Mooney 	return (cmderr);
1283*4c87aefeSPatrick Mooney }
1284*4c87aefeSPatrick Mooney 
1285*4c87aefeSPatrick Mooney static uint32_t
1286*4c87aefeSPatrick Mooney pci_xhci_cmd_eval_ctx(struct pci_xhci_softc *sc, uint32_t slot,
1287*4c87aefeSPatrick Mooney     struct xhci_trb *trb)
1288*4c87aefeSPatrick Mooney {
1289*4c87aefeSPatrick Mooney 	struct xhci_input_dev_ctx *input_ctx;
1290*4c87aefeSPatrick Mooney 	struct xhci_slot_ctx      *islot_ctx;
1291*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx       *dev_ctx;
1292*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx      *ep0_ctx;
1293*4c87aefeSPatrick Mooney 	uint32_t cmderr;
1294*4c87aefeSPatrick Mooney 
1295*4c87aefeSPatrick Mooney 	input_ctx = XHCI_GADDR(sc, trb->qwTrb0 & ~0xFUL);
1296*4c87aefeSPatrick Mooney 	islot_ctx = &input_ctx->ctx_slot;
1297*4c87aefeSPatrick Mooney 	ep0_ctx = &input_ctx->ctx_ep[1];
1298*4c87aefeSPatrick Mooney 
1299*4c87aefeSPatrick Mooney 	cmderr = XHCI_TRB_ERROR_SUCCESS;
1300*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: eval ctx, input ctl: D 0x%08x A 0x%08x,\r\n"
1301*4c87aefeSPatrick Mooney 	         "          slot %08x %08x %08x %08x\r\n"
1302*4c87aefeSPatrick Mooney 	         "          ep0  %08x %08x %016lx %08x\r\n",
1303*4c87aefeSPatrick Mooney 	        input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1,
1304*4c87aefeSPatrick Mooney 	        islot_ctx->dwSctx0, islot_ctx->dwSctx1,
1305*4c87aefeSPatrick Mooney 	        islot_ctx->dwSctx2, islot_ctx->dwSctx3,
1306*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2,
1307*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx4));
1308*4c87aefeSPatrick Mooney 
1309*4c87aefeSPatrick Mooney 	/* this command expects drop-ctx=0 & add-ctx=slot+ep0 */
1310*4c87aefeSPatrick Mooney 	if ((input_ctx->ctx_input.dwInCtx0 != 0) ||
1311*4c87aefeSPatrick Mooney 	    (input_ctx->ctx_input.dwInCtx1 & 0x03) == 0) {
1312*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: eval ctx, input ctl invalid\r\n"));
1313*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_TRB;
1314*4c87aefeSPatrick Mooney 		goto done;
1315*4c87aefeSPatrick Mooney 	}
1316*4c87aefeSPatrick Mooney 
1317*4c87aefeSPatrick Mooney 	/* assign address to slot; in this emulation, slot_id = address */
1318*4c87aefeSPatrick Mooney 	dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
1319*4c87aefeSPatrick Mooney 
1320*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: eval ctx, dev ctx\r\n"
1321*4c87aefeSPatrick Mooney 	         "          slot %08x %08x %08x %08x\r\n",
1322*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1,
1323*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3));
1324*4c87aefeSPatrick Mooney 
1325*4c87aefeSPatrick Mooney 	if (input_ctx->ctx_input.dwInCtx1 & 0x01) {	/* slot ctx */
1326*4c87aefeSPatrick Mooney 		/* set max exit latency */
1327*4c87aefeSPatrick Mooney 		dev_ctx->ctx_slot.dwSctx1 = FIELD_COPY(
1328*4c87aefeSPatrick Mooney 		    dev_ctx->ctx_slot.dwSctx1, input_ctx->ctx_slot.dwSctx1,
1329*4c87aefeSPatrick Mooney 		    0xFFFF, 0);
1330*4c87aefeSPatrick Mooney 
1331*4c87aefeSPatrick Mooney 		/* set interrupter target */
1332*4c87aefeSPatrick Mooney 		dev_ctx->ctx_slot.dwSctx2 = FIELD_COPY(
1333*4c87aefeSPatrick Mooney 		    dev_ctx->ctx_slot.dwSctx2, input_ctx->ctx_slot.dwSctx2,
1334*4c87aefeSPatrick Mooney 		    0x3FF, 22);
1335*4c87aefeSPatrick Mooney 	}
1336*4c87aefeSPatrick Mooney 	if (input_ctx->ctx_input.dwInCtx1 & 0x02) {	/* control ctx */
1337*4c87aefeSPatrick Mooney 		/* set max packet size */
1338*4c87aefeSPatrick Mooney 		dev_ctx->ctx_ep[1].dwEpCtx1 = FIELD_COPY(
1339*4c87aefeSPatrick Mooney 		    dev_ctx->ctx_ep[1].dwEpCtx1, ep0_ctx->dwEpCtx1,
1340*4c87aefeSPatrick Mooney 		    0xFFFF, 16);
1341*4c87aefeSPatrick Mooney 
1342*4c87aefeSPatrick Mooney 		ep0_ctx = &dev_ctx->ctx_ep[1];
1343*4c87aefeSPatrick Mooney 	}
1344*4c87aefeSPatrick Mooney 
1345*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: eval ctx, output ctx\r\n"
1346*4c87aefeSPatrick Mooney 	         "          slot %08x %08x %08x %08x\r\n"
1347*4c87aefeSPatrick Mooney 	         "          ep0  %08x %08x %016lx %08x\r\n",
1348*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1,
1349*4c87aefeSPatrick Mooney 	        dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3,
1350*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2,
1351*4c87aefeSPatrick Mooney 	        ep0_ctx->dwEpCtx4));
1352*4c87aefeSPatrick Mooney 
1353*4c87aefeSPatrick Mooney done:
1354*4c87aefeSPatrick Mooney 	return (cmderr);
1355*4c87aefeSPatrick Mooney }
1356*4c87aefeSPatrick Mooney 
1357*4c87aefeSPatrick Mooney static int
1358*4c87aefeSPatrick Mooney pci_xhci_complete_commands(struct pci_xhci_softc *sc)
1359*4c87aefeSPatrick Mooney {
1360*4c87aefeSPatrick Mooney 	struct xhci_trb	evtrb;
1361*4c87aefeSPatrick Mooney 	struct xhci_trb	*trb;
1362*4c87aefeSPatrick Mooney 	uint64_t	crcr;
1363*4c87aefeSPatrick Mooney 	uint32_t	ccs;		/* cycle state (XHCI 4.9.2) */
1364*4c87aefeSPatrick Mooney 	uint32_t	type;
1365*4c87aefeSPatrick Mooney 	uint32_t	slot;
1366*4c87aefeSPatrick Mooney 	uint32_t	cmderr;
1367*4c87aefeSPatrick Mooney 	int		error;
1368*4c87aefeSPatrick Mooney 
1369*4c87aefeSPatrick Mooney 	error = 0;
1370*4c87aefeSPatrick Mooney 	sc->opregs.crcr |= XHCI_CRCR_LO_CRR;
1371*4c87aefeSPatrick Mooney 
1372*4c87aefeSPatrick Mooney 	trb = sc->opregs.cr_p;
1373*4c87aefeSPatrick Mooney 	ccs = sc->opregs.crcr & XHCI_CRCR_LO_RCS;
1374*4c87aefeSPatrick Mooney 	crcr = sc->opregs.crcr & ~0xF;
1375*4c87aefeSPatrick Mooney 
1376*4c87aefeSPatrick Mooney 	while (1) {
1377*4c87aefeSPatrick Mooney 		sc->opregs.cr_p = trb;
1378*4c87aefeSPatrick Mooney 
1379*4c87aefeSPatrick Mooney 		type = XHCI_TRB_3_TYPE_GET(trb->dwTrb3);
1380*4c87aefeSPatrick Mooney 
1381*4c87aefeSPatrick Mooney 		if ((trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT) !=
1382*4c87aefeSPatrick Mooney 		    (ccs & XHCI_TRB_3_CYCLE_BIT))
1383*4c87aefeSPatrick Mooney 			break;
1384*4c87aefeSPatrick Mooney 
1385*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: cmd type 0x%x, Trb0 x%016lx dwTrb2 x%08x"
1386*4c87aefeSPatrick Mooney 		        " dwTrb3 x%08x, TRB_CYCLE %u/ccs %u\r\n",
1387*4c87aefeSPatrick Mooney 		        type, trb->qwTrb0, trb->dwTrb2, trb->dwTrb3,
1388*4c87aefeSPatrick Mooney 		        trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT, ccs));
1389*4c87aefeSPatrick Mooney 
1390*4c87aefeSPatrick Mooney 		cmderr = XHCI_TRB_ERROR_SUCCESS;
1391*4c87aefeSPatrick Mooney 		evtrb.dwTrb2 = 0;
1392*4c87aefeSPatrick Mooney 		evtrb.dwTrb3 = (ccs & XHCI_TRB_3_CYCLE_BIT) |
1393*4c87aefeSPatrick Mooney 		      XHCI_TRB_3_TYPE_SET(XHCI_TRB_EVENT_CMD_COMPLETE);
1394*4c87aefeSPatrick Mooney 		slot = 0;
1395*4c87aefeSPatrick Mooney 
1396*4c87aefeSPatrick Mooney 		switch (type) {
1397*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_LINK:			/* 0x06 */
1398*4c87aefeSPatrick Mooney 			if (trb->dwTrb3 & XHCI_TRB_3_TC_BIT)
1399*4c87aefeSPatrick Mooney 				ccs ^= XHCI_CRCR_LO_RCS;
1400*4c87aefeSPatrick Mooney 			break;
1401*4c87aefeSPatrick Mooney 
1402*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_ENABLE_SLOT:			/* 0x09 */
1403*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_enable_slot(sc, &slot);
1404*4c87aefeSPatrick Mooney 			break;
1405*4c87aefeSPatrick Mooney 
1406*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_DISABLE_SLOT:		/* 0x0A */
1407*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1408*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_disable_slot(sc, slot);
1409*4c87aefeSPatrick Mooney 			break;
1410*4c87aefeSPatrick Mooney 
1411*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_ADDRESS_DEVICE:		/* 0x0B */
1412*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1413*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_address_device(sc, slot, trb);
1414*4c87aefeSPatrick Mooney 			break;
1415*4c87aefeSPatrick Mooney 
1416*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_CONFIGURE_EP:		/* 0x0C */
1417*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1418*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_config_ep(sc, slot, trb);
1419*4c87aefeSPatrick Mooney 			break;
1420*4c87aefeSPatrick Mooney 
1421*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_EVALUATE_CTX:		/* 0x0D */
1422*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1423*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_eval_ctx(sc, slot, trb);
1424*4c87aefeSPatrick Mooney 			break;
1425*4c87aefeSPatrick Mooney 
1426*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_RESET_EP:			/* 0x0E */
1427*4c87aefeSPatrick Mooney 			DPRINTF(("Reset Endpoint on slot %d\r\n", slot));
1428*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1429*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_reset_ep(sc, slot, trb);
1430*4c87aefeSPatrick Mooney 			break;
1431*4c87aefeSPatrick Mooney 
1432*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_STOP_EP:			/* 0x0F */
1433*4c87aefeSPatrick Mooney 			DPRINTF(("Stop Endpoint on slot %d\r\n", slot));
1434*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1435*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_reset_ep(sc, slot, trb);
1436*4c87aefeSPatrick Mooney 			break;
1437*4c87aefeSPatrick Mooney 
1438*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_SET_TR_DEQUEUE:		/* 0x10 */
1439*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1440*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_set_tr(sc, slot, trb);
1441*4c87aefeSPatrick Mooney 			break;
1442*4c87aefeSPatrick Mooney 
1443*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_RESET_DEVICE:		/* 0x11 */
1444*4c87aefeSPatrick Mooney 			slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3);
1445*4c87aefeSPatrick Mooney 			cmderr = pci_xhci_cmd_reset_device(sc, slot);
1446*4c87aefeSPatrick Mooney 			break;
1447*4c87aefeSPatrick Mooney 
1448*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_FORCE_EVENT:			/* 0x12 */
1449*4c87aefeSPatrick Mooney 			/* TODO: */
1450*4c87aefeSPatrick Mooney 			break;
1451*4c87aefeSPatrick Mooney 
1452*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_NEGOTIATE_BW:		/* 0x13 */
1453*4c87aefeSPatrick Mooney 			break;
1454*4c87aefeSPatrick Mooney 
1455*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_SET_LATENCY_TOL:		/* 0x14 */
1456*4c87aefeSPatrick Mooney 			break;
1457*4c87aefeSPatrick Mooney 
1458*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_GET_PORT_BW:			/* 0x15 */
1459*4c87aefeSPatrick Mooney 			break;
1460*4c87aefeSPatrick Mooney 
1461*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_FORCE_HEADER:		/* 0x16 */
1462*4c87aefeSPatrick Mooney 			break;
1463*4c87aefeSPatrick Mooney 
1464*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_NOOP_CMD:			/* 0x17 */
1465*4c87aefeSPatrick Mooney 			break;
1466*4c87aefeSPatrick Mooney 
1467*4c87aefeSPatrick Mooney 		default:
1468*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci: unsupported cmd %x\r\n", type));
1469*4c87aefeSPatrick Mooney 			break;
1470*4c87aefeSPatrick Mooney 		}
1471*4c87aefeSPatrick Mooney 
1472*4c87aefeSPatrick Mooney 		if (type != XHCI_TRB_TYPE_LINK) {
1473*4c87aefeSPatrick Mooney 			/*
1474*4c87aefeSPatrick Mooney 			 * insert command completion event and assert intr
1475*4c87aefeSPatrick Mooney 			 */
1476*4c87aefeSPatrick Mooney 			evtrb.qwTrb0 = crcr;
1477*4c87aefeSPatrick Mooney 			evtrb.dwTrb2 |= XHCI_TRB_2_ERROR_SET(cmderr);
1478*4c87aefeSPatrick Mooney 			evtrb.dwTrb3 |= XHCI_TRB_3_SLOT_SET(slot);
1479*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci: command 0x%x result: 0x%x\r\n",
1480*4c87aefeSPatrick Mooney 			        type, cmderr));
1481*4c87aefeSPatrick Mooney 			pci_xhci_insert_event(sc, &evtrb, 1);
1482*4c87aefeSPatrick Mooney 		}
1483*4c87aefeSPatrick Mooney 
1484*4c87aefeSPatrick Mooney 		trb = pci_xhci_trb_next(sc, trb, &crcr);
1485*4c87aefeSPatrick Mooney 	}
1486*4c87aefeSPatrick Mooney 
1487*4c87aefeSPatrick Mooney 	sc->opregs.crcr = crcr | (sc->opregs.crcr & XHCI_CRCR_LO_CA) | ccs;
1488*4c87aefeSPatrick Mooney 	sc->opregs.crcr &= ~XHCI_CRCR_LO_CRR;
1489*4c87aefeSPatrick Mooney 	return (error);
1490*4c87aefeSPatrick Mooney }
1491*4c87aefeSPatrick Mooney 
1492*4c87aefeSPatrick Mooney static void
1493*4c87aefeSPatrick Mooney pci_xhci_dump_trb(struct xhci_trb *trb)
1494*4c87aefeSPatrick Mooney {
1495*4c87aefeSPatrick Mooney 	static const char *trbtypes[] = {
1496*4c87aefeSPatrick Mooney 		"RESERVED",
1497*4c87aefeSPatrick Mooney 		"NORMAL",
1498*4c87aefeSPatrick Mooney 		"SETUP_STAGE",
1499*4c87aefeSPatrick Mooney 		"DATA_STAGE",
1500*4c87aefeSPatrick Mooney 		"STATUS_STAGE",
1501*4c87aefeSPatrick Mooney 		"ISOCH",
1502*4c87aefeSPatrick Mooney 		"LINK",
1503*4c87aefeSPatrick Mooney 		"EVENT_DATA",
1504*4c87aefeSPatrick Mooney 		"NOOP",
1505*4c87aefeSPatrick Mooney 		"ENABLE_SLOT",
1506*4c87aefeSPatrick Mooney 		"DISABLE_SLOT",
1507*4c87aefeSPatrick Mooney 		"ADDRESS_DEVICE",
1508*4c87aefeSPatrick Mooney 		"CONFIGURE_EP",
1509*4c87aefeSPatrick Mooney 		"EVALUATE_CTX",
1510*4c87aefeSPatrick Mooney 		"RESET_EP",
1511*4c87aefeSPatrick Mooney 		"STOP_EP",
1512*4c87aefeSPatrick Mooney 		"SET_TR_DEQUEUE",
1513*4c87aefeSPatrick Mooney 		"RESET_DEVICE",
1514*4c87aefeSPatrick Mooney 		"FORCE_EVENT",
1515*4c87aefeSPatrick Mooney 		"NEGOTIATE_BW",
1516*4c87aefeSPatrick Mooney 		"SET_LATENCY_TOL",
1517*4c87aefeSPatrick Mooney 		"GET_PORT_BW",
1518*4c87aefeSPatrick Mooney 		"FORCE_HEADER",
1519*4c87aefeSPatrick Mooney 		"NOOP_CMD"
1520*4c87aefeSPatrick Mooney 	};
1521*4c87aefeSPatrick Mooney 	uint32_t type;
1522*4c87aefeSPatrick Mooney 
1523*4c87aefeSPatrick Mooney 	type = XHCI_TRB_3_TYPE_GET(trb->dwTrb3);
1524*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: trb[@%p] type x%02x %s 0:x%016lx 2:x%08x 3:x%08x\r\n",
1525*4c87aefeSPatrick Mooney 	         trb, type,
1526*4c87aefeSPatrick Mooney 	         type <= XHCI_TRB_TYPE_NOOP_CMD ? trbtypes[type] : "INVALID",
1527*4c87aefeSPatrick Mooney 	         trb->qwTrb0, trb->dwTrb2, trb->dwTrb3));
1528*4c87aefeSPatrick Mooney }
1529*4c87aefeSPatrick Mooney 
1530*4c87aefeSPatrick Mooney static int
1531*4c87aefeSPatrick Mooney pci_xhci_xfer_complete(struct pci_xhci_softc *sc, struct usb_data_xfer *xfer,
1532*4c87aefeSPatrick Mooney      uint32_t slot, uint32_t epid, int *do_intr)
1533*4c87aefeSPatrick Mooney {
1534*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu *dev;
1535*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_ep	*devep;
1536*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
1537*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx	*ep_ctx;
1538*4c87aefeSPatrick Mooney 	struct xhci_trb		*trb;
1539*4c87aefeSPatrick Mooney 	struct xhci_trb		evtrb;
1540*4c87aefeSPatrick Mooney 	uint32_t trbflags;
1541*4c87aefeSPatrick Mooney 	uint32_t edtla;
1542*4c87aefeSPatrick Mooney 	int i, err;
1543*4c87aefeSPatrick Mooney 
1544*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
1545*4c87aefeSPatrick Mooney 	devep = &dev->eps[epid];
1546*4c87aefeSPatrick Mooney 	dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
1547*4c87aefeSPatrick Mooney 
1548*4c87aefeSPatrick Mooney 	assert(dev_ctx != NULL);
1549*4c87aefeSPatrick Mooney 
1550*4c87aefeSPatrick Mooney 	ep_ctx = &dev_ctx->ctx_ep[epid];
1551*4c87aefeSPatrick Mooney 
1552*4c87aefeSPatrick Mooney 	err = XHCI_TRB_ERROR_SUCCESS;
1553*4c87aefeSPatrick Mooney 	*do_intr = 0;
1554*4c87aefeSPatrick Mooney 	edtla = 0;
1555*4c87aefeSPatrick Mooney 
1556*4c87aefeSPatrick Mooney 	/* go through list of TRBs and insert event(s) */
1557*4c87aefeSPatrick Mooney 	for (i = xfer->head; xfer->ndata > 0; ) {
1558*4c87aefeSPatrick Mooney 		evtrb.qwTrb0 = (uint64_t)xfer->data[i].hci_data;
1559*4c87aefeSPatrick Mooney 		trb = XHCI_GADDR(sc, evtrb.qwTrb0);
1560*4c87aefeSPatrick Mooney 		trbflags = trb->dwTrb3;
1561*4c87aefeSPatrick Mooney 
1562*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: xfer[%d] done?%u:%d trb %x %016lx %x "
1563*4c87aefeSPatrick Mooney 		         "(err %d) IOC?%d\r\n",
1564*4c87aefeSPatrick Mooney 		     i, xfer->data[i].processed, xfer->data[i].blen,
1565*4c87aefeSPatrick Mooney 		     XHCI_TRB_3_TYPE_GET(trbflags), evtrb.qwTrb0,
1566*4c87aefeSPatrick Mooney 		     trbflags, err,
1567*4c87aefeSPatrick Mooney 		     trb->dwTrb3 & XHCI_TRB_3_IOC_BIT ? 1 : 0));
1568*4c87aefeSPatrick Mooney 
1569*4c87aefeSPatrick Mooney 		if (!xfer->data[i].processed) {
1570*4c87aefeSPatrick Mooney 			xfer->head = i;
1571*4c87aefeSPatrick Mooney 			break;
1572*4c87aefeSPatrick Mooney 		}
1573*4c87aefeSPatrick Mooney 
1574*4c87aefeSPatrick Mooney 		xfer->ndata--;
1575*4c87aefeSPatrick Mooney 		edtla += xfer->data[i].bdone;
1576*4c87aefeSPatrick Mooney 
1577*4c87aefeSPatrick Mooney 		trb->dwTrb3 = (trb->dwTrb3 & ~0x1) | (xfer->data[i].ccs);
1578*4c87aefeSPatrick Mooney 
1579*4c87aefeSPatrick Mooney 		pci_xhci_update_ep_ring(sc, dev, devep, ep_ctx,
1580*4c87aefeSPatrick Mooney 		    xfer->data[i].streamid, xfer->data[i].trbnext,
1581*4c87aefeSPatrick Mooney 		    xfer->data[i].ccs);
1582*4c87aefeSPatrick Mooney 
1583*4c87aefeSPatrick Mooney 		/* Only interrupt if IOC or short packet */
1584*4c87aefeSPatrick Mooney 		if (!(trb->dwTrb3 & XHCI_TRB_3_IOC_BIT) &&
1585*4c87aefeSPatrick Mooney 		    !((err == XHCI_TRB_ERROR_SHORT_PKT) &&
1586*4c87aefeSPatrick Mooney 		      (trb->dwTrb3 & XHCI_TRB_3_ISP_BIT))) {
1587*4c87aefeSPatrick Mooney 
1588*4c87aefeSPatrick Mooney 			i = (i + 1) % USB_MAX_XFER_BLOCKS;
1589*4c87aefeSPatrick Mooney 			continue;
1590*4c87aefeSPatrick Mooney 		}
1591*4c87aefeSPatrick Mooney 
1592*4c87aefeSPatrick Mooney 		evtrb.dwTrb2 = XHCI_TRB_2_ERROR_SET(err) |
1593*4c87aefeSPatrick Mooney 		               XHCI_TRB_2_REM_SET(xfer->data[i].blen);
1594*4c87aefeSPatrick Mooney 
1595*4c87aefeSPatrick Mooney 		evtrb.dwTrb3 = XHCI_TRB_3_TYPE_SET(XHCI_TRB_EVENT_TRANSFER) |
1596*4c87aefeSPatrick Mooney 		    XHCI_TRB_3_SLOT_SET(slot) | XHCI_TRB_3_EP_SET(epid);
1597*4c87aefeSPatrick Mooney 
1598*4c87aefeSPatrick Mooney 		if (XHCI_TRB_3_TYPE_GET(trbflags) == XHCI_TRB_TYPE_EVENT_DATA) {
1599*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci EVENT_DATA edtla %u\r\n", edtla));
1600*4c87aefeSPatrick Mooney 			evtrb.qwTrb0 = trb->qwTrb0;
1601*4c87aefeSPatrick Mooney 			evtrb.dwTrb2 = (edtla & 0xFFFFF) |
1602*4c87aefeSPatrick Mooney 			         XHCI_TRB_2_ERROR_SET(err);
1603*4c87aefeSPatrick Mooney 			evtrb.dwTrb3 |= XHCI_TRB_3_ED_BIT;
1604*4c87aefeSPatrick Mooney 			edtla = 0;
1605*4c87aefeSPatrick Mooney 		}
1606*4c87aefeSPatrick Mooney 
1607*4c87aefeSPatrick Mooney 		*do_intr = 1;
1608*4c87aefeSPatrick Mooney 
1609*4c87aefeSPatrick Mooney 		err = pci_xhci_insert_event(sc, &evtrb, 0);
1610*4c87aefeSPatrick Mooney 		if (err != XHCI_TRB_ERROR_SUCCESS) {
1611*4c87aefeSPatrick Mooney 			break;
1612*4c87aefeSPatrick Mooney 		}
1613*4c87aefeSPatrick Mooney 
1614*4c87aefeSPatrick Mooney 		i = (i + 1) % USB_MAX_XFER_BLOCKS;
1615*4c87aefeSPatrick Mooney 	}
1616*4c87aefeSPatrick Mooney 
1617*4c87aefeSPatrick Mooney 	return (err);
1618*4c87aefeSPatrick Mooney }
1619*4c87aefeSPatrick Mooney 
1620*4c87aefeSPatrick Mooney static void
1621*4c87aefeSPatrick Mooney pci_xhci_update_ep_ring(struct pci_xhci_softc *sc, struct pci_xhci_dev_emu *dev,
1622*4c87aefeSPatrick Mooney     struct pci_xhci_dev_ep *devep, struct xhci_endp_ctx *ep_ctx,
1623*4c87aefeSPatrick Mooney     uint32_t streamid, uint64_t ringaddr, int ccs)
1624*4c87aefeSPatrick Mooney {
1625*4c87aefeSPatrick Mooney 
1626*4c87aefeSPatrick Mooney 	if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) {
1627*4c87aefeSPatrick Mooney 		devep->ep_sctx[streamid].qwSctx0 = (ringaddr & ~0xFUL) |
1628*4c87aefeSPatrick Mooney 		                                   (ccs & 0x1);
1629*4c87aefeSPatrick Mooney 
1630*4c87aefeSPatrick Mooney 		devep->ep_sctx_trbs[streamid].ringaddr = ringaddr & ~0xFUL;
1631*4c87aefeSPatrick Mooney 		devep->ep_sctx_trbs[streamid].ccs = ccs & 0x1;
1632*4c87aefeSPatrick Mooney 		ep_ctx->qwEpCtx2 = (ep_ctx->qwEpCtx2 & ~0x1) | (ccs & 0x1);
1633*4c87aefeSPatrick Mooney 
1634*4c87aefeSPatrick Mooney 		DPRINTF(("xhci update ep-ring stream %d, addr %lx\r\n",
1635*4c87aefeSPatrick Mooney 		    streamid, devep->ep_sctx[streamid].qwSctx0));
1636*4c87aefeSPatrick Mooney 	} else {
1637*4c87aefeSPatrick Mooney 		devep->ep_ringaddr = ringaddr & ~0xFUL;
1638*4c87aefeSPatrick Mooney 		devep->ep_ccs = ccs & 0x1;
1639*4c87aefeSPatrick Mooney 		devep->ep_tr = XHCI_GADDR(sc, ringaddr & ~0xFUL);
1640*4c87aefeSPatrick Mooney 		ep_ctx->qwEpCtx2 = (ringaddr & ~0xFUL) | (ccs & 0x1);
1641*4c87aefeSPatrick Mooney 
1642*4c87aefeSPatrick Mooney 		DPRINTF(("xhci update ep-ring, addr %lx\r\n",
1643*4c87aefeSPatrick Mooney 		    (devep->ep_ringaddr | devep->ep_ccs)));
1644*4c87aefeSPatrick Mooney 	}
1645*4c87aefeSPatrick Mooney }
1646*4c87aefeSPatrick Mooney 
1647*4c87aefeSPatrick Mooney /*
1648*4c87aefeSPatrick Mooney  * Outstanding transfer still in progress (device NAK'd earlier) so retry
1649*4c87aefeSPatrick Mooney  * the transfer again to see if it succeeds.
1650*4c87aefeSPatrick Mooney  */
1651*4c87aefeSPatrick Mooney static int
1652*4c87aefeSPatrick Mooney pci_xhci_try_usb_xfer(struct pci_xhci_softc *sc,
1653*4c87aefeSPatrick Mooney     struct pci_xhci_dev_emu *dev, struct pci_xhci_dev_ep *devep,
1654*4c87aefeSPatrick Mooney     struct xhci_endp_ctx *ep_ctx, uint32_t slot, uint32_t epid)
1655*4c87aefeSPatrick Mooney {
1656*4c87aefeSPatrick Mooney 	struct usb_data_xfer *xfer;
1657*4c87aefeSPatrick Mooney 	int		err;
1658*4c87aefeSPatrick Mooney 	int		do_intr;
1659*4c87aefeSPatrick Mooney 
1660*4c87aefeSPatrick Mooney 	ep_ctx->dwEpCtx0 = FIELD_REPLACE(
1661*4c87aefeSPatrick Mooney 		    ep_ctx->dwEpCtx0, XHCI_ST_EPCTX_RUNNING, 0x7, 0);
1662*4c87aefeSPatrick Mooney 
1663*4c87aefeSPatrick Mooney 	err = 0;
1664*4c87aefeSPatrick Mooney 	do_intr = 0;
1665*4c87aefeSPatrick Mooney 
1666*4c87aefeSPatrick Mooney 	xfer = devep->ep_xfer;
1667*4c87aefeSPatrick Mooney #ifdef __FreeBSD__
1668*4c87aefeSPatrick Mooney 	USB_DATA_XFER_LOCK(xfer);
1669*4c87aefeSPatrick Mooney #else
1670*4c87aefeSPatrick Mooney 	/*
1671*4c87aefeSPatrick Mooney 	 * At least one caller needs to hold this lock across the call to this
1672*4c87aefeSPatrick Mooney 	 * function and other code.  To avoid deadlock from a recursive mutex
1673*4c87aefeSPatrick Mooney 	 * enter, we ensure that all callers hold this lock.
1674*4c87aefeSPatrick Mooney 	 */
1675*4c87aefeSPatrick Mooney 	assert(USB_DATA_XFER_LOCK_HELD(xfer));
1676*4c87aefeSPatrick Mooney #endif
1677*4c87aefeSPatrick Mooney 
1678*4c87aefeSPatrick Mooney 	/* outstanding requests queued up */
1679*4c87aefeSPatrick Mooney 	if (dev->dev_ue->ue_data != NULL) {
1680*4c87aefeSPatrick Mooney 		err = dev->dev_ue->ue_data(dev->dev_sc, xfer,
1681*4c87aefeSPatrick Mooney 		            epid & 0x1 ? USB_XFER_IN : USB_XFER_OUT, epid/2);
1682*4c87aefeSPatrick Mooney 		if (err == USB_ERR_CANCELLED) {
1683*4c87aefeSPatrick Mooney 			if (USB_DATA_GET_ERRCODE(&xfer->data[xfer->head]) ==
1684*4c87aefeSPatrick Mooney 			    USB_NAK)
1685*4c87aefeSPatrick Mooney 				err = XHCI_TRB_ERROR_SUCCESS;
1686*4c87aefeSPatrick Mooney 		} else {
1687*4c87aefeSPatrick Mooney 			err = pci_xhci_xfer_complete(sc, xfer, slot, epid,
1688*4c87aefeSPatrick Mooney 			                             &do_intr);
1689*4c87aefeSPatrick Mooney 			if (err == XHCI_TRB_ERROR_SUCCESS && do_intr) {
1690*4c87aefeSPatrick Mooney 				pci_xhci_assert_interrupt(sc);
1691*4c87aefeSPatrick Mooney 			}
1692*4c87aefeSPatrick Mooney 
1693*4c87aefeSPatrick Mooney 
1694*4c87aefeSPatrick Mooney 			/* XXX should not do it if error? */
1695*4c87aefeSPatrick Mooney 			USB_DATA_XFER_RESET(xfer);
1696*4c87aefeSPatrick Mooney 		}
1697*4c87aefeSPatrick Mooney 	}
1698*4c87aefeSPatrick Mooney 
1699*4c87aefeSPatrick Mooney #ifdef __FreeBSD__
1700*4c87aefeSPatrick Mooney 	USB_DATA_XFER_UNLOCK(xfer);
1701*4c87aefeSPatrick Mooney #endif
1702*4c87aefeSPatrick Mooney 
1703*4c87aefeSPatrick Mooney 	return (err);
1704*4c87aefeSPatrick Mooney }
1705*4c87aefeSPatrick Mooney 
1706*4c87aefeSPatrick Mooney 
1707*4c87aefeSPatrick Mooney static int
1708*4c87aefeSPatrick Mooney pci_xhci_handle_transfer(struct pci_xhci_softc *sc,
1709*4c87aefeSPatrick Mooney     struct pci_xhci_dev_emu *dev, struct pci_xhci_dev_ep *devep,
1710*4c87aefeSPatrick Mooney     struct xhci_endp_ctx *ep_ctx, struct xhci_trb *trb, uint32_t slot,
1711*4c87aefeSPatrick Mooney     uint32_t epid, uint64_t addr, uint32_t ccs, uint32_t streamid)
1712*4c87aefeSPatrick Mooney {
1713*4c87aefeSPatrick Mooney 	struct xhci_trb *setup_trb;
1714*4c87aefeSPatrick Mooney 	struct usb_data_xfer *xfer;
1715*4c87aefeSPatrick Mooney 	struct usb_data_xfer_block *xfer_block;
1716*4c87aefeSPatrick Mooney 	uint64_t	val;
1717*4c87aefeSPatrick Mooney 	uint32_t	trbflags;
1718*4c87aefeSPatrick Mooney 	int		do_intr, err;
1719*4c87aefeSPatrick Mooney 	int		do_retry;
1720*4c87aefeSPatrick Mooney 
1721*4c87aefeSPatrick Mooney 	ep_ctx->dwEpCtx0 = FIELD_REPLACE(ep_ctx->dwEpCtx0,
1722*4c87aefeSPatrick Mooney 	                                 XHCI_ST_EPCTX_RUNNING, 0x7, 0);
1723*4c87aefeSPatrick Mooney 
1724*4c87aefeSPatrick Mooney 	xfer = devep->ep_xfer;
1725*4c87aefeSPatrick Mooney 	USB_DATA_XFER_LOCK(xfer);
1726*4c87aefeSPatrick Mooney 
1727*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci handle_transfer slot %u\r\n", slot));
1728*4c87aefeSPatrick Mooney 
1729*4c87aefeSPatrick Mooney retry:
1730*4c87aefeSPatrick Mooney 	err = 0;
1731*4c87aefeSPatrick Mooney 	do_retry = 0;
1732*4c87aefeSPatrick Mooney 	do_intr = 0;
1733*4c87aefeSPatrick Mooney 	setup_trb = NULL;
1734*4c87aefeSPatrick Mooney 
1735*4c87aefeSPatrick Mooney 	while (1) {
1736*4c87aefeSPatrick Mooney 		pci_xhci_dump_trb(trb);
1737*4c87aefeSPatrick Mooney 
1738*4c87aefeSPatrick Mooney 		trbflags = trb->dwTrb3;
1739*4c87aefeSPatrick Mooney 
1740*4c87aefeSPatrick Mooney 		if (XHCI_TRB_3_TYPE_GET(trbflags) != XHCI_TRB_TYPE_LINK &&
1741*4c87aefeSPatrick Mooney 		    (trbflags & XHCI_TRB_3_CYCLE_BIT) !=
1742*4c87aefeSPatrick Mooney 		    (ccs & XHCI_TRB_3_CYCLE_BIT)) {
1743*4c87aefeSPatrick Mooney 			DPRINTF(("Cycle-bit changed trbflags %x, ccs %x\r\n",
1744*4c87aefeSPatrick Mooney 			    trbflags & XHCI_TRB_3_CYCLE_BIT, ccs));
1745*4c87aefeSPatrick Mooney 			break;
1746*4c87aefeSPatrick Mooney 		}
1747*4c87aefeSPatrick Mooney 
1748*4c87aefeSPatrick Mooney 		xfer_block = NULL;
1749*4c87aefeSPatrick Mooney 
1750*4c87aefeSPatrick Mooney 		switch (XHCI_TRB_3_TYPE_GET(trbflags)) {
1751*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_LINK:
1752*4c87aefeSPatrick Mooney 			if (trb->dwTrb3 & XHCI_TRB_3_TC_BIT)
1753*4c87aefeSPatrick Mooney 				ccs ^= 0x1;
1754*4c87aefeSPatrick Mooney 
1755*4c87aefeSPatrick Mooney 			xfer_block = usb_data_xfer_append(xfer, NULL, 0,
1756*4c87aefeSPatrick Mooney 			                                  (void *)addr, ccs);
1757*4c87aefeSPatrick Mooney 			xfer_block->processed = 1;
1758*4c87aefeSPatrick Mooney 			break;
1759*4c87aefeSPatrick Mooney 
1760*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_SETUP_STAGE:
1761*4c87aefeSPatrick Mooney 			if ((trbflags & XHCI_TRB_3_IDT_BIT) == 0 ||
1762*4c87aefeSPatrick Mooney 			    XHCI_TRB_2_BYTES_GET(trb->dwTrb2) != 8) {
1763*4c87aefeSPatrick Mooney 				DPRINTF(("pci_xhci: invalid setup trb\r\n"));
1764*4c87aefeSPatrick Mooney 				err = XHCI_TRB_ERROR_TRB;
1765*4c87aefeSPatrick Mooney 				goto errout;
1766*4c87aefeSPatrick Mooney 			}
1767*4c87aefeSPatrick Mooney 			setup_trb = trb;
1768*4c87aefeSPatrick Mooney 
1769*4c87aefeSPatrick Mooney 			val = trb->qwTrb0;
1770*4c87aefeSPatrick Mooney 			if (!xfer->ureq)
1771*4c87aefeSPatrick Mooney 				xfer->ureq = malloc(
1772*4c87aefeSPatrick Mooney 				           sizeof(struct usb_device_request));
1773*4c87aefeSPatrick Mooney 			memcpy(xfer->ureq, &val,
1774*4c87aefeSPatrick Mooney 			       sizeof(struct usb_device_request));
1775*4c87aefeSPatrick Mooney 
1776*4c87aefeSPatrick Mooney 			xfer_block = usb_data_xfer_append(xfer, NULL, 0,
1777*4c87aefeSPatrick Mooney 			                                  (void *)addr, ccs);
1778*4c87aefeSPatrick Mooney 			xfer_block->processed = 1;
1779*4c87aefeSPatrick Mooney 			break;
1780*4c87aefeSPatrick Mooney 
1781*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_NORMAL:
1782*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_ISOCH:
1783*4c87aefeSPatrick Mooney 			if (setup_trb != NULL) {
1784*4c87aefeSPatrick Mooney 				DPRINTF(("pci_xhci: trb not supposed to be in "
1785*4c87aefeSPatrick Mooney 				         "ctl scope\r\n"));
1786*4c87aefeSPatrick Mooney 				err = XHCI_TRB_ERROR_TRB;
1787*4c87aefeSPatrick Mooney 				goto errout;
1788*4c87aefeSPatrick Mooney 			}
1789*4c87aefeSPatrick Mooney 			/* fall through */
1790*4c87aefeSPatrick Mooney 
1791*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_DATA_STAGE:
1792*4c87aefeSPatrick Mooney 			xfer_block = usb_data_xfer_append(xfer,
1793*4c87aefeSPatrick Mooney 			     (void *)(trbflags & XHCI_TRB_3_IDT_BIT ?
1794*4c87aefeSPatrick Mooney 			         &trb->qwTrb0 : XHCI_GADDR(sc, trb->qwTrb0)),
1795*4c87aefeSPatrick Mooney 			     trb->dwTrb2 & 0x1FFFF, (void *)addr, ccs);
1796*4c87aefeSPatrick Mooney 			break;
1797*4c87aefeSPatrick Mooney 
1798*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_STATUS_STAGE:
1799*4c87aefeSPatrick Mooney 			xfer_block = usb_data_xfer_append(xfer, NULL, 0,
1800*4c87aefeSPatrick Mooney 			                                  (void *)addr, ccs);
1801*4c87aefeSPatrick Mooney 			break;
1802*4c87aefeSPatrick Mooney 
1803*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_NOOP:
1804*4c87aefeSPatrick Mooney 			xfer_block = usb_data_xfer_append(xfer, NULL, 0,
1805*4c87aefeSPatrick Mooney 			                                  (void *)addr, ccs);
1806*4c87aefeSPatrick Mooney 			xfer_block->processed = 1;
1807*4c87aefeSPatrick Mooney 			break;
1808*4c87aefeSPatrick Mooney 
1809*4c87aefeSPatrick Mooney 		case XHCI_TRB_TYPE_EVENT_DATA:
1810*4c87aefeSPatrick Mooney 			xfer_block = usb_data_xfer_append(xfer, NULL, 0,
1811*4c87aefeSPatrick Mooney 			                                  (void *)addr, ccs);
1812*4c87aefeSPatrick Mooney 			if ((epid > 1) && (trbflags & XHCI_TRB_3_IOC_BIT)) {
1813*4c87aefeSPatrick Mooney 				xfer_block->processed = 1;
1814*4c87aefeSPatrick Mooney 			}
1815*4c87aefeSPatrick Mooney 			break;
1816*4c87aefeSPatrick Mooney 
1817*4c87aefeSPatrick Mooney 		default:
1818*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci: handle xfer unexpected trb type "
1819*4c87aefeSPatrick Mooney 			         "0x%x\r\n",
1820*4c87aefeSPatrick Mooney 			         XHCI_TRB_3_TYPE_GET(trbflags)));
1821*4c87aefeSPatrick Mooney 			err = XHCI_TRB_ERROR_TRB;
1822*4c87aefeSPatrick Mooney 			goto errout;
1823*4c87aefeSPatrick Mooney 		}
1824*4c87aefeSPatrick Mooney 
1825*4c87aefeSPatrick Mooney 		trb = pci_xhci_trb_next(sc, trb, &addr);
1826*4c87aefeSPatrick Mooney 
1827*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: next trb: 0x%lx\r\n", (uint64_t)trb));
1828*4c87aefeSPatrick Mooney 
1829*4c87aefeSPatrick Mooney 		if (xfer_block) {
1830*4c87aefeSPatrick Mooney 			xfer_block->trbnext = addr;
1831*4c87aefeSPatrick Mooney 			xfer_block->streamid = streamid;
1832*4c87aefeSPatrick Mooney 		}
1833*4c87aefeSPatrick Mooney 
1834*4c87aefeSPatrick Mooney 		if (!setup_trb && !(trbflags & XHCI_TRB_3_CHAIN_BIT) &&
1835*4c87aefeSPatrick Mooney 		    XHCI_TRB_3_TYPE_GET(trbflags) != XHCI_TRB_TYPE_LINK) {
1836*4c87aefeSPatrick Mooney 			break;
1837*4c87aefeSPatrick Mooney 		}
1838*4c87aefeSPatrick Mooney 
1839*4c87aefeSPatrick Mooney 		/* handle current batch that requires interrupt on complete */
1840*4c87aefeSPatrick Mooney 		if (trbflags & XHCI_TRB_3_IOC_BIT) {
1841*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci: trb IOC bit set\r\n"));
1842*4c87aefeSPatrick Mooney 			if (epid == 1)
1843*4c87aefeSPatrick Mooney 				do_retry = 1;
1844*4c87aefeSPatrick Mooney 			break;
1845*4c87aefeSPatrick Mooney 		}
1846*4c87aefeSPatrick Mooney 	}
1847*4c87aefeSPatrick Mooney 
1848*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci[%d]: xfer->ndata %u\r\n", __LINE__, xfer->ndata));
1849*4c87aefeSPatrick Mooney 
1850*4c87aefeSPatrick Mooney 	if (epid == 1) {
1851*4c87aefeSPatrick Mooney 		err = USB_ERR_NOT_STARTED;
1852*4c87aefeSPatrick Mooney 		if (dev->dev_ue->ue_request != NULL)
1853*4c87aefeSPatrick Mooney 			err = dev->dev_ue->ue_request(dev->dev_sc, xfer);
1854*4c87aefeSPatrick Mooney 		setup_trb = NULL;
1855*4c87aefeSPatrick Mooney 	} else {
1856*4c87aefeSPatrick Mooney 		/* handle data transfer */
1857*4c87aefeSPatrick Mooney 		pci_xhci_try_usb_xfer(sc, dev, devep, ep_ctx, slot, epid);
1858*4c87aefeSPatrick Mooney 		err = XHCI_TRB_ERROR_SUCCESS;
1859*4c87aefeSPatrick Mooney 		goto errout;
1860*4c87aefeSPatrick Mooney 	}
1861*4c87aefeSPatrick Mooney 
1862*4c87aefeSPatrick Mooney 	err = USB_TO_XHCI_ERR(err);
1863*4c87aefeSPatrick Mooney 	if ((err == XHCI_TRB_ERROR_SUCCESS) ||
1864*4c87aefeSPatrick Mooney 	    (err == XHCI_TRB_ERROR_SHORT_PKT)) {
1865*4c87aefeSPatrick Mooney 		err = pci_xhci_xfer_complete(sc, xfer, slot, epid, &do_intr);
1866*4c87aefeSPatrick Mooney 		if (err != XHCI_TRB_ERROR_SUCCESS)
1867*4c87aefeSPatrick Mooney 			do_retry = 0;
1868*4c87aefeSPatrick Mooney 	}
1869*4c87aefeSPatrick Mooney 
1870*4c87aefeSPatrick Mooney errout:
1871*4c87aefeSPatrick Mooney 	if (err == XHCI_TRB_ERROR_EV_RING_FULL)
1872*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci[%d]: event ring full\r\n", __LINE__));
1873*4c87aefeSPatrick Mooney 
1874*4c87aefeSPatrick Mooney 	if (!do_retry)
1875*4c87aefeSPatrick Mooney 		USB_DATA_XFER_UNLOCK(xfer);
1876*4c87aefeSPatrick Mooney 
1877*4c87aefeSPatrick Mooney 	if (do_intr)
1878*4c87aefeSPatrick Mooney 		pci_xhci_assert_interrupt(sc);
1879*4c87aefeSPatrick Mooney 
1880*4c87aefeSPatrick Mooney 	if (do_retry) {
1881*4c87aefeSPatrick Mooney 		USB_DATA_XFER_RESET(xfer);
1882*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci[%d]: retry:continuing with next TRBs\r\n",
1883*4c87aefeSPatrick Mooney 		         __LINE__));
1884*4c87aefeSPatrick Mooney 		goto retry;
1885*4c87aefeSPatrick Mooney 	}
1886*4c87aefeSPatrick Mooney 
1887*4c87aefeSPatrick Mooney 	if (epid == 1)
1888*4c87aefeSPatrick Mooney 		USB_DATA_XFER_RESET(xfer);
1889*4c87aefeSPatrick Mooney 
1890*4c87aefeSPatrick Mooney 	return (err);
1891*4c87aefeSPatrick Mooney }
1892*4c87aefeSPatrick Mooney 
1893*4c87aefeSPatrick Mooney static void
1894*4c87aefeSPatrick Mooney pci_xhci_device_doorbell(struct pci_xhci_softc *sc, uint32_t slot,
1895*4c87aefeSPatrick Mooney     uint32_t epid, uint32_t streamid)
1896*4c87aefeSPatrick Mooney {
1897*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu *dev;
1898*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_ep	*devep;
1899*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
1900*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx	*ep_ctx;
1901*4c87aefeSPatrick Mooney 	struct pci_xhci_trb_ring *sctx_tr;
1902*4c87aefeSPatrick Mooney 	struct xhci_trb	*trb;
1903*4c87aefeSPatrick Mooney 	uint64_t	ringaddr;
1904*4c87aefeSPatrick Mooney 	uint32_t	ccs;
1905*4c87aefeSPatrick Mooney 
1906*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci doorbell slot %u epid %u stream %u\r\n",
1907*4c87aefeSPatrick Mooney 	    slot, epid, streamid));
1908*4c87aefeSPatrick Mooney 
1909*4c87aefeSPatrick Mooney 	if (slot == 0 || slot > sc->ndevices) {
1910*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: invalid doorbell slot %u\r\n", slot));
1911*4c87aefeSPatrick Mooney 		return;
1912*4c87aefeSPatrick Mooney 	}
1913*4c87aefeSPatrick Mooney 
1914*4c87aefeSPatrick Mooney 	dev = XHCI_SLOTDEV_PTR(sc, slot);
1915*4c87aefeSPatrick Mooney 	devep = &dev->eps[epid];
1916*4c87aefeSPatrick Mooney 	dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
1917*4c87aefeSPatrick Mooney 	if (!dev_ctx) {
1918*4c87aefeSPatrick Mooney 		return;
1919*4c87aefeSPatrick Mooney 	}
1920*4c87aefeSPatrick Mooney 	ep_ctx = &dev_ctx->ctx_ep[epid];
1921*4c87aefeSPatrick Mooney 
1922*4c87aefeSPatrick Mooney 	sctx_tr = NULL;
1923*4c87aefeSPatrick Mooney 
1924*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: device doorbell ep[%u] %08x %08x %016lx %08x\r\n",
1925*4c87aefeSPatrick Mooney 	        epid, ep_ctx->dwEpCtx0, ep_ctx->dwEpCtx1, ep_ctx->qwEpCtx2,
1926*4c87aefeSPatrick Mooney 	        ep_ctx->dwEpCtx4));
1927*4c87aefeSPatrick Mooney 
1928*4c87aefeSPatrick Mooney 	if (ep_ctx->qwEpCtx2 == 0)
1929*4c87aefeSPatrick Mooney 		return;
1930*4c87aefeSPatrick Mooney 
1931*4c87aefeSPatrick Mooney 	/* handle pending transfers */
1932*4c87aefeSPatrick Mooney 	if (devep->ep_xfer->ndata > 0) {
1933*4c87aefeSPatrick Mooney #ifndef __FreeBSD__
1934*4c87aefeSPatrick Mooney 		USB_DATA_XFER_LOCK(devep->ep_xfer);
1935*4c87aefeSPatrick Mooney #endif
1936*4c87aefeSPatrick Mooney 		pci_xhci_try_usb_xfer(sc, dev, devep, ep_ctx, slot, epid);
1937*4c87aefeSPatrick Mooney #ifndef __FreeBSD__
1938*4c87aefeSPatrick Mooney 		USB_DATA_XFER_UNLOCK(devep->ep_xfer);
1939*4c87aefeSPatrick Mooney #endif
1940*4c87aefeSPatrick Mooney 		return;
1941*4c87aefeSPatrick Mooney 	}
1942*4c87aefeSPatrick Mooney 
1943*4c87aefeSPatrick Mooney 	/* get next trb work item */
1944*4c87aefeSPatrick Mooney 	if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) {
1945*4c87aefeSPatrick Mooney 		sctx_tr = &devep->ep_sctx_trbs[streamid];
1946*4c87aefeSPatrick Mooney 		ringaddr = sctx_tr->ringaddr;
1947*4c87aefeSPatrick Mooney 		ccs = sctx_tr->ccs;
1948*4c87aefeSPatrick Mooney 		trb = XHCI_GADDR(sc, sctx_tr->ringaddr & ~0xFUL);
1949*4c87aefeSPatrick Mooney 		DPRINTF(("doorbell, stream %u, ccs %lx, trb ccs %x\r\n",
1950*4c87aefeSPatrick Mooney 		        streamid, ep_ctx->qwEpCtx2 & XHCI_TRB_3_CYCLE_BIT,
1951*4c87aefeSPatrick Mooney 		        trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT));
1952*4c87aefeSPatrick Mooney 	} else {
1953*4c87aefeSPatrick Mooney 		ringaddr = devep->ep_ringaddr;
1954*4c87aefeSPatrick Mooney 		ccs = devep->ep_ccs;
1955*4c87aefeSPatrick Mooney 		trb = devep->ep_tr;
1956*4c87aefeSPatrick Mooney 		DPRINTF(("doorbell, ccs %lx, trb ccs %x\r\n",
1957*4c87aefeSPatrick Mooney 		        ep_ctx->qwEpCtx2 & XHCI_TRB_3_CYCLE_BIT,
1958*4c87aefeSPatrick Mooney 		        trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT));
1959*4c87aefeSPatrick Mooney 	}
1960*4c87aefeSPatrick Mooney 
1961*4c87aefeSPatrick Mooney 	if (XHCI_TRB_3_TYPE_GET(trb->dwTrb3) == 0) {
1962*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: ring %lx trb[%lx] EP %u is RESERVED?\r\n",
1963*4c87aefeSPatrick Mooney 		        ep_ctx->qwEpCtx2, devep->ep_ringaddr, epid));
1964*4c87aefeSPatrick Mooney 		return;
1965*4c87aefeSPatrick Mooney 	}
1966*4c87aefeSPatrick Mooney 
1967*4c87aefeSPatrick Mooney 	pci_xhci_handle_transfer(sc, dev, devep, ep_ctx, trb, slot, epid,
1968*4c87aefeSPatrick Mooney 	                         ringaddr, ccs, streamid);
1969*4c87aefeSPatrick Mooney }
1970*4c87aefeSPatrick Mooney 
1971*4c87aefeSPatrick Mooney static void
1972*4c87aefeSPatrick Mooney pci_xhci_dbregs_write(struct pci_xhci_softc *sc, uint64_t offset,
1973*4c87aefeSPatrick Mooney     uint64_t value)
1974*4c87aefeSPatrick Mooney {
1975*4c87aefeSPatrick Mooney 
1976*4c87aefeSPatrick Mooney 	offset = (offset - sc->dboff) / sizeof(uint32_t);
1977*4c87aefeSPatrick Mooney 
1978*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: doorbell write offset 0x%lx: 0x%lx\r\n",
1979*4c87aefeSPatrick Mooney 	        offset, value));
1980*4c87aefeSPatrick Mooney 
1981*4c87aefeSPatrick Mooney 	if (XHCI_HALTED(sc)) {
1982*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: controller halted\r\n"));
1983*4c87aefeSPatrick Mooney 		return;
1984*4c87aefeSPatrick Mooney 	}
1985*4c87aefeSPatrick Mooney 
1986*4c87aefeSPatrick Mooney 	if (offset == 0)
1987*4c87aefeSPatrick Mooney 		pci_xhci_complete_commands(sc);
1988*4c87aefeSPatrick Mooney 	else if (sc->portregs != NULL)
1989*4c87aefeSPatrick Mooney 		pci_xhci_device_doorbell(sc, offset,
1990*4c87aefeSPatrick Mooney 		   XHCI_DB_TARGET_GET(value), XHCI_DB_SID_GET(value));
1991*4c87aefeSPatrick Mooney }
1992*4c87aefeSPatrick Mooney 
1993*4c87aefeSPatrick Mooney static void
1994*4c87aefeSPatrick Mooney pci_xhci_rtsregs_write(struct pci_xhci_softc *sc, uint64_t offset,
1995*4c87aefeSPatrick Mooney     uint64_t value)
1996*4c87aefeSPatrick Mooney {
1997*4c87aefeSPatrick Mooney 	struct pci_xhci_rtsregs *rts;
1998*4c87aefeSPatrick Mooney 
1999*4c87aefeSPatrick Mooney 	offset -= sc->rtsoff;
2000*4c87aefeSPatrick Mooney 
2001*4c87aefeSPatrick Mooney 	if (offset == 0) {
2002*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci attempted write to MFINDEX\r\n"));
2003*4c87aefeSPatrick Mooney 		return;
2004*4c87aefeSPatrick Mooney 	}
2005*4c87aefeSPatrick Mooney 
2006*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: runtime regs write offset 0x%lx: 0x%lx\r\n",
2007*4c87aefeSPatrick Mooney 	        offset, value));
2008*4c87aefeSPatrick Mooney 
2009*4c87aefeSPatrick Mooney 	offset -= 0x20;		/* start of intrreg */
2010*4c87aefeSPatrick Mooney 
2011*4c87aefeSPatrick Mooney 	rts = &sc->rtsregs;
2012*4c87aefeSPatrick Mooney 
2013*4c87aefeSPatrick Mooney 	switch (offset) {
2014*4c87aefeSPatrick Mooney 	case 0x00:
2015*4c87aefeSPatrick Mooney 		if (value & XHCI_IMAN_INTR_PEND)
2016*4c87aefeSPatrick Mooney 			rts->intrreg.iman &= ~XHCI_IMAN_INTR_PEND;
2017*4c87aefeSPatrick Mooney 		rts->intrreg.iman = (value & XHCI_IMAN_INTR_ENA) |
2018*4c87aefeSPatrick Mooney 		                    (rts->intrreg.iman & XHCI_IMAN_INTR_PEND);
2019*4c87aefeSPatrick Mooney 
2020*4c87aefeSPatrick Mooney 		if (!(value & XHCI_IMAN_INTR_ENA))
2021*4c87aefeSPatrick Mooney 			pci_xhci_deassert_interrupt(sc);
2022*4c87aefeSPatrick Mooney 
2023*4c87aefeSPatrick Mooney 		break;
2024*4c87aefeSPatrick Mooney 
2025*4c87aefeSPatrick Mooney 	case 0x04:
2026*4c87aefeSPatrick Mooney 		rts->intrreg.imod = value;
2027*4c87aefeSPatrick Mooney 		break;
2028*4c87aefeSPatrick Mooney 
2029*4c87aefeSPatrick Mooney 	case 0x08:
2030*4c87aefeSPatrick Mooney 		rts->intrreg.erstsz = value & 0xFFFF;
2031*4c87aefeSPatrick Mooney 		break;
2032*4c87aefeSPatrick Mooney 
2033*4c87aefeSPatrick Mooney 	case 0x10:
2034*4c87aefeSPatrick Mooney 		/* ERSTBA low bits */
2035*4c87aefeSPatrick Mooney 		rts->intrreg.erstba = MASK_64_HI(sc->rtsregs.intrreg.erstba) |
2036*4c87aefeSPatrick Mooney 		                      (value & ~0x3F);
2037*4c87aefeSPatrick Mooney 		break;
2038*4c87aefeSPatrick Mooney 
2039*4c87aefeSPatrick Mooney 	case 0x14:
2040*4c87aefeSPatrick Mooney 		/* ERSTBA high bits */
2041*4c87aefeSPatrick Mooney 		rts->intrreg.erstba = (value << 32) |
2042*4c87aefeSPatrick Mooney 		    MASK_64_LO(sc->rtsregs.intrreg.erstba);
2043*4c87aefeSPatrick Mooney 
2044*4c87aefeSPatrick Mooney 		rts->erstba_p = XHCI_GADDR(sc,
2045*4c87aefeSPatrick Mooney 		                        sc->rtsregs.intrreg.erstba & ~0x3FUL);
2046*4c87aefeSPatrick Mooney 
2047*4c87aefeSPatrick Mooney 		rts->erst_p = XHCI_GADDR(sc,
2048*4c87aefeSPatrick Mooney 		              sc->rtsregs.erstba_p->qwEvrsTablePtr & ~0x3FUL);
2049*4c87aefeSPatrick Mooney 
2050*4c87aefeSPatrick Mooney 		rts->er_enq_idx = 0;
2051*4c87aefeSPatrick Mooney 		rts->er_events_cnt = 0;
2052*4c87aefeSPatrick Mooney 
2053*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: wr erstba erst (%p) ptr 0x%lx, sz %u\r\n",
2054*4c87aefeSPatrick Mooney 		        rts->erstba_p,
2055*4c87aefeSPatrick Mooney 		        rts->erstba_p->qwEvrsTablePtr,
2056*4c87aefeSPatrick Mooney 		        rts->erstba_p->dwEvrsTableSize));
2057*4c87aefeSPatrick Mooney 		break;
2058*4c87aefeSPatrick Mooney 
2059*4c87aefeSPatrick Mooney 	case 0x18:
2060*4c87aefeSPatrick Mooney 		/* ERDP low bits */
2061*4c87aefeSPatrick Mooney 		rts->intrreg.erdp =
2062*4c87aefeSPatrick Mooney 		    MASK_64_HI(sc->rtsregs.intrreg.erdp) |
2063*4c87aefeSPatrick Mooney 		    (rts->intrreg.erdp & XHCI_ERDP_LO_BUSY) |
2064*4c87aefeSPatrick Mooney 		    (value & ~0xF);
2065*4c87aefeSPatrick Mooney 		if (value & XHCI_ERDP_LO_BUSY) {
2066*4c87aefeSPatrick Mooney 			rts->intrreg.erdp &= ~XHCI_ERDP_LO_BUSY;
2067*4c87aefeSPatrick Mooney 			rts->intrreg.iman &= ~XHCI_IMAN_INTR_PEND;
2068*4c87aefeSPatrick Mooney 		}
2069*4c87aefeSPatrick Mooney 
2070*4c87aefeSPatrick Mooney 		rts->er_deq_seg = XHCI_ERDP_LO_SINDEX(value);
2071*4c87aefeSPatrick Mooney 
2072*4c87aefeSPatrick Mooney 		break;
2073*4c87aefeSPatrick Mooney 
2074*4c87aefeSPatrick Mooney 	case 0x1C:
2075*4c87aefeSPatrick Mooney 		/* ERDP high bits */
2076*4c87aefeSPatrick Mooney 		rts->intrreg.erdp = (value << 32) |
2077*4c87aefeSPatrick Mooney 		    MASK_64_LO(sc->rtsregs.intrreg.erdp);
2078*4c87aefeSPatrick Mooney 
2079*4c87aefeSPatrick Mooney 		if (rts->er_events_cnt > 0) {
2080*4c87aefeSPatrick Mooney 			uint64_t erdp;
2081*4c87aefeSPatrick Mooney 			uint32_t erdp_i;
2082*4c87aefeSPatrick Mooney 
2083*4c87aefeSPatrick Mooney 			erdp = rts->intrreg.erdp & ~0xF;
2084*4c87aefeSPatrick Mooney 			erdp_i = (erdp - rts->erstba_p->qwEvrsTablePtr) /
2085*4c87aefeSPatrick Mooney 			           sizeof(struct xhci_trb);
2086*4c87aefeSPatrick Mooney 
2087*4c87aefeSPatrick Mooney 			if (erdp_i <= rts->er_enq_idx)
2088*4c87aefeSPatrick Mooney 				rts->er_events_cnt = rts->er_enq_idx - erdp_i;
2089*4c87aefeSPatrick Mooney 			else
2090*4c87aefeSPatrick Mooney 				rts->er_events_cnt =
2091*4c87aefeSPatrick Mooney 				          rts->erstba_p->dwEvrsTableSize -
2092*4c87aefeSPatrick Mooney 				          (erdp_i - rts->er_enq_idx);
2093*4c87aefeSPatrick Mooney 
2094*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci: erdp 0x%lx, events cnt %u\r\n",
2095*4c87aefeSPatrick Mooney 			        erdp, rts->er_events_cnt));
2096*4c87aefeSPatrick Mooney 		}
2097*4c87aefeSPatrick Mooney 
2098*4c87aefeSPatrick Mooney 		break;
2099*4c87aefeSPatrick Mooney 
2100*4c87aefeSPatrick Mooney 	default:
2101*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci attempted write to RTS offset 0x%lx\r\n",
2102*4c87aefeSPatrick Mooney 		        offset));
2103*4c87aefeSPatrick Mooney 		break;
2104*4c87aefeSPatrick Mooney 	}
2105*4c87aefeSPatrick Mooney }
2106*4c87aefeSPatrick Mooney 
2107*4c87aefeSPatrick Mooney static uint64_t
2108*4c87aefeSPatrick Mooney pci_xhci_portregs_read(struct pci_xhci_softc *sc, uint64_t offset)
2109*4c87aefeSPatrick Mooney {
2110*4c87aefeSPatrick Mooney 	int port;
2111*4c87aefeSPatrick Mooney 	uint32_t *p;
2112*4c87aefeSPatrick Mooney 
2113*4c87aefeSPatrick Mooney 	if (sc->portregs == NULL)
2114*4c87aefeSPatrick Mooney 		return (0);
2115*4c87aefeSPatrick Mooney 
2116*4c87aefeSPatrick Mooney 	port = (offset - 0x3F0) / 0x10;
2117*4c87aefeSPatrick Mooney 
2118*4c87aefeSPatrick Mooney 	if (port > XHCI_MAX_DEVS) {
2119*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: portregs_read port %d >= XHCI_MAX_DEVS\r\n",
2120*4c87aefeSPatrick Mooney 		    port));
2121*4c87aefeSPatrick Mooney 
2122*4c87aefeSPatrick Mooney 		/* return default value for unused port */
2123*4c87aefeSPatrick Mooney 		return (XHCI_PS_SPEED_SET(3));
2124*4c87aefeSPatrick Mooney 	}
2125*4c87aefeSPatrick Mooney 
2126*4c87aefeSPatrick Mooney 	offset = (offset - 0x3F0) % 0x10;
2127*4c87aefeSPatrick Mooney 
2128*4c87aefeSPatrick Mooney 	p = &sc->portregs[port].portsc;
2129*4c87aefeSPatrick Mooney 	p += offset / sizeof(uint32_t);
2130*4c87aefeSPatrick Mooney 
2131*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: portregs read offset 0x%lx port %u -> 0x%x\r\n",
2132*4c87aefeSPatrick Mooney 	        offset, port, *p));
2133*4c87aefeSPatrick Mooney 
2134*4c87aefeSPatrick Mooney 	return (*p);
2135*4c87aefeSPatrick Mooney }
2136*4c87aefeSPatrick Mooney 
2137*4c87aefeSPatrick Mooney static void
2138*4c87aefeSPatrick Mooney pci_xhci_hostop_write(struct pci_xhci_softc *sc, uint64_t offset,
2139*4c87aefeSPatrick Mooney     uint64_t value)
2140*4c87aefeSPatrick Mooney {
2141*4c87aefeSPatrick Mooney 	offset -= XHCI_CAPLEN;
2142*4c87aefeSPatrick Mooney 
2143*4c87aefeSPatrick Mooney 	if (offset < 0x400)
2144*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: hostop write offset 0x%lx: 0x%lx\r\n",
2145*4c87aefeSPatrick Mooney 		         offset, value));
2146*4c87aefeSPatrick Mooney 
2147*4c87aefeSPatrick Mooney 	switch (offset) {
2148*4c87aefeSPatrick Mooney 	case XHCI_USBCMD:
2149*4c87aefeSPatrick Mooney 		sc->opregs.usbcmd = pci_xhci_usbcmd_write(sc, value & 0x3F0F);
2150*4c87aefeSPatrick Mooney 		break;
2151*4c87aefeSPatrick Mooney 
2152*4c87aefeSPatrick Mooney 	case XHCI_USBSTS:
2153*4c87aefeSPatrick Mooney 		/* clear bits on write */
2154*4c87aefeSPatrick Mooney 		sc->opregs.usbsts &= ~(value &
2155*4c87aefeSPatrick Mooney 		      (XHCI_STS_HSE|XHCI_STS_EINT|XHCI_STS_PCD|XHCI_STS_SSS|
2156*4c87aefeSPatrick Mooney 		       XHCI_STS_RSS|XHCI_STS_SRE|XHCI_STS_CNR));
2157*4c87aefeSPatrick Mooney 		break;
2158*4c87aefeSPatrick Mooney 
2159*4c87aefeSPatrick Mooney 	case XHCI_PAGESIZE:
2160*4c87aefeSPatrick Mooney 		/* read only */
2161*4c87aefeSPatrick Mooney 		break;
2162*4c87aefeSPatrick Mooney 
2163*4c87aefeSPatrick Mooney 	case XHCI_DNCTRL:
2164*4c87aefeSPatrick Mooney 		sc->opregs.dnctrl = value & 0xFFFF;
2165*4c87aefeSPatrick Mooney 		break;
2166*4c87aefeSPatrick Mooney 
2167*4c87aefeSPatrick Mooney 	case XHCI_CRCR_LO:
2168*4c87aefeSPatrick Mooney 		if (sc->opregs.crcr & XHCI_CRCR_LO_CRR) {
2169*4c87aefeSPatrick Mooney 			sc->opregs.crcr &= ~(XHCI_CRCR_LO_CS|XHCI_CRCR_LO_CA);
2170*4c87aefeSPatrick Mooney 			sc->opregs.crcr |= value &
2171*4c87aefeSPatrick Mooney 			                   (XHCI_CRCR_LO_CS|XHCI_CRCR_LO_CA);
2172*4c87aefeSPatrick Mooney 		} else {
2173*4c87aefeSPatrick Mooney 			sc->opregs.crcr = MASK_64_HI(sc->opregs.crcr) |
2174*4c87aefeSPatrick Mooney 			           (value & (0xFFFFFFC0 | XHCI_CRCR_LO_RCS));
2175*4c87aefeSPatrick Mooney 		}
2176*4c87aefeSPatrick Mooney 		break;
2177*4c87aefeSPatrick Mooney 
2178*4c87aefeSPatrick Mooney 	case XHCI_CRCR_HI:
2179*4c87aefeSPatrick Mooney 		if (!(sc->opregs.crcr & XHCI_CRCR_LO_CRR)) {
2180*4c87aefeSPatrick Mooney 			sc->opregs.crcr = MASK_64_LO(sc->opregs.crcr) |
2181*4c87aefeSPatrick Mooney 			                  (value << 32);
2182*4c87aefeSPatrick Mooney 
2183*4c87aefeSPatrick Mooney 			sc->opregs.cr_p = XHCI_GADDR(sc,
2184*4c87aefeSPatrick Mooney 			                  sc->opregs.crcr & ~0xF);
2185*4c87aefeSPatrick Mooney 		}
2186*4c87aefeSPatrick Mooney 
2187*4c87aefeSPatrick Mooney 		if (sc->opregs.crcr & XHCI_CRCR_LO_CS) {
2188*4c87aefeSPatrick Mooney 			/* Stop operation of Command Ring */
2189*4c87aefeSPatrick Mooney 		}
2190*4c87aefeSPatrick Mooney 
2191*4c87aefeSPatrick Mooney 		if (sc->opregs.crcr & XHCI_CRCR_LO_CA) {
2192*4c87aefeSPatrick Mooney 			/* Abort command */
2193*4c87aefeSPatrick Mooney 		}
2194*4c87aefeSPatrick Mooney 
2195*4c87aefeSPatrick Mooney 		break;
2196*4c87aefeSPatrick Mooney 
2197*4c87aefeSPatrick Mooney 	case XHCI_DCBAAP_LO:
2198*4c87aefeSPatrick Mooney 		sc->opregs.dcbaap = MASK_64_HI(sc->opregs.dcbaap) |
2199*4c87aefeSPatrick Mooney 		                    (value & 0xFFFFFFC0);
2200*4c87aefeSPatrick Mooney 		break;
2201*4c87aefeSPatrick Mooney 
2202*4c87aefeSPatrick Mooney 	case XHCI_DCBAAP_HI:
2203*4c87aefeSPatrick Mooney 		sc->opregs.dcbaap =  MASK_64_LO(sc->opregs.dcbaap) |
2204*4c87aefeSPatrick Mooney 		                     (value << 32);
2205*4c87aefeSPatrick Mooney 		sc->opregs.dcbaa_p = XHCI_GADDR(sc, sc->opregs.dcbaap & ~0x3FUL);
2206*4c87aefeSPatrick Mooney 
2207*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: opregs dcbaap = 0x%lx (vaddr 0x%lx)\r\n",
2208*4c87aefeSPatrick Mooney 		    sc->opregs.dcbaap, (uint64_t)sc->opregs.dcbaa_p));
2209*4c87aefeSPatrick Mooney 		break;
2210*4c87aefeSPatrick Mooney 
2211*4c87aefeSPatrick Mooney 	case XHCI_CONFIG:
2212*4c87aefeSPatrick Mooney 		sc->opregs.config = value & 0x03FF;
2213*4c87aefeSPatrick Mooney 		break;
2214*4c87aefeSPatrick Mooney 
2215*4c87aefeSPatrick Mooney 	default:
2216*4c87aefeSPatrick Mooney 		if (offset >= 0x400)
2217*4c87aefeSPatrick Mooney 			pci_xhci_portregs_write(sc, offset, value);
2218*4c87aefeSPatrick Mooney 
2219*4c87aefeSPatrick Mooney 		break;
2220*4c87aefeSPatrick Mooney 	}
2221*4c87aefeSPatrick Mooney }
2222*4c87aefeSPatrick Mooney 
2223*4c87aefeSPatrick Mooney 
2224*4c87aefeSPatrick Mooney static void
2225*4c87aefeSPatrick Mooney pci_xhci_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
2226*4c87aefeSPatrick Mooney                 int baridx, uint64_t offset, int size, uint64_t value)
2227*4c87aefeSPatrick Mooney {
2228*4c87aefeSPatrick Mooney 	struct pci_xhci_softc *sc;
2229*4c87aefeSPatrick Mooney 
2230*4c87aefeSPatrick Mooney 	sc = pi->pi_arg;
2231*4c87aefeSPatrick Mooney 
2232*4c87aefeSPatrick Mooney 	assert(baridx == 0);
2233*4c87aefeSPatrick Mooney 
2234*4c87aefeSPatrick Mooney 
2235*4c87aefeSPatrick Mooney 	pthread_mutex_lock(&sc->mtx);
2236*4c87aefeSPatrick Mooney 	if (offset < XHCI_CAPLEN)	/* read only registers */
2237*4c87aefeSPatrick Mooney 		WPRINTF(("pci_xhci: write RO-CAPs offset %ld\r\n", offset));
2238*4c87aefeSPatrick Mooney 	else if (offset < sc->dboff)
2239*4c87aefeSPatrick Mooney 		pci_xhci_hostop_write(sc, offset, value);
2240*4c87aefeSPatrick Mooney 	else if (offset < sc->rtsoff)
2241*4c87aefeSPatrick Mooney 		pci_xhci_dbregs_write(sc, offset, value);
2242*4c87aefeSPatrick Mooney 	else if (offset < sc->regsend)
2243*4c87aefeSPatrick Mooney 		pci_xhci_rtsregs_write(sc, offset, value);
2244*4c87aefeSPatrick Mooney 	else
2245*4c87aefeSPatrick Mooney 		WPRINTF(("pci_xhci: write invalid offset %ld\r\n", offset));
2246*4c87aefeSPatrick Mooney 
2247*4c87aefeSPatrick Mooney 	pthread_mutex_unlock(&sc->mtx);
2248*4c87aefeSPatrick Mooney }
2249*4c87aefeSPatrick Mooney 
2250*4c87aefeSPatrick Mooney static uint64_t
2251*4c87aefeSPatrick Mooney pci_xhci_hostcap_read(struct pci_xhci_softc *sc, uint64_t offset)
2252*4c87aefeSPatrick Mooney {
2253*4c87aefeSPatrick Mooney 	uint64_t	value;
2254*4c87aefeSPatrick Mooney 
2255*4c87aefeSPatrick Mooney 	switch (offset) {
2256*4c87aefeSPatrick Mooney 	case XHCI_CAPLENGTH:	/* 0x00 */
2257*4c87aefeSPatrick Mooney 		value = sc->caplength;
2258*4c87aefeSPatrick Mooney 		break;
2259*4c87aefeSPatrick Mooney 
2260*4c87aefeSPatrick Mooney 	case XHCI_HCSPARAMS1:	/* 0x04 */
2261*4c87aefeSPatrick Mooney 		value = sc->hcsparams1;
2262*4c87aefeSPatrick Mooney 		break;
2263*4c87aefeSPatrick Mooney 
2264*4c87aefeSPatrick Mooney 	case XHCI_HCSPARAMS2:	/* 0x08 */
2265*4c87aefeSPatrick Mooney 		value = sc->hcsparams2;
2266*4c87aefeSPatrick Mooney 		break;
2267*4c87aefeSPatrick Mooney 
2268*4c87aefeSPatrick Mooney 	case XHCI_HCSPARAMS3:	/* 0x0C */
2269*4c87aefeSPatrick Mooney 		value = sc->hcsparams3;
2270*4c87aefeSPatrick Mooney 		break;
2271*4c87aefeSPatrick Mooney 
2272*4c87aefeSPatrick Mooney 	case XHCI_HCSPARAMS0:	/* 0x10 */
2273*4c87aefeSPatrick Mooney 		value = sc->hccparams1;
2274*4c87aefeSPatrick Mooney 		break;
2275*4c87aefeSPatrick Mooney 
2276*4c87aefeSPatrick Mooney 	case XHCI_DBOFF:	/* 0x14 */
2277*4c87aefeSPatrick Mooney 		value = sc->dboff;
2278*4c87aefeSPatrick Mooney 		break;
2279*4c87aefeSPatrick Mooney 
2280*4c87aefeSPatrick Mooney 	case XHCI_RTSOFF:	/* 0x18 */
2281*4c87aefeSPatrick Mooney 		value = sc->rtsoff;
2282*4c87aefeSPatrick Mooney 		break;
2283*4c87aefeSPatrick Mooney 
2284*4c87aefeSPatrick Mooney 	case XHCI_HCCPRAMS2:	/* 0x1C */
2285*4c87aefeSPatrick Mooney 		value = sc->hccparams2;
2286*4c87aefeSPatrick Mooney 		break;
2287*4c87aefeSPatrick Mooney 
2288*4c87aefeSPatrick Mooney 	default:
2289*4c87aefeSPatrick Mooney 		value = 0;
2290*4c87aefeSPatrick Mooney 		break;
2291*4c87aefeSPatrick Mooney 	}
2292*4c87aefeSPatrick Mooney 
2293*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: hostcap read offset 0x%lx -> 0x%lx\r\n",
2294*4c87aefeSPatrick Mooney 	        offset, value));
2295*4c87aefeSPatrick Mooney 
2296*4c87aefeSPatrick Mooney 	return (value);
2297*4c87aefeSPatrick Mooney }
2298*4c87aefeSPatrick Mooney 
2299*4c87aefeSPatrick Mooney static uint64_t
2300*4c87aefeSPatrick Mooney pci_xhci_hostop_read(struct pci_xhci_softc *sc, uint64_t offset)
2301*4c87aefeSPatrick Mooney {
2302*4c87aefeSPatrick Mooney 	uint64_t value;
2303*4c87aefeSPatrick Mooney 
2304*4c87aefeSPatrick Mooney 	offset = (offset - XHCI_CAPLEN);
2305*4c87aefeSPatrick Mooney 
2306*4c87aefeSPatrick Mooney 	switch (offset) {
2307*4c87aefeSPatrick Mooney 	case XHCI_USBCMD:	/* 0x00 */
2308*4c87aefeSPatrick Mooney 		value = sc->opregs.usbcmd;
2309*4c87aefeSPatrick Mooney 		break;
2310*4c87aefeSPatrick Mooney 
2311*4c87aefeSPatrick Mooney 	case XHCI_USBSTS:	/* 0x04 */
2312*4c87aefeSPatrick Mooney 		value = sc->opregs.usbsts;
2313*4c87aefeSPatrick Mooney 		break;
2314*4c87aefeSPatrick Mooney 
2315*4c87aefeSPatrick Mooney 	case XHCI_PAGESIZE:	/* 0x08 */
2316*4c87aefeSPatrick Mooney 		value = sc->opregs.pgsz;
2317*4c87aefeSPatrick Mooney 		break;
2318*4c87aefeSPatrick Mooney 
2319*4c87aefeSPatrick Mooney 	case XHCI_DNCTRL:	/* 0x14 */
2320*4c87aefeSPatrick Mooney 		value = sc->opregs.dnctrl;
2321*4c87aefeSPatrick Mooney 		break;
2322*4c87aefeSPatrick Mooney 
2323*4c87aefeSPatrick Mooney 	case XHCI_CRCR_LO:	/* 0x18 */
2324*4c87aefeSPatrick Mooney 		value = sc->opregs.crcr & XHCI_CRCR_LO_CRR;
2325*4c87aefeSPatrick Mooney 		break;
2326*4c87aefeSPatrick Mooney 
2327*4c87aefeSPatrick Mooney 	case XHCI_CRCR_HI:	/* 0x1C */
2328*4c87aefeSPatrick Mooney 		value = 0;
2329*4c87aefeSPatrick Mooney 		break;
2330*4c87aefeSPatrick Mooney 
2331*4c87aefeSPatrick Mooney 	case XHCI_DCBAAP_LO:	/* 0x30 */
2332*4c87aefeSPatrick Mooney 		value = sc->opregs.dcbaap & 0xFFFFFFFF;
2333*4c87aefeSPatrick Mooney 		break;
2334*4c87aefeSPatrick Mooney 
2335*4c87aefeSPatrick Mooney 	case XHCI_DCBAAP_HI:	/* 0x34 */
2336*4c87aefeSPatrick Mooney 		value = (sc->opregs.dcbaap >> 32) & 0xFFFFFFFF;
2337*4c87aefeSPatrick Mooney 		break;
2338*4c87aefeSPatrick Mooney 
2339*4c87aefeSPatrick Mooney 	case XHCI_CONFIG:	/* 0x38 */
2340*4c87aefeSPatrick Mooney 		value = sc->opregs.config;
2341*4c87aefeSPatrick Mooney 		break;
2342*4c87aefeSPatrick Mooney 
2343*4c87aefeSPatrick Mooney 	default:
2344*4c87aefeSPatrick Mooney 		if (offset >= 0x400)
2345*4c87aefeSPatrick Mooney 			value = pci_xhci_portregs_read(sc, offset);
2346*4c87aefeSPatrick Mooney 		else
2347*4c87aefeSPatrick Mooney 			value = 0;
2348*4c87aefeSPatrick Mooney 
2349*4c87aefeSPatrick Mooney 		break;
2350*4c87aefeSPatrick Mooney 	}
2351*4c87aefeSPatrick Mooney 
2352*4c87aefeSPatrick Mooney 	if (offset < 0x400)
2353*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: hostop read offset 0x%lx -> 0x%lx\r\n",
2354*4c87aefeSPatrick Mooney 		        offset, value));
2355*4c87aefeSPatrick Mooney 
2356*4c87aefeSPatrick Mooney 	return (value);
2357*4c87aefeSPatrick Mooney }
2358*4c87aefeSPatrick Mooney 
2359*4c87aefeSPatrick Mooney static uint64_t
2360*4c87aefeSPatrick Mooney pci_xhci_dbregs_read(struct pci_xhci_softc *sc, uint64_t offset)
2361*4c87aefeSPatrick Mooney {
2362*4c87aefeSPatrick Mooney 
2363*4c87aefeSPatrick Mooney 	/* read doorbell always returns 0 */
2364*4c87aefeSPatrick Mooney 	return (0);
2365*4c87aefeSPatrick Mooney }
2366*4c87aefeSPatrick Mooney 
2367*4c87aefeSPatrick Mooney static uint64_t
2368*4c87aefeSPatrick Mooney pci_xhci_rtsregs_read(struct pci_xhci_softc *sc, uint64_t offset)
2369*4c87aefeSPatrick Mooney {
2370*4c87aefeSPatrick Mooney 	uint32_t	value;
2371*4c87aefeSPatrick Mooney 
2372*4c87aefeSPatrick Mooney 	offset -= sc->rtsoff;
2373*4c87aefeSPatrick Mooney 	value = 0;
2374*4c87aefeSPatrick Mooney 
2375*4c87aefeSPatrick Mooney 	if (offset == XHCI_MFINDEX) {
2376*4c87aefeSPatrick Mooney 		value = sc->rtsregs.mfindex;
2377*4c87aefeSPatrick Mooney 	} else if (offset >= 0x20) {
2378*4c87aefeSPatrick Mooney 		int item;
2379*4c87aefeSPatrick Mooney 		uint32_t *p;
2380*4c87aefeSPatrick Mooney 
2381*4c87aefeSPatrick Mooney 		offset -= 0x20;
2382*4c87aefeSPatrick Mooney 		item = offset % 32;
2383*4c87aefeSPatrick Mooney 
2384*4c87aefeSPatrick Mooney 		assert(offset < sizeof(sc->rtsregs.intrreg));
2385*4c87aefeSPatrick Mooney 
2386*4c87aefeSPatrick Mooney 		p = &sc->rtsregs.intrreg.iman;
2387*4c87aefeSPatrick Mooney 		p += item / sizeof(uint32_t);
2388*4c87aefeSPatrick Mooney 		value = *p;
2389*4c87aefeSPatrick Mooney 	}
2390*4c87aefeSPatrick Mooney 
2391*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: rtsregs read offset 0x%lx -> 0x%x\r\n",
2392*4c87aefeSPatrick Mooney 	        offset, value));
2393*4c87aefeSPatrick Mooney 
2394*4c87aefeSPatrick Mooney 	return (value);
2395*4c87aefeSPatrick Mooney }
2396*4c87aefeSPatrick Mooney 
2397*4c87aefeSPatrick Mooney static uint64_t
2398*4c87aefeSPatrick Mooney pci_xhci_xecp_read(struct pci_xhci_softc *sc, uint64_t offset)
2399*4c87aefeSPatrick Mooney {
2400*4c87aefeSPatrick Mooney 	uint32_t	value;
2401*4c87aefeSPatrick Mooney 
2402*4c87aefeSPatrick Mooney 	offset -= sc->regsend;
2403*4c87aefeSPatrick Mooney 	value = 0;
2404*4c87aefeSPatrick Mooney 
2405*4c87aefeSPatrick Mooney 	switch (offset) {
2406*4c87aefeSPatrick Mooney 	case 0:
2407*4c87aefeSPatrick Mooney 		/* rev major | rev minor | next-cap | cap-id */
2408*4c87aefeSPatrick Mooney 		value = (0x02 << 24) | (4 << 8) | XHCI_ID_PROTOCOLS;
2409*4c87aefeSPatrick Mooney 		break;
2410*4c87aefeSPatrick Mooney 	case 4:
2411*4c87aefeSPatrick Mooney 		/* name string = "USB" */
2412*4c87aefeSPatrick Mooney 		value = 0x20425355;
2413*4c87aefeSPatrick Mooney 		break;
2414*4c87aefeSPatrick Mooney 	case 8:
2415*4c87aefeSPatrick Mooney 		/* psic | proto-defined | compat # | compat offset */
2416*4c87aefeSPatrick Mooney 		value = ((XHCI_MAX_DEVS/2) << 8) | sc->usb2_port_start;
2417*4c87aefeSPatrick Mooney 		break;
2418*4c87aefeSPatrick Mooney 	case 12:
2419*4c87aefeSPatrick Mooney 		break;
2420*4c87aefeSPatrick Mooney 	case 16:
2421*4c87aefeSPatrick Mooney 		/* rev major | rev minor | next-cap | cap-id */
2422*4c87aefeSPatrick Mooney 		value = (0x03 << 24) | XHCI_ID_PROTOCOLS;
2423*4c87aefeSPatrick Mooney 		break;
2424*4c87aefeSPatrick Mooney 	case 20:
2425*4c87aefeSPatrick Mooney 		/* name string = "USB" */
2426*4c87aefeSPatrick Mooney 		value = 0x20425355;
2427*4c87aefeSPatrick Mooney 		break;
2428*4c87aefeSPatrick Mooney 	case 24:
2429*4c87aefeSPatrick Mooney 		/* psic | proto-defined | compat # | compat offset */
2430*4c87aefeSPatrick Mooney 		value = ((XHCI_MAX_DEVS/2) << 8) | sc->usb3_port_start;
2431*4c87aefeSPatrick Mooney 		break;
2432*4c87aefeSPatrick Mooney 	case 28:
2433*4c87aefeSPatrick Mooney 		break;
2434*4c87aefeSPatrick Mooney 	default:
2435*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci: xecp invalid offset 0x%lx\r\n", offset));
2436*4c87aefeSPatrick Mooney 		break;
2437*4c87aefeSPatrick Mooney 	}
2438*4c87aefeSPatrick Mooney 
2439*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci: xecp read offset 0x%lx -> 0x%x\r\n",
2440*4c87aefeSPatrick Mooney 	        offset, value));
2441*4c87aefeSPatrick Mooney 
2442*4c87aefeSPatrick Mooney 	return (value);
2443*4c87aefeSPatrick Mooney }
2444*4c87aefeSPatrick Mooney 
2445*4c87aefeSPatrick Mooney 
2446*4c87aefeSPatrick Mooney static uint64_t
2447*4c87aefeSPatrick Mooney pci_xhci_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
2448*4c87aefeSPatrick Mooney     uint64_t offset, int size)
2449*4c87aefeSPatrick Mooney {
2450*4c87aefeSPatrick Mooney 	struct pci_xhci_softc *sc;
2451*4c87aefeSPatrick Mooney 	uint32_t	value;
2452*4c87aefeSPatrick Mooney 
2453*4c87aefeSPatrick Mooney 	sc = pi->pi_arg;
2454*4c87aefeSPatrick Mooney 
2455*4c87aefeSPatrick Mooney 	assert(baridx == 0);
2456*4c87aefeSPatrick Mooney 
2457*4c87aefeSPatrick Mooney 	pthread_mutex_lock(&sc->mtx);
2458*4c87aefeSPatrick Mooney 	if (offset < XHCI_CAPLEN)
2459*4c87aefeSPatrick Mooney 		value = pci_xhci_hostcap_read(sc, offset);
2460*4c87aefeSPatrick Mooney 	else if (offset < sc->dboff)
2461*4c87aefeSPatrick Mooney 		value = pci_xhci_hostop_read(sc, offset);
2462*4c87aefeSPatrick Mooney 	else if (offset < sc->rtsoff)
2463*4c87aefeSPatrick Mooney 		value = pci_xhci_dbregs_read(sc, offset);
2464*4c87aefeSPatrick Mooney 	else if (offset < sc->regsend)
2465*4c87aefeSPatrick Mooney 		value = pci_xhci_rtsregs_read(sc, offset);
2466*4c87aefeSPatrick Mooney 	else if (offset < (sc->regsend + 4*32))
2467*4c87aefeSPatrick Mooney 		value = pci_xhci_xecp_read(sc, offset);
2468*4c87aefeSPatrick Mooney 	else {
2469*4c87aefeSPatrick Mooney 		value = 0;
2470*4c87aefeSPatrick Mooney 		WPRINTF(("pci_xhci: read invalid offset %ld\r\n", offset));
2471*4c87aefeSPatrick Mooney 	}
2472*4c87aefeSPatrick Mooney 
2473*4c87aefeSPatrick Mooney 	pthread_mutex_unlock(&sc->mtx);
2474*4c87aefeSPatrick Mooney 
2475*4c87aefeSPatrick Mooney 	switch (size) {
2476*4c87aefeSPatrick Mooney 	case 1:
2477*4c87aefeSPatrick Mooney 		value &= 0xFF;
2478*4c87aefeSPatrick Mooney 		break;
2479*4c87aefeSPatrick Mooney 	case 2:
2480*4c87aefeSPatrick Mooney 		value &= 0xFFFF;
2481*4c87aefeSPatrick Mooney 		break;
2482*4c87aefeSPatrick Mooney 	case 4:
2483*4c87aefeSPatrick Mooney 		value &= 0xFFFFFFFF;
2484*4c87aefeSPatrick Mooney 		break;
2485*4c87aefeSPatrick Mooney 	}
2486*4c87aefeSPatrick Mooney 
2487*4c87aefeSPatrick Mooney 	return (value);
2488*4c87aefeSPatrick Mooney }
2489*4c87aefeSPatrick Mooney 
2490*4c87aefeSPatrick Mooney static void
2491*4c87aefeSPatrick Mooney pci_xhci_reset_port(struct pci_xhci_softc *sc, int portn, int warm)
2492*4c87aefeSPatrick Mooney {
2493*4c87aefeSPatrick Mooney 	struct pci_xhci_portregs *port;
2494*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	*dev;
2495*4c87aefeSPatrick Mooney 	struct xhci_trb		evtrb;
2496*4c87aefeSPatrick Mooney 	int	error;
2497*4c87aefeSPatrick Mooney 
2498*4c87aefeSPatrick Mooney 	assert(portn <= XHCI_MAX_DEVS);
2499*4c87aefeSPatrick Mooney 
2500*4c87aefeSPatrick Mooney 	DPRINTF(("xhci reset port %d\r\n", portn));
2501*4c87aefeSPatrick Mooney 
2502*4c87aefeSPatrick Mooney 	port = XHCI_PORTREG_PTR(sc, portn);
2503*4c87aefeSPatrick Mooney 	dev = XHCI_DEVINST_PTR(sc, portn);
2504*4c87aefeSPatrick Mooney 	if (dev) {
2505*4c87aefeSPatrick Mooney 		port->portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC);
2506*4c87aefeSPatrick Mooney 		port->portsc |= XHCI_PS_PED |
2507*4c87aefeSPatrick Mooney 		    XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed);
2508*4c87aefeSPatrick Mooney 
2509*4c87aefeSPatrick Mooney 		if (warm && dev->dev_ue->ue_usbver == 3) {
2510*4c87aefeSPatrick Mooney 			port->portsc |= XHCI_PS_WRC;
2511*4c87aefeSPatrick Mooney 		}
2512*4c87aefeSPatrick Mooney 
2513*4c87aefeSPatrick Mooney 		if ((port->portsc & XHCI_PS_PRC) == 0) {
2514*4c87aefeSPatrick Mooney 			port->portsc |= XHCI_PS_PRC;
2515*4c87aefeSPatrick Mooney 
2516*4c87aefeSPatrick Mooney 			pci_xhci_set_evtrb(&evtrb, portn,
2517*4c87aefeSPatrick Mooney 			     XHCI_TRB_ERROR_SUCCESS,
2518*4c87aefeSPatrick Mooney 			     XHCI_TRB_EVENT_PORT_STS_CHANGE);
2519*4c87aefeSPatrick Mooney 			error = pci_xhci_insert_event(sc, &evtrb, 1);
2520*4c87aefeSPatrick Mooney 			if (error != XHCI_TRB_ERROR_SUCCESS)
2521*4c87aefeSPatrick Mooney 				DPRINTF(("xhci reset port insert event "
2522*4c87aefeSPatrick Mooney 				         "failed\r\n"));
2523*4c87aefeSPatrick Mooney 		}
2524*4c87aefeSPatrick Mooney 	}
2525*4c87aefeSPatrick Mooney }
2526*4c87aefeSPatrick Mooney 
2527*4c87aefeSPatrick Mooney static void
2528*4c87aefeSPatrick Mooney pci_xhci_init_port(struct pci_xhci_softc *sc, int portn)
2529*4c87aefeSPatrick Mooney {
2530*4c87aefeSPatrick Mooney 	struct pci_xhci_portregs *port;
2531*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	*dev;
2532*4c87aefeSPatrick Mooney 
2533*4c87aefeSPatrick Mooney 	port = XHCI_PORTREG_PTR(sc, portn);
2534*4c87aefeSPatrick Mooney 	dev = XHCI_DEVINST_PTR(sc, portn);
2535*4c87aefeSPatrick Mooney 	if (dev) {
2536*4c87aefeSPatrick Mooney 		port->portsc = XHCI_PS_CCS |		/* connected */
2537*4c87aefeSPatrick Mooney 		               XHCI_PS_PP;		/* port power */
2538*4c87aefeSPatrick Mooney 
2539*4c87aefeSPatrick Mooney 		if (dev->dev_ue->ue_usbver == 2) {
2540*4c87aefeSPatrick Mooney 			port->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_POLL) |
2541*4c87aefeSPatrick Mooney 		               XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed);
2542*4c87aefeSPatrick Mooney 		} else {
2543*4c87aefeSPatrick Mooney 			port->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_U0) |
2544*4c87aefeSPatrick Mooney 		               XHCI_PS_PED |		/* enabled */
2545*4c87aefeSPatrick Mooney 		               XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed);
2546*4c87aefeSPatrick Mooney 		}
2547*4c87aefeSPatrick Mooney 
2548*4c87aefeSPatrick Mooney 		DPRINTF(("Init port %d 0x%x\n", portn, port->portsc));
2549*4c87aefeSPatrick Mooney 	} else {
2550*4c87aefeSPatrick Mooney 		port->portsc = XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET) | XHCI_PS_PP;
2551*4c87aefeSPatrick Mooney 		DPRINTF(("Init empty port %d 0x%x\n", portn, port->portsc));
2552*4c87aefeSPatrick Mooney 	}
2553*4c87aefeSPatrick Mooney }
2554*4c87aefeSPatrick Mooney 
2555*4c87aefeSPatrick Mooney static int
2556*4c87aefeSPatrick Mooney pci_xhci_dev_intr(struct usb_hci *hci, int epctx)
2557*4c87aefeSPatrick Mooney {
2558*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu *dev;
2559*4c87aefeSPatrick Mooney 	struct xhci_dev_ctx	*dev_ctx;
2560*4c87aefeSPatrick Mooney 	struct xhci_trb		evtrb;
2561*4c87aefeSPatrick Mooney 	struct pci_xhci_softc	*sc;
2562*4c87aefeSPatrick Mooney 	struct pci_xhci_portregs *p;
2563*4c87aefeSPatrick Mooney 	struct xhci_endp_ctx	*ep_ctx;
2564*4c87aefeSPatrick Mooney 	int	error;
2565*4c87aefeSPatrick Mooney 	int	dir_in;
2566*4c87aefeSPatrick Mooney 	int	epid;
2567*4c87aefeSPatrick Mooney 
2568*4c87aefeSPatrick Mooney 	dir_in = epctx & 0x80;
2569*4c87aefeSPatrick Mooney 	epid = epctx & ~0x80;
2570*4c87aefeSPatrick Mooney 
2571*4c87aefeSPatrick Mooney 	/* HW endpoint contexts are 0-15; convert to epid based on dir */
2572*4c87aefeSPatrick Mooney 	epid = (epid * 2) + (dir_in ? 1 : 0);
2573*4c87aefeSPatrick Mooney 
2574*4c87aefeSPatrick Mooney 	assert(epid >= 1 && epid <= 31);
2575*4c87aefeSPatrick Mooney 
2576*4c87aefeSPatrick Mooney 	dev = hci->hci_sc;
2577*4c87aefeSPatrick Mooney 	sc = dev->xsc;
2578*4c87aefeSPatrick Mooney 
2579*4c87aefeSPatrick Mooney 	/* check if device is ready; OS has to initialise it */
2580*4c87aefeSPatrick Mooney 	if (sc->rtsregs.erstba_p == NULL ||
2581*4c87aefeSPatrick Mooney 	    (sc->opregs.usbcmd & XHCI_CMD_RS) == 0 ||
2582*4c87aefeSPatrick Mooney 	    dev->dev_ctx == NULL)
2583*4c87aefeSPatrick Mooney 		return (0);
2584*4c87aefeSPatrick Mooney 
2585*4c87aefeSPatrick Mooney 	p = XHCI_PORTREG_PTR(sc, hci->hci_port);
2586*4c87aefeSPatrick Mooney 
2587*4c87aefeSPatrick Mooney 	/* raise event if link U3 (suspended) state */
2588*4c87aefeSPatrick Mooney 	if (XHCI_PS_PLS_GET(p->portsc) == 3) {
2589*4c87aefeSPatrick Mooney 		p->portsc &= ~XHCI_PS_PLS_MASK;
2590*4c87aefeSPatrick Mooney 		p->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_RESUME);
2591*4c87aefeSPatrick Mooney 		if ((p->portsc & XHCI_PS_PLC) != 0)
2592*4c87aefeSPatrick Mooney 			return (0);
2593*4c87aefeSPatrick Mooney 
2594*4c87aefeSPatrick Mooney 		p->portsc |= XHCI_PS_PLC;
2595*4c87aefeSPatrick Mooney 
2596*4c87aefeSPatrick Mooney 		pci_xhci_set_evtrb(&evtrb, hci->hci_port,
2597*4c87aefeSPatrick Mooney 		      XHCI_TRB_ERROR_SUCCESS, XHCI_TRB_EVENT_PORT_STS_CHANGE);
2598*4c87aefeSPatrick Mooney 		error = pci_xhci_insert_event(sc, &evtrb, 0);
2599*4c87aefeSPatrick Mooney 		if (error != XHCI_TRB_ERROR_SUCCESS)
2600*4c87aefeSPatrick Mooney 			goto done;
2601*4c87aefeSPatrick Mooney 	}
2602*4c87aefeSPatrick Mooney 
2603*4c87aefeSPatrick Mooney 	dev_ctx = dev->dev_ctx;
2604*4c87aefeSPatrick Mooney 	ep_ctx = &dev_ctx->ctx_ep[epid];
2605*4c87aefeSPatrick Mooney 	if ((ep_ctx->dwEpCtx0 & 0x7) == XHCI_ST_EPCTX_DISABLED) {
2606*4c87aefeSPatrick Mooney 		DPRINTF(("xhci device interrupt on disabled endpoint %d\r\n",
2607*4c87aefeSPatrick Mooney 		         epid));
2608*4c87aefeSPatrick Mooney 		return (0);
2609*4c87aefeSPatrick Mooney 	}
2610*4c87aefeSPatrick Mooney 
2611*4c87aefeSPatrick Mooney 	DPRINTF(("xhci device interrupt on endpoint %d\r\n", epid));
2612*4c87aefeSPatrick Mooney 
2613*4c87aefeSPatrick Mooney 	pci_xhci_device_doorbell(sc, hci->hci_port, epid, 0);
2614*4c87aefeSPatrick Mooney 
2615*4c87aefeSPatrick Mooney done:
2616*4c87aefeSPatrick Mooney 	return (error);
2617*4c87aefeSPatrick Mooney }
2618*4c87aefeSPatrick Mooney 
2619*4c87aefeSPatrick Mooney static int
2620*4c87aefeSPatrick Mooney pci_xhci_dev_event(struct usb_hci *hci, enum hci_usbev evid, void *param)
2621*4c87aefeSPatrick Mooney {
2622*4c87aefeSPatrick Mooney 
2623*4c87aefeSPatrick Mooney 	DPRINTF(("xhci device event port %d\r\n", hci->hci_port));
2624*4c87aefeSPatrick Mooney 	return (0);
2625*4c87aefeSPatrick Mooney }
2626*4c87aefeSPatrick Mooney 
2627*4c87aefeSPatrick Mooney 
2628*4c87aefeSPatrick Mooney 
2629*4c87aefeSPatrick Mooney static void
2630*4c87aefeSPatrick Mooney pci_xhci_device_usage(char *opt)
2631*4c87aefeSPatrick Mooney {
2632*4c87aefeSPatrick Mooney 
2633*4c87aefeSPatrick Mooney 	fprintf(stderr, "Invalid USB emulation \"%s\"\r\n", opt);
2634*4c87aefeSPatrick Mooney }
2635*4c87aefeSPatrick Mooney 
2636*4c87aefeSPatrick Mooney static int
2637*4c87aefeSPatrick Mooney pci_xhci_parse_opts(struct pci_xhci_softc *sc, char *opts)
2638*4c87aefeSPatrick Mooney {
2639*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	**devices;
2640*4c87aefeSPatrick Mooney 	struct pci_xhci_dev_emu	*dev;
2641*4c87aefeSPatrick Mooney 	struct usb_devemu	*ue;
2642*4c87aefeSPatrick Mooney 	void	*devsc;
2643*4c87aefeSPatrick Mooney 	char	*uopt, *xopts, *config;
2644*4c87aefeSPatrick Mooney 	int	usb3_port, usb2_port, i;
2645*4c87aefeSPatrick Mooney 
2646*4c87aefeSPatrick Mooney 	uopt = NULL;
2647*4c87aefeSPatrick Mooney 	usb3_port = sc->usb3_port_start - 1;
2648*4c87aefeSPatrick Mooney 	usb2_port = sc->usb2_port_start - 1;
2649*4c87aefeSPatrick Mooney 	devices = NULL;
2650*4c87aefeSPatrick Mooney 
2651*4c87aefeSPatrick Mooney 	if (opts == NULL)
2652*4c87aefeSPatrick Mooney 		goto portsfinal;
2653*4c87aefeSPatrick Mooney 
2654*4c87aefeSPatrick Mooney 	devices = calloc(XHCI_MAX_DEVS, sizeof(struct pci_xhci_dev_emu *));
2655*4c87aefeSPatrick Mooney 
2656*4c87aefeSPatrick Mooney 	sc->slots = calloc(XHCI_MAX_SLOTS, sizeof(struct pci_xhci_dev_emu *));
2657*4c87aefeSPatrick Mooney 	sc->devices = devices;
2658*4c87aefeSPatrick Mooney 	sc->ndevices = 0;
2659*4c87aefeSPatrick Mooney 
2660*4c87aefeSPatrick Mooney 	uopt = strdup(opts);
2661*4c87aefeSPatrick Mooney 	for (xopts = strtok(uopt, ",");
2662*4c87aefeSPatrick Mooney 	     xopts != NULL;
2663*4c87aefeSPatrick Mooney 	     xopts = strtok(NULL, ",")) {
2664*4c87aefeSPatrick Mooney 		if (usb2_port == ((sc->usb2_port_start-1) + XHCI_MAX_DEVS/2) ||
2665*4c87aefeSPatrick Mooney 		    usb3_port == ((sc->usb3_port_start-1) + XHCI_MAX_DEVS/2)) {
2666*4c87aefeSPatrick Mooney 			WPRINTF(("pci_xhci max number of USB 2 or 3 "
2667*4c87aefeSPatrick Mooney 			     "devices reached, max %d\r\n", XHCI_MAX_DEVS/2));
2668*4c87aefeSPatrick Mooney 			usb2_port = usb3_port = -1;
2669*4c87aefeSPatrick Mooney 			goto done;
2670*4c87aefeSPatrick Mooney 		}
2671*4c87aefeSPatrick Mooney 
2672*4c87aefeSPatrick Mooney 		/* device[=<config>] */
2673*4c87aefeSPatrick Mooney 		if ((config = strchr(xopts, '=')) == NULL)
2674*4c87aefeSPatrick Mooney 			config = "";		/* no config */
2675*4c87aefeSPatrick Mooney 		else
2676*4c87aefeSPatrick Mooney 			*config++ = '\0';
2677*4c87aefeSPatrick Mooney 
2678*4c87aefeSPatrick Mooney 		ue = usb_emu_finddev(xopts);
2679*4c87aefeSPatrick Mooney 		if (ue == NULL) {
2680*4c87aefeSPatrick Mooney 			pci_xhci_device_usage(xopts);
2681*4c87aefeSPatrick Mooney 			DPRINTF(("pci_xhci device not found %s\r\n", xopts));
2682*4c87aefeSPatrick Mooney 			usb2_port = usb3_port = -1;
2683*4c87aefeSPatrick Mooney 			goto done;
2684*4c87aefeSPatrick Mooney 		}
2685*4c87aefeSPatrick Mooney 
2686*4c87aefeSPatrick Mooney 		DPRINTF(("pci_xhci adding device %s, opts \"%s\"\r\n",
2687*4c87aefeSPatrick Mooney 		        xopts, config));
2688*4c87aefeSPatrick Mooney 
2689*4c87aefeSPatrick Mooney 		dev = calloc(1, sizeof(struct pci_xhci_dev_emu));
2690*4c87aefeSPatrick Mooney 		dev->xsc = sc;
2691*4c87aefeSPatrick Mooney 		dev->hci.hci_sc = dev;
2692*4c87aefeSPatrick Mooney 		dev->hci.hci_intr = pci_xhci_dev_intr;
2693*4c87aefeSPatrick Mooney 		dev->hci.hci_event = pci_xhci_dev_event;
2694*4c87aefeSPatrick Mooney 
2695*4c87aefeSPatrick Mooney 		if (ue->ue_usbver == 2) {
2696*4c87aefeSPatrick Mooney 			dev->hci.hci_port = usb2_port + 1;
2697*4c87aefeSPatrick Mooney 			devices[usb2_port] = dev;
2698*4c87aefeSPatrick Mooney 			usb2_port++;
2699*4c87aefeSPatrick Mooney 		} else {
2700*4c87aefeSPatrick Mooney 			dev->hci.hci_port = usb3_port + 1;
2701*4c87aefeSPatrick Mooney 			devices[usb3_port] = dev;
2702*4c87aefeSPatrick Mooney 			usb3_port++;
2703*4c87aefeSPatrick Mooney 		}
2704*4c87aefeSPatrick Mooney 
2705*4c87aefeSPatrick Mooney 		dev->hci.hci_address = 0;
2706*4c87aefeSPatrick Mooney 		devsc = ue->ue_init(&dev->hci, config);
2707*4c87aefeSPatrick Mooney 		if (devsc == NULL) {
2708*4c87aefeSPatrick Mooney 			pci_xhci_device_usage(xopts);
2709*4c87aefeSPatrick Mooney 			usb2_port = usb3_port = -1;
2710*4c87aefeSPatrick Mooney 			goto done;
2711*4c87aefeSPatrick Mooney 		}
2712*4c87aefeSPatrick Mooney 
2713*4c87aefeSPatrick Mooney 		dev->dev_ue = ue;
2714*4c87aefeSPatrick Mooney 		dev->dev_sc = devsc;
2715*4c87aefeSPatrick Mooney 
2716*4c87aefeSPatrick Mooney 		/* assign slot number to device */
2717*4c87aefeSPatrick Mooney 		sc->slots[sc->ndevices] = dev;
2718*4c87aefeSPatrick Mooney 
2719*4c87aefeSPatrick Mooney 		sc->ndevices++;
2720*4c87aefeSPatrick Mooney 	}
2721*4c87aefeSPatrick Mooney 
2722*4c87aefeSPatrick Mooney portsfinal:
2723*4c87aefeSPatrick Mooney 	sc->portregs = calloc(XHCI_MAX_DEVS, sizeof(struct pci_xhci_portregs));
2724*4c87aefeSPatrick Mooney 
2725*4c87aefeSPatrick Mooney 	if (sc->ndevices > 0) {
2726*4c87aefeSPatrick Mooney 		/* port and slot numbering start from 1 */
2727*4c87aefeSPatrick Mooney 		sc->devices--;
2728*4c87aefeSPatrick Mooney 		sc->portregs--;
2729*4c87aefeSPatrick Mooney 		sc->slots--;
2730*4c87aefeSPatrick Mooney 
2731*4c87aefeSPatrick Mooney 		for (i = 1; i <= XHCI_MAX_DEVS; i++) {
2732*4c87aefeSPatrick Mooney 			pci_xhci_init_port(sc, i);
2733*4c87aefeSPatrick Mooney 		}
2734*4c87aefeSPatrick Mooney 	} else {
2735*4c87aefeSPatrick Mooney 		WPRINTF(("pci_xhci no USB devices configured\r\n"));
2736*4c87aefeSPatrick Mooney 		sc->ndevices = 1;
2737*4c87aefeSPatrick Mooney 	}
2738*4c87aefeSPatrick Mooney 
2739*4c87aefeSPatrick Mooney done:
2740*4c87aefeSPatrick Mooney 	if (devices != NULL) {
2741*4c87aefeSPatrick Mooney 		if (usb2_port <= 0 && usb3_port <= 0) {
2742*4c87aefeSPatrick Mooney 			sc->devices = NULL;
2743*4c87aefeSPatrick Mooney 			for (i = 0; devices[i] != NULL; i++)
2744*4c87aefeSPatrick Mooney 				free(devices[i]);
2745*4c87aefeSPatrick Mooney 			sc->ndevices = -1;
2746*4c87aefeSPatrick Mooney 
2747*4c87aefeSPatrick Mooney 			free(devices);
2748*4c87aefeSPatrick Mooney 		}
2749*4c87aefeSPatrick Mooney 	}
2750*4c87aefeSPatrick Mooney 	free(uopt);
2751*4c87aefeSPatrick Mooney 	return (sc->ndevices);
2752*4c87aefeSPatrick Mooney }
2753*4c87aefeSPatrick Mooney 
2754*4c87aefeSPatrick Mooney static int
2755*4c87aefeSPatrick Mooney pci_xhci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
2756*4c87aefeSPatrick Mooney {
2757*4c87aefeSPatrick Mooney 	struct pci_xhci_softc *sc;
2758*4c87aefeSPatrick Mooney 	int	error;
2759*4c87aefeSPatrick Mooney 
2760*4c87aefeSPatrick Mooney 	if (xhci_in_use) {
2761*4c87aefeSPatrick Mooney 		WPRINTF(("pci_xhci controller already defined\r\n"));
2762*4c87aefeSPatrick Mooney 		return (-1);
2763*4c87aefeSPatrick Mooney 	}
2764*4c87aefeSPatrick Mooney 	xhci_in_use = 1;
2765*4c87aefeSPatrick Mooney 
2766*4c87aefeSPatrick Mooney 	sc = calloc(1, sizeof(struct pci_xhci_softc));
2767*4c87aefeSPatrick Mooney 	pi->pi_arg = sc;
2768*4c87aefeSPatrick Mooney 	sc->xsc_pi = pi;
2769*4c87aefeSPatrick Mooney 
2770*4c87aefeSPatrick Mooney 	sc->usb2_port_start = (XHCI_MAX_DEVS/2) + 1;
2771*4c87aefeSPatrick Mooney 	sc->usb3_port_start = 1;
2772*4c87aefeSPatrick Mooney 
2773*4c87aefeSPatrick Mooney 	/* discover devices */
2774*4c87aefeSPatrick Mooney 	error = pci_xhci_parse_opts(sc, opts);
2775*4c87aefeSPatrick Mooney 	if (error < 0)
2776*4c87aefeSPatrick Mooney 		goto done;
2777*4c87aefeSPatrick Mooney 	else
2778*4c87aefeSPatrick Mooney 		error = 0;
2779*4c87aefeSPatrick Mooney 
2780*4c87aefeSPatrick Mooney 	sc->caplength = XHCI_SET_CAPLEN(XHCI_CAPLEN) |
2781*4c87aefeSPatrick Mooney 	                XHCI_SET_HCIVERSION(0x0100);
2782*4c87aefeSPatrick Mooney 	sc->hcsparams1 = XHCI_SET_HCSP1_MAXPORTS(XHCI_MAX_DEVS) |
2783*4c87aefeSPatrick Mooney 	                 XHCI_SET_HCSP1_MAXINTR(1) |	/* interrupters */
2784*4c87aefeSPatrick Mooney 	                 XHCI_SET_HCSP1_MAXSLOTS(XHCI_MAX_SLOTS);
2785*4c87aefeSPatrick Mooney 	sc->hcsparams2 = XHCI_SET_HCSP2_ERSTMAX(XHCI_ERST_MAX) |
2786*4c87aefeSPatrick Mooney 	                 XHCI_SET_HCSP2_IST(0x04);
2787*4c87aefeSPatrick Mooney 	sc->hcsparams3 = 0;				/* no latency */
2788*4c87aefeSPatrick Mooney 	sc->hccparams1 = XHCI_SET_HCCP1_NSS(1) |	/* no 2nd-streams */
2789*4c87aefeSPatrick Mooney 	                 XHCI_SET_HCCP1_SPC(1) |	/* short packet */
2790*4c87aefeSPatrick Mooney 	                 XHCI_SET_HCCP1_MAXPSA(XHCI_STREAMS_MAX);
2791*4c87aefeSPatrick Mooney 	sc->hccparams2 = XHCI_SET_HCCP2_LEC(1) |
2792*4c87aefeSPatrick Mooney 	                 XHCI_SET_HCCP2_U3C(1);
2793*4c87aefeSPatrick Mooney 	sc->dboff = XHCI_SET_DOORBELL(XHCI_CAPLEN + XHCI_PORTREGS_START +
2794*4c87aefeSPatrick Mooney 	            XHCI_MAX_DEVS * sizeof(struct pci_xhci_portregs));
2795*4c87aefeSPatrick Mooney 
2796*4c87aefeSPatrick Mooney 	/* dboff must be 32-bit aligned */
2797*4c87aefeSPatrick Mooney 	if (sc->dboff & 0x3)
2798*4c87aefeSPatrick Mooney 		sc->dboff = (sc->dboff + 0x3) & ~0x3;
2799*4c87aefeSPatrick Mooney 
2800*4c87aefeSPatrick Mooney 	/* rtsoff must be 32-bytes aligned */
2801*4c87aefeSPatrick Mooney 	sc->rtsoff = XHCI_SET_RTSOFFSET(sc->dboff + (XHCI_MAX_SLOTS+1) * 32);
2802*4c87aefeSPatrick Mooney 	if (sc->rtsoff & 0x1F)
2803*4c87aefeSPatrick Mooney 		sc->rtsoff = (sc->rtsoff + 0x1F) & ~0x1F;
2804*4c87aefeSPatrick Mooney 
2805*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci dboff: 0x%x, rtsoff: 0x%x\r\n", sc->dboff,
2806*4c87aefeSPatrick Mooney 	        sc->rtsoff));
2807*4c87aefeSPatrick Mooney 
2808*4c87aefeSPatrick Mooney 	sc->opregs.usbsts = XHCI_STS_HCH;
2809*4c87aefeSPatrick Mooney 	sc->opregs.pgsz = XHCI_PAGESIZE_4K;
2810*4c87aefeSPatrick Mooney 
2811*4c87aefeSPatrick Mooney 	pci_xhci_reset(sc);
2812*4c87aefeSPatrick Mooney 
2813*4c87aefeSPatrick Mooney 	sc->regsend = sc->rtsoff + 0x20 + 32;		/* only 1 intrpter */
2814*4c87aefeSPatrick Mooney 
2815*4c87aefeSPatrick Mooney 	/*
2816*4c87aefeSPatrick Mooney 	 * Set extended capabilities pointer to be after regsend;
2817*4c87aefeSPatrick Mooney 	 * value of xecp field is 32-bit offset.
2818*4c87aefeSPatrick Mooney 	 */
2819*4c87aefeSPatrick Mooney 	sc->hccparams1 |= XHCI_SET_HCCP1_XECP(sc->regsend/4);
2820*4c87aefeSPatrick Mooney 
2821*4c87aefeSPatrick Mooney 	pci_set_cfgdata16(pi, PCIR_DEVICE, 0x1E31);
2822*4c87aefeSPatrick Mooney 	pci_set_cfgdata16(pi, PCIR_VENDOR, 0x8086);
2823*4c87aefeSPatrick Mooney 	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SERIALBUS);
2824*4c87aefeSPatrick Mooney 	pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_SERIALBUS_USB);
2825*4c87aefeSPatrick Mooney 	pci_set_cfgdata8(pi, PCIR_PROGIF,PCIP_SERIALBUS_USB_XHCI);
2826*4c87aefeSPatrick Mooney 	pci_set_cfgdata8(pi, PCI_USBREV, PCI_USB_REV_3_0);
2827*4c87aefeSPatrick Mooney 
2828*4c87aefeSPatrick Mooney 	pci_emul_add_msicap(pi, 1);
2829*4c87aefeSPatrick Mooney 
2830*4c87aefeSPatrick Mooney 	/* regsend + xecp registers */
2831*4c87aefeSPatrick Mooney 	pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, sc->regsend + 4*32);
2832*4c87aefeSPatrick Mooney 	DPRINTF(("pci_xhci pci_emu_alloc: %d\r\n", sc->regsend + 4*32));
2833*4c87aefeSPatrick Mooney 
2834*4c87aefeSPatrick Mooney 
2835*4c87aefeSPatrick Mooney 	pci_lintr_request(pi);
2836*4c87aefeSPatrick Mooney 
2837*4c87aefeSPatrick Mooney 	pthread_mutex_init(&sc->mtx, NULL);
2838*4c87aefeSPatrick Mooney 
2839*4c87aefeSPatrick Mooney done:
2840*4c87aefeSPatrick Mooney 	if (error) {
2841*4c87aefeSPatrick Mooney 		free(sc);
2842*4c87aefeSPatrick Mooney 	}
2843*4c87aefeSPatrick Mooney 
2844*4c87aefeSPatrick Mooney 	return (error);
2845*4c87aefeSPatrick Mooney }
2846*4c87aefeSPatrick Mooney 
2847*4c87aefeSPatrick Mooney 
2848*4c87aefeSPatrick Mooney 
2849*4c87aefeSPatrick Mooney struct pci_devemu pci_de_xhci = {
2850*4c87aefeSPatrick Mooney 	.pe_emu =	"xhci",
2851*4c87aefeSPatrick Mooney 	.pe_init =	pci_xhci_init,
2852*4c87aefeSPatrick Mooney 	.pe_barwrite =	pci_xhci_write,
2853*4c87aefeSPatrick Mooney 	.pe_barread =	pci_xhci_read
2854*4c87aefeSPatrick Mooney };
2855*4c87aefeSPatrick Mooney PCI_EMUL_SET(pci_de_xhci);
2856