xref: /illumos-gate/usr/src/uts/common/io/usb/hcd/uhci/uhci.c (revision 6a634c9d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 
26 /*
27  * Universal Host Controller Driver (UHCI)
28  *
29  * The UHCI driver is a driver which interfaces to the Universal
30  * Serial Bus Architecture (USBA) and the Host Controller (HC). The interface to
31  * the Host Controller is defined by the Universal Host Controller Interface.
32  * This file contains code for auto-configuration entry points and interrupt
33  * handling.
34  */
35 #include <sys/usb/hcd/uhci/uhcid.h>
36 #include <sys/usb/hcd/uhci/uhcihub.h>
37 #include <sys/usb/hcd/uhci/uhciutil.h>
38 
39 /*
40  * Prototype Declarations for cb_ops and dev_ops
41  */
42 static	int uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
43 static	int uhci_add_intrs(uhci_state_t *uhcip, int	intr_type);
44 static	int uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
45 static void uhci_rem_intrs(uhci_state_t	*uhcip);
46 static	int uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
47 static	int uhci_close(dev_t dev, int flag, int otyp, cred_t *credp);
48 static	int uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
49 		cred_t *credp, int *rvalp);
50 static	int uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd);
51 static	int uhci_quiesce(dev_info_t *dip);
52 static	int uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
53 		void **result);
54 
55 /* extern */
56 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level);
57 
58 static struct cb_ops uhci_cb_ops = {
59 	uhci_open,			/* Open */
60 	uhci_close,			/* Close */
61 	nodev,				/* Strategy */
62 	nodev,				/* Print */
63 	nodev,				/* Dump */
64 	nodev,				/* Read */
65 	nodev,				/* Write */
66 	uhci_ioctl,			/* Ioctl */
67 	nodev,				/* Devmap */
68 	nodev,				/* Mmap */
69 	nodev,				/* Segmap */
70 	nochpoll,			/* Poll */
71 	ddi_prop_op,			/* cb_prop_op */
72 	NULL,				/* Streamtab */
73 	D_MP				/* Driver compatibility flag */
74 };
75 
76 static struct dev_ops uhci_ops = {
77 	DEVO_REV,			/* Devo_rev */
78 	0,				/* Refcnt */
79 	uhci_info,			/* Info */
80 	nulldev,			/* Identify */
81 	nulldev,			/* Probe */
82 	uhci_attach,			/* Attach */
83 	uhci_detach,			/* Detach */
84 	uhci_reset,			/* Reset */
85 	&uhci_cb_ops,			/* Driver operations */
86 	&usba_hubdi_busops,		/* Bus operations */
87 	usba_hubdi_root_hub_power,	/* Power */
88 	uhci_quiesce			/* quiesce */
89 };
90 
91 static struct modldrv modldrv = {
92 	&mod_driverops,		/* Type of module. This one is a driver */
93 	"USB UHCI Controller Driver",	/* Name of the module. */
94 	&uhci_ops,		/* Driver ops */
95 };
96 
97 static struct modlinkage modlinkage = {
98 	MODREV_1, (void *)&modldrv, NULL
99 };
100 
101 /*
102  *  Globals
103  */
104 void		*uhci_statep;
105 uint_t		uhci_errlevel = USB_LOG_L2;
106 uint_t		uhci_errmask = PRINT_MASK_ALL;
107 uint_t		uhci_instance_debug = (uint_t)-1;
108 
109 uint_t		uhci_td_pool_size = 256;			/* Num TDs */
110 uint_t		uhci_qh_pool_size = 130;			/* Num QHs */
111 ushort_t	uhci_tree_bottom_nodes[NUM_FRAME_LST_ENTRIES];
112 
113 
114 /*
115  * UHCI MSI tunable:
116  *
117  * By default MSI is enabled on all supported platforms.
118  */
119 boolean_t uhci_enable_msi = B_TRUE;
120 
121 /*
122  * tunable, delay during attach in seconds
123  */
124 int		uhci_attach_wait = 0;
125 
126 /* function prototypes */
127 static void	uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td,
128 			uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp);
129 static void	uhci_handle_one_xfer_completion(uhci_state_t *uhcip,
130 			usb_cr_t usb_err, uhci_td_t *td);
131 static uint_t	uhci_intr(caddr_t arg1, caddr_t arg2);
132 static int	uhci_cleanup(uhci_state_t *uhcip);
133 static int	uhci_cpr_suspend(uhci_state_t *uhcip);
134 static int	uhci_cpr_resume(uhci_state_t *uhcip);
135 
136 
137 int
_init(void)138 _init(void)
139 {
140 	int error;
141 	ushort_t i, j, k, *temp, num_of_nodes;
142 
143 	/* Initialize the soft state structures */
144 	if ((error = ddi_soft_state_init(&uhci_statep, sizeof (uhci_state_t),
145 	    UHCI_MAX_INSTS)) != 0) {
146 
147 		return (error);
148 	}
149 
150 	/* Install the loadable module */
151 	if ((error = mod_install(&modlinkage)) != 0) {
152 		ddi_soft_state_fini(&uhci_statep);
153 
154 		return (error);
155 	}
156 
157 	/*
158 	 *  Build the tree bottom shared by all instances
159 	 */
160 	temp = kmem_zalloc(NUM_FRAME_LST_ENTRIES * 2, KM_SLEEP);
161 
162 	num_of_nodes = 1;
163 	for (i = 0; i < log_2(NUM_FRAME_LST_ENTRIES); i++) {
164 		for (j = 0, k = 0; k < num_of_nodes; k++, j++) {
165 			uhci_tree_bottom_nodes[j++] = temp[k];
166 			uhci_tree_bottom_nodes[j]   = temp[k] + pow_2(i);
167 		}
168 
169 		num_of_nodes *= 2;
170 		for (k = 0; k < num_of_nodes; k++)
171 			temp[k] = uhci_tree_bottom_nodes[k];
172 
173 	}
174 	kmem_free(temp, (NUM_FRAME_LST_ENTRIES*2));
175 
176 
177 	return (error);
178 }
179 
180 
181 int
_info(struct modinfo * modinfop)182 _info(struct modinfo *modinfop)
183 {
184 	return (mod_info(&modlinkage, modinfop));
185 }
186 
187 
188 int
_fini(void)189 _fini(void)
190 {
191 	int error;
192 
193 	error = mod_remove(&modlinkage);
194 
195 	if (error == 0) {
196 		/* Release per module resources */
197 		ddi_soft_state_fini(&uhci_statep);
198 	}
199 
200 	return (error);
201 }
202 
203 /*
204  * The following simulated polling is for debugging purposes only.
205  * It is activated on x86 by setting usb-polling=true in GRUB or uhci.conf.
206  */
207 static int
uhci_is_polled(dev_info_t * dip)208 uhci_is_polled(dev_info_t *dip)
209 {
210 	int ret;
211 	char *propval;
212 
213 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
214 	    "usb-polling", &propval) != DDI_SUCCESS)
215 
216 		return (0);
217 
218 	ret = (strcmp(propval, "true") == 0);
219 	ddi_prop_free(propval);
220 
221 	return (ret);
222 }
223 
224 static void
uhci_poll_intr(void * arg)225 uhci_poll_intr(void *arg)
226 {
227 	/* poll every msec */
228 	for (;;) {
229 		(void) uhci_intr(arg, NULL);
230 		delay(drv_usectohz(1000));
231 	}
232 }
233 
234 /*
235  * Host Controller Driver (HCD) Auto configuration entry points
236  */
237 
238 /*
239  * Function Name  :  uhci_attach:
240  * Description	  :  Attach entry point - called by the Kernel.
241  *		     Allocates of per controller data structure.
242  *		     Initializes the controller.
243  * Output	  :  DDI_SUCCESS / DDI_FAILURE
244  */
245 static int
uhci_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)246 uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
247 {
248 	int				instance, polled;
249 	int				i, intr_types;
250 	uhci_state_t			*uhcip = NULL;
251 	usba_hcdi_register_args_t	hcdi_args;
252 
253 	USB_DPRINTF_L4(PRINT_MASK_ATTA, NULL, "uhci_attach:");
254 
255 	switch (cmd) {
256 	case DDI_ATTACH:
257 		break;
258 	case DDI_RESUME:
259 		uhcip = uhci_obtain_state(dip);
260 
261 		return (uhci_cpr_resume(uhcip));
262 	default:
263 
264 		return (DDI_FAILURE);
265 	}
266 
267 	/* Get the instance and create soft state */
268 	instance = ddi_get_instance(dip);
269 
270 	/* Allocate the soft state structure for this instance of the driver */
271 	if (ddi_soft_state_zalloc(uhci_statep, instance) != 0) {
272 
273 		return (DDI_FAILURE);
274 	}
275 
276 	if ((uhcip = ddi_get_soft_state(uhci_statep, instance)) == NULL) {
277 
278 		return (DDI_FAILURE);
279 	}
280 
281 	uhcip->uhci_log_hdl = usb_alloc_log_hdl(dip, "uhci", &uhci_errlevel,
282 	    &uhci_errmask, &uhci_instance_debug, 0);
283 
284 	/* Set host controller soft state to initialization */
285 	uhcip->uhci_hc_soft_state = UHCI_CTLR_INIT_STATE;
286 
287 	/* Save the dip and instance */
288 	uhcip->uhci_dip		= dip;
289 	uhcip->uhci_instance	= instance;
290 
291 	polled = uhci_is_polled(dip);
292 	if (polled)
293 
294 		goto skip_intr;
295 
296 	/* Get supported interrupt types */
297 	if (ddi_intr_get_supported_types(uhcip->uhci_dip,
298 	    &intr_types) != DDI_SUCCESS) {
299 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
300 		    "uhci_attach: ddi_intr_get_supported_types failed");
301 
302 		usb_free_log_hdl(uhcip->uhci_log_hdl);
303 		ddi_soft_state_free(uhci_statep, instance);
304 
305 		return (DDI_FAILURE);
306 	}
307 
308 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
309 	    "uhci_attach: supported interrupt types 0x%x", intr_types);
310 
311 	if ((intr_types & DDI_INTR_TYPE_MSI) && uhci_enable_msi) {
312 		if (uhci_add_intrs(uhcip, DDI_INTR_TYPE_MSI)
313 		    != DDI_SUCCESS) {
314 			USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
315 			    "uhci_attach: MSI registration failed, "
316 			    "trying FIXED interrupt \n");
317 		} else {
318 			USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
319 			    "uhci_attach: Using MSI interrupt type\n");
320 
321 			uhcip->uhci_intr_type = DDI_INTR_TYPE_MSI;
322 		}
323 	}
324 
325 	if (!(uhcip->uhci_htable) && (intr_types & DDI_INTR_TYPE_FIXED)) {
326 		if (uhci_add_intrs(uhcip, DDI_INTR_TYPE_FIXED)
327 		    != DDI_SUCCESS) {
328 			USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
329 			    "uhci_attach: FIXED interrupt registration "
330 			    "failed\n");
331 
332 			usb_free_log_hdl(uhcip->uhci_log_hdl);
333 			ddi_soft_state_free(uhci_statep, instance);
334 
335 			return (DDI_FAILURE);
336 		}
337 
338 		USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
339 		    "uhci_attach: Using FIXED interrupt type\n");
340 
341 		uhcip->uhci_intr_type = DDI_INTR_TYPE_FIXED;
342 	}
343 
344 skip_intr:
345 	/* Semaphore to serialize opens and closes */
346 	sema_init(&uhcip->uhci_ocsem, 1, NULL, SEMA_DRIVER, NULL);
347 
348 	/* Create prototype condition variable */
349 	cv_init(&uhcip->uhci_cv_SOF, NULL, CV_DRIVER, NULL);
350 
351 	/* Initialize the DMA attributes */
352 	uhci_set_dma_attributes(uhcip);
353 
354 	/* Initialize the kstat structures */
355 	uhci_create_stats(uhcip);
356 
357 	/* Create the td and ed pools */
358 	if (uhci_allocate_pools(uhcip) != USB_SUCCESS) {
359 
360 		goto fail;
361 	}
362 
363 	/* Map the registers */
364 	if (uhci_map_regs(uhcip) != USB_SUCCESS) {
365 
366 		goto fail;
367 	}
368 
369 	/* Enable all interrupts */
370 	if (polled) {
371 		extern pri_t maxclsyspri;
372 
373 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
374 		    "uhci_attach: running in simulated polled mode.");
375 
376 		/* create thread to poll */
377 		(void) thread_create(NULL, 0, uhci_poll_intr, uhcip, 0, &p0,
378 		    TS_RUN, maxclsyspri);
379 	} else if (uhcip->uhci_intr_cap & DDI_INTR_FLAG_BLOCK) {
380 		/* Call ddi_intr_block_enable() for MSI interrupts */
381 		(void) ddi_intr_block_enable(uhcip->uhci_htable,
382 		    uhcip->uhci_intr_cnt);
383 	} else {
384 		/* Call ddi_intr_enable for MSI or FIXED interrupts */
385 		for (i = 0; i < uhcip->uhci_intr_cnt; i++)
386 			(void) ddi_intr_enable(uhcip->uhci_htable[i]);
387 	}
388 
389 
390 	/* Initialize the controller */
391 	if (uhci_init_ctlr(uhcip) != USB_SUCCESS) {
392 
393 		goto fail;
394 	}
395 
396 	/*
397 	 * At this point, the hardware will be okay.
398 	 * Initialize the usba_hcdi structure
399 	 */
400 	uhcip->uhci_hcdi_ops = uhci_alloc_hcdi_ops(uhcip);
401 
402 	/*
403 	 * Make this HCD instance known to USBA
404 	 * (dma_attr must be passed for USBA busctl's)
405 	 */
406 	hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION;
407 	hcdi_args.usba_hcdi_register_dip = dip;
408 	hcdi_args.usba_hcdi_register_ops = uhcip->uhci_hcdi_ops;
409 	hcdi_args.usba_hcdi_register_dma_attr = &uhcip->uhci_dma_attr;
410 	hcdi_args.usba_hcdi_register_iblock_cookie =
411 	    (ddi_iblock_cookie_t)(uintptr_t)uhcip->uhci_intr_pri;
412 
413 	if (usba_hcdi_register(&hcdi_args, 0) != USB_SUCCESS) {
414 
415 		goto fail;
416 	}
417 
418 #ifndef __sparc
419 	/*
420 	 * On NCR system,  the driver seen  failure of some commands
421 	 * while booting. This delay mysteriously solved the problem.
422 	 */
423 	delay(drv_usectohz(uhci_attach_wait*1000000));
424 #endif
425 
426 	/*
427 	 * Create another timeout handler to check whether any
428 	 * control/bulk/interrupt commands failed.
429 	 * This gets called every second.
430 	 */
431 	uhcip->uhci_cmd_timeout_id = timeout(uhci_cmd_timeout_hdlr,
432 	    (void *)uhcip, UHCI_ONE_SECOND);
433 
434 	mutex_enter(&uhcip->uhci_int_mutex);
435 
436 	/*
437 	 * Set HcInterruptEnable to enable all interrupts except Root
438 	 * Hub Status change and SOF interrupts.
439 	 */
440 	Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
441 
442 	/* Test the SOF interrupt */
443 	if (uhci_wait_for_sof(uhcip) != USB_SUCCESS) {
444 		USB_DPRINTF_L0(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
445 		    "No SOF interrupts have been received, this USB UHCI host"
446 		    " controller is unusable");
447 		mutex_exit(&uhcip->uhci_int_mutex);
448 
449 		goto fail;
450 	}
451 
452 	mutex_exit(&uhcip->uhci_int_mutex);
453 
454 	/* This should be the last step which might fail during attaching */
455 	if (uhci_init_root_hub(uhcip) != USB_SUCCESS) {
456 
457 		goto fail;
458 	}
459 
460 	/* Display information in the banner */
461 	ddi_report_dev(dip);
462 
463 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
464 	    "uhci_attach successful");
465 
466 	return (DDI_SUCCESS);
467 
468 fail:
469 	USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
470 	    "failed to attach");
471 
472 	(void) uhci_cleanup(uhcip);
473 
474 	return (DDI_FAILURE);
475 }
476 
477 
478 /*
479  * uhci_add_intrs:
480  *
481  * Register FIXED or MSI interrupts.
482  */
483 static int
uhci_add_intrs(uhci_state_t * uhcip,int intr_type)484 uhci_add_intrs(uhci_state_t	*uhcip,
485 		int		intr_type)
486 {
487 	int	actual, avail, intr_size, count = 0;
488 	int	i, flag, ret;
489 
490 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
491 	    "uhci_add_intrs: interrupt type 0x%x", intr_type);
492 
493 	/* Get number of interrupts */
494 	ret = ddi_intr_get_nintrs(uhcip->uhci_dip, intr_type, &count);
495 	if ((ret != DDI_SUCCESS) || (count == 0)) {
496 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
497 		    "uhci_add_intrs: ddi_intr_get_nintrs() failure, "
498 		    "ret: %d, count: %d", ret, count);
499 
500 		return (DDI_FAILURE);
501 	}
502 
503 	/* Get number of available interrupts */
504 	ret = ddi_intr_get_navail(uhcip->uhci_dip, intr_type, &avail);
505 	if ((ret != DDI_SUCCESS) || (avail == 0)) {
506 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
507 		    "uhci_add_intrs: ddi_intr_get_navail() failure, "
508 		    "ret: %d, count: %d", ret, count);
509 
510 		return (DDI_FAILURE);
511 	}
512 
513 	if (avail < count) {
514 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
515 		    "uhci_add_intrs: uhci_add_intrs: nintrs () "
516 		    "returned %d, navail returned %d\n", count, avail);
517 	}
518 
519 	/* Allocate an array of interrupt handles */
520 	intr_size = count * sizeof (ddi_intr_handle_t);
521 	uhcip->uhci_htable = kmem_zalloc(intr_size, KM_SLEEP);
522 
523 	flag = (intr_type == DDI_INTR_TYPE_MSI) ?
524 	    DDI_INTR_ALLOC_STRICT:DDI_INTR_ALLOC_NORMAL;
525 
526 	/* call ddi_intr_alloc() */
527 	ret = ddi_intr_alloc(uhcip->uhci_dip, uhcip->uhci_htable,
528 	    intr_type, 0, count, &actual, flag);
529 
530 	if ((ret != DDI_SUCCESS) || (actual == 0)) {
531 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
532 		    "uhci_add_intrs: ddi_intr_alloc() failed %d", ret);
533 
534 		kmem_free(uhcip->uhci_htable, intr_size);
535 
536 		return (DDI_FAILURE);
537 	}
538 
539 	if (actual < count) {
540 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
541 		    "uhci_add_intrs: Requested: %d, Received: %d\n",
542 		    count, actual);
543 
544 		for (i = 0; i < actual; i++)
545 			(void) ddi_intr_free(uhcip->uhci_htable[i]);
546 
547 		kmem_free(uhcip->uhci_htable, intr_size);
548 
549 		return (DDI_FAILURE);
550 	}
551 
552 	uhcip->uhci_intr_cnt = actual;
553 
554 	if ((ret = ddi_intr_get_pri(uhcip->uhci_htable[0],
555 	    &uhcip->uhci_intr_pri)) != DDI_SUCCESS) {
556 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
557 		    "uhci_add_intrs: ddi_intr_get_pri() failed %d", ret);
558 
559 		for (i = 0; i < actual; i++)
560 			(void) ddi_intr_free(uhcip->uhci_htable[i]);
561 
562 		kmem_free(uhcip->uhci_htable, intr_size);
563 
564 		return (DDI_FAILURE);
565 	}
566 
567 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
568 	    "uhci_add_intrs: Supported Interrupt priority 0x%x",
569 	    uhcip->uhci_intr_pri);
570 
571 	/* Test for high level mutex */
572 	if (uhcip->uhci_intr_pri >= ddi_intr_get_hilevel_pri()) {
573 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
574 		    "uhci_add_intrs: Hi level interrupt not supported");
575 
576 		for (i = 0; i < actual; i++)
577 			(void) ddi_intr_free(uhcip->uhci_htable[i]);
578 
579 		kmem_free(uhcip->uhci_htable, intr_size);
580 
581 		return (DDI_FAILURE);
582 	}
583 
584 	/* Initialize the mutex */
585 	mutex_init(&uhcip->uhci_int_mutex, NULL, MUTEX_DRIVER,
586 	    DDI_INTR_PRI(uhcip->uhci_intr_pri));
587 
588 	/* Call ddi_intr_add_handler() */
589 	for (i = 0; i < actual; i++) {
590 		if ((ret = ddi_intr_add_handler(uhcip->uhci_htable[i],
591 		    uhci_intr, (caddr_t)uhcip,
592 		    (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
593 			USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
594 			    "uhci_add_intrs: ddi_intr_add_handler() "
595 			    "failed %d", ret);
596 
597 			for (i = 0; i < actual; i++)
598 				(void) ddi_intr_free(uhcip->uhci_htable[i]);
599 
600 			mutex_destroy(&uhcip->uhci_int_mutex);
601 			kmem_free(uhcip->uhci_htable, intr_size);
602 
603 			return (DDI_FAILURE);
604 		}
605 	}
606 
607 	if ((ret = ddi_intr_get_cap(uhcip->uhci_htable[0],
608 	    &uhcip->uhci_intr_cap)) != DDI_SUCCESS) {
609 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
610 		    "uhci_add_intrs: ddi_intr_get_cap() failed %d", ret);
611 
612 		for (i = 0; i < actual; i++) {
613 			(void) ddi_intr_remove_handler(uhcip->uhci_htable[i]);
614 			(void) ddi_intr_free(uhcip->uhci_htable[i]);
615 		}
616 
617 		mutex_destroy(&uhcip->uhci_int_mutex);
618 		kmem_free(uhcip->uhci_htable, intr_size);
619 
620 		return (DDI_FAILURE);
621 	}
622 
623 	return (DDI_SUCCESS);
624 }
625 
626 
627 /*
628  * Function Name:	uhci_detach
629  * Description:		Detach entry point - called by the Kernel.
630  *			Deallocates all the memory
631  *			Unregisters the interrupt handle and other resources.
632  * Output:		DDI_SUCCESS / DDI_FAILURE
633  */
634 static int
uhci_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)635 uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
636 {
637 	uhci_state_t	*uhcip = uhci_obtain_state(dip);
638 
639 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
640 	    "uhci_detach:");
641 
642 	switch (cmd) {
643 	case DDI_DETACH:
644 
645 		return (uhci_cleanup(uhcip) == USB_SUCCESS ?
646 		    DDI_SUCCESS : DDI_FAILURE);
647 	case DDI_SUSPEND:
648 
649 		return (uhci_cpr_suspend(uhcip));
650 	default:
651 
652 		return (DDI_FAILURE);
653 	}
654 }
655 
656 
657 /*
658  * uhci_rem_intrs:
659  *
660  * Unregister FIXED or MSI interrupts
661  */
662 static void
uhci_rem_intrs(uhci_state_t * uhcip)663 uhci_rem_intrs(uhci_state_t	*uhcip)
664 {
665 	int	i;
666 
667 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
668 	    "uhci_rem_intrs: interrupt type 0x%x", uhcip->uhci_intr_type);
669 
670 	/* Disable all interrupts */
671 	if (uhcip->uhci_intr_cap & DDI_INTR_FLAG_BLOCK) {
672 		(void) ddi_intr_block_disable(uhcip->uhci_htable,
673 		    uhcip->uhci_intr_cnt);
674 	} else {
675 		for (i = 0; i < uhcip->uhci_intr_cnt; i++) {
676 			(void) ddi_intr_disable(uhcip->uhci_htable[i]);
677 		}
678 	}
679 
680 	/* Call ddi_intr_remove_handler() */
681 	for (i = 0; i < uhcip->uhci_intr_cnt; i++) {
682 		(void) ddi_intr_remove_handler(uhcip->uhci_htable[i]);
683 		(void) ddi_intr_free(uhcip->uhci_htable[i]);
684 	}
685 
686 	kmem_free(uhcip->uhci_htable,
687 	    uhcip->uhci_intr_cnt * sizeof (ddi_intr_handle_t));
688 }
689 
690 
691 /*
692  * Function Name:	uhci_reset
693  * Description:		Reset entry point - called by the Kernel
694  *			on the way down.
695  *			The Toshiba laptop has been observed to	hang
696  *			on reboot when BIOS is set to suspend/resume.
697  *			The resetting uhci on the way down solves the
698  *			problem.
699  * Output:		DDI_SUCCESS / DDI_FAILURE
700  */
701 /* ARGSUSED */
702 static int
uhci_reset(dev_info_t * dip,ddi_reset_cmd_t cmd)703 uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
704 {
705 	uhci_state_t	*uhcip = uhci_obtain_state(dip);
706 
707 	/* Disable all HC ED list processing */
708 	Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
709 	Set_OpReg16(USBCMD, 0);
710 
711 	return (DDI_SUCCESS);
712 }
713 
714 /*
715  * quiesce(9E) entry point.
716  *
717  * This function is called when the system is single-threaded at high
718  * PIL with preemption disabled. Therefore, this function must not be
719  * blocked.
720  *
721  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
722  * DDI_FAILURE indicates an error condition and should almost never happen.
723  */
724 static int
uhci_quiesce(dev_info_t * dip)725 uhci_quiesce(dev_info_t *dip)
726 {
727 	uhci_state_t	*uhcip = uhci_obtain_state(dip);
728 
729 	if (uhcip == NULL)
730 		return (DDI_FAILURE);
731 
732 	/* Disable interrupts */
733 	Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
734 
735 	/* Stop the Host Controller */
736 	Set_OpReg16(USBCMD, 0);
737 
738 	/* Clear all status bits */
739 	Set_OpReg16(USBSTS, Get_OpReg16(USBSTS) & UHCI_INTR_MASK);
740 
741 	return (DDI_SUCCESS);
742 }
743 
744 
745 /*
746  * uhci_info:
747  */
748 /* ARGSUSED */
749 static int
uhci_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)750 uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
751 {
752 	dev_t		dev;
753 	int		instance;
754 	int		error = DDI_FAILURE;
755 	uhci_state_t	*uhcip;
756 
757 	switch (infocmd) {
758 	case DDI_INFO_DEVT2DEVINFO:
759 		dev = (dev_t)arg;
760 		instance = UHCI_UNIT(dev);
761 		uhcip = ddi_get_soft_state(uhci_statep, instance);
762 		if (uhcip != NULL) {
763 			*result = (void *)uhcip->uhci_dip;
764 			if (*result != NULL) {
765 				error = DDI_SUCCESS;
766 			}
767 		} else {
768 			*result = NULL;
769 		}
770 
771 		break;
772 	case DDI_INFO_DEVT2INSTANCE:
773 		dev = (dev_t)arg;
774 		instance = UHCI_UNIT(dev);
775 		*result = (void *)(uintptr_t)instance;
776 		error = DDI_SUCCESS;
777 
778 		break;
779 	default:
780 		break;
781 	}
782 
783 	return (error);
784 }
785 
786 
787 /*
788  * uhci_cleanup:
789  *	Cleanup on attach failure or detach
790  */
791 static int
uhci_cleanup(uhci_state_t * uhcip)792 uhci_cleanup(uhci_state_t *uhcip)
793 {
794 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_cleanup:");
795 
796 	if (usba_hubdi_unbind_root_hub(uhcip->uhci_dip) != USB_SUCCESS) {
797 
798 		return (USB_FAILURE);
799 	}
800 
801 	mutex_enter(&uhcip->uhci_int_mutex);
802 
803 	if (uhcip->uhci_cmd_timeout_id) {
804 		timeout_id_t timeout_id = uhcip->uhci_cmd_timeout_id;
805 		uhcip->uhci_cmd_timeout_id = 0;
806 		mutex_exit(&uhcip->uhci_int_mutex);
807 		(void) untimeout(timeout_id);
808 		mutex_enter(&uhcip->uhci_int_mutex);
809 	}
810 
811 	uhci_uninit_ctlr(uhcip);
812 
813 	mutex_exit(&uhcip->uhci_int_mutex);
814 
815 	/* do interrupt cleanup */
816 	if (uhcip->uhci_htable) {
817 		uhci_rem_intrs(uhcip);
818 	}
819 
820 	mutex_enter(&uhcip->uhci_int_mutex);
821 
822 	usba_hcdi_unregister(uhcip->uhci_dip);
823 
824 	uhci_unmap_regs(uhcip);
825 
826 	uhci_free_pools(uhcip);
827 
828 	mutex_exit(&uhcip->uhci_int_mutex);
829 
830 	mutex_destroy(&uhcip->uhci_int_mutex);
831 	cv_destroy(&uhcip->uhci_cv_SOF);
832 	sema_destroy(&uhcip->uhci_ocsem);
833 
834 	/* cleanup kstat structures */
835 	uhci_destroy_stats(uhcip);
836 
837 	usba_free_hcdi_ops(uhcip->uhci_hcdi_ops);
838 	usb_free_log_hdl(uhcip->uhci_log_hdl);
839 	ddi_prop_remove_all(uhcip->uhci_dip);
840 	ddi_soft_state_free(uhci_statep, uhcip->uhci_instance);
841 
842 	return (USB_SUCCESS);
843 }
844 
845 
846 /*
847  * uhci_cpr_suspend
848  */
849 static int
uhci_cpr_suspend(uhci_state_t * uhcip)850 uhci_cpr_suspend(uhci_state_t	*uhcip)
851 {
852 	uint16_t	cmd_reg;
853 	int		i;
854 
855 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
856 	    "uhci_cpr_suspend:");
857 
858 	/* Call into the root hub and suspend it */
859 	if (usba_hubdi_detach(uhcip->uhci_dip, DDI_SUSPEND) != DDI_SUCCESS) {
860 
861 		return (DDI_FAILURE);
862 	}
863 
864 	mutex_enter(&uhcip->uhci_int_mutex);
865 
866 	/* Stop the Host Controller */
867 	cmd_reg = Get_OpReg16(USBCMD);
868 	cmd_reg &= ~USBCMD_REG_HC_RUN;
869 	Set_OpReg16(USBCMD, cmd_reg);
870 
871 	/*
872 	 * Wait for the duration of an SOF period until the host controller
873 	 * reaches the stopped state, indicated by the HCHalted bit in the
874 	 * USB status register.
875 	 */
876 	for (i = 0; i <= UHCI_TIMEWAIT / 1000; i++) {
877 		if (Get_OpReg16(USBSTS) & USBSTS_REG_HC_HALTED)
878 			break;
879 		drv_usecwait(1000);
880 	}
881 
882 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
883 	    "uhci_cpr_suspend: waited %d milliseconds for hc to halt", i);
884 
885 	/* Disable interrupts */
886 	Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
887 
888 	/* Clear any scheduled pending interrupts */
889 	Set_OpReg16(USBSTS, USBSTS_REG_HC_HALTED |
890 	    USBSTS_REG_HC_PROCESS_ERR | USBSTS_REG_HOST_SYS_ERR |
891 	    USBSTS_REG_RESUME_DETECT | USBSTS_REG_USB_ERR_INTR |
892 	    USBSTS_REG_USB_INTR);
893 
894 	/* Set Global Suspend bit */
895 	Set_OpReg16(USBCMD, USBCMD_REG_ENTER_GBL_SUSPEND);
896 
897 	/* Set host controller soft state to suspend */
898 	uhcip->uhci_hc_soft_state = UHCI_CTLR_SUSPEND_STATE;
899 
900 	mutex_exit(&uhcip->uhci_int_mutex);
901 
902 	return (USB_SUCCESS);
903 }
904 
905 
906 /*
907  * uhci_cpr_cleanup:
908  *
909  * Cleanup uhci specific information across resuming.
910  */
911 static void
uhci_cpr_cleanup(uhci_state_t * uhcip)912 uhci_cpr_cleanup(uhci_state_t	*uhcip)
913 {
914 	ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
915 
916 	/* Reset software part of usb frame number */
917 	uhcip->uhci_sw_frnum = 0;
918 }
919 
920 
921 /*
922  * uhci_cpr_resume
923  */
924 static int
uhci_cpr_resume(uhci_state_t * uhcip)925 uhci_cpr_resume(uhci_state_t	*uhcip)
926 {
927 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
928 	    "uhci_cpr_resume: Restart the controller");
929 
930 	mutex_enter(&uhcip->uhci_int_mutex);
931 
932 	/* Cleanup uhci specific information across cpr */
933 	uhci_cpr_cleanup(uhcip);
934 
935 	mutex_exit(&uhcip->uhci_int_mutex);
936 
937 	/* Restart the controller */
938 	if (uhci_init_ctlr(uhcip) != DDI_SUCCESS) {
939 
940 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
941 		    "uhci_cpr_resume: uhci host controller resume failed ");
942 
943 		return (DDI_FAILURE);
944 	}
945 
946 	mutex_enter(&uhcip->uhci_int_mutex);
947 
948 	/*
949 	 * Set HcInterruptEnable to enable all interrupts except Root
950 	 * Hub Status change and SOF interrupts.
951 	 */
952 	Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
953 
954 	mutex_exit(&uhcip->uhci_int_mutex);
955 
956 	/* Now resume the root hub */
957 	if (usba_hubdi_attach(uhcip->uhci_dip, DDI_RESUME) != DDI_SUCCESS) {
958 
959 		return (DDI_FAILURE);
960 	}
961 
962 	return (DDI_SUCCESS);
963 }
964 
965 
966 /*
967  * uhci_intr:
968  *	uhci interrupt handling routine.
969  */
970 static uint_t
uhci_intr(caddr_t arg1,caddr_t arg2)971 uhci_intr(caddr_t arg1, caddr_t arg2)
972 {
973 	ushort_t	intr_status, cmd_reg, intr_reg;
974 	uhci_state_t	*uhcip = (uhci_state_t *)arg1;
975 
976 	USB_DPRINTF_L4(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
977 	    "uhci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p",
978 	    (void *)arg1, (void *)arg2);
979 
980 	mutex_enter(&uhcip->uhci_int_mutex);
981 
982 	/* Any interrupt is not handled for the suspended device. */
983 	if (uhcip->uhci_hc_soft_state == UHCI_CTLR_SUSPEND_STATE) {
984 		mutex_exit(&uhcip->uhci_int_mutex);
985 
986 		return (DDI_INTR_UNCLAIMED);
987 	}
988 
989 	/* Get the status of the interrupts */
990 	intr_status = Get_OpReg16(USBSTS);
991 	intr_reg = Get_OpReg16(USBINTR);
992 
993 	USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
994 	    "uhci_intr: intr_status = %x, intr_reg = %x",
995 	    intr_status, intr_reg);
996 
997 	/*
998 	 * If uhci interrupts are all disabled, the driver should return
999 	 * unclaimed.
1000 	 * HC Process Error and Host System Error interrupts cannot be
1001 	 * disabled by intr register, and need to be judged separately.
1002 	 */
1003 	if (((intr_reg & ENABLE_ALL_INTRS) == 0) &&
1004 	    ((intr_status & USBSTS_REG_HC_PROCESS_ERR) == 0) &&
1005 	    ((intr_status & USBSTS_REG_HOST_SYS_ERR) == 0)) {
1006 
1007 		USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1008 		    "uhci_intr: interrupts disabled, unclaim");
1009 		mutex_exit(&uhcip->uhci_int_mutex);
1010 
1011 		return (DDI_INTR_UNCLAIMED);
1012 	}
1013 
1014 	/*
1015 	 * If the intr is not from our controller, just return unclaimed.
1016 	 * HCHalted status bit cannot generate interrupts and should be
1017 	 * ignored.
1018 	 */
1019 	if (!(intr_status & UHCI_INTR_MASK)) {
1020 
1021 		USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1022 		    "uhci_intr: no interrupt status set, unclaim");
1023 		mutex_exit(&uhcip->uhci_int_mutex);
1024 
1025 		return (DDI_INTR_UNCLAIMED);
1026 	}
1027 
1028 	/* Update kstat values */
1029 	uhci_do_intrs_stats(uhcip, intr_status);
1030 
1031 	/* Acknowledge the interrupt */
1032 	Set_OpReg16(USBSTS, intr_status);
1033 
1034 	/*
1035 	 * If uhci controller has not been initialized, just clear the
1036 	 * interrupter status and return claimed.
1037 	 */
1038 	if (uhcip->uhci_hc_soft_state != UHCI_CTLR_OPERATIONAL_STATE) {
1039 
1040 		USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1041 		    "uhci_intr: uhci controller is not in the operational "
1042 		    "state");
1043 		mutex_exit(&uhcip->uhci_int_mutex);
1044 
1045 		return (DDI_INTR_CLAIMED);
1046 	}
1047 
1048 	/*
1049 	 * We configured the hw incorrectly, disable future interrupts.
1050 	 */
1051 	if ((intr_status & USBSTS_REG_HOST_SYS_ERR)) {
1052 		USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1053 		    "uhci_intr: Sys Err Disabling Interrupt");
1054 		Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
1055 		uhcip->uhci_hc_soft_state = UHCI_CTLR_ERROR_STATE;
1056 
1057 		mutex_exit(&uhcip->uhci_int_mutex);
1058 
1059 		return (DDI_INTR_CLAIMED);
1060 	}
1061 
1062 	/*
1063 	 * Check whether a frame number overflow occurred.
1064 	 * if so, update the sw frame number.
1065 	 */
1066 	uhci_isoc_update_sw_frame_number(uhcip);
1067 
1068 	/*
1069 	 * Check whether any commands got completed. If so, process them.
1070 	 */
1071 	uhci_process_submitted_td_queue(uhcip);
1072 
1073 	/*
1074 	 * This should not occur. It occurs only if a HC controller
1075 	 * experiences internal problem.
1076 	 */
1077 	if (intr_status & USBSTS_REG_HC_HALTED) {
1078 		USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1079 		    "uhci_intr: Controller halted");
1080 		cmd_reg = Get_OpReg16(USBCMD);
1081 		Set_OpReg16(USBCMD, (cmd_reg | USBCMD_REG_HC_RUN));
1082 	}
1083 
1084 	/*
1085 	 * Wake up all the threads which are waiting for the Start of Frame
1086 	 */
1087 	if (uhcip->uhci_cv_signal == B_TRUE) {
1088 		cv_broadcast(&uhcip->uhci_cv_SOF);
1089 		uhcip->uhci_cv_signal = B_FALSE;
1090 	}
1091 
1092 	mutex_exit(&uhcip->uhci_int_mutex);
1093 
1094 	return (DDI_INTR_CLAIMED);
1095 }
1096 
1097 
1098 /*
1099  * uhci_process_submitted_td_queue:
1100  *    Traverse thru the submitted queue and process the completed ones.
1101  */
1102 void
uhci_process_submitted_td_queue(uhci_state_t * uhcip)1103 uhci_process_submitted_td_queue(uhci_state_t *uhcip)
1104 {
1105 	uhci_td_t		*head = uhcip->uhci_outst_tds_head;
1106 	uhci_trans_wrapper_t	*tw;
1107 
1108 	while (head != NULL) {
1109 		if ((!(GetTD_status(uhcip, head) & UHCI_TD_ACTIVE)) &&
1110 		    (head->tw->tw_claim == UHCI_NOT_CLAIMED)) {
1111 			tw = head->tw;
1112 
1113 			/*
1114 			 * Call the corresponding handle_td routine
1115 			 */
1116 			(*tw->tw_handle_td)(uhcip, head);
1117 
1118 			/* restart at the beginning again */
1119 			head = uhcip->uhci_outst_tds_head;
1120 		} else {
1121 			head = head->outst_td_next;
1122 		}
1123 	}
1124 }
1125 
1126 
1127 /*
1128  * uhci_handle_intr_td:
1129  *     handles the completed interrupt transfer TD's.
1130  */
1131 void
uhci_handle_intr_td(uhci_state_t * uhcip,uhci_td_t * td)1132 uhci_handle_intr_td(uhci_state_t *uhcip, uhci_td_t *td)
1133 {
1134 	usb_req_attrs_t		attrs;
1135 	uint_t			bytes_xfered;
1136 	usb_cr_t		usb_err;
1137 	uhci_trans_wrapper_t	*tw = td->tw;
1138 	uhci_pipe_private_t	*pp = tw->tw_pipe_private;
1139 	usb_intr_req_t		*intr_reqp =
1140 	    (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1141 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
1142 
1143 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1144 	    "uhci_handle_intr_td: intr_reqp = 0x%p", (void *)intr_reqp);
1145 
1146 	ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1147 
1148 	/* set tw->tw_claim flag, so that nobody else works on this td. */
1149 	tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
1150 
1151 	/* Interrupt OUT */
1152 	if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) {
1153 
1154 		/* process errors first */
1155 		usb_err = uhci_parse_td_error(uhcip, pp, td);
1156 
1157 		/* get the actual xfered data size */
1158 		bytes_xfered = GetTD_alen(uhcip, td);
1159 
1160 		/* check data underrun error */
1161 		if ((usb_err == USB_CR_OK) && (bytes_xfered !=
1162 		    GetTD_mlen(uhcip, td))) {
1163 
1164 			USB_DPRINTF_L2(PRINT_MASK_LISTS,
1165 			    uhcip->uhci_log_hdl, "uhci_handle_intr_td:"
1166 			    " Intr out pipe, data underrun occurred");
1167 
1168 			usb_err = USB_CR_DATA_UNDERRUN;
1169 
1170 		}
1171 
1172 		bytes_xfered = (bytes_xfered == ZERO_LENGTH) ?
1173 		    0 : bytes_xfered+1;
1174 		tw->tw_bytes_xfered += bytes_xfered;
1175 		uhci_do_byte_stats(uhcip, tw->tw_bytes_xfered,
1176 		    ph->p_ep.bmAttributes, ph->p_ep.bEndpointAddress);
1177 
1178 
1179 		/*
1180 		 * If error occurred or all data xfered, delete the current td,
1181 		 * free tw, do the callback. Otherwise wait for the next td.
1182 		 */
1183 		if (usb_err != USB_CR_OK) {
1184 
1185 			USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1186 			    "uhci_handle_intr_td: Intr out pipe error");
1187 
1188 			/* update the element pointer */
1189 			SetQH32(uhcip, pp->pp_qh->element_ptr, GetTD32(
1190 			    uhcip, tw->tw_hctd_tail->link_ptr));
1191 
1192 
1193 		} else if (tw->tw_bytes_xfered == tw->tw_length) {
1194 
1195 			/* all data xfered */
1196 			USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1197 			    "uhci_handle_intr_td: Intr out pipe,"
1198 			    " all data xfered");
1199 
1200 		} else {
1201 
1202 			/* remove the current td and wait for the next one. */
1203 			uhci_delete_td(uhcip, td);
1204 			tw->tw_claim = UHCI_NOT_CLAIMED;
1205 
1206 			return;
1207 		}
1208 
1209 		uhci_delete_td(uhcip, td);
1210 		uhci_hcdi_callback(uhcip, pp, ph, tw, usb_err);
1211 		uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw);
1212 
1213 		return;
1214 	}
1215 
1216 	/* Interrupt IN */
1217 
1218 	/* Get the actual received data size */
1219 	tw->tw_bytes_xfered = GetTD_alen(uhcip, td);
1220 	if (tw->tw_bytes_xfered == ZERO_LENGTH) {
1221 		tw->tw_bytes_xfered = 0;
1222 	} else {
1223 		tw->tw_bytes_xfered++;
1224 	}
1225 
1226 	/* process errors first */
1227 	if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
1228 		SetQH32(uhcip, pp->pp_qh->element_ptr,
1229 		    GetTD32(uhcip, td->link_ptr));
1230 
1231 		uhci_handle_intr_td_errors(uhcip, td, tw, pp);
1232 
1233 		return;
1234 	}
1235 
1236 	/*
1237 	 * Check for data underruns.
1238 	 * For data underrun case, the host controller does not update
1239 	 * element pointer. So, we update here.
1240 	 */
1241 	if (GetTD_alen(uhcip, td) != GetTD_mlen(uhcip, td)) {
1242 		SetQH32(uhcip, pp->pp_qh->element_ptr,
1243 		    GetTD32(uhcip, td->link_ptr));
1244 	}
1245 
1246 	/*
1247 	 * Call uhci_sendup_td_message to send message upstream.
1248 	 * The function uhci_sendup_td_message returns USB_NO_RESOURCES
1249 	 * if allocb fails and also sends error message to upstream by
1250 	 * calling USBA callback function. Under error conditions just
1251 	 * drop the current message.
1252 	 */
1253 
1254 	/* Get the interrupt xfer attributes */
1255 	attrs = intr_reqp->intr_attributes;
1256 
1257 	/*
1258 	 * Check usb flag whether USB_FLAGS_ONE_XFER flag is set
1259 	 * and if so, free duplicate request.
1260 	 */
1261 	if (attrs & USB_ATTRS_ONE_XFER) {
1262 		uhci_handle_one_xfer_completion(uhcip, USB_CR_OK, td);
1263 
1264 		return;
1265 	}
1266 
1267 	/* save it temporarily */
1268 	if (tw->tw_bytes_xfered != 0) {
1269 		uhci_sendup_td_message(uhcip, USB_CR_OK, tw);
1270 	}
1271 
1272 	/* Clear the tw->tw_claim flag */
1273 	tw->tw_claim = UHCI_NOT_CLAIMED;
1274 
1275 	uhci_delete_td(uhcip, td);
1276 
1277 	/* allocate another interrupt periodic resource */
1278 	if (pp->pp_state == UHCI_PIPE_STATE_ACTIVE) {
1279 		if (uhci_allocate_periodic_in_resource(uhcip, pp, tw, 0) !=
1280 		    USB_SUCCESS) {
1281 			USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1282 			    "uhci_insert_intr_req: Interrupt request structure"
1283 			    "allocation failed");
1284 
1285 			uhci_hcdi_callback(uhcip, pp, ph,
1286 			    tw, USB_CR_NO_RESOURCES);
1287 
1288 			return;
1289 		}
1290 
1291 		/* Insert another interrupt TD */
1292 		if (uhci_insert_hc_td(uhcip, 0,
1293 		    tw->tw_length, pp, tw, PID_IN, attrs) != USB_SUCCESS) {
1294 
1295 			uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
1296 
1297 			USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1298 			    "uhci_handle_intr_td: TD exhausted");
1299 
1300 			uhci_hcdi_callback(uhcip, pp, ph,
1301 			    tw, USB_CR_NO_RESOURCES);
1302 		}
1303 	}
1304 }
1305 
1306 
1307 /*
1308  * uhci_sendup_td_message:
1309  *
1310  * Get a message block and send the received message upstream.
1311  */
1312 void
uhci_sendup_td_message(uhci_state_t * uhcip,usb_cr_t usb_err,uhci_trans_wrapper_t * tw)1313 uhci_sendup_td_message(
1314 	uhci_state_t		*uhcip,
1315 	usb_cr_t		usb_err,
1316 	uhci_trans_wrapper_t	*tw)
1317 {
1318 	mblk_t			*mp = NULL;
1319 	size_t			length = 0;
1320 	size_t			skip_len = 0;
1321 	uchar_t			*buf;
1322 	usb_opaque_t		curr_xfer_reqp = tw->tw_curr_xfer_reqp;
1323 	uhci_pipe_private_t	*pp = tw->tw_pipe_private;
1324 	usb_ep_descr_t		*ept = &pp->pp_pipe_handle->p_ep;
1325 
1326 	ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1327 
1328 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1329 	    "uhci_sendup_td_message: bytes transferred=0x%x, "
1330 	    "bytes pending=0x%x",
1331 	    tw->tw_bytes_xfered, tw->tw_bytes_pending);
1332 
1333 	length = tw->tw_bytes_xfered;
1334 
1335 	switch (UHCI_XFER_TYPE(ept)) {
1336 	case USB_EP_ATTR_CONTROL:
1337 		skip_len = UHCI_CTRL_EPT_MAX_SIZE; /* length to skip */
1338 		mp = ((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_data;
1339 		break;
1340 	case USB_EP_ATTR_INTR:
1341 		mp = ((usb_intr_req_t *)curr_xfer_reqp)->intr_data;
1342 		break;
1343 	case USB_EP_ATTR_BULK:
1344 		mp = ((usb_bulk_req_t *)curr_xfer_reqp)->bulk_data;
1345 		break;
1346 	case USB_EP_ATTR_ISOCH:
1347 		length = tw->tw_length;
1348 		mp = ((usb_isoc_req_t *)curr_xfer_reqp)->isoc_data;
1349 		break;
1350 	default:
1351 		break;
1352 	}
1353 
1354 	/* Copy the data into the mblk_t */
1355 	buf = (uchar_t *)tw->tw_buf + skip_len;
1356 
1357 	ASSERT(mp != NULL);
1358 
1359 	/*
1360 	 * Update kstat byte counts
1361 	 * The control endpoints don't have direction bits so in
1362 	 * order for control stats to be counted correctly an IN
1363 	 * bit must be faked on a control read.
1364 	 */
1365 	uhci_do_byte_stats(uhcip, length, ept->bmAttributes,
1366 	    (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_CONTROL) ?
1367 	    USB_EP_DIR_IN : ept->bEndpointAddress);
1368 
1369 	if (length) {
1370 		int rval, i;
1371 		uchar_t *p = mp->b_rptr;
1372 
1373 		if (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_ISOCH) {
1374 			/* Deal with isoc data by packets */
1375 			for (i = 0; i < tw->tw_ncookies; i++) {
1376 				rval = ddi_dma_sync(
1377 				    tw->tw_isoc_bufs[i].dma_handle, 0,
1378 				    tw->tw_isoc_bufs[i].length,
1379 				    DDI_DMA_SYNC_FORCPU);
1380 				ASSERT(rval == DDI_SUCCESS);
1381 
1382 				ddi_rep_get8(tw->tw_isoc_bufs[i].mem_handle,
1383 				    p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
1384 				    tw->tw_isoc_bufs[i].length,
1385 				    DDI_DEV_AUTOINCR);
1386 				p += tw->tw_isoc_bufs[i].length;
1387 			}
1388 		} else {
1389 			/* Sync the streaming buffer */
1390 			rval = ddi_dma_sync(tw->tw_dmahandle, 0,
1391 			    (skip_len + length), DDI_DMA_SYNC_FORCPU);
1392 			ASSERT(rval == DDI_SUCCESS);
1393 
1394 			/* Copy the data into the message */
1395 			ddi_rep_get8(tw->tw_accesshandle,
1396 			    mp->b_rptr, buf, length, DDI_DEV_AUTOINCR);
1397 		}
1398 
1399 		/* Increment the write pointer */
1400 		mp->b_wptr += length;
1401 	} else {
1402 		USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1403 		    "uhci_sendup_td_message: Zero length packet");
1404 	}
1405 
1406 	/* Do the callback */
1407 	uhci_hcdi_callback(uhcip, pp, pp->pp_pipe_handle, tw, usb_err);
1408 }
1409 
1410 
1411 /*
1412  * uhci_handle_ctrl_td:
1413  *	Handle a control Transfer Descriptor (TD).
1414  */
1415 void
uhci_handle_ctrl_td(uhci_state_t * uhcip,uhci_td_t * td)1416 uhci_handle_ctrl_td(uhci_state_t *uhcip, uhci_td_t *td)
1417 {
1418 	ushort_t		direction;
1419 	ushort_t		bytes_for_xfer;
1420 	ushort_t		bytes_xfered;
1421 	ushort_t		MaxPacketSize;
1422 	usb_cr_t		error;
1423 	uhci_trans_wrapper_t	*tw = td->tw;
1424 	uhci_pipe_private_t	*pp = tw->tw_pipe_private;
1425 	usba_pipe_handle_data_t	*usb_pp = pp->pp_pipe_handle;
1426 	usb_ep_descr_t		*eptd = &usb_pp->p_ep;
1427 	usb_ctrl_req_t		*reqp = (usb_ctrl_req_t *)tw->tw_curr_xfer_reqp;
1428 
1429 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1430 	    "uhci_handle_ctrl_td: pp = 0x%p tw = 0x%p td = 0x%p "
1431 	    "state = 0x%x len = 0x%lx", (void *)pp, (void *)tw,
1432 	    (void *)td, tw->tw_ctrl_state, tw->tw_length);
1433 
1434 	ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1435 
1436 	error = uhci_parse_td_error(uhcip, pp, td);
1437 
1438 	/*
1439 	 * In case of control transfers, the device can send NAK when it
1440 	 * is busy. If a NAK is received, then send the status TD again.
1441 	 */
1442 	if (error != USB_CR_OK) {
1443 		USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1444 		    "uhci_handle_ctrl_td: Ctrl cmd failed, error = %x", error);
1445 
1446 		SetQH32(uhcip, pp->pp_qh->element_ptr,
1447 		    GetTD32(uhcip, td->link_ptr));
1448 		uhci_delete_td(uhcip, td);
1449 
1450 		/* Return number of bytes xfered */
1451 		if (GetTD_alen(uhcip, td) != ZERO_LENGTH) {
1452 			tw->tw_bytes_xfered = GetTD_alen(uhcip, td) + 1;
1453 		}
1454 
1455 		USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1456 		    "uhci_handle_ctrl_td: Bytes transferred = %x",
1457 		    tw->tw_bytes_xfered);
1458 
1459 		if ((tw->tw_ctrl_state == DATA) &&
1460 		    (tw->tw_direction == PID_IN)) {
1461 			uhci_sendup_td_message(uhcip, error, tw);
1462 		} else {
1463 			uhci_hcdi_callback(uhcip, pp, usb_pp, tw, error);
1464 
1465 			uhci_deallocate_tw(uhcip, pp, tw);
1466 		}
1467 
1468 		return;
1469 	}
1470 
1471 	/*
1472 	 * A control transfer consists of three phases:
1473 	 *	- Setup
1474 	 *	- Data (optional)
1475 	 *	- Status
1476 	 *
1477 	 * There is a TD per phase. A TD for a given phase isn't
1478 	 * enqueued until the previous phase is finished.
1479 	 */
1480 	switch (tw->tw_ctrl_state) {
1481 	case SETUP:
1482 		/*
1483 		 * Enqueue either the data or the status
1484 		 * phase depending on the length.
1485 		 */
1486 		pp->pp_data_toggle = 1;
1487 		uhci_delete_td(uhcip, td);
1488 
1489 		/*
1490 		 * If the length is 0, move to the status.
1491 		 * If length is not 0, then we have some data
1492 		 * to move on the bus to device either IN or OUT.
1493 		 */
1494 		if ((tw->tw_length - SETUP_SIZE) == 0) {
1495 			/*
1496 			 * There is no data stage,  then
1497 			 * initiate status phase from the host.
1498 			 */
1499 			if ((uhci_insert_hc_td(uhcip, 0, 0, pp, tw, PID_IN,
1500 			    reqp->ctrl_attributes)) != USB_SUCCESS) {
1501 				USB_DPRINTF_L2(PRINT_MASK_LISTS,
1502 				    uhcip->uhci_log_hdl,
1503 				    "uhci_handle_ctrl_td: No resources");
1504 
1505 				uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1506 				    USB_CR_NO_RESOURCES);
1507 
1508 				return;
1509 			}
1510 
1511 			tw->tw_ctrl_state = STATUS;
1512 		} else {
1513 			uint_t xx;
1514 
1515 			/*
1516 			 * Each USB device can send/receive 8/16/32/64
1517 			 * depending on wMaxPacketSize's implementation.
1518 			 * We need to insert 'N = Number of byte/
1519 			 * MaxpktSize" TD's in the lattice to send/
1520 			 * receive the data. Though the USB protocol
1521 			 * allows to insert more than one TD in the same
1522 			 * frame, we are inserting only one TD in one
1523 			 * frame. This is bcos OHCI has seen some problem
1524 			 * when multiple TD's are inserted at the same time.
1525 			 */
1526 			tw->tw_length -= UHCI_CTRL_EPT_MAX_SIZE;
1527 			MaxPacketSize = eptd->wMaxPacketSize;
1528 
1529 			/*
1530 			 * We dont know the maximum packet size that
1531 			 * the device can handle(MaxPAcketSize=0).
1532 			 * In that case insert a data phase with
1533 			 * eight bytes or less.
1534 			 */
1535 			if (MaxPacketSize == 0) {
1536 				xx = (tw->tw_length > 8) ? 8 : tw->tw_length;
1537 			} else {
1538 				xx = (tw->tw_length > MaxPacketSize) ?
1539 				    MaxPacketSize : tw->tw_length;
1540 			}
1541 
1542 			tw->tw_tmp = xx;
1543 
1544 			/*
1545 			 * Create the TD.  If this is an OUT
1546 			 * transaction,  the data is already
1547 			 * in the buffer of the TW.
1548 			 * Get first 8 bytes of the command only.
1549 			 */
1550 			if ((uhci_insert_hc_td(uhcip,
1551 			    UHCI_CTRL_EPT_MAX_SIZE, xx,
1552 			    pp, tw, tw->tw_direction,
1553 			    reqp->ctrl_attributes)) != USB_SUCCESS) {
1554 
1555 				USB_DPRINTF_L2(PRINT_MASK_LISTS,
1556 				    uhcip->uhci_log_hdl,
1557 				    "uhci_handle_ctrl_td: No resources");
1558 
1559 				uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1560 				    USB_CR_NO_RESOURCES);
1561 
1562 				return;
1563 			}
1564 
1565 			tw->tw_ctrl_state = DATA;
1566 		}
1567 
1568 		USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1569 		    "Setup complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
1570 
1571 		break;
1572 	case DATA:
1573 		uhci_delete_td(uhcip, td);
1574 
1575 		MaxPacketSize = eptd->wMaxPacketSize;
1576 
1577 		/*
1578 		 * Decrement pending bytes and increment the total
1579 		 * number bytes transferred by the actual number of bytes
1580 		 * transferred in this TD. If the number of bytes transferred
1581 		 * is less than requested, that means an underrun has
1582 		 * occurred. Set the tw_tmp varible to indicate UNDER run.
1583 		 */
1584 		bytes_xfered = GetTD_alen(uhcip, td);
1585 		if (bytes_xfered == ZERO_LENGTH) {
1586 			bytes_xfered = 0;
1587 		} else {
1588 			bytes_xfered++;
1589 		}
1590 
1591 		tw->tw_bytes_pending -= bytes_xfered;
1592 		tw->tw_bytes_xfered += bytes_xfered;
1593 
1594 		if (bytes_xfered < tw->tw_tmp) {
1595 			tw->tw_bytes_pending = 0;
1596 			tw->tw_tmp = UHCI_UNDERRUN_OCCURRED;
1597 
1598 			/*
1599 			 * Controller does not update the queue head
1600 			 * element pointer when a data underrun occurs.
1601 			 */
1602 			SetQH32(uhcip, pp->pp_qh->element_ptr,
1603 			    GetTD32(uhcip, td->link_ptr));
1604 		}
1605 
1606 		if (bytes_xfered > tw->tw_tmp) {
1607 			tw->tw_bytes_pending = 0;
1608 			tw->tw_tmp = UHCI_OVERRUN_OCCURRED;
1609 		}
1610 
1611 		/*
1612 		 * If no more bytes are pending, insert status
1613 		 * phase. Otherwise insert data phase.
1614 		 */
1615 		if (tw->tw_bytes_pending) {
1616 			bytes_for_xfer = (tw->tw_bytes_pending >
1617 			    MaxPacketSize) ? MaxPacketSize :
1618 			    tw->tw_bytes_pending;
1619 
1620 			tw->tw_tmp = bytes_for_xfer;
1621 
1622 			if ((uhci_insert_hc_td(uhcip,
1623 			    UHCI_CTRL_EPT_MAX_SIZE + tw->tw_bytes_xfered,
1624 			    bytes_for_xfer, pp, tw,
1625 			    tw->tw_direction,
1626 			    reqp->ctrl_attributes)) != USB_SUCCESS) {
1627 				USB_DPRINTF_L2(PRINT_MASK_LISTS,
1628 				    uhcip->uhci_log_hdl,
1629 				    "uhci_handle_ctrl_td: No TD");
1630 
1631 				uhci_hcdi_callback(uhcip, pp, usb_pp,
1632 				    tw, USB_NO_RESOURCES);
1633 
1634 				return;
1635 			}
1636 
1637 			tw->tw_ctrl_state = DATA;
1638 
1639 			break;
1640 		}
1641 
1642 		pp->pp_data_toggle = 1;
1643 		direction = (tw->tw_direction == PID_IN) ? PID_OUT : PID_IN;
1644 
1645 		if ((uhci_insert_hc_td(uhcip, 0, 0, pp, tw, direction,
1646 		    reqp->ctrl_attributes)) != USB_SUCCESS) {
1647 			USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1648 			    "uhci_handle_ctrl_td: TD exhausted");
1649 
1650 			uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1651 			    USB_NO_RESOURCES);
1652 
1653 			return;
1654 		}
1655 
1656 		tw->tw_ctrl_state = STATUS;
1657 		USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1658 		    "Data complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
1659 
1660 		break;
1661 	case STATUS:
1662 		/*
1663 		 * Send the data to the client if it is a DATA IN,
1664 		 * else send just return status for DATA OUT commnads.
1665 		 * And set the tw_claim flag.
1666 		 */
1667 		tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
1668 
1669 		if ((tw->tw_length != 0) && (tw->tw_direction == PID_IN)) {
1670 			usb_req_attrs_t	attrs = ((usb_ctrl_req_t *)
1671 			    tw->tw_curr_xfer_reqp)->ctrl_attributes;
1672 			/*
1673 			 * Call uhci_sendup_td_message to send message
1674 			 * upstream. The function uhci_sendup_td_message
1675 			 * returns USB_NO_RESOURCES if allocb fails and
1676 			 * also sends error message to upstream by calling
1677 			 * USBA callback function.
1678 			 *
1679 			 * Under error conditions just drop the current msg.
1680 			 */
1681 			if ((tw->tw_tmp == UHCI_UNDERRUN_OCCURRED) &&
1682 			    (!(attrs & USB_ATTRS_SHORT_XFER_OK))) {
1683 				error = USB_CR_DATA_UNDERRUN;
1684 			} else if (tw->tw_tmp == UHCI_OVERRUN_OCCURRED) {
1685 				error = USB_CR_DATA_OVERRUN;
1686 			}
1687 			uhci_sendup_td_message(uhcip, error, tw);
1688 
1689 		} else {
1690 			uhci_do_byte_stats(uhcip, tw->tw_length,
1691 			    eptd->bmAttributes, eptd->bEndpointAddress);
1692 
1693 			uhci_hcdi_callback(uhcip, pp, usb_pp, tw, USB_CR_OK);
1694 		}
1695 
1696 		USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1697 		    "Status complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
1698 
1699 		uhci_delete_td(uhcip, td);
1700 		uhci_deallocate_tw(uhcip, pp, tw);
1701 
1702 		break;
1703 	default:
1704 		USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1705 		    "uhci_handle_ctrl_td: Bad control state");
1706 
1707 		uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1708 		    USB_CR_UNSPECIFIED_ERR);
1709 	}
1710 }
1711 
1712 
1713 /*
1714  * uhci_handle_intr_td_errors:
1715  *	Handles the errors encountered for the interrupt transfers.
1716  */
1717 static void
uhci_handle_intr_td_errors(uhci_state_t * uhcip,uhci_td_t * td,uhci_trans_wrapper_t * tw,uhci_pipe_private_t * pp)1718 uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td,
1719     uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp)
1720 {
1721 	usb_cr_t		usb_err;
1722 	usb_intr_req_t		*intr_reqp =
1723 	    (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1724 
1725 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1726 	    "uhci_handle_intr_td_errors: td = 0x%p tw = 0x%p",
1727 	    (void *)td, (void *)tw);
1728 
1729 	usb_err = uhci_parse_td_error(uhcip, pp, td);
1730 
1731 	if (intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) {
1732 		uhci_handle_one_xfer_completion(uhcip, usb_err, td);
1733 
1734 		return;
1735 	}
1736 
1737 	uhci_delete_td(uhcip, td);
1738 	uhci_sendup_td_message(uhcip, usb_err, tw);
1739 	uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw);
1740 }
1741 
1742 
1743 /*
1744  * uhci_handle_one_xfer_completion:
1745  */
1746 static void
uhci_handle_one_xfer_completion(uhci_state_t * uhcip,usb_cr_t usb_err,uhci_td_t * td)1747 uhci_handle_one_xfer_completion(
1748 	uhci_state_t		*uhcip,
1749 	usb_cr_t		usb_err,
1750 	uhci_td_t		*td)
1751 {
1752 	uhci_trans_wrapper_t	*tw = td->tw;
1753 	uhci_pipe_private_t	*pp = tw->tw_pipe_private;
1754 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
1755 	usb_intr_req_t		*intr_reqp =
1756 	    (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1757 
1758 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1759 	    "uhci_handle_one_xfer_completion: td = 0x%p", (void *)td);
1760 
1761 	ASSERT(intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER);
1762 
1763 	/* set state to idle */
1764 	pp->pp_state = UHCI_PIPE_STATE_IDLE;
1765 
1766 	((usb_intr_req_t *)(pp->pp_client_periodic_in_reqp))->
1767 	    intr_data = ((usb_intr_req_t *)(tw->tw_curr_xfer_reqp))->intr_data;
1768 
1769 	((usb_intr_req_t *)tw->tw_curr_xfer_reqp)->intr_data = NULL;
1770 
1771 	/* now free duplicate current request */
1772 	usb_free_intr_req((usb_intr_req_t *)tw->tw_curr_xfer_reqp);
1773 	mutex_enter(&ph->p_mutex);
1774 	ph->p_req_count--;
1775 	mutex_exit(&ph->p_mutex);
1776 
1777 	/* make client's request the current request */
1778 	tw->tw_curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
1779 	pp->pp_client_periodic_in_reqp = NULL;
1780 
1781 	uhci_sendup_td_message(uhcip, usb_err, tw);
1782 	/* Clear the tw->tw_claim flag */
1783 	tw->tw_claim = UHCI_NOT_CLAIMED;
1784 
1785 	uhci_delete_td(uhcip, td);
1786 	uhci_deallocate_tw(uhcip, pp, tw);
1787 }
1788 
1789 
1790 /*
1791  * uhci_parse_td_error
1792  *	Parses the Transfer Descriptors error
1793  */
1794 usb_cr_t
uhci_parse_td_error(uhci_state_t * uhcip,uhci_pipe_private_t * pp,uhci_td_t * td)1795 uhci_parse_td_error(uhci_state_t *uhcip, uhci_pipe_private_t *pp, uhci_td_t *td)
1796 {
1797 	uint_t	status;
1798 
1799 	status = GetTD_status(uhcip, td) & TD_STATUS_MASK;
1800 
1801 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1802 	    "uhci_parse_td_error: status_bits=0x%x", status);
1803 
1804 	if (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep) == USB_EP_ATTR_ISOCH) {
1805 
1806 		return (USB_CR_OK);
1807 	}
1808 
1809 	if (!status) {
1810 
1811 		return (USB_CR_OK);
1812 	}
1813 
1814 	USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1815 	    "uhci_parse_td_error: status_bits=0x%x", status);
1816 
1817 
1818 	if (status & UHCI_TD_BITSTUFF_ERR) {
1819 
1820 		return (USB_CR_BITSTUFFING);
1821 	}
1822 
1823 	if (status & UHCI_TD_CRC_TIMEOUT) {
1824 		pp->pp_data_toggle = GetTD_dtogg(uhcip, td);
1825 
1826 		USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1827 		    "uhci_parse_td_error: timeout & data toggle reset; "
1828 		    "data toggle: %x", pp->pp_data_toggle);
1829 
1830 		return ((GetTD_PID(uhcip, td) == PID_IN) ? USB_CR_DEV_NOT_RESP :
1831 		    USB_CR_TIMEOUT);
1832 	}
1833 
1834 	if (status & UHCI_TD_BABBLE_ERR) {
1835 		USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1836 		    "babble error");
1837 
1838 		return (USB_CR_UNSPECIFIED_ERR);
1839 	}
1840 
1841 	if (status & UHCI_TD_DATA_BUFFER_ERR) {
1842 		USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1843 		    "buffer error");
1844 
1845 		return ((GetTD_PID(uhcip, td) == PID_IN) ?
1846 		    USB_CR_BUFFER_OVERRUN : USB_CR_BUFFER_UNDERRUN);
1847 	}
1848 
1849 	if (status & UHCI_TD_STALLED) {
1850 		pp->pp_data_toggle = 0;
1851 		USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1852 		    "uhci_parse_td_error: stall; data toggle reset; "
1853 		    "data toggle: %x", pp->pp_data_toggle);
1854 
1855 		return (USB_CR_STALL);
1856 	}
1857 
1858 	if (status) {
1859 		USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1860 		    "unspecified error=0x%x", status);
1861 	}
1862 
1863 	return (USB_CR_OK);
1864 }
1865 
1866 
1867 static dev_info_t *
uhci_get_dip(dev_t dev)1868 uhci_get_dip(dev_t dev)
1869 {
1870 	int instance = UHCI_UNIT(dev);
1871 	uhci_state_t *uhcip = ddi_get_soft_state(uhci_statep, instance);
1872 
1873 	return (uhcip ? uhcip->uhci_dip : NULL);
1874 }
1875 
1876 
1877 /*
1878  * cb_ops entry points
1879  */
1880 static int
uhci_open(dev_t * devp,int flags,int otyp,cred_t * credp)1881 uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1882 {
1883 	dev_info_t *dip = uhci_get_dip(*devp);
1884 
1885 	return (usba_hubdi_open(dip, devp, flags, otyp, credp));
1886 }
1887 
1888 
1889 static int
uhci_close(dev_t dev,int flag,int otyp,cred_t * credp)1890 uhci_close(dev_t dev, int flag, int otyp, cred_t *credp)
1891 {
1892 	dev_info_t *dip = uhci_get_dip(dev);
1893 
1894 	return (usba_hubdi_close(dip, dev, flag, otyp, credp));
1895 }
1896 
1897 
1898 static int
uhci_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)1899 uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
1900     cred_t *credp, int *rvalp)
1901 {
1902 	dev_info_t *dip = uhci_get_dip(dev);
1903 
1904 	return (usba_hubdi_ioctl(dip, dev, cmd, arg, mode, credp, rvalp));
1905 }
1906