1*ec82ef79SMatthias Scheler /*
2*ec82ef79SMatthias Scheler  * This file and its contents are supplied under the terms of the
3*ec82ef79SMatthias Scheler  * Common Development and Distribution License ("CDDL"), version 1.0.
4*ec82ef79SMatthias Scheler  * You may only use this file in accordance with the terms of version
5*ec82ef79SMatthias Scheler  * 1.0 of the CDDL.
6*ec82ef79SMatthias Scheler  *
7*ec82ef79SMatthias Scheler  * A full copy of the text of the CDDL should have accompanied this
8*ec82ef79SMatthias Scheler  * source.  A copy of the CDDL is also available via the Internet at
9*ec82ef79SMatthias Scheler  * http://www.illumos.org/license/CDDL.
10*ec82ef79SMatthias Scheler  */
11*ec82ef79SMatthias Scheler 
12*ec82ef79SMatthias Scheler /*
13*ec82ef79SMatthias Scheler  * Copyright (c) 2018, Joyent, Inc.
14*ec82ef79SMatthias Scheler  *
15*ec82ef79SMatthias Scheler  * Copyright (c) 2019 by Western Digital Corporation
16*ec82ef79SMatthias Scheler  */
17*ec82ef79SMatthias Scheler 
18*ec82ef79SMatthias Scheler /*
19*ec82ef79SMatthias Scheler  * This next series of routines is used for USB console polled I/O.
20*ec82ef79SMatthias Scheler  */
21*ec82ef79SMatthias Scheler 
22*ec82ef79SMatthias Scheler #include <sys/usb/hcd/xhci/xhci.h>
23*ec82ef79SMatthias Scheler 
24*ec82ef79SMatthias Scheler #include <sys/cmn_err.h>
25*ec82ef79SMatthias Scheler 
26*ec82ef79SMatthias Scheler static void xhci_polled_panic(xhci_polled_t *xhci_polledp, const char *format,
27*ec82ef79SMatthias Scheler     ...) __KVPRINTFLIKE(2) __NORETURN;
28*ec82ef79SMatthias Scheler 
29*ec82ef79SMatthias Scheler static void
xhci_polled_panic(xhci_polled_t * xhci_polledp,const char * format,...)30*ec82ef79SMatthias Scheler xhci_polled_panic(xhci_polled_t *xhci_polledp, const char *format, ...)
31*ec82ef79SMatthias Scheler {
32*ec82ef79SMatthias Scheler 	va_list ap;
33*ec82ef79SMatthias Scheler 
34*ec82ef79SMatthias Scheler 	va_start(ap, format);
35*ec82ef79SMatthias Scheler 	vdev_err(xhci_polledp->xhci_polled_xhci->xhci_dip, CE_PANIC, format,
36*ec82ef79SMatthias Scheler 	    ap);
37*ec82ef79SMatthias Scheler 
38*ec82ef79SMatthias Scheler 	/*
39*ec82ef79SMatthias Scheler 	 * We will not reach this call. However the compiler doesn't know
40*ec82ef79SMatthias Scheler 	 * that vdev_err(..., CE_PANIC, ...) will not return. So this call
41*ec82ef79SMatthias Scheler 	 * convinces it that this function does indeed never return.
42*ec82ef79SMatthias Scheler 	 */
43*ec82ef79SMatthias Scheler 	panic(__func__);
44*ec82ef79SMatthias Scheler }
45*ec82ef79SMatthias Scheler 
46*ec82ef79SMatthias Scheler static void
xhci_polled_set_persistent_error(xhci_polled_t * xhci_polledp,int error)47*ec82ef79SMatthias Scheler xhci_polled_set_persistent_error(xhci_polled_t *xhci_polledp, int error)
48*ec82ef79SMatthias Scheler {
49*ec82ef79SMatthias Scheler 	if (error != USB_SUCCESS &&
50*ec82ef79SMatthias Scheler 	    xhci_polledp->xhci_polled_persistent_error == USB_SUCCESS) {
51*ec82ef79SMatthias Scheler 		xhci_polledp->xhci_polled_persistent_error = error;
52*ec82ef79SMatthias Scheler 	}
53*ec82ef79SMatthias Scheler }
54*ec82ef79SMatthias Scheler 
55*ec82ef79SMatthias Scheler /*
56*ec82ef79SMatthias Scheler  * xhci_polled_init:
57*ec82ef79SMatthias Scheler  *
58*ec82ef79SMatthias Scheler  * Initialize generic information that is needed to provide USB/POLLED
59*ec82ef79SMatthias Scheler  * support.
60*ec82ef79SMatthias Scheler  */
61*ec82ef79SMatthias Scheler static int
xhci_polled_init(usba_pipe_handle_data_t * input_pipe_handle,xhci_t * xhcip,usb_console_info_impl_t * console_info)62*ec82ef79SMatthias Scheler xhci_polled_init(usba_pipe_handle_data_t *input_pipe_handle, xhci_t *xhcip,
63*ec82ef79SMatthias Scheler     usb_console_info_impl_t *console_info)
64*ec82ef79SMatthias Scheler {
65*ec82ef79SMatthias Scheler 	xhci_pipe_t *xp;
66*ec82ef79SMatthias Scheler 	xhci_endpoint_t *xep;
67*ec82ef79SMatthias Scheler 	xhci_polled_t *xhci_polledp;
68*ec82ef79SMatthias Scheler 
69*ec82ef79SMatthias Scheler 	ASSERT(mutex_owned(&xhcip->xhci_lock));
70*ec82ef79SMatthias Scheler 
71*ec82ef79SMatthias Scheler 	/*
72*ec82ef79SMatthias Scheler 	 * We have already initialized this structure. If the structure
73*ec82ef79SMatthias Scheler 	 * has already been initialized, then we don't need to redo it.
74*ec82ef79SMatthias Scheler 	 */
75*ec82ef79SMatthias Scheler 	if (console_info->uci_private != NULL)
76*ec82ef79SMatthias Scheler 		return (USB_SUCCESS);
77*ec82ef79SMatthias Scheler 
78*ec82ef79SMatthias Scheler 	xp = (xhci_pipe_t *)input_pipe_handle->p_hcd_private;
79*ec82ef79SMatthias Scheler 	if (xp == NULL)
80*ec82ef79SMatthias Scheler 		return (USB_FAILURE);
81*ec82ef79SMatthias Scheler 
82*ec82ef79SMatthias Scheler 	/*
83*ec82ef79SMatthias Scheler 	 * We only support interrupt (keyboards) and not bulk (serial)
84*ec82ef79SMatthias Scheler 	 * endpoints at the moment.
85*ec82ef79SMatthias Scheler 	 */
86*ec82ef79SMatthias Scheler 	xep = xp->xp_ep;
87*ec82ef79SMatthias Scheler 	if (xep->xep_type != USB_EP_ATTR_INTR)
88*ec82ef79SMatthias Scheler 		return (USB_NOT_SUPPORTED);
89*ec82ef79SMatthias Scheler 
90*ec82ef79SMatthias Scheler 	/* Allocate and initialize a state structure */
91*ec82ef79SMatthias Scheler 	xhci_polledp = kmem_zalloc(sizeof (xhci_polled_t), KM_SLEEP);
92*ec82ef79SMatthias Scheler 
93*ec82ef79SMatthias Scheler 	xhci_polledp->xhci_polled_xhci = xhcip;
94*ec82ef79SMatthias Scheler 	xhci_polledp->xhci_polled_input_pipe_handle = input_pipe_handle;
95*ec82ef79SMatthias Scheler 	xhci_polledp->xhci_polled_endpoint = xep;
96*ec82ef79SMatthias Scheler 
97*ec82ef79SMatthias Scheler 	console_info->uci_private = (usb_console_info_private_t)xhci_polledp;
98*ec82ef79SMatthias Scheler 	return (USB_SUCCESS);
99*ec82ef79SMatthias Scheler }
100*ec82ef79SMatthias Scheler 
101*ec82ef79SMatthias Scheler static xhci_endpoint_t *
xhci_polled_get_endpoint(xhci_t * xhcip,xhci_trb_t * trb)102*ec82ef79SMatthias Scheler xhci_polled_get_endpoint(xhci_t *xhcip, xhci_trb_t *trb)
103*ec82ef79SMatthias Scheler {
104*ec82ef79SMatthias Scheler 	int slot, endpoint;
105*ec82ef79SMatthias Scheler 	xhci_device_t *xd;
106*ec82ef79SMatthias Scheler 
107*ec82ef79SMatthias Scheler 	endpoint = XHCI_TRB_GET_EP(LE_32(trb->trb_flags));
108*ec82ef79SMatthias Scheler 	slot = XHCI_TRB_GET_SLOT(LE_32(trb->trb_flags));
109*ec82ef79SMatthias Scheler 
110*ec82ef79SMatthias Scheler 	xd = xhci_device_lookup_by_slot(xhcip, slot);
111*ec82ef79SMatthias Scheler 	if (xd == NULL)
112*ec82ef79SMatthias Scheler 		return (NULL);
113*ec82ef79SMatthias Scheler 
114*ec82ef79SMatthias Scheler 	/*
115*ec82ef79SMatthias Scheler 	 * Endpoint IDs are indexed based on their Device Context Index, which
116*ec82ef79SMatthias Scheler 	 * means that we need to subtract one to get the actual ID that we use.
117*ec82ef79SMatthias Scheler 	 */
118*ec82ef79SMatthias Scheler 	return (xd->xd_endpoints[endpoint - 1]);
119*ec82ef79SMatthias Scheler }
120*ec82ef79SMatthias Scheler 
121*ec82ef79SMatthias Scheler static int
xhci_polled_endpoint_transfer(xhci_polled_t * xhci_polledp,xhci_endpoint_t * xep,xhci_trb_t * trb,uint_t * num_characters)122*ec82ef79SMatthias Scheler xhci_polled_endpoint_transfer(xhci_polled_t *xhci_polledp, xhci_endpoint_t *xep,
123*ec82ef79SMatthias Scheler     xhci_trb_t *trb, uint_t *num_characters)
124*ec82ef79SMatthias Scheler {
125*ec82ef79SMatthias Scheler 	xhci_t *xhcip = xhci_polledp->xhci_polled_xhci;
126*ec82ef79SMatthias Scheler 	xhci_device_t *xd = xep->xep_xd;
127*ec82ef79SMatthias Scheler 	uint_t off;
128*ec82ef79SMatthias Scheler 	int code;
129*ec82ef79SMatthias Scheler 	xhci_transfer_t *xt;
130*ec82ef79SMatthias Scheler 	size_t len;
131*ec82ef79SMatthias Scheler 	xhci_transfer_t *rem;
132*ec82ef79SMatthias Scheler 	int sched_err;
133*ec82ef79SMatthias Scheler 
134*ec82ef79SMatthias Scheler 	/*
135*ec82ef79SMatthias Scheler 	 * This TRB should be part of a transfer. If it's not, then we ignore
136*ec82ef79SMatthias Scheler 	 * it. We also check whether or not it's for the first transfer. Because
137*ec82ef79SMatthias Scheler 	 * the rings are serviced in order, it should be.
138*ec82ef79SMatthias Scheler 	 */
139*ec82ef79SMatthias Scheler 	if ((xt = xhci_endpoint_determine_transfer(xhcip, xep, trb, &off)) ==
140*ec82ef79SMatthias Scheler 	    NULL) {
141*ec82ef79SMatthias Scheler 		return (USB_FAILURE);
142*ec82ef79SMatthias Scheler 	}
143*ec82ef79SMatthias Scheler 
144*ec82ef79SMatthias Scheler 	code = XHCI_TRB_GET_CODE(LE_32(trb->trb_status));
145*ec82ef79SMatthias Scheler 	if (code != XHCI_CODE_SUCCESS)
146*ec82ef79SMatthias Scheler 		return (USB_FAILURE);
147*ec82ef79SMatthias Scheler 
148*ec82ef79SMatthias Scheler 	ASSERT(xep->xep_type == USB_EP_ATTR_INTR);
149*ec82ef79SMatthias Scheler 
150*ec82ef79SMatthias Scheler 	if (!xt->xt_data_tohost)
151*ec82ef79SMatthias Scheler 		return (USB_SUCCESS);
152*ec82ef79SMatthias Scheler 
153*ec82ef79SMatthias Scheler 	if (xt->xt_short != 0)
154*ec82ef79SMatthias Scheler 		return (USB_CR_DATA_UNDERRUN);
155*ec82ef79SMatthias Scheler 
156*ec82ef79SMatthias Scheler 	if (xhci_transfer_sync(xhcip, xt, DDI_DMA_SYNC_FORCPU) != DDI_FM_OK) {
157*ec82ef79SMatthias Scheler 		xhci_polled_panic(xhci_polledp, "failed to process normal "
158*ec82ef79SMatthias Scheler 		    "transfer callback for endpoint %u of device on slot %d "
159*ec82ef79SMatthias Scheler 		    "and port %d: encountered fatal FM error synchronizing "
160*ec82ef79SMatthias Scheler 		    "DMA memory", xhcip, xep->xep_num, xd->xd_slot,
161*ec82ef79SMatthias Scheler 		    xd->xd_port);
162*ec82ef79SMatthias Scheler 	}
163*ec82ef79SMatthias Scheler 
164*ec82ef79SMatthias Scheler 	len = xt->xt_buffer.xdb_len;
165*ec82ef79SMatthias Scheler 	if (len > sizeof (xhci_polledp->xhci_polled_buf))
166*ec82ef79SMatthias Scheler 		len = sizeof (xhci_polledp->xhci_polled_buf);
167*ec82ef79SMatthias Scheler 	xhci_transfer_copy(xt, xhci_polledp->xhci_polled_buf, len, B_TRUE);
168*ec82ef79SMatthias Scheler 
169*ec82ef79SMatthias Scheler 	*num_characters = (uint_t)len;
170*ec82ef79SMatthias Scheler 
171*ec82ef79SMatthias Scheler 	VERIFY(xhci_ring_trb_consumed(&xep->xep_ring, LE_64(trb->trb_addr)));
172*ec82ef79SMatthias Scheler 	rem = list_remove_head(&xep->xep_transfers);
173*ec82ef79SMatthias Scheler 	VERIFY3P(rem, ==, xt);
174*ec82ef79SMatthias Scheler 
175*ec82ef79SMatthias Scheler 	xt->xt_short = 0;
176*ec82ef79SMatthias Scheler 	xt->xt_cr = USB_CR_OK;
177*ec82ef79SMatthias Scheler 
178*ec82ef79SMatthias Scheler 	/*
179*ec82ef79SMatthias Scheler 	 * The call below can fail but there isn't much we can do other
180*ec82ef79SMatthias Scheler 	 * than panicing the machine. But that might only re-enter the
181*ec82ef79SMatthias Scheler 	 * kernel debugger with now broken keyboard input. So we are
182*ec82ef79SMatthias Scheler 	 * simply returning the keyboard input that we have succesfully
183*ec82ef79SMatthias Scheler 	 * received because it might enable some progress.
184*ec82ef79SMatthias Scheler 	 */
185*ec82ef79SMatthias Scheler 	sched_err = xhci_endpoint_schedule(xhcip, xd, xep, xt, B_TRUE);
186*ec82ef79SMatthias Scheler 	xhci_polled_set_persistent_error(xhci_polledp, sched_err);
187*ec82ef79SMatthias Scheler 
188*ec82ef79SMatthias Scheler 	return (USB_SUCCESS);
189*ec82ef79SMatthias Scheler }
190*ec82ef79SMatthias Scheler 
191*ec82ef79SMatthias Scheler /*
192*ec82ef79SMatthias Scheler  * Process the event ring
193*ec82ef79SMatthias Scheler  */
194*ec82ef79SMatthias Scheler static int
xhci_polled_event_process(xhci_polled_t * xhci_polledp,uint_t * num_characters)195*ec82ef79SMatthias Scheler xhci_polled_event_process(xhci_polled_t *xhci_polledp, uint_t *num_characters)
196*ec82ef79SMatthias Scheler {
197*ec82ef79SMatthias Scheler 	xhci_t *xhcip = xhci_polledp->xhci_polled_xhci;
198*ec82ef79SMatthias Scheler 	xhci_ring_t *xrp = &xhcip->xhci_event.xev_ring;
199*ec82ef79SMatthias Scheler 	uint_t nevents;
200*ec82ef79SMatthias Scheler 	int ret;
201*ec82ef79SMatthias Scheler 	uint64_t addr;
202*ec82ef79SMatthias Scheler 
203*ec82ef79SMatthias Scheler 	if (xhcip->xhci_state & XHCI_S_ERROR)
204*ec82ef79SMatthias Scheler 		return (USB_HC_HARDWARE_ERROR);
205*ec82ef79SMatthias Scheler 
206*ec82ef79SMatthias Scheler 	VERIFY(xhcip->xhci_event.xev_segs != NULL);
207*ec82ef79SMatthias Scheler 
208*ec82ef79SMatthias Scheler 	XHCI_DMA_SYNC(xrp->xr_dma, DDI_DMA_SYNC_FORKERNEL);
209*ec82ef79SMatthias Scheler 
210*ec82ef79SMatthias Scheler 	/* Look for any transfer events */
211*ec82ef79SMatthias Scheler 	ret = USB_SUCCESS;
212*ec82ef79SMatthias Scheler 	for (nevents = 0; nevents < xrp->xr_ntrb; nevents++) {
213*ec82ef79SMatthias Scheler 		xhci_trb_t *trb;
214*ec82ef79SMatthias Scheler 		xhci_endpoint_t *xep;
215*ec82ef79SMatthias Scheler 		uint32_t type;
216*ec82ef79SMatthias Scheler 
217*ec82ef79SMatthias Scheler 		if ((trb = xhci_ring_event_advance(xrp)) == NULL)
218*ec82ef79SMatthias Scheler 			break;
219*ec82ef79SMatthias Scheler 
220*ec82ef79SMatthias Scheler 		xep = xhci_polled_get_endpoint(xhcip, trb);
221*ec82ef79SMatthias Scheler 		if (xep == NULL) {
222*ec82ef79SMatthias Scheler 			xhci_polled_set_persistent_error(xhci_polledp,
223*ec82ef79SMatthias Scheler 			    USB_HC_HARDWARE_ERROR);
224*ec82ef79SMatthias Scheler 			return (USB_HC_HARDWARE_ERROR);
225*ec82ef79SMatthias Scheler 		}
226*ec82ef79SMatthias Scheler 		type = LE_32(trb->trb_flags) & XHCI_TRB_TYPE_MASK;
227*ec82ef79SMatthias Scheler 
228*ec82ef79SMatthias Scheler 		if (xep != xhci_polledp->xhci_polled_endpoint ||
229*ec82ef79SMatthias Scheler 		    type != XHCI_EVT_XFER) {
230*ec82ef79SMatthias Scheler 			/*
231*ec82ef79SMatthias Scheler 			 * We got an event which we are not prepared to
232*ec82ef79SMatthias Scheler 			 * handle here. Call into the normal driver code
233*ec82ef79SMatthias Scheler 			 * which should return here after dispatching a task.
234*ec82ef79SMatthias Scheler 			 */
235*ec82ef79SMatthias Scheler 			boolean_t processed;
236*ec82ef79SMatthias Scheler 
237*ec82ef79SMatthias Scheler 			mutex_exit(&xhcip->xhci_lock);
238*ec82ef79SMatthias Scheler 			processed = xhci_event_process_trb(xhcip, trb);
239*ec82ef79SMatthias Scheler 			mutex_enter(&xhcip->xhci_lock);
240*ec82ef79SMatthias Scheler 
241*ec82ef79SMatthias Scheler 			if (!processed && xhcip->xhci_state & XHCI_S_ERROR)
242*ec82ef79SMatthias Scheler 				return (USB_HC_HARDWARE_ERROR);
243*ec82ef79SMatthias Scheler 			continue;
244*ec82ef79SMatthias Scheler 		}
245*ec82ef79SMatthias Scheler 
246*ec82ef79SMatthias Scheler 		ret = xhci_polled_endpoint_transfer(xhci_polledp, xep, trb,
247*ec82ef79SMatthias Scheler 		    num_characters);
248*ec82ef79SMatthias Scheler 		if (ret != USB_SUCCESS) {
249*ec82ef79SMatthias Scheler 			xhci_polled_set_persistent_error(xhci_polledp, ret);
250*ec82ef79SMatthias Scheler 			break;
251*ec82ef79SMatthias Scheler 		}
252*ec82ef79SMatthias Scheler 	}
253*ec82ef79SMatthias Scheler 
254*ec82ef79SMatthias Scheler 	addr = xhci_dma_pa(&xrp->xr_dma) + sizeof (xhci_trb_t) * xrp->xr_tail;
255*ec82ef79SMatthias Scheler 	addr |= XHCI_ERDP_BUSY;
256*ec82ef79SMatthias Scheler 	xhci_put64(xhcip, XHCI_R_RUN, XHCI_ERDP(0), addr);
257*ec82ef79SMatthias Scheler 
258*ec82ef79SMatthias Scheler 	return (ret);
259*ec82ef79SMatthias Scheler }
260*ec82ef79SMatthias Scheler 
261*ec82ef79SMatthias Scheler int
xhci_hcdi_console_input_init(usba_pipe_handle_data_t * pipe_handle,uchar_t ** polled_buf,usb_console_info_impl_t * console_input_info)262*ec82ef79SMatthias Scheler xhci_hcdi_console_input_init(usba_pipe_handle_data_t *pipe_handle,
263*ec82ef79SMatthias Scheler     uchar_t **polled_buf, usb_console_info_impl_t *console_input_info)
264*ec82ef79SMatthias Scheler {
265*ec82ef79SMatthias Scheler 	xhci_t *xhcip;
266*ec82ef79SMatthias Scheler 	int ret;
267*ec82ef79SMatthias Scheler 	xhci_polled_t *xhci_polledp;
268*ec82ef79SMatthias Scheler 
269*ec82ef79SMatthias Scheler 	xhcip = xhci_hcdi_get_xhcip_from_dev(pipe_handle->p_usba_device);
270*ec82ef79SMatthias Scheler 
271*ec82ef79SMatthias Scheler 	mutex_enter(&xhcip->xhci_lock);
272*ec82ef79SMatthias Scheler 
273*ec82ef79SMatthias Scheler 	ret = xhci_polled_init(pipe_handle, xhcip, console_input_info);
274*ec82ef79SMatthias Scheler 	if (ret != USB_SUCCESS) {
275*ec82ef79SMatthias Scheler 		mutex_exit(&xhcip->xhci_lock);
276*ec82ef79SMatthias Scheler 		return (ret);
277*ec82ef79SMatthias Scheler 	}
278*ec82ef79SMatthias Scheler 
279*ec82ef79SMatthias Scheler 	xhci_polledp = (xhci_polled_t *)console_input_info->uci_private;
280*ec82ef79SMatthias Scheler 	*polled_buf = xhci_polledp->xhci_polled_buf;
281*ec82ef79SMatthias Scheler 
282*ec82ef79SMatthias Scheler 	mutex_exit(&xhcip->xhci_lock);
283*ec82ef79SMatthias Scheler 
284*ec82ef79SMatthias Scheler 	return (ret);
285*ec82ef79SMatthias Scheler }
286*ec82ef79SMatthias Scheler 
287*ec82ef79SMatthias Scheler int
xhci_hcdi_console_input_fini(usb_console_info_impl_t * console_input_info)288*ec82ef79SMatthias Scheler xhci_hcdi_console_input_fini(usb_console_info_impl_t *console_input_info)
289*ec82ef79SMatthias Scheler {
290*ec82ef79SMatthias Scheler 	xhci_polled_t *xhci_polledp;
291*ec82ef79SMatthias Scheler 
292*ec82ef79SMatthias Scheler 	xhci_polledp = (xhci_polled_t *)console_input_info->uci_private;
293*ec82ef79SMatthias Scheler 	if (xhci_polledp != NULL) {
294*ec82ef79SMatthias Scheler 		kmem_free(xhci_polledp, sizeof (xhci_polled_t));
295*ec82ef79SMatthias Scheler 		console_input_info->uci_private = NULL;
296*ec82ef79SMatthias Scheler 	}
297*ec82ef79SMatthias Scheler 
298*ec82ef79SMatthias Scheler 	return (USB_SUCCESS);
299*ec82ef79SMatthias Scheler }
300*ec82ef79SMatthias Scheler 
301*ec82ef79SMatthias Scheler int
xhci_hcdi_console_input_enter(usb_console_info_impl_t * console_input_info)302*ec82ef79SMatthias Scheler xhci_hcdi_console_input_enter(usb_console_info_impl_t *console_input_info)
303*ec82ef79SMatthias Scheler {
304*ec82ef79SMatthias Scheler 	xhci_polled_t *xhci_polledp;
305*ec82ef79SMatthias Scheler 	xhci_t *xhcip;
306*ec82ef79SMatthias Scheler 	xhci_endpoint_t *xep;
307*ec82ef79SMatthias Scheler 	uint32_t status;
308*ec82ef79SMatthias Scheler 
309*ec82ef79SMatthias Scheler 	xhci_polledp = (xhci_polled_t *)console_input_info->uci_private;
310*ec82ef79SMatthias Scheler 	xhcip = xhci_polledp->xhci_polled_xhci;
311*ec82ef79SMatthias Scheler 	xep = xhci_polledp->xhci_polled_endpoint;
312*ec82ef79SMatthias Scheler 
313*ec82ef79SMatthias Scheler 	if (mutex_tryenter(&xhcip->xhci_lock) == 0)
314*ec82ef79SMatthias Scheler 		return (USB_BUSY);
315*ec82ef79SMatthias Scheler 
316*ec82ef79SMatthias Scheler 	/*
317*ec82ef79SMatthias Scheler 	 * If the controller is already switched over, just return
318*ec82ef79SMatthias Scheler 	 */
319*ec82ef79SMatthias Scheler 	if (xhci_polledp->xhci_polled_entry > 0) {
320*ec82ef79SMatthias Scheler 		xhci_polledp->xhci_polled_entry++;
321*ec82ef79SMatthias Scheler 		ASSERT(xep->xep_state & XHCI_ENDPOINT_POLLED);
322*ec82ef79SMatthias Scheler 		mutex_exit(&xhcip->xhci_lock);
323*ec82ef79SMatthias Scheler 		return (USB_SUCCESS);
324*ec82ef79SMatthias Scheler 	}
325*ec82ef79SMatthias Scheler 
326*ec82ef79SMatthias Scheler 	/*
327*ec82ef79SMatthias Scheler 	 * Check to see if we have a fatal bit set. If this is the case the
328*ec82ef79SMatthias Scheler 	 * host controller is not working properly and we don't want to
329*ec82ef79SMatthias Scheler 	 * enter the kernel debugger and leave the system unresponsive.
330*ec82ef79SMatthias Scheler 	 */
331*ec82ef79SMatthias Scheler 	status = xhci_get32(xhcip, XHCI_R_OPER, XHCI_USBSTS);
332*ec82ef79SMatthias Scheler 	if ((status & (XHCI_STS_HSE | XHCI_STS_SRE | XHCI_STS_HCE)) != 0) {
333*ec82ef79SMatthias Scheler 		mutex_exit(&xhcip->xhci_lock);
334*ec82ef79SMatthias Scheler 		xhci_polled_set_persistent_error(xhci_polledp,
335*ec82ef79SMatthias Scheler 		    USB_HC_HARDWARE_ERROR);
336*ec82ef79SMatthias Scheler 		return (USB_HC_HARDWARE_ERROR);
337*ec82ef79SMatthias Scheler 	}
338*ec82ef79SMatthias Scheler 
339*ec82ef79SMatthias Scheler 	/*
340*ec82ef79SMatthias Scheler 	 * We only support interrupt (keyboards) and not bulk (serial)
341*ec82ef79SMatthias Scheler 	 * endpoints at the moment.
342*ec82ef79SMatthias Scheler 	 */
343*ec82ef79SMatthias Scheler 	if (xhci_polledp->xhci_polled_endpoint->xep_type != USB_EP_ATTR_INTR) {
344*ec82ef79SMatthias Scheler 		mutex_exit(&xhcip->xhci_lock);
345*ec82ef79SMatthias Scheler 		return (USB_NOT_SUPPORTED);
346*ec82ef79SMatthias Scheler 	}
347*ec82ef79SMatthias Scheler 
348*ec82ef79SMatthias Scheler 	xhci_polledp->xhci_polled_persistent_error = USB_SUCCESS;
349*ec82ef79SMatthias Scheler 	xhci_polledp->xhci_polled_entry++;
350*ec82ef79SMatthias Scheler 
351*ec82ef79SMatthias Scheler 	ASSERT(!(xep->xep_state & XHCI_ENDPOINT_POLLED));
352*ec82ef79SMatthias Scheler 	xep->xep_state |= XHCI_ENDPOINT_POLLED;
353*ec82ef79SMatthias Scheler 
354*ec82ef79SMatthias Scheler 	mutex_exit(&xhcip->xhci_lock);
355*ec82ef79SMatthias Scheler 	return (USB_SUCCESS);
356*ec82ef79SMatthias Scheler }
357*ec82ef79SMatthias Scheler 
358*ec82ef79SMatthias Scheler int
xhci_hcdi_console_read(usb_console_info_impl_t * console_input_info,uint_t * num_characters)359*ec82ef79SMatthias Scheler xhci_hcdi_console_read(usb_console_info_impl_t *console_input_info,
360*ec82ef79SMatthias Scheler     uint_t *num_characters)
361*ec82ef79SMatthias Scheler {
362*ec82ef79SMatthias Scheler 	xhci_polled_t *xhci_polledp;
363*ec82ef79SMatthias Scheler 	xhci_t *xhcip;
364*ec82ef79SMatthias Scheler 	uint32_t status, iman;
365*ec82ef79SMatthias Scheler 	int ret;
366*ec82ef79SMatthias Scheler 
367*ec82ef79SMatthias Scheler 	*num_characters = 0;
368*ec82ef79SMatthias Scheler 
369*ec82ef79SMatthias Scheler 	xhci_polledp = (xhci_polled_t *)console_input_info->uci_private;
370*ec82ef79SMatthias Scheler 	VERIFY(xhci_polledp != NULL);
371*ec82ef79SMatthias Scheler 
372*ec82ef79SMatthias Scheler 	if (xhci_polledp->xhci_polled_persistent_error != USB_SUCCESS)
373*ec82ef79SMatthias Scheler 		return (xhci_polledp->xhci_polled_persistent_error);
374*ec82ef79SMatthias Scheler 
375*ec82ef79SMatthias Scheler 	xhcip = xhci_polledp->xhci_polled_xhci;
376*ec82ef79SMatthias Scheler 	if (mutex_tryenter(&xhcip->xhci_lock) == 0)
377*ec82ef79SMatthias Scheler 		return (USB_BUSY);
378*ec82ef79SMatthias Scheler 
379*ec82ef79SMatthias Scheler 	/*
380*ec82ef79SMatthias Scheler 	 * Before we read the interrupt management register, check to see if we
381*ec82ef79SMatthias Scheler 	 * have a fatal bit set. As we cannot reset the host controller while
382*ec82ef79SMatthias Scheler 	 * the kernel debugger is running we give up.
383*ec82ef79SMatthias Scheler 	 */
384*ec82ef79SMatthias Scheler 	status = xhci_get32(xhcip, XHCI_R_OPER, XHCI_USBSTS);
385*ec82ef79SMatthias Scheler 	if ((status & (XHCI_STS_HSE | XHCI_STS_SRE | XHCI_STS_HCE)) != 0) {
386*ec82ef79SMatthias Scheler 		xhci_polled_panic(xhci_polledp, "found fatal error bit in "
387*ec82ef79SMatthias Scheler 		    "status register, value: 0x%x", xhcip, status);
388*ec82ef79SMatthias Scheler 	}
389*ec82ef79SMatthias Scheler 
390*ec82ef79SMatthias Scheler 	iman = xhci_get32(xhcip, XHCI_R_RUN, XHCI_IMAN(0));
391*ec82ef79SMatthias Scheler 
392*ec82ef79SMatthias Scheler 	ret = xhci_polled_event_process(xhci_polledp, num_characters);
393*ec82ef79SMatthias Scheler 
394*ec82ef79SMatthias Scheler 	if (ret == USB_SUCCESS)
395*ec82ef79SMatthias Scheler 		xhci_put32(xhcip, XHCI_R_RUN, XHCI_IMAN(0), iman);
396*ec82ef79SMatthias Scheler 
397*ec82ef79SMatthias Scheler 	mutex_exit(&xhcip->xhci_lock);
398*ec82ef79SMatthias Scheler 	return (ret);
399*ec82ef79SMatthias Scheler }
400*ec82ef79SMatthias Scheler 
401*ec82ef79SMatthias Scheler int
xhci_hcdi_console_input_exit(usb_console_info_impl_t * console_input_info)402*ec82ef79SMatthias Scheler xhci_hcdi_console_input_exit(usb_console_info_impl_t *console_input_info)
403*ec82ef79SMatthias Scheler {
404*ec82ef79SMatthias Scheler 	xhci_polled_t *xhci_polledp;
405*ec82ef79SMatthias Scheler 	xhci_t *xhcip;
406*ec82ef79SMatthias Scheler 	xhci_endpoint_t *xep;
407*ec82ef79SMatthias Scheler 
408*ec82ef79SMatthias Scheler 	xhci_polledp = (xhci_polled_t *)console_input_info->uci_private;
409*ec82ef79SMatthias Scheler 	VERIFY(xhci_polledp != NULL);
410*ec82ef79SMatthias Scheler 
411*ec82ef79SMatthias Scheler 	xhcip = xhci_polledp->xhci_polled_xhci;
412*ec82ef79SMatthias Scheler 	mutex_enter(&xhcip->xhci_lock);
413*ec82ef79SMatthias Scheler 
414*ec82ef79SMatthias Scheler 	xep = xhci_polledp->xhci_polled_endpoint;
415*ec82ef79SMatthias Scheler 	ASSERT(xep->xep_state & XHCI_ENDPOINT_POLLED);
416*ec82ef79SMatthias Scheler 
417*ec82ef79SMatthias Scheler 	VERIFY(xhci_polledp->xhci_polled_entry > 0);
418*ec82ef79SMatthias Scheler 	xhci_polledp->xhci_polled_entry--;
419*ec82ef79SMatthias Scheler 	if (xhci_polledp->xhci_polled_entry > 0) {
420*ec82ef79SMatthias Scheler 		mutex_exit(&xhcip->xhci_lock);
421*ec82ef79SMatthias Scheler 		return (USB_SUCCESS);
422*ec82ef79SMatthias Scheler 	}
423*ec82ef79SMatthias Scheler 
424*ec82ef79SMatthias Scheler 	xep->xep_state &= ~XHCI_ENDPOINT_POLLED;
425*ec82ef79SMatthias Scheler 
426*ec82ef79SMatthias Scheler 	/*
427*ec82ef79SMatthias Scheler 	 * Initiate a reset of the host controller if we encountered problems
428*ec82ef79SMatthias Scheler 	 * or ignored events while in polled mode. The reset will not be
429*ec82ef79SMatthias Scheler 	 * performed in this context and instead be scheduled to a
430*ec82ef79SMatthias Scheler 	 * task queue. It will therefore only happen once the kernel is
431*ec82ef79SMatthias Scheler 	 * fully up and running again which should be perfectly safe.
432*ec82ef79SMatthias Scheler 	 */
433*ec82ef79SMatthias Scheler 	if (xhci_polledp->xhci_polled_persistent_error != USB_SUCCESS) {
434*ec82ef79SMatthias Scheler 		xhci_fm_runtime_reset(xhcip);
435*ec82ef79SMatthias Scheler 	}
436*ec82ef79SMatthias Scheler 
437*ec82ef79SMatthias Scheler 	mutex_exit(&xhcip->xhci_lock);
438*ec82ef79SMatthias Scheler 	return (USB_SUCCESS);
439*ec82ef79SMatthias Scheler }
440*ec82ef79SMatthias Scheler 
441*ec82ef79SMatthias Scheler int
xhci_hcdi_console_output_init(usba_pipe_handle_data_t * pipe_handle,usb_console_info_impl_t * console_output_info)442*ec82ef79SMatthias Scheler xhci_hcdi_console_output_init(usba_pipe_handle_data_t *pipe_handle,
443*ec82ef79SMatthias Scheler     usb_console_info_impl_t *console_output_info)
444*ec82ef79SMatthias Scheler {
445*ec82ef79SMatthias Scheler 	return (USB_NOT_SUPPORTED);
446*ec82ef79SMatthias Scheler }
447*ec82ef79SMatthias Scheler 
448*ec82ef79SMatthias Scheler int
xhci_hcdi_console_output_fini(usb_console_info_impl_t * console_output_info)449*ec82ef79SMatthias Scheler xhci_hcdi_console_output_fini(usb_console_info_impl_t *console_output_info)
450*ec82ef79SMatthias Scheler {
451*ec82ef79SMatthias Scheler 	return (USB_NOT_SUPPORTED);
452*ec82ef79SMatthias Scheler }
453*ec82ef79SMatthias Scheler 
454*ec82ef79SMatthias Scheler int
xhci_hcdi_console_output_enter(usb_console_info_impl_t * console_output_info)455*ec82ef79SMatthias Scheler xhci_hcdi_console_output_enter(usb_console_info_impl_t *console_output_info)
456*ec82ef79SMatthias Scheler {
457*ec82ef79SMatthias Scheler 	return (USB_NOT_SUPPORTED);
458*ec82ef79SMatthias Scheler }
459*ec82ef79SMatthias Scheler 
460*ec82ef79SMatthias Scheler int
xhci_hcdi_console_write(usb_console_info_impl_t * console_output_info,uchar_t * buf,uint_t num_characters,uint_t * num_characters_written)461*ec82ef79SMatthias Scheler xhci_hcdi_console_write(usb_console_info_impl_t	*console_output_info,
462*ec82ef79SMatthias Scheler     uchar_t *buf, uint_t num_characters, uint_t *num_characters_written)
463*ec82ef79SMatthias Scheler {
464*ec82ef79SMatthias Scheler 	return (USB_NOT_SUPPORTED);
465*ec82ef79SMatthias Scheler }
466*ec82ef79SMatthias Scheler 
467*ec82ef79SMatthias Scheler int
xhci_hcdi_console_output_exit(usb_console_info_impl_t * console_output_info)468*ec82ef79SMatthias Scheler xhci_hcdi_console_output_exit(usb_console_info_impl_t *console_output_info)
469*ec82ef79SMatthias Scheler {
470*ec82ef79SMatthias Scheler 	return (USB_NOT_SUPPORTED);
471*ec82ef79SMatthias Scheler }
472