xref: /illumos-gate/usr/src/uts/common/io/usb/usba/usba.c (revision ff0e937b)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * USBA: Solaris USB Architecture support
29  */
30 #define	USBA_FRAMEWORK
31 #include <sys/usb/usba/usba_impl.h>
32 #include <sys/usb/usba/hcdi_impl.h>
33 #include <sys/usb/hubd/hub.h>
34 #include <sys/fs/dv_node.h>
35 
36 static int usba_str_startcmp(char *, char *);
37 
38 /*
39  * USBA private variables and tunables
40  */
41 static kmutex_t	usba_mutex;
42 
43 /* mutex to protect usba_root_hubs */
44 static kmutex_t usba_hub_mutex;
45 
46 typedef struct usba_root_hub_ent {
47 	dev_info_t *dip;
48 	struct usba_root_hub_ent *next;
49 }usba_root_hub_ent_t;
50 
51 static usba_root_hub_ent_t *usba_root_hubs = NULL;
52 
53 /*
54  * ddivs forced binding:
55  *
56  *    usbc usbc_xhubs usbc_xaddress  node name
57  *
58  *	0	x	x	class name or "device"
59  *
60  *	1	0	0	ddivs_usbc
61  *	1	0	>1	ddivs_usbc except device
62  *				at usbc_xaddress
63  *	1	1	0	ddivs_usbc except hubs
64  *	1	1	>1	ddivs_usbc except hubs and
65  *				device at usbc_xaddress
66  */
67 uint_t usba_ddivs_usbc;
68 uint_t usba_ddivs_usbc_xhubs;
69 uint_t usba_ddivs_usbc_xaddress;
70 
71 uint_t usba_ugen_force_binding;
72 
73 /*
74  * compatible name handling
75  */
76 /* allowing for 15 compat names, plus one force bind name */
77 #define	USBA_MAX_COMPAT_NAMES		16
78 #define	USBA_MAX_COMPAT_NAME_LEN	64
79 
80 /* double linked list for usba_devices */
81 usba_list_entry_t	usba_device_list;
82 
83 _NOTE(MUTEX_PROTECTS_DATA(usba_mutex, usba_device_list))
84 
85 /*
86  * modload support
87  */
88 
89 static struct modlmisc modlmisc	= {
90 	&mod_miscops,	/* Type	of module */
91 	"USBA: USB Architecture 2.0 1.66"
92 };
93 
94 static struct modlinkage modlinkage = {
95 	MODREV_1, (void	*)&modlmisc, NULL
96 };
97 
98 
99 static usb_log_handle_t	usba_log_handle;
100 uint_t		usba_errlevel = USB_LOG_L4;
101 uint_t		usba_errmask = (uint_t)-1;
102 
103 extern usb_log_handle_t	hubdi_log_handle;
104 
105 int
106 _init(void)
107 {
108 	int rval;
109 
110 	/*
111 	 * usbai providing log support needs to be init'ed first
112 	 * and destroyed last
113 	 */
114 	usba_usbai_initialization();
115 	usba_usba_initialization();
116 	usba_usbai_register_initialization();
117 	usba_hcdi_initialization();
118 	usba_hubdi_initialization();
119 	usba_whcdi_initialization();
120 	usba_devdb_initialization();
121 
122 	if ((rval = mod_install(&modlinkage)) != 0) {
123 		usba_devdb_destroy();
124 		usba_whcdi_destroy();
125 		usba_hubdi_destroy();
126 		usba_hcdi_destroy();
127 		usba_usbai_register_destroy();
128 		usba_usba_destroy();
129 		usba_usbai_destroy();
130 	}
131 
132 	return (rval);
133 }
134 
135 int
136 _fini()
137 {
138 	int rval;
139 
140 	if ((rval = mod_remove(&modlinkage)) == 0) {
141 		usba_devdb_destroy();
142 		usba_whcdi_destroy();
143 		usba_hubdi_destroy();
144 		usba_hcdi_destroy();
145 		usba_usbai_register_destroy();
146 		usba_usba_destroy();
147 		usba_usbai_destroy();
148 	}
149 
150 	return (rval);
151 }
152 
153 int
154 _info(struct modinfo *modinfop)
155 {
156 	return (mod_info(&modlinkage, modinfop));
157 }
158 
159 boolean_t
160 usba_owns_ia(dev_info_t *dip)
161 {
162 	int if_count = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
163 	    "interface-count", 0);
164 
165 	return ((if_count) ? B_TRUE : B_FALSE);
166 }
167 
168 /*
169  * common bus ctl for hcd, usb_mid, and hubd
170  */
171 int
172 usba_bus_ctl(dev_info_t	*dip,
173 	dev_info_t		*rdip,
174 	ddi_ctl_enum_t		op,
175 	void			*arg,
176 	void			*result)
177 {
178 	dev_info_t		*child_dip = (dev_info_t *)arg;
179 	usba_device_t		*usba_device;
180 	usba_hcdi_t		*usba_hcdi;
181 	usba_hcdi_ops_t		*usba_hcdi_ops;
182 
183 	USB_DPRINTF_L4(DPRINT_MASK_USBA, hubdi_log_handle,
184 	    "usba_bus_ctl: %s%d %s%d op=%d", ddi_node_name(rdip),
185 	    ddi_get_instance(rdip), ddi_node_name(dip),
186 	    ddi_get_instance(dip), op);
187 
188 	switch (op) {
189 
190 	case DDI_CTLOPS_REPORTDEV:
191 	{
192 		char *name, compat_name[64], *speed;
193 		usba_device_t	*hub_usba_device;
194 		dev_info_t	*hubdip;
195 
196 		usba_device = usba_get_usba_device(rdip);
197 
198 		/* find the parent hub */
199 		hubdip = ddi_get_parent(rdip);
200 		while ((strcmp(ddi_driver_name(hubdip), "hubd") != 0) &&
201 		    !(usba_is_root_hub(hubdip))) {
202 			hubdip = ddi_get_parent(hubdip);
203 		}
204 
205 		hub_usba_device = usba_get_usba_device(hubdip);
206 
207 		if (usba_device) {
208 			if (usb_owns_device(rdip)) {
209 				(void) snprintf(compat_name,
210 				    sizeof (compat_name),
211 				    "usb%x,%x",
212 				    usba_device->usb_dev_descr->idVendor,
213 				    usba_device->usb_dev_descr->idProduct);
214 			} else if (usba_owns_ia(rdip)) {
215 				(void) snprintf(compat_name,
216 				    sizeof (compat_name),
217 				    "usbia%x,%x.config%x.%x",
218 				    usba_device->usb_dev_descr->idVendor,
219 				    usba_device->usb_dev_descr->idProduct,
220 				    usba_device->usb_cfg_value,
221 				    usb_get_if_number(rdip));
222 			} else {
223 				(void) snprintf(compat_name,
224 				    sizeof (compat_name),
225 				    "usbif%x,%x.config%x.%x",
226 				    usba_device->usb_dev_descr->idVendor,
227 				    usba_device->usb_dev_descr->idProduct,
228 				    usba_device->usb_cfg_value,
229 				    usb_get_if_number(rdip));
230 			}
231 			switch (usba_device->usb_port_status) {
232 			case USBA_HIGH_SPEED_DEV:
233 				speed = "hi speed (USB 2.x)";
234 
235 				break;
236 			case USBA_LOW_SPEED_DEV:
237 				speed = "low speed (USB 1.x)";
238 
239 				break;
240 			case USBA_FULL_SPEED_DEV:
241 			default:
242 				speed = "full speed (USB 1.x)";
243 
244 				break;
245 			}
246 
247 			cmn_err(CE_CONT,
248 			    "?USB %x.%x %s (%s) operating at %s on "
249 			    "USB %x.%x %s hub: "
250 			    "%s@%s, %s%d at bus address %d\n",
251 			    (usba_device->usb_dev_descr->bcdUSB & 0xff00) >> 8,
252 			    usba_device->usb_dev_descr->bcdUSB & 0xff,
253 			    (usb_owns_device(rdip) ? "device" :
254 			    ((usba_owns_ia(rdip) ? "interface-association" :
255 			    "interface"))),
256 			    compat_name, speed,
257 			    (hub_usba_device->usb_dev_descr->bcdUSB &
258 			    0xff00) >> 8,
259 			    hub_usba_device->usb_dev_descr->bcdUSB & 0xff,
260 			    usba_is_root_hub(hubdip) ? "root" : "external",
261 			    ddi_node_name(rdip), ddi_get_name_addr(rdip),
262 			    ddi_driver_name(rdip),
263 			    ddi_get_instance(rdip), usba_device->usb_addr);
264 
265 			name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
266 			(void) usba_get_mfg_prod_sn_str(rdip, name, MAXNAMELEN);
267 			if (name[0] != '\0') {
268 				cmn_err(CE_CONT, "?\t%s\n", name);
269 			}
270 			kmem_free(name, MAXNAMELEN);
271 
272 		} else { /* harden USBA against this case; if it happens */
273 
274 			cmn_err(CE_CONT,
275 			    "?USB-device: %s@%s, %s%d\n",
276 			    ddi_node_name(rdip), ddi_get_name_addr(rdip),
277 			    ddi_driver_name(rdip), ddi_get_instance(rdip));
278 		}
279 
280 		return (DDI_SUCCESS);
281 	}
282 
283 	case DDI_CTLOPS_INITCHILD:
284 	{
285 		int			usb_addr;
286 		uint_t			n;
287 		char			name[32];
288 		int			*data;
289 		int			rval;
290 		int			len = sizeof (usb_addr);
291 
292 		usba_hcdi	= usba_hcdi_get_hcdi(dip);
293 		usba_hcdi_ops	= usba_hcdi->hcdi_ops;
294 		ASSERT(usba_hcdi_ops != NULL);
295 
296 		/*
297 		 * as long as the dip exists, it should have
298 		 * usba_device structure associated with it
299 		 */
300 		usba_device = usba_get_usba_device(child_dip);
301 		if (usba_device == NULL) {
302 
303 			USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
304 			    "usba_bus_ctl: DDI_NOT_WELL_FORMED (%s (0x%p))",
305 			    ddi_node_name(child_dip), (void *)child_dip);
306 
307 			return (DDI_NOT_WELL_FORMED);
308 		}
309 
310 		/* the dip should have an address and reg property */
311 		if (ddi_prop_op(DDI_DEV_T_NONE, child_dip, PROP_LEN_AND_VAL_BUF,
312 		    DDI_PROP_DONTPASS |	DDI_PROP_CANSLEEP, "assigned-address",
313 		    (caddr_t)&usb_addr,	&len) != DDI_SUCCESS) {
314 
315 			USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
316 			    "usba_bus_ctl:\n\t"
317 			    "%s%d %s%d op=%d rdip = 0x%p dip = 0x%p",
318 			    ddi_node_name(rdip), ddi_get_instance(rdip),
319 			    ddi_node_name(dip), ddi_get_instance(dip), op,
320 			    (void *)rdip, (void *)dip);
321 
322 			USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
323 			    "usba_bus_ctl: DDI_NOT_WELL_FORMED (%s (0x%p))",
324 			    ddi_node_name(child_dip), (void *)child_dip);
325 
326 			return (DDI_NOT_WELL_FORMED);
327 		}
328 
329 		if ((rval = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child_dip,
330 		    DDI_PROP_DONTPASS, "reg",
331 		    &data, &n)) != DDI_SUCCESS) {
332 
333 			USB_DPRINTF_L2(DPRINT_MASK_USBA, hubdi_log_handle,
334 			    "usba_bus_ctl: %d, DDI_NOT_WELL_FORMED", rval);
335 
336 			return (DDI_NOT_WELL_FORMED);
337 		}
338 
339 
340 		/*
341 		 * if the configuration is 1, the unit address is
342 		 * just the interface number
343 		 */
344 		if ((n == 1) || ((n > 1) && (data[1] == 1))) {
345 			(void) sprintf(name, "%x", data[0]);
346 		} else {
347 			(void) sprintf(name, "%x,%x", data[0], data[1]);
348 		}
349 
350 		USB_DPRINTF_L3(DPRINT_MASK_USBA,
351 		    hubdi_log_handle, "usba_bus_ctl: name = %s", name);
352 
353 		ddi_prop_free(data);
354 		ddi_set_name_addr(child_dip, name);
355 
356 		/*
357 		 * increment the reference count for each child using this
358 		 * usba_device structure
359 		 */
360 		mutex_enter(&usba_device->usb_mutex);
361 		usba_device->usb_ref_count++;
362 
363 		USB_DPRINTF_L3(DPRINT_MASK_USBA, hubdi_log_handle,
364 		    "usba_bus_ctl: init usba_device = 0x%p ref_count = %d",
365 		    (void *)usba_device, usba_device->usb_ref_count);
366 
367 		mutex_exit(&usba_device->usb_mutex);
368 
369 		return (DDI_SUCCESS);
370 	}
371 
372 	case DDI_CTLOPS_UNINITCHILD:
373 	{
374 		usba_device = usba_get_usba_device(child_dip);
375 
376 		if (usba_device != NULL) {
377 			/*
378 			 * decrement the reference count for each child
379 			 * using this  usba_device structure
380 			 */
381 			mutex_enter(&usba_device->usb_mutex);
382 			usba_device->usb_ref_count--;
383 
384 			USB_DPRINTF_L3(DPRINT_MASK_USBA, hubdi_log_handle,
385 			    "usba_hcdi_bus_ctl: uninit usba_device=0x%p "
386 			    "ref_count=%d",
387 			    (void *)usba_device, usba_device->usb_ref_count);
388 
389 			mutex_exit(&usba_device->usb_mutex);
390 		}
391 		ddi_set_name_addr(child_dip, NULL);
392 
393 		return (DDI_SUCCESS);
394 	}
395 
396 	case DDI_CTLOPS_IOMIN:
397 		/* Do nothing */
398 		return (DDI_SUCCESS);
399 
400 	/*
401 	 * These ops correspond	to functions that "shouldn't" be called
402 	 * by a	USB client driver.  So	we whine when we're called.
403 	 */
404 	case DDI_CTLOPS_DMAPMAPC:
405 	case DDI_CTLOPS_REPORTINT:
406 	case DDI_CTLOPS_REGSIZE:
407 	case DDI_CTLOPS_NREGS:
408 	case DDI_CTLOPS_SIDDEV:
409 	case DDI_CTLOPS_SLAVEONLY:
410 	case DDI_CTLOPS_AFFINITY:
411 	case DDI_CTLOPS_POKE:
412 	case DDI_CTLOPS_PEEK:
413 		cmn_err(CE_CONT, "%s%d:	invalid	op (%d)	from %s%d",
414 		    ddi_node_name(dip), ddi_get_instance(dip),
415 		    op, ddi_node_name(rdip), ddi_get_instance(rdip));
416 		return (DDI_FAILURE);
417 
418 	/*
419 	 * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
420 	 */
421 	default:
422 		return (ddi_ctlops(dip,	rdip, op, arg, result));
423 	}
424 }
425 
426 
427 /*
428  * initialize and destroy USBA module
429  */
430 void
431 usba_usba_initialization()
432 {
433 	usba_log_handle = usb_alloc_log_hdl(NULL, "usba", &usba_errlevel,
434 	    &usba_errmask, NULL, 0);
435 
436 	USB_DPRINTF_L4(DPRINT_MASK_USBA,
437 	    usba_log_handle, "usba_usba_initialization");
438 
439 	mutex_init(&usba_mutex, NULL, MUTEX_DRIVER, NULL);
440 	mutex_init(&usba_hub_mutex, NULL, MUTEX_DRIVER, NULL);
441 	usba_init_list(&usba_device_list, NULL, NULL);
442 }
443 
444 
445 void
446 usba_usba_destroy()
447 {
448 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle, "usba_usba_destroy");
449 
450 	mutex_destroy(&usba_hub_mutex);
451 	mutex_destroy(&usba_mutex);
452 	usba_destroy_list(&usba_device_list);
453 
454 	usb_free_log_hdl(usba_log_handle);
455 }
456 
457 
458 /*
459  * usba_set_usb_address:
460  *	set usb address in usba_device structure
461  */
462 int
463 usba_set_usb_address(usba_device_t *usba_device)
464 {
465 	usb_addr_t address;
466 	uchar_t s = 8;
467 	usba_hcdi_t *hcdi;
468 	char *usb_address_in_use;
469 
470 	mutex_enter(&usba_device->usb_mutex);
471 
472 	hcdi = usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
473 
474 	mutex_enter(&hcdi->hcdi_mutex);
475 	usb_address_in_use = hcdi->hcdi_usb_address_in_use;
476 
477 	for (address = ROOT_HUB_ADDR + 1;
478 	    address <= USBA_MAX_ADDRESS; address++) {
479 		if (usb_address_in_use[address/s] & (1 << (address % s))) {
480 			continue;
481 		}
482 		usb_address_in_use[address/s] |= (1 << (address % s));
483 		hcdi->hcdi_device_count++;
484 		HCDI_HOTPLUG_STATS_DATA(hcdi)->hcdi_device_count.value.ui64++;
485 		mutex_exit(&hcdi->hcdi_mutex);
486 
487 		USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
488 		    "usba_set_usb_address: %d", address);
489 
490 		usba_device->usb_addr = address;
491 
492 		mutex_exit(&usba_device->usb_mutex);
493 
494 		return (USB_SUCCESS);
495 	}
496 
497 	usba_device->usb_addr = 0;
498 
499 	USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
500 	    "no usb address available");
501 
502 	mutex_exit(&hcdi->hcdi_mutex);
503 	mutex_exit(&usba_device->usb_mutex);
504 
505 	return (USB_FAILURE);
506 }
507 
508 
509 /*
510  * usba_unset_usb_address:
511  *	unset usb_address in usba_device structure
512  */
513 void
514 usba_unset_usb_address(usba_device_t *usba_device)
515 {
516 	usb_addr_t address;
517 	usba_hcdi_t *hcdi;
518 	uchar_t s = 8;
519 	char *usb_address_in_use;
520 
521 	mutex_enter(&usba_device->usb_mutex);
522 	address = usba_device->usb_addr;
523 	hcdi = usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
524 
525 	if (address > ROOT_HUB_ADDR) {
526 		USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
527 		    "usba_unset_usb_address: address=%d", address);
528 
529 		mutex_enter(&hcdi->hcdi_mutex);
530 		usb_address_in_use = hcdi->hcdi_usb_address_in_use;
531 
532 		ASSERT(usb_address_in_use[address/s] & (1 << (address % s)));
533 
534 		usb_address_in_use[address/s] &= ~(1 << (address % s));
535 
536 		hcdi->hcdi_device_count--;
537 		HCDI_HOTPLUG_STATS_DATA(hcdi)->hcdi_device_count.value.ui64--;
538 
539 		mutex_exit(&hcdi->hcdi_mutex);
540 
541 		usba_device->usb_addr = 0;
542 	}
543 	mutex_exit(&usba_device->usb_mutex);
544 }
545 
546 
547 struct usba_evdata *
548 usba_get_evdata(dev_info_t *dip)
549 {
550 	usba_evdata_t *evdata;
551 	usba_device_t *usba_device = usba_get_usba_device(dip);
552 
553 	/* called when dip attaches */
554 	ASSERT(usba_device != NULL);
555 
556 	mutex_enter(&usba_device->usb_mutex);
557 	evdata = usba_device->usb_evdata;
558 	while (evdata) {
559 		if (evdata->ev_dip == dip) {
560 			mutex_exit(&usba_device->usb_mutex);
561 
562 			return (evdata);
563 		}
564 		evdata = evdata->ev_next;
565 	}
566 
567 	evdata = kmem_zalloc(sizeof (usba_evdata_t), KM_SLEEP);
568 	evdata->ev_dip = dip;
569 	evdata->ev_next = usba_device->usb_evdata;
570 	usba_device->usb_evdata = evdata;
571 	mutex_exit(&usba_device->usb_mutex);
572 
573 	return (evdata);
574 }
575 
576 
577 /*
578  * allocate a usb device structure and link it in the list
579  */
580 usba_device_t *
581 usba_alloc_usba_device(dev_info_t *root_hub_dip)
582 {
583 	usba_device_t	*usba_device;
584 	int		ep_idx;
585 	ddi_iblock_cookie_t iblock_cookie =
586 	    usba_hcdi_get_hcdi(root_hub_dip)->hcdi_iblock_cookie;
587 
588 	/*
589 	 * create a new usba_device structure
590 	 */
591 	usba_device = kmem_zalloc(sizeof (usba_device_t), KM_SLEEP);
592 
593 	/*
594 	 * initialize usba_device
595 	 */
596 	mutex_init(&usba_device->usb_mutex, NULL, MUTEX_DRIVER,
597 	    iblock_cookie);
598 
599 	usba_init_list(&usba_device->usb_device_list, (usb_opaque_t)usba_device,
600 	    iblock_cookie);
601 	usba_init_list(&usba_device->usb_allocated, (usb_opaque_t)usba_device,
602 	    iblock_cookie);
603 	mutex_enter(&usba_device->usb_mutex);
604 	usba_device->usb_root_hub_dip = root_hub_dip;
605 
606 	/*
607 	 * add to list of usba_devices
608 	 */
609 	usba_add_to_list(&usba_device_list, &usba_device->usb_device_list);
610 
611 	/* init mutex in each usba_ph_impl structure */
612 	for (ep_idx = 0; ep_idx < USBA_N_ENDPOINTS; ep_idx++) {
613 		mutex_init(&usba_device->usb_ph_list[ep_idx].usba_ph_mutex,
614 		    NULL, MUTEX_DRIVER, iblock_cookie);
615 	}
616 
617 	USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
618 	    "allocated usba_device 0x%p", (void *)usba_device);
619 
620 	mutex_exit(&usba_device->usb_mutex);
621 
622 	return (usba_device);
623 }
624 
625 
626 /* free NDI event data associated with usba_device */
627 void
628 usba_free_evdata(usba_evdata_t *evdata)
629 {
630 	usba_evdata_t *next;
631 
632 	while (evdata) {
633 		next = evdata->ev_next;
634 		kmem_free(evdata, sizeof (usba_evdata_t));
635 		evdata = next;
636 	}
637 }
638 
639 
640 /*
641  * free wireless usb specific structure
642  */
643 void
644 usba_free_wireless_data(usba_wireless_data_t *wireless_data)
645 {
646 	if (wireless_data == NULL) {
647 
648 		return;
649 	}
650 
651 	if (wireless_data->wusb_bos) {
652 		kmem_free(wireless_data->wusb_bos,
653 		    wireless_data->wusb_bos_length);
654 	}
655 
656 	kmem_free(wireless_data, sizeof (usba_wireless_data_t));
657 }
658 
659 
660 /*
661  * free usb device structure
662  */
663 void
664 usba_free_usba_device(usba_device_t *usba_device)
665 {
666 	int			i, ep_idx;
667 	usb_pipe_handle_t	def_ph;
668 
669 	if (usba_device == NULL) {
670 
671 		return;
672 	}
673 
674 	mutex_enter(&usba_device->usb_mutex);
675 	if (usba_device->usb_ref_count) {
676 		mutex_exit(&usba_device->usb_mutex);
677 
678 		return;
679 	}
680 
681 	USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
682 	    "usba_free_usba_device 0x%p, address=0x%x, ref cnt=%d",
683 	    (void *)usba_device, usba_device->usb_addr,
684 	    usba_device->usb_ref_count);
685 
686 	usba_free_evdata(usba_device->usb_evdata);
687 	mutex_exit(&usba_device->usb_mutex);
688 
689 	def_ph = usba_usbdev_to_dflt_pipe_handle(usba_device);
690 	if (def_ph != NULL) {
691 		usba_pipe_handle_data_t	*ph_data = usba_get_ph_data(def_ph);
692 
693 		if (ph_data) {
694 			usb_pipe_close(ph_data->p_dip, def_ph,
695 			    USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
696 			    NULL, NULL);
697 		}
698 	}
699 
700 	mutex_enter(&usba_mutex);
701 
702 	/* destroy mutex in each usba_ph_impl structure */
703 	for (ep_idx = 0; ep_idx < USBA_N_ENDPOINTS; ep_idx++) {
704 		mutex_destroy(&usba_device->usb_ph_list[ep_idx].usba_ph_mutex);
705 	}
706 
707 	(void) usba_rm_from_list(&usba_device_list,
708 	    &usba_device->usb_device_list);
709 
710 	mutex_exit(&usba_mutex);
711 
712 	usba_destroy_list(&usba_device->usb_device_list);
713 	usba_destroy_list(&usba_device->usb_allocated);
714 
715 	USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
716 	    "deallocating usba_device = 0x%p, address = 0x%x",
717 	    (void *)usba_device, usba_device->usb_addr);
718 
719 	/*
720 	 * ohci allocates descriptors for root hub so we can't
721 	 * deallocate these here
722 	 */
723 
724 	if (usba_device->usb_addr != ROOT_HUB_ADDR) {
725 		if (usba_device->usb_cfg_array) {
726 			USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
727 			    "deallocating usb_config_array: 0x%p",
728 			    (void *)usba_device->usb_cfg_array);
729 			mutex_enter(&usba_device->usb_mutex);
730 			for (i = 0;
731 			    i < usba_device->usb_dev_descr->bNumConfigurations;
732 			    i++) {
733 				if (usba_device->usb_cfg_array[i]) {
734 					kmem_free(
735 					    usba_device->usb_cfg_array[i],
736 					    usba_device->usb_cfg_array_len[i]);
737 				}
738 			}
739 
740 			/* free the array pointers */
741 			kmem_free(usba_device->usb_cfg_array,
742 			    usba_device->usb_cfg_array_length);
743 			kmem_free(usba_device->usb_cfg_array_len,
744 			    usba_device->usb_cfg_array_len_length);
745 
746 			mutex_exit(&usba_device->usb_mutex);
747 		}
748 
749 		if (usba_device->usb_cfg_str_descr) {
750 			USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
751 			    "deallocating usb_cfg_str_descr: 0x%p",
752 			    (void *)usba_device->usb_cfg_str_descr);
753 			for (i = 0;
754 			    i < usba_device->usb_dev_descr->bNumConfigurations;
755 			    i++) {
756 				if (usba_device->usb_cfg_str_descr[i]) {
757 					kmem_free(
758 					    usba_device->usb_cfg_str_descr[i],
759 					    strlen(usba_device->
760 					    usb_cfg_str_descr[i]) + 1);
761 				}
762 			}
763 			/* free the array pointers */
764 			kmem_free(usba_device->usb_cfg_str_descr,
765 			    sizeof (uchar_t *) * usba_device->usb_n_cfgs);
766 		}
767 
768 		if (usba_device->usb_dev_descr) {
769 			kmem_free(usba_device->usb_dev_descr,
770 			    sizeof (usb_dev_descr_t));
771 		}
772 
773 		if (usba_device->usb_mfg_str) {
774 			kmem_free(usba_device->usb_mfg_str,
775 			    strlen(usba_device->usb_mfg_str) + 1);
776 		}
777 
778 		if (usba_device->usb_product_str) {
779 			kmem_free(usba_device->usb_product_str,
780 			    strlen(usba_device->usb_product_str) + 1);
781 		}
782 
783 		if (usba_device->usb_serialno_str) {
784 			kmem_free(usba_device->usb_serialno_str,
785 			    strlen(usba_device->usb_serialno_str) + 1);
786 		}
787 
788 		if (usba_device->usb_wireless_data) {
789 			mutex_enter(&usba_device->usb_mutex);
790 			usba_free_wireless_data(
791 			    usba_device->usb_wireless_data);
792 			mutex_exit(&usba_device->usb_mutex);
793 		}
794 
795 		/*
796 		 * The device address on the wireless bus is assigned
797 		 * by the wireless host controller driver(whci or hwahc),
798 		 * not by USBA framework, so skip this for wireless
799 		 * USB devices.
800 		 */
801 		if (!usba_device->usb_is_wireless) {
802 			usba_unset_usb_address(usba_device);
803 		}
804 	}
805 
806 #ifndef __lock_lint
807 	ASSERT(usba_device->usb_client_dev_data_list.cddl_next == NULL);
808 #endif
809 
810 	if (usba_device->usb_client_flags) {
811 #ifndef __lock_lint
812 		int i;
813 
814 		for (i = 0; i < usba_device->usb_n_ifs; i++) {
815 			ASSERT(usba_device->usb_client_flags[i] == 0);
816 		}
817 #endif
818 		kmem_free(usba_device->usb_client_flags,
819 		    usba_device->usb_n_ifs * USBA_CLIENT_FLAG_SIZE);
820 	}
821 
822 
823 	if (usba_device->usb_client_attach_list) {
824 		kmem_free(usba_device->usb_client_attach_list,
825 		    usba_device->usb_n_ifs *
826 		    sizeof (*usba_device->usb_client_attach_list));
827 	}
828 	if (usba_device->usb_client_ev_cb_list) {
829 		kmem_free(usba_device->usb_client_ev_cb_list,
830 		    usba_device->usb_n_ifs *
831 		    sizeof (*usba_device->usb_client_ev_cb_list));
832 	}
833 
834 	/*
835 	 * finally ready to destroy the structure
836 	 */
837 	mutex_destroy(&usba_device->usb_mutex);
838 
839 	kmem_free((caddr_t)usba_device, sizeof (usba_device_t));
840 }
841 
842 
843 /* clear the data toggle for all endpoints on this device */
844 void
845 usba_clear_data_toggle(usba_device_t *usba_device)
846 {
847 	int	i;
848 
849 	if (usba_device != NULL) {
850 		mutex_enter(&usba_device->usb_mutex);
851 		for (i = 0; i < USBA_N_ENDPOINTS; i++) {
852 			usba_device->usb_ph_list[i].usba_ph_flags &=
853 			    ~USBA_PH_DATA_TOGGLE;
854 		}
855 		mutex_exit(&usba_device->usb_mutex);
856 	}
857 }
858 
859 
860 /*
861  * usba_create_child_devi():
862  *	create a child devinfo node, usba_device, attach properties.
863  *	the usba_device structure is shared between all interfaces
864  */
865 int
866 usba_create_child_devi(dev_info_t	*dip,
867 		char			*node_name,
868 		usba_hcdi_ops_t		*usba_hcdi_ops,
869 		dev_info_t		*usb_root_hub_dip,
870 		usb_port_status_t	port_status,
871 		usba_device_t		*usba_device,
872 		dev_info_t		**child_dip)
873 {
874 	int rval = USB_FAILURE;
875 	int usba_device_allocated = 0;
876 	usb_addr_t	address;
877 
878 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
879 	    "usba_create_child_devi: %s usba_device=0x%p "
880 	    "port status=0x%x", node_name,
881 	    (void *)usba_device, port_status);
882 
883 	ndi_devi_alloc_sleep(dip, node_name, (pnode_t)DEVI_SID_NODEID,
884 	    child_dip);
885 
886 	USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
887 	    "child dip=0x%p", (void *)*child_dip);
888 
889 	if (usba_device == NULL) {
890 
891 		usba_device = usba_alloc_usba_device(usb_root_hub_dip);
892 
893 		/* grab the mutex to keep warlock happy */
894 		mutex_enter(&usba_device->usb_mutex);
895 		usba_device->usb_hcdi_ops	= usba_hcdi_ops;
896 		usba_device->usb_port_status	= port_status;
897 		mutex_exit(&usba_device->usb_mutex);
898 
899 		usba_device_allocated++;
900 	} else {
901 		mutex_enter(&usba_device->usb_mutex);
902 		if (usba_hcdi_ops) {
903 			ASSERT(usba_device->usb_hcdi_ops == usba_hcdi_ops);
904 		}
905 		if (usb_root_hub_dip) {
906 			ASSERT(usba_device->usb_root_hub_dip ==
907 			    usb_root_hub_dip);
908 		}
909 
910 		usba_device->usb_port_status	= port_status;
911 
912 		mutex_exit(&usba_device->usb_mutex);
913 	}
914 
915 	if (usba_device->usb_addr == 0) {
916 		if (usba_set_usb_address(usba_device) == USB_FAILURE) {
917 			address = 0;
918 
919 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
920 			    "cannot set usb address for dip=0x%p",
921 			    (void *)*child_dip);
922 
923 			goto fail;
924 		}
925 	}
926 	address = usba_device->usb_addr;
927 
928 	/* attach properties */
929 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, *child_dip,
930 	    "assigned-address", address);
931 	if (rval != DDI_PROP_SUCCESS) {
932 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
933 		    "cannot set usb address property for dip=0x%p",
934 		    (void *)*child_dip);
935 		rval = USB_FAILURE;
936 
937 		goto fail;
938 	}
939 
940 	/*
941 	 * store the usba_device point in the dip
942 	 */
943 	usba_set_usba_device(*child_dip, usba_device);
944 
945 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
946 	    "usba_create_child_devi: devi=0x%p (%s) ud=0x%p",
947 	    (void *)*child_dip, ddi_driver_name(*child_dip),
948 	    (void *)usba_device);
949 
950 	return (USB_SUCCESS);
951 
952 fail:
953 	if (*child_dip) {
954 		int rval = usba_destroy_child_devi(*child_dip, NDI_DEVI_REMOVE);
955 		ASSERT(rval == USB_SUCCESS);
956 		*child_dip = NULL;
957 	}
958 
959 	if (usba_device_allocated) {
960 		usba_free_usba_device(usba_device);
961 	} else if (address && usba_device) {
962 		usba_unset_usb_address(usba_device);
963 	}
964 
965 	USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
966 	    "usba_create_child_devi failed: rval=%d", rval);
967 
968 	return (rval);
969 }
970 
971 
972 int
973 usba_destroy_child_devi(dev_info_t *dip, uint_t flag)
974 {
975 	usba_device_t	*usba_device;
976 	int		rval = NDI_SUCCESS;
977 
978 	USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
979 	    "usba_destroy_child_devi: %s%d (0x%p)",
980 	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip);
981 
982 	usba_device = usba_get_usba_device(dip);
983 
984 	/*
985 	 * if the child hasn't been bound yet, we can just
986 	 * free the dip
987 	 */
988 	if (i_ddi_node_state(dip) < DS_INITIALIZED) {
989 		/*
990 		 * do not call ndi_devi_free() since it might
991 		 * deadlock
992 		 */
993 		rval = ddi_remove_child(dip, 0);
994 
995 	} else {
996 		char *devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
997 		dev_info_t *pdip = ddi_get_parent(dip);
998 
999 		(void) ddi_deviname(dip, devnm);
1000 
1001 		USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
1002 		    "usba_destroy_child_devi:\n\t"
1003 		    "offlining dip 0x%p usba_device=0x%p (%s)", (void *)dip,
1004 		    (void *)usba_device, devnm);
1005 
1006 		(void) devfs_clean(pdip, NULL, DV_CLEAN_FORCE);
1007 		rval =	ndi_devi_unconfig_one(pdip, devnm + 1, NULL,
1008 		    flag | NDI_UNCONFIG | NDI_DEVI_OFFLINE);
1009 		if (rval != NDI_SUCCESS) {
1010 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
1011 			    " ndi_devi_unconfig_one %s%d failed (%d)",
1012 			    ddi_driver_name(dip), ddi_get_instance(dip),
1013 			    rval);
1014 		}
1015 		kmem_free(devnm, MAXNAMELEN + 1);
1016 	}
1017 
1018 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1019 	    "usba_destroy_child_devi: rval=%d", rval);
1020 
1021 	return (rval == NDI_SUCCESS ? USB_SUCCESS : USB_FAILURE);
1022 }
1023 
1024 
1025 /*
1026  * list management
1027  */
1028 void
1029 usba_init_list(usba_list_entry_t *element, usb_opaque_t private,
1030 	ddi_iblock_cookie_t	iblock_cookie)
1031 {
1032 	mutex_init(&element->list_mutex, NULL, MUTEX_DRIVER,
1033 	    iblock_cookie);
1034 	mutex_enter(&element->list_mutex);
1035 	element->private = private;
1036 	mutex_exit(&element->list_mutex);
1037 }
1038 
1039 
1040 void
1041 usba_destroy_list(usba_list_entry_t *head)
1042 {
1043 	mutex_enter(&head->list_mutex);
1044 	ASSERT(head->next == NULL);
1045 	ASSERT(head->prev == NULL);
1046 	mutex_exit(&head->list_mutex);
1047 
1048 	mutex_destroy(&head->list_mutex);
1049 }
1050 
1051 
1052 void
1053 usba_add_to_list(usba_list_entry_t *head, usba_list_entry_t *element)
1054 {
1055 	usba_list_entry_t *next;
1056 	int		remaining;
1057 
1058 	mutex_enter(&head->list_mutex);
1059 	mutex_enter(&element->list_mutex);
1060 
1061 	remaining = head->count;
1062 
1063 	/* check if it is not in another list */
1064 	ASSERT(element->next == NULL);
1065 	ASSERT(element->prev == NULL);
1066 
1067 #ifdef DEBUG
1068 	/*
1069 	 * only verify the list when not in interrupt context, we
1070 	 * have to trust the HCD
1071 	 */
1072 	if (!servicing_interrupt()) {
1073 
1074 		/* check if not already in this list */
1075 		for (next = head->next; (next != NULL);
1076 		    next = next->next) {
1077 			if (next == element) {
1078 				USB_DPRINTF_L0(DPRINT_MASK_USBA,
1079 				    usba_log_handle,
1080 				    "Attempt to corrupt USB list at 0x%p",
1081 				    (void *)head);
1082 				ASSERT(next == element);
1083 
1084 				goto done;
1085 			}
1086 			remaining--;
1087 
1088 			/*
1089 			 * Detect incorrect circ links or found
1090 			 * unexpected elements.
1091 			 */
1092 			if ((next->next && (remaining == 0)) ||
1093 			    ((next->next == NULL) && remaining)) {
1094 				panic("Corrupted USB list at 0x%p",
1095 				    (void *)head);
1096 				/*NOTREACHED*/
1097 			}
1098 		}
1099 	}
1100 #endif
1101 
1102 	if (head->next == NULL) {
1103 		head->prev = head->next = element;
1104 	} else {
1105 		/* add to tail */
1106 		head->prev->next = element;
1107 		element->prev = head->prev;
1108 		head->prev = element;
1109 	}
1110 
1111 	head->count++;
1112 
1113 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1114 	    "usba_add_to_list: head=0x%p element=0x%p count=%d",
1115 	    (void *)head, (void *)element, head->count);
1116 
1117 done:
1118 	mutex_exit(&head->list_mutex);
1119 	mutex_exit(&element->list_mutex);
1120 }
1121 
1122 
1123 int
1124 usba_rm_from_list(usba_list_entry_t *head, usba_list_entry_t *element)
1125 {
1126 	usba_list_entry_t *e;
1127 	int		found = 0;
1128 	int		remaining;
1129 
1130 	/* find the element in the list first */
1131 	mutex_enter(&head->list_mutex);
1132 
1133 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1134 	    "usba_rm_from_list: head=0x%p element=0x%p count=%d",
1135 	    (void *)head, (void *)element, head->count);
1136 
1137 	remaining = head->count;
1138 	e = head->next;
1139 
1140 	while (e) {
1141 		if (e == element) {
1142 			found++;
1143 			break;
1144 		}
1145 		e = e->next;
1146 
1147 		remaining--;
1148 
1149 		/* Detect incorrect circ links or found unexpected elements. */
1150 		if ((e && (remaining == 0)) ||
1151 		    ((e == NULL) && (remaining))) {
1152 			panic("Corrupted USB list at 0x%p", (void *)head);
1153 			/*NOTREACHED*/
1154 		}
1155 	}
1156 
1157 	if (!found) {
1158 		mutex_exit(&head->list_mutex);
1159 
1160 		return (USB_FAILURE);
1161 	}
1162 
1163 	/* now remove the element */
1164 	mutex_enter(&element->list_mutex);
1165 
1166 	if (element->next) {
1167 		element->next->prev = element->prev;
1168 	}
1169 	if (element->prev) {
1170 		element->prev->next = element->next;
1171 	}
1172 	if (head->next == element) {
1173 		head->next = element->next;
1174 	}
1175 	if (head->prev == element) {
1176 		head->prev = element->prev;
1177 	}
1178 
1179 	element->prev = element->next = NULL;
1180 	if (head->next == NULL) {
1181 		ASSERT(head->prev == NULL);
1182 	} else {
1183 		ASSERT(head->next->prev == NULL);
1184 	}
1185 	if (head->prev == NULL) {
1186 		ASSERT(head->next == NULL);
1187 	} else {
1188 		ASSERT(head->prev->next == NULL);
1189 	}
1190 
1191 	head->count--;
1192 
1193 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1194 	    "usba_rm_from_list success: head=0x%p element=0x%p cnt=%d",
1195 	    (void *)head, (void *)element, head->count);
1196 
1197 	mutex_exit(&element->list_mutex);
1198 	mutex_exit(&head->list_mutex);
1199 
1200 	return (USB_SUCCESS);
1201 }
1202 
1203 
1204 usba_list_entry_t *
1205 usba_rm_first_from_list(usba_list_entry_t *head)
1206 {
1207 	usba_list_entry_t *element = NULL;
1208 
1209 	if (head) {
1210 		mutex_enter(&head->list_mutex);
1211 		element = head->next;
1212 		if (element) {
1213 			/* now remove the element */
1214 			mutex_enter(&element->list_mutex);
1215 			head->next = element->next;
1216 			if (head->next) {
1217 				head->next->prev = NULL;
1218 			}
1219 			if (head->prev == element) {
1220 				head->prev = element->next;
1221 			}
1222 			element->prev = element->next = NULL;
1223 			mutex_exit(&element->list_mutex);
1224 			head->count--;
1225 		}
1226 		if (head->next == NULL) {
1227 			ASSERT(head->prev == NULL);
1228 		} else {
1229 			ASSERT(head->next->prev == NULL);
1230 		}
1231 		if (head->prev == NULL) {
1232 			ASSERT(head->next == NULL);
1233 		} else {
1234 			ASSERT(head->prev->next == NULL);
1235 		}
1236 		USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1237 		    "usba_rm_first_from_list: head=0x%p el=0x%p cnt=%d",
1238 		    (void *)head, (void *)element, head->count);
1239 
1240 		mutex_exit(&head->list_mutex);
1241 	}
1242 
1243 	return (element);
1244 }
1245 
1246 
1247 usb_opaque_t
1248 usba_rm_first_pvt_from_list(usba_list_entry_t *head)
1249 {
1250 	usba_list_entry_t *element = usba_rm_first_from_list(head);
1251 	usb_opaque_t private = NULL;
1252 
1253 	if (element) {
1254 		mutex_enter(&element->list_mutex);
1255 		private = element->private;
1256 		mutex_exit(&element->list_mutex);
1257 	}
1258 
1259 	return (private);
1260 }
1261 
1262 
1263 /*
1264  * move list to new list and zero original list
1265  */
1266 void
1267 usba_move_list(usba_list_entry_t *head, usba_list_entry_t *new,
1268 	ddi_iblock_cookie_t iblock_cookie)
1269 {
1270 	usba_init_list(new, NULL, iblock_cookie);
1271 	mutex_enter(&head->list_mutex);
1272 	mutex_enter(&new->list_mutex);
1273 
1274 	new->next = head->next;
1275 	new->prev = head->prev;
1276 	new->count = head->count;
1277 	new->private = head->private;
1278 
1279 	head->next = NULL;
1280 	head->prev = NULL;
1281 	head->count = 0;
1282 	head->private = NULL;
1283 	mutex_exit(&head->list_mutex);
1284 	mutex_exit(&new->list_mutex);
1285 }
1286 
1287 
1288 int
1289 usba_check_in_list(usba_list_entry_t *head, usba_list_entry_t *element)
1290 {
1291 	int		rval = USB_FAILURE;
1292 	int		remaining;
1293 	usba_list_entry_t *next;
1294 
1295 	mutex_enter(&head->list_mutex);
1296 	remaining = head->count;
1297 
1298 	mutex_enter(&element->list_mutex);
1299 	for (next = head->next; next != NULL; next = next->next) {
1300 		if (next == element) {
1301 			rval = USB_SUCCESS;
1302 			break;
1303 		}
1304 		remaining--;
1305 
1306 		/* Detect incorrect circ links or found unexpected elements. */
1307 		if ((next->next && (remaining == 0)) ||
1308 		    ((next->next == NULL) && remaining)) {
1309 			panic("Corrupted USB list at 0x%p", (void *)head);
1310 			/*NOTREACHED*/
1311 		}
1312 	}
1313 	mutex_exit(&element->list_mutex);
1314 	mutex_exit(&head->list_mutex);
1315 
1316 	return (rval);
1317 }
1318 
1319 
1320 int
1321 usba_list_entry_leaks(usba_list_entry_t *head, char *what)
1322 {
1323 	int		count = 0;
1324 	int		remaining;
1325 	usba_list_entry_t *next;
1326 
1327 	mutex_enter(&head->list_mutex);
1328 	remaining = head->count;
1329 	for (next = head->next; next != NULL; next = next->next) {
1330 		USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1331 		    "leaking %s 0x%p", what, (void *)next->private);
1332 		count++;
1333 
1334 		remaining--;
1335 
1336 		/* Detect incorrect circ links or found unexpected elements. */
1337 		if ((next->next && (remaining == 0)) ||
1338 		    ((next->next == NULL) && remaining)) {
1339 			panic("Corrupted USB list at 0x%p", (void *)head);
1340 			/*NOTREACHED*/
1341 		}
1342 	}
1343 	ASSERT(count == head->count);
1344 	mutex_exit(&head->list_mutex);
1345 
1346 	if (count) {
1347 		USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1348 		    "usba_list_entry_count: leaking %d", count);
1349 	}
1350 
1351 	return (count);
1352 }
1353 
1354 
1355 int
1356 usba_list_entry_count(usba_list_entry_t *head)
1357 {
1358 	int count;
1359 
1360 	mutex_enter(&head->list_mutex);
1361 	count = head->count;
1362 	mutex_exit(&head->list_mutex);
1363 
1364 	return (count);
1365 }
1366 
1367 /* add a new root hub to the usba_root_hubs list */
1368 
1369 void
1370 usba_add_root_hub(dev_info_t *dip)
1371 {
1372 	usba_root_hub_ent_t *hub;
1373 
1374 	hub = (usba_root_hub_ent_t *)
1375 	    kmem_zalloc(sizeof (usba_root_hub_ent_t), KM_SLEEP);
1376 
1377 	mutex_enter(&usba_hub_mutex);
1378 	hub->dip = dip;
1379 	hub->next = usba_root_hubs;
1380 	usba_root_hubs = hub;
1381 	mutex_exit(&usba_hub_mutex);
1382 }
1383 
1384 /* remove a root hub from the usba_root_hubs list */
1385 
1386 void
1387 usba_rem_root_hub(dev_info_t *dip)
1388 {
1389 	usba_root_hub_ent_t **hubp, *hub;
1390 
1391 	mutex_enter(&usba_hub_mutex);
1392 	hubp = &usba_root_hubs;
1393 	while (*hubp) {
1394 		if ((*hubp)->dip == dip) {
1395 			hub = *hubp;
1396 			*hubp = hub->next;
1397 			kmem_free(hub, sizeof (struct usba_root_hub_ent));
1398 			mutex_exit(&usba_hub_mutex);
1399 
1400 			return;
1401 		}
1402 		hubp = &(*hubp)->next;
1403 	}
1404 	mutex_exit(&usba_hub_mutex);
1405 }
1406 
1407 /*
1408  * check whether this dip is the root hub. Any root hub known by
1409  * usba is recorded in the linked list pointed to by usba_root_hubs
1410  */
1411 int
1412 usba_is_root_hub(dev_info_t *dip)
1413 {
1414 	usba_root_hub_ent_t *hub;
1415 
1416 	mutex_enter(&usba_hub_mutex);
1417 	hub = usba_root_hubs;
1418 	while (hub) {
1419 		if (hub->dip == dip) {
1420 			mutex_exit(&usba_hub_mutex);
1421 
1422 			return (1);
1423 		}
1424 		hub = hub->next;
1425 	}
1426 	mutex_exit(&usba_hub_mutex);
1427 
1428 	return (0);
1429 }
1430 
1431 /*
1432  * check whether this dip is a wire adapter device
1433  */
1434 int
1435 usba_is_wa(dev_info_t *dip)
1436 {
1437 	if (dip) {
1438 		usba_device_t *usba_device;
1439 
1440 		usba_device = usba_get_usba_device(dip);
1441 
1442 		return (usba_device->usb_is_wa? 1:0);
1443 	}
1444 
1445 	return (0);
1446 }
1447 
1448 /*
1449  * check whether this dip is a host wire adapter device node
1450  */
1451 int
1452 usba_is_hwa(dev_info_t *dip)
1453 {
1454 	dev_info_t	*cdip;
1455 
1456 	if (dip == NULL) {
1457 
1458 		return (0);
1459 	}
1460 
1461 	if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
1462 
1463 		return (0);
1464 	}
1465 
1466 	for (cdip = ddi_get_child(dip); cdip;
1467 	    cdip = ddi_get_next_sibling(cdip)) {
1468 		if (strcmp(ddi_driver_name(cdip), "hwarc") == 0) {
1469 
1470 			return (1);
1471 		}
1472 	}
1473 
1474 	return (0);
1475 }
1476 
1477 /*
1478  * get and store usba_device pointer in the devi
1479  */
1480 usba_device_t *
1481 usba_get_usba_device(dev_info_t *dip)
1482 {
1483 	/*
1484 	 * we cannot use parent_data in the usb node because its
1485 	 * bus parent (eg. PCI nexus driver) uses this data
1486 	 *
1487 	 * we cannot use driver data in the other usb nodes since
1488 	 * usb drivers may need to use this
1489 	 */
1490 	if (usba_is_root_hub(dip)) {
1491 		usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip);
1492 
1493 		return (hcdi->hcdi_usba_device);
1494 	} else {
1495 
1496 		return (ddi_get_parent_data(dip));
1497 	}
1498 }
1499 
1500 
1501 /*
1502  * Retrieve the usba_device pointer from the dev without checking for
1503  * the root hub first.	This function is only used in polled mode.
1504  */
1505 usba_device_t *
1506 usba_polled_get_usba_device(dev_info_t *dip)
1507 {
1508 	/*
1509 	 * Don't call usba_is_root_hub() to find out if this is
1510 	 * the root hub  usba_is_root_hub() calls into the DDI
1511 	 * where there are locking issues. The dip sent in during
1512 	 * polled mode will never be the root hub, so just get
1513 	 * the usba_device pointer from the dip.
1514 	 */
1515 	return (ddi_get_parent_data(dip));
1516 }
1517 
1518 
1519 void
1520 usba_set_usba_device(dev_info_t *dip, usba_device_t *usba_device)
1521 {
1522 	if (usba_is_root_hub(dip)) {
1523 		usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip);
1524 		/* no locking is needed here */
1525 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(hcdi->hcdi_usba_device))
1526 		hcdi->hcdi_usba_device = usba_device;
1527 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(hcdi->hcdi_usba_device))
1528 	} else {
1529 		ddi_set_parent_data(dip, usba_device);
1530 	}
1531 }
1532 
1533 
1534 /*
1535  * usba_set_node_name() according to class, subclass, and protocol
1536  * following the 1275 USB binding tables.
1537  */
1538 
1539 /* device node table, refer to section 3.2.2.1 of 1275 binding */
1540 static node_name_entry_t device_node_name_table[] = {
1541 { USB_CLASS_COMM,	DONTCARE,	DONTCARE,	"communications" },
1542 { USB_CLASS_HUB,	DONTCARE,	DONTCARE,	"hub" },
1543 { USB_CLASS_DIAG,	DONTCARE,	DONTCARE,	"diagnostics" },
1544 { USB_CLASS_MISC,	DONTCARE,	DONTCARE,	"miscellaneous" },
1545 { DONTCARE,		DONTCARE,	DONTCARE,	"device" }
1546 };
1547 
1548 /* interface-association node table */
1549 static node_name_entry_t ia_node_name_table[] = {
1550 { USB_CLASS_AUDIO,	DONTCARE,	DONTCARE, "audio" },
1551 { USB_CLASS_VIDEO,	DONTCARE,	DONTCARE, "video" },
1552 { USB_CLASS_WIRELESS,	USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_DWA,
1553 						"device-wire-adaptor" },
1554 { USB_CLASS_WIRELESS,	DONTCARE,	DONTCARE, "wireless-controller" },
1555 { DONTCARE,		DONTCARE,	DONTCARE, "interface-association" }
1556 };
1557 
1558 /* interface node table, refer to section 3.3.2.1 */
1559 static node_name_entry_t if_node_name_table[] = {
1560 { USB_CLASS_AUDIO, USB_SUBCLS_AUD_CONTROL, DONTCARE,	"sound-control" },
1561 { USB_CLASS_AUDIO, USB_SUBCLS_AUD_STREAMING, DONTCARE, "sound" },
1562 { USB_CLASS_AUDIO, USB_SUBCLS_AUD_MIDI_STREAMING, DONTCARE, "midi" },
1563 { USB_CLASS_AUDIO, DONTCARE,		DONTCARE,	"sound" },
1564 
1565 { USB_CLASS_COMM, USB_SUBCLS_CDCC_DIRECT_LINE,	DONTCARE, "line" },
1566 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ABSTRCT_CTRL,	DONTCARE, "modem" },
1567 { USB_CLASS_COMM, USB_SUBCLS_CDCC_PHONE_CTRL, DONTCARE, "telephone" },
1568 { USB_CLASS_COMM, USB_SUBCLS_CDCC_MULTCNL_ISDN, DONTCARE, "isdn" },
1569 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ISDN,		DONTCARE, "isdn" },
1570 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ETHERNET,	DONTCARE, "ethernet" },
1571 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ATM_NETWORK, DONTCARE, "atm-network" },
1572 { USB_CLASS_COMM, DONTCARE,		DONTCARE,	"communications" },
1573 
1574 { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_KEYBOARD,	"keyboard" },
1575 { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_MOUSE,	"mouse" },
1576 { USB_CLASS_HID,	DONTCARE,	DONTCARE,	"input" },
1577 
1578 { USB_CLASS_HUB,	DONTCARE,	DONTCARE,	"hub" },
1579 
1580 { USB_CLASS_PHYSICAL,	DONTCARE,	DONTCARE,	"physical" },
1581 
1582 { USB_CLASS_IMAGE,	DONTCARE,	DONTCARE,	"image" },
1583 
1584 { USB_CLASS_PRINTER,	DONTCARE,	DONTCARE,	"printer" },
1585 
1586 { USB_CLASS_MASS_STORAGE, DONTCARE,	DONTCARE,	"storage" },
1587 
1588 { USB_CLASS_CDC_DATA,	DONTCARE,	DONTCARE,	"data" },
1589 
1590 { USB_CLASS_SECURITY,	DONTCARE,	DONTCARE,	"security" },
1591 
1592 { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_CONTROL, DONTCARE,	"video-control" },
1593 { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_STREAM,  DONTCARE,	"video-stream" },
1594 { USB_CLASS_VIDEO,	DONTCARE,	DONTCARE,	"video" },
1595 
1596 { USB_CLASS_APP,	USB_SUBCLS_APP_FIRMWARE, DONTCARE, "firmware" },
1597 { USB_CLASS_APP,	USB_SUBCLS_APP_IRDA,	DONTCARE, "IrDa" },
1598 { USB_CLASS_APP,	USB_SUBCLS_APP_TEST,	DONTCARE, "test" },
1599 
1600 { USB_CLASS_MISC,	USB_SUBCLS_CBAF, USB_PROTO_CBAF,  "wusb_ca"},
1601 { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_1, USB_PROTO_WUSB_RC, "hwa-radio" },
1602 { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_HWA, "hwa-host" },
1603 { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_DWA, "dwa-control" },
1604 { USB_CLASS_WIRELESS, USB_SUBCLS_WUSB_2, USB_PROTO_WUSB_DWA_ISO, "dwa-isoc" },
1605 { USB_CLASS_WIRELESS, DONTCARE, DONTCARE, "wireless" },
1606 
1607 { DONTCARE,		DONTCARE,	DONTCARE,	"interface" },
1608 
1609 };
1610 
1611 /* combined node table, refer to section 3.4.2.1 */
1612 static node_name_entry_t combined_node_name_table[] = {
1613 { USB_CLASS_AUDIO, USB_SUBCLS_AUD_CONTROL, DONTCARE,	"sound-control" },
1614 { USB_CLASS_AUDIO, USB_SUBCLS_AUD_STREAMING, DONTCARE, "sound" },
1615 { USB_CLASS_AUDIO, USB_SUBCLS_AUD_MIDI_STREAMING, DONTCARE, "midi" },
1616 { USB_CLASS_AUDIO, DONTCARE,		DONTCARE,	"sound" },
1617 
1618 { USB_CLASS_COMM, USB_SUBCLS_CDCC_DIRECT_LINE,	DONTCARE, "line" },
1619 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ABSTRCT_CTRL,	DONTCARE, "modem" },
1620 { USB_CLASS_COMM, USB_SUBCLS_CDCC_PHONE_CTRL, DONTCARE, "telephone" },
1621 { USB_CLASS_COMM, USB_SUBCLS_CDCC_MULTCNL_ISDN, DONTCARE, "isdn" },
1622 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ISDN,		DONTCARE, "isdn" },
1623 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ETHERNET,	DONTCARE, "ethernet" },
1624 { USB_CLASS_COMM, USB_SUBCLS_CDCC_ATM_NETWORK, DONTCARE, "atm-network" },
1625 { USB_CLASS_COMM, DONTCARE,		DONTCARE,	"communications" },
1626 
1627 { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_KEYBOARD, "keyboard" },
1628 { USB_CLASS_HID, USB_SUBCLS_HID_1, USB_PROTO_HID_MOUSE,	"mouse" },
1629 { USB_CLASS_HID,	DONTCARE,	DONTCARE,	"input" },
1630 
1631 { USB_CLASS_PHYSICAL,	DONTCARE,	DONTCARE,	"physical" },
1632 
1633 { USB_CLASS_IMAGE,	DONTCARE,	DONTCARE,	"image" },
1634 
1635 { USB_CLASS_PRINTER,	DONTCARE,	DONTCARE,	"printer" },
1636 
1637 { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_RBC_T10,	DONTCARE, "storage" },
1638 { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_SFF8020I,	DONTCARE, "cdrom" },
1639 { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_QIC_157,	DONTCARE, "tape" },
1640 { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_UFI,		DONTCARE, "floppy" },
1641 { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_SFF8070I,	DONTCARE, "storage" },
1642 { USB_CLASS_MASS_STORAGE, USB_SUBCLS_MS_SCSI,		DONTCARE, "storage" },
1643 { USB_CLASS_MASS_STORAGE, DONTCARE,	DONTCARE,	"storage" },
1644 
1645 { USB_CLASS_CDC_DATA,	DONTCARE,	DONTCARE,	"data" },
1646 
1647 { USB_CLASS_SECURITY,	DONTCARE,	DONTCARE,	"security" },
1648 
1649 { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_CONTROL, DONTCARE,	"video-control" },
1650 { USB_CLASS_VIDEO, USB_SUBCLS_VIDEO_STREAM,  DONTCARE,	"video-stream" },
1651 { USB_CLASS_VIDEO,	DONTCARE,	DONTCARE,	"video" },
1652 
1653 { USB_CLASS_APP,	USB_SUBCLS_APP_FIRMWARE, DONTCARE, "firmware" },
1654 { USB_CLASS_APP,	USB_SUBCLS_APP_IRDA,	DONTCARE, "IrDa" },
1655 { USB_CLASS_APP,	USB_SUBCLS_APP_TEST,	DONTCARE, "test" },
1656 
1657 { USB_CLASS_COMM,	DONTCARE,	DONTCARE,	"communications" },
1658 { USB_CLASS_HUB,	DONTCARE,	DONTCARE,	"hub" },
1659 { USB_CLASS_DIAG,	DONTCARE,	DONTCARE,	"diagnostics" },
1660 { USB_CLASS_MISC,	DONTCARE,	DONTCARE,	"miscellaneous" },
1661 { DONTCARE,		DONTCARE,	DONTCARE,	"device" }
1662 };
1663 
1664 static size_t device_node_name_table_size =
1665 	sizeof (device_node_name_table)/sizeof (struct node_name_entry);
1666 static size_t ia_node_name_table_size =
1667 	sizeof (ia_node_name_table)/sizeof (struct node_name_entry);
1668 static size_t if_node_name_table_size =
1669 	sizeof (if_node_name_table)/sizeof (struct node_name_entry);
1670 static size_t combined_node_name_table_size =
1671 	sizeof (combined_node_name_table)/sizeof (struct node_name_entry);
1672 
1673 
1674 static void
1675 usba_set_node_name(dev_info_t *dip, uint8_t class, uint8_t subclass,
1676     uint8_t protocol, uint_t flag)
1677 {
1678 	int i;
1679 	size_t size;
1680 	node_name_entry_t *node_name_table;
1681 
1682 	switch (flag) {
1683 	/* interface share node names with interface-association */
1684 	case FLAG_INTERFACE_ASSOCIATION_NODE:
1685 		node_name_table = ia_node_name_table;
1686 		size = ia_node_name_table_size;
1687 		break;
1688 	case FLAG_INTERFACE_NODE:
1689 		node_name_table = if_node_name_table;
1690 		size = if_node_name_table_size;
1691 		break;
1692 	case FLAG_DEVICE_NODE:
1693 		node_name_table = device_node_name_table;
1694 		size = device_node_name_table_size;
1695 		break;
1696 	case FLAG_COMBINED_NODE:
1697 		node_name_table = combined_node_name_table;
1698 		size = combined_node_name_table_size;
1699 		break;
1700 	default:
1701 
1702 		return;
1703 	}
1704 
1705 	for (i = 0; i < size; i++) {
1706 		int16_t c = node_name_table[i].class;
1707 		int16_t s = node_name_table[i].subclass;
1708 		int16_t p = node_name_table[i].protocol;
1709 
1710 		if (((c == DONTCARE) || (c == class)) &&
1711 		    ((s == DONTCARE) || (s == subclass)) &&
1712 		    ((p == DONTCARE) || (p == protocol))) {
1713 			char *name = node_name_table[i].name;
1714 
1715 			(void) ndi_devi_set_nodename(dip, name, 0);
1716 			break;
1717 		}
1718 	}
1719 }
1720 
1721 
1722 #ifdef DEBUG
1723 /*
1724  * walk the children of the parent of this devi and compare the
1725  * name and  reg property of each child. If there is a match
1726  * return this node
1727  */
1728 static dev_info_t *
1729 usba_find_existing_node(dev_info_t *odip)
1730 {
1731 	dev_info_t *ndip, *child, *pdip;
1732 	int	*odata, *ndata;
1733 	uint_t	n_odata, n_ndata;
1734 	int	circular;
1735 
1736 	pdip = ddi_get_parent(odip);
1737 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
1738 	    odip, DDI_PROP_DONTPASS, "reg",
1739 	    &odata, &n_odata) != DDI_SUCCESS) {
1740 		USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1741 		    "usba_find_existing_node: "
1742 		    "%s: DDI_NOT_WELL_FORMED", ddi_driver_name(odip));
1743 
1744 		return (NULL);
1745 	}
1746 
1747 	ndi_devi_enter(pdip, &circular);
1748 	ndip = (dev_info_t *)(DEVI(pdip)->devi_child);
1749 	while ((child = ndip) != NULL) {
1750 
1751 		ndip = (dev_info_t *)(DEVI(child)->devi_sibling);
1752 
1753 		if (child == odip) {
1754 			continue;
1755 		}
1756 
1757 		if (strcmp(DEVI(child)->devi_node_name,
1758 		    DEVI(odip)->devi_node_name)) {
1759 			continue;
1760 		}
1761 
1762 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
1763 		    child, DDI_PROP_DONTPASS, "reg",
1764 		    &ndata, &n_ndata) != DDI_SUCCESS) {
1765 
1766 			USB_DPRINTF_L2(DPRINT_MASK_HCDI, usba_log_handle,
1767 			    "usba_find_existing_node: "
1768 			    "%s DDI_NOT_WELL_FORMED", ddi_driver_name(child));
1769 
1770 		} else if (n_ndata && n_odata && (bcmp(odata, ndata,
1771 		    max(n_odata, n_ndata) * sizeof (int)) == 0)) {
1772 
1773 			USB_DPRINTF_L3(DPRINT_MASK_HCDI, usba_log_handle,
1774 			    "usba_find_existing_node: found %s%d (%p)",
1775 			    ddi_driver_name(child),
1776 			    ddi_get_instance(child), (void *)child);
1777 
1778 			USB_DPRINTF_L3(DPRINT_MASK_HCDI, usba_log_handle,
1779 			    "usba_find_existing_node: "
1780 			    "reg: %x %x %x - %x %x %x",
1781 			    n_odata, odata[0], odata[1],
1782 			    n_ndata, ndata[0], ndata[1]);
1783 
1784 			ddi_prop_free(ndata);
1785 			break;
1786 
1787 		} else {
1788 			ddi_prop_free(ndata);
1789 		}
1790 	}
1791 
1792 	ndi_devi_exit(pdip, circular);
1793 
1794 	ddi_prop_free(odata);
1795 
1796 	return (child);
1797 }
1798 #endif
1799 
1800 /* change all unprintable characters to spaces */
1801 static void
1802 usba_filter_string(char *instr, char *outstr)
1803 {
1804 	while (*instr) {
1805 		if ((*instr >= ' ') && (*instr <= '~')) {
1806 			*outstr = *instr;
1807 		} else {
1808 			*outstr = ' ';
1809 		}
1810 		outstr++;
1811 		instr++;
1812 	}
1813 	*outstr = '\0';
1814 }
1815 
1816 
1817 /*
1818  * lookup ugen binding specified in property in
1819  * hcd.conf files
1820  */
1821 int
1822 usba_get_ugen_binding(dev_info_t *dip)
1823 {
1824 	usba_device_t	*usba_device = usba_get_usba_device(dip);
1825 	usba_hcdi_t	*hcdi =
1826 	    usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
1827 
1828 	return (hcdi->hcdi_ugen_default_binding);
1829 }
1830 
1831 
1832 /*
1833  * driver binding support at device level
1834  */
1835 dev_info_t *
1836 usba_ready_device_node(dev_info_t *child_dip)
1837 {
1838 	int		rval, i;
1839 	int		n = 0;
1840 	usba_device_t	*usba_device = usba_get_usba_device(child_dip);
1841 	usb_dev_descr_t	*usb_dev_descr;
1842 	uint_t		n_cfgs;	/* number of configs */
1843 	uint_t		n_ifs;	/* number of interfaces */
1844 	uint_t		port;
1845 	size_t		usb_config_length;
1846 	uchar_t 	*usb_config;
1847 	int		reg[1];
1848 	usb_addr_t	address = usb_get_addr(child_dip);
1849 	usb_if_descr_t	if_descr;
1850 	size_t		size;
1851 	int		combined_node = 0;
1852 	int		is_hub;
1853 	char		*devprop_str;
1854 	char		*force_bind = NULL;
1855 	char		*usba_name_buf = NULL;
1856 	char		*usba_name[USBA_MAX_COMPAT_NAMES];
1857 
1858 	usb_config = usb_get_raw_cfg_data(child_dip, &usb_config_length);
1859 
1860 	mutex_enter(&usba_device->usb_mutex);
1861 	mutex_enter(&usba_mutex);
1862 
1863 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
1864 	    "usba_ready_device_node: child=0x%p", (void *)child_dip);
1865 
1866 	port = usba_device->usb_port;
1867 	usb_dev_descr = usba_device->usb_dev_descr;
1868 	n_cfgs = usba_device->usb_n_cfgs;
1869 	n_ifs = usba_device->usb_n_ifs;
1870 
1871 
1872 	if (address != ROOT_HUB_ADDR) {
1873 		size = usb_parse_if_descr(
1874 		    usb_config,
1875 		    usb_config_length,
1876 		    0,		/* interface index */
1877 		    0,		/* alt interface index */
1878 		    &if_descr,
1879 		    USB_IF_DESCR_SIZE);
1880 
1881 		if (size != USB_IF_DESCR_SIZE) {
1882 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
1883 			    "parsing interface: "
1884 			    "size (%lu) != USB_IF_DESCR_SIZE (%d)",
1885 			    size, USB_IF_DESCR_SIZE);
1886 
1887 			mutex_exit(&usba_mutex);
1888 			mutex_exit(&usba_device->usb_mutex);
1889 
1890 			return (child_dip);
1891 		}
1892 	} else {
1893 		/* fake an interface descriptor for the root hub */
1894 		bzero(&if_descr, sizeof (if_descr));
1895 
1896 		if_descr.bInterfaceClass = USB_CLASS_HUB;
1897 	}
1898 
1899 	reg[0] = port;
1900 
1901 	mutex_exit(&usba_mutex);
1902 	mutex_exit(&usba_device->usb_mutex);
1903 
1904 	rval = ndi_prop_update_int_array(
1905 	    DDI_DEV_T_NONE, child_dip, "reg", reg, 1);
1906 
1907 	if (rval != DDI_PROP_SUCCESS) {
1908 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
1909 		    "usba_ready_device_node: property update failed");
1910 
1911 		return (child_dip);
1912 	}
1913 
1914 	combined_node = ((n_cfgs == 1) && (n_ifs == 1) &&
1915 	    ((usb_dev_descr->bDeviceClass == USB_CLASS_HUB) ||
1916 	    (usb_dev_descr->bDeviceClass == 0)));
1917 
1918 	is_hub = (if_descr.bInterfaceClass == USB_CLASS_HUB) ||
1919 	    (usb_dev_descr->bDeviceClass == USB_CLASS_HUB);
1920 
1921 	/* set node name */
1922 	if (combined_node) {
1923 		usba_set_node_name(child_dip,
1924 		    if_descr.bInterfaceClass,
1925 		    if_descr.bInterfaceSubClass,
1926 		    if_descr.bInterfaceProtocol,
1927 		    FLAG_COMBINED_NODE);
1928 	} else {
1929 		usba_set_node_name(child_dip,
1930 		    usb_dev_descr->bDeviceClass,
1931 		    usb_dev_descr->bDeviceSubClass,
1932 		    usb_dev_descr->bDeviceProtocol,
1933 		    FLAG_DEVICE_NODE);
1934 	}
1935 
1936 	/*
1937 	 * check force binding rules
1938 	 */
1939 	if ((address != ROOT_HUB_ADDR) && usba_ddivs_usbc &&
1940 	    (address != usba_ddivs_usbc_xaddress) &&
1941 	    (!(usba_ddivs_usbc_xhubs && is_hub))) {
1942 		force_bind = "ddivs_usbc";
1943 		(void) ndi_devi_set_nodename(child_dip, "ddivs_usbc", 0);
1944 
1945 	} else if (usba_device->usb_preferred_driver) {
1946 		force_bind = usba_device->usb_preferred_driver;
1947 
1948 	} else if ((address != ROOT_HUB_ADDR) &&
1949 	    ((usba_ugen_force_binding == USBA_UGEN_DEVICE_BINDING) ||
1950 	    ((usba_ugen_force_binding == USBA_UGEN_INTERFACE_BINDING) &&
1951 	    combined_node)) && (!is_hub)) {
1952 		force_bind = "ugen";
1953 	}
1954 
1955 #ifdef DEBUG
1956 	/*
1957 	 * check whether there is another dip with this name and address
1958 	 * If the dip contains usba_device, it is held by the previous
1959 	 * round of configuration.
1960 	 */
1961 	ASSERT(usba_find_existing_node(child_dip) == NULL);
1962 #endif
1963 
1964 	usba_name_buf = kmem_zalloc(USBA_MAX_COMPAT_NAMES *
1965 	    USBA_MAX_COMPAT_NAME_LEN, KM_SLEEP);
1966 
1967 	for (i = 0; i < USBA_MAX_COMPAT_NAMES; i++) {
1968 		usba_name[i] = usba_name_buf + (i * USBA_MAX_COMPAT_NAME_LEN);
1969 	}
1970 
1971 	if (force_bind) {
1972 		(void) ndi_devi_set_nodename(child_dip, force_bind, 0);
1973 		(void) strncpy(usba_name[n++], force_bind,
1974 		    USBA_MAX_COMPAT_NAME_LEN);
1975 	}
1976 
1977 	/* create compatible names */
1978 	if (combined_node) {
1979 
1980 		/* 1. usbVID,PID.REV */
1981 		(void) sprintf(usba_name[n++],
1982 		    "usb%x,%x.%x",
1983 		    usb_dev_descr->idVendor,
1984 		    usb_dev_descr->idProduct,
1985 		    usb_dev_descr->bcdDevice);
1986 
1987 		/* 2. usbVID,PID */
1988 		(void) sprintf(usba_name[n++],
1989 		    "usb%x,%x",
1990 		    usb_dev_descr->idVendor,
1991 		    usb_dev_descr->idProduct);
1992 
1993 		if (usb_dev_descr->bDeviceClass != 0) {
1994 			/* 3. usbVID,classDC.DSC.DPROTO */
1995 			(void) sprintf(usba_name[n++],
1996 			    "usb%x,class%x.%x.%x",
1997 			    usb_dev_descr->idVendor,
1998 			    usb_dev_descr->bDeviceClass,
1999 			    usb_dev_descr->bDeviceSubClass,
2000 			    usb_dev_descr->bDeviceProtocol);
2001 
2002 			/* 4. usbVID,classDC.DSC */
2003 			(void) sprintf(usba_name[n++],
2004 			    "usb%x,class%x.%x",
2005 			    usb_dev_descr->idVendor,
2006 			    usb_dev_descr->bDeviceClass,
2007 			    usb_dev_descr->bDeviceSubClass);
2008 
2009 			/* 5. usbVID,classDC */
2010 			(void) sprintf(usba_name[n++],
2011 			    "usb%x,class%x",
2012 			    usb_dev_descr->idVendor,
2013 			    usb_dev_descr->bDeviceClass);
2014 
2015 			/* 6. usb,classDC.DSC.DPROTO */
2016 			(void) sprintf(usba_name[n++],
2017 			    "usb,class%x.%x.%x",
2018 			    usb_dev_descr->bDeviceClass,
2019 			    usb_dev_descr->bDeviceSubClass,
2020 			    usb_dev_descr->bDeviceProtocol);
2021 
2022 			/* 7. usb,classDC.DSC */
2023 			(void) sprintf(usba_name[n++],
2024 			    "usb,class%x.%x",
2025 			    usb_dev_descr->bDeviceClass,
2026 			    usb_dev_descr->bDeviceSubClass);
2027 
2028 			/* 8. usb,classDC */
2029 			(void) sprintf(usba_name[n++],
2030 			    "usb,class%x",
2031 			    usb_dev_descr->bDeviceClass);
2032 		}
2033 
2034 		if (if_descr.bInterfaceClass != 0) {
2035 			/* 9. usbifVID,classIC.ISC.IPROTO */
2036 			(void) sprintf(usba_name[n++],
2037 			    "usbif%x,class%x.%x.%x",
2038 			    usb_dev_descr->idVendor,
2039 			    if_descr.bInterfaceClass,
2040 			    if_descr.bInterfaceSubClass,
2041 			    if_descr.bInterfaceProtocol);
2042 
2043 			/* 10. usbifVID,classIC.ISC */
2044 			(void) sprintf(usba_name[n++],
2045 			    "usbif%x,class%x.%x",
2046 			    usb_dev_descr->idVendor,
2047 			    if_descr.bInterfaceClass,
2048 			    if_descr.bInterfaceSubClass);
2049 
2050 			/* 11. usbifVID,classIC */
2051 			(void) sprintf(usba_name[n++],
2052 			    "usbif%x,class%x",
2053 			    usb_dev_descr->idVendor,
2054 			    if_descr.bInterfaceClass);
2055 
2056 			/* 12. usbif,classIC.ISC.IPROTO */
2057 			(void) sprintf(usba_name[n++],
2058 			    "usbif,class%x.%x.%x",
2059 			    if_descr.bInterfaceClass,
2060 			    if_descr.bInterfaceSubClass,
2061 			    if_descr.bInterfaceProtocol);
2062 
2063 			/* 13. usbif,classIC.ISC */
2064 			(void) sprintf(usba_name[n++],
2065 			    "usbif,class%x.%x",
2066 			    if_descr.bInterfaceClass,
2067 			    if_descr.bInterfaceSubClass);
2068 
2069 			/* 14. usbif,classIC */
2070 			(void) sprintf(usba_name[n++],
2071 			    "usbif,class%x",
2072 			    if_descr.bInterfaceClass);
2073 		}
2074 
2075 		/* 15. ugen or usb_mid */
2076 		if (usba_get_ugen_binding(child_dip) ==
2077 		    USBA_UGEN_DEVICE_BINDING) {
2078 			(void) sprintf(usba_name[n++], "ugen");
2079 		} else {
2080 			(void) sprintf(usba_name[n++], "usb,device");
2081 		}
2082 
2083 	} else {
2084 		if (n_cfgs > 1) {
2085 			/* 1. usbVID,PID.REV.configCN */
2086 			(void) sprintf(usba_name[n++],
2087 			    "usb%x,%x.%x.config%x",
2088 			    usb_dev_descr->idVendor,
2089 			    usb_dev_descr->idProduct,
2090 			    usb_dev_descr->bcdDevice,
2091 			    usba_device->usb_cfg_value);
2092 		}
2093 
2094 		/* 2. usbVID,PID.REV */
2095 		(void) sprintf(usba_name[n++],
2096 		    "usb%x,%x.%x",
2097 		    usb_dev_descr->idVendor,
2098 		    usb_dev_descr->idProduct,
2099 		    usb_dev_descr->bcdDevice);
2100 
2101 		/* 3. usbVID,PID.configCN */
2102 		if (n_cfgs > 1) {
2103 			(void) sprintf(usba_name[n++],
2104 			    "usb%x,%x.%x",
2105 			    usb_dev_descr->idVendor,
2106 			    usb_dev_descr->idProduct,
2107 			    usba_device->usb_cfg_value);
2108 		}
2109 
2110 		/* 4. usbVID,PID */
2111 		(void) sprintf(usba_name[n++],
2112 		    "usb%x,%x",
2113 		    usb_dev_descr->idVendor,
2114 		    usb_dev_descr->idProduct);
2115 
2116 		if (usb_dev_descr->bDeviceClass != 0) {
2117 			/* 5. usbVID,classDC.DSC.DPROTO */
2118 			(void) sprintf(usba_name[n++],
2119 			    "usb%x,class%x.%x.%x",
2120 			    usb_dev_descr->idVendor,
2121 			    usb_dev_descr->bDeviceClass,
2122 			    usb_dev_descr->bDeviceSubClass,
2123 			    usb_dev_descr->bDeviceProtocol);
2124 
2125 			/* 6. usbVID,classDC.DSC */
2126 			(void) sprintf(usba_name[n++],
2127 			    "usb%x.class%x.%x",
2128 			    usb_dev_descr->idVendor,
2129 			    usb_dev_descr->bDeviceClass,
2130 			    usb_dev_descr->bDeviceSubClass);
2131 
2132 			/* 7. usbVID,classDC */
2133 			(void) sprintf(usba_name[n++],
2134 			    "usb%x.class%x",
2135 			    usb_dev_descr->idVendor,
2136 			    usb_dev_descr->bDeviceClass);
2137 
2138 			/* 8. usb,classDC.DSC.DPROTO */
2139 			(void) sprintf(usba_name[n++],
2140 			    "usb,class%x.%x.%x",
2141 			    usb_dev_descr->bDeviceClass,
2142 			    usb_dev_descr->bDeviceSubClass,
2143 			    usb_dev_descr->bDeviceProtocol);
2144 
2145 			/* 9. usb,classDC.DSC */
2146 			(void) sprintf(usba_name[n++],
2147 			    "usb,class%x.%x",
2148 			    usb_dev_descr->bDeviceClass,
2149 			    usb_dev_descr->bDeviceSubClass);
2150 
2151 			/* 10. usb,classDC */
2152 			(void) sprintf(usba_name[n++],
2153 			    "usb,class%x",
2154 			    usb_dev_descr->bDeviceClass);
2155 		}
2156 
2157 		if (usba_get_ugen_binding(child_dip) ==
2158 		    USBA_UGEN_DEVICE_BINDING) {
2159 			/* 11. ugen */
2160 			(void) sprintf(usba_name[n++], "ugen");
2161 		} else {
2162 			/* 11. usb,device */
2163 			(void) sprintf(usba_name[n++], "usb,device");
2164 		}
2165 	}
2166 
2167 	for (i = 0; i < n; i += 2) {
2168 		USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2169 		    "compatible name:\t%s\t%s", usba_name[i],
2170 		    (((i+1) < n)? usba_name[i+1] : ""));
2171 	}
2172 
2173 	rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip,
2174 	    "compatible", (char **)usba_name, n);
2175 
2176 	kmem_free(usba_name_buf, USBA_MAX_COMPAT_NAMES *
2177 	    USBA_MAX_COMPAT_NAME_LEN);
2178 
2179 	if (rval != DDI_PROP_SUCCESS) {
2180 
2181 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2182 		    "usba_ready_device_node: property update failed");
2183 
2184 		return (child_dip);
2185 	}
2186 
2187 	/* update the address property */
2188 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2189 	    "assigned-address", usba_device->usb_addr);
2190 	if (rval != DDI_PROP_SUCCESS) {
2191 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2192 		    "usba_ready_device_node: address update failed");
2193 	}
2194 
2195 	/* update the usb device properties (PSARC/2000/454) */
2196 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2197 	    "usb-vendor-id", usb_dev_descr->idVendor);
2198 	if (rval != DDI_PROP_SUCCESS) {
2199 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2200 		    "usba_ready_device_node: usb-vendor-id update failed");
2201 	}
2202 
2203 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2204 	    "usb-product-id", usb_dev_descr->idProduct);
2205 	if (rval != DDI_PROP_SUCCESS) {
2206 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2207 		    "usba_ready_device_node: usb-product-id update failed");
2208 	}
2209 
2210 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2211 	    "usb-revision-id", usb_dev_descr->bcdDevice);
2212 	if (rval != DDI_PROP_SUCCESS) {
2213 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2214 		    "usba_ready_device_node: usb-revision-id update failed");
2215 	}
2216 
2217 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2218 	    "usb-num-configs", usb_dev_descr->bNumConfigurations);
2219 	if (rval != DDI_PROP_SUCCESS) {
2220 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2221 		    "usba_ready_device_node: usb-num-configs update failed");
2222 	}
2223 
2224 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2225 	    "usb-release", usb_dev_descr->bcdUSB);
2226 	if (rval != DDI_PROP_SUCCESS) {
2227 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2228 		    "usba_ready_device_node: usb-release update failed");
2229 	}
2230 
2231 	rval = ndi_prop_update_byte_array(DDI_DEV_T_NONE, child_dip,
2232 	    "usb-dev-descriptor", (uchar_t *)usb_dev_descr,
2233 	    sizeof (usb_dev_descr_t));
2234 	if (rval != DDI_PROP_SUCCESS) {
2235 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2236 		    "usba_ready_device_node: usb-descriptor update failed");
2237 	}
2238 
2239 	rval = ndi_prop_update_byte_array(DDI_DEV_T_NONE, child_dip,
2240 	    "usb-raw-cfg-descriptors", usb_config, usb_config_length);
2241 	if (rval != DDI_PROP_SUCCESS) {
2242 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2243 		    "usba_ready_device_node: usb-raw-cfg-descriptors update "
2244 		    "failed");
2245 	}
2246 
2247 	devprop_str = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
2248 
2249 	if (usba_device->usb_serialno_str) {
2250 		usba_filter_string(usba_device->usb_serialno_str, devprop_str);
2251 		rval = ndi_prop_update_string(DDI_DEV_T_NONE, child_dip,
2252 		    "usb-serialno", devprop_str);
2253 		if (rval != DDI_PROP_SUCCESS) {
2254 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2255 			    "usba_ready_device_node: "
2256 			    "usb-serialno update failed");
2257 		}
2258 	}
2259 
2260 	if (usba_device->usb_mfg_str) {
2261 		usba_filter_string(usba_device->usb_mfg_str, devprop_str);
2262 		rval = ndi_prop_update_string(DDI_DEV_T_NONE, child_dip,
2263 		    "usb-vendor-name", devprop_str);
2264 		if (rval != DDI_PROP_SUCCESS) {
2265 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2266 			    "usba_ready_device_node: "
2267 			    "usb-vendor-name update failed");
2268 		}
2269 	}
2270 
2271 	if (usba_device->usb_product_str) {
2272 		usba_filter_string(usba_device->usb_product_str, devprop_str);
2273 		rval = ndi_prop_update_string(DDI_DEV_T_NONE, child_dip,
2274 		    "usb-product-name", devprop_str);
2275 		if (rval != DDI_PROP_SUCCESS) {
2276 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2277 			    "usba_ready_device_node: "
2278 			    "usb-product-name update failed");
2279 		}
2280 	}
2281 
2282 	kmem_free(devprop_str, USB_MAXSTRINGLEN);
2283 
2284 	if (!combined_node) {
2285 		/* update the configuration property */
2286 		rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2287 		    "configuration#", usba_device->usb_cfg_value);
2288 		if (rval != DDI_PROP_SUCCESS) {
2289 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2290 			    "usba_ready_device_node: "
2291 			    "config prop update failed");
2292 		}
2293 	}
2294 
2295 	if (usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
2296 		/* create boolean property */
2297 		rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, child_dip,
2298 		    "low-speed");
2299 		if (rval != DDI_PROP_SUCCESS) {
2300 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2301 			    "usba_ready_device_node: "
2302 			    "low speed prop update failed");
2303 		}
2304 	}
2305 
2306 	if (usba_device->usb_port_status == USBA_HIGH_SPEED_DEV) {
2307 		/* create boolean property */
2308 		rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, child_dip,
2309 		    "high-speed");
2310 		if (rval != DDI_PROP_SUCCESS) {
2311 			USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2312 			    "usba_ready_device_node: "
2313 			    "high speed prop update failed");
2314 		}
2315 	}
2316 
2317 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
2318 	    "%s%d at port %d: %s, dip=0x%p",
2319 	    ddi_node_name(ddi_get_parent(child_dip)),
2320 	    ddi_get_instance(ddi_get_parent(child_dip)),
2321 	    port, ddi_node_name(child_dip), (void *)child_dip);
2322 
2323 	usba_set_usba_device(child_dip, usba_device);
2324 
2325 	ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip)->usb_mutex)));
2326 
2327 	return (child_dip);
2328 }
2329 
2330 
2331 /*
2332  * driver binding at interface association level. the first arg is the parent
2333  * dip. if_count returns amount of interfaces which are associated within
2334  * this interface-association that starts from first_if.
2335  */
2336 /*ARGSUSED*/
2337 dev_info_t *
2338 usba_ready_interface_association_node(dev_info_t	*dip,
2339 					uint_t		first_if,
2340 					uint_t		*if_count)
2341 {
2342 	dev_info_t		*child_dip = NULL;
2343 	usba_device_t		*child_ud = usba_get_usba_device(dip);
2344 	usb_dev_descr_t		*usb_dev_descr;
2345 	size_t			usb_cfg_length;
2346 	uchar_t			*usb_cfg;
2347 	usb_ia_descr_t		ia_descr;
2348 	int			i, n, rval;
2349 	int			reg[2];
2350 	size_t			size;
2351 	usb_port_status_t	port_status;
2352 	char			*force_bind = NULL;
2353 	char			*usba_name_buf = NULL;
2354 	char			*usba_name[USBA_MAX_COMPAT_NAMES];
2355 
2356 	usb_cfg = usb_get_raw_cfg_data(dip, &usb_cfg_length);
2357 
2358 	mutex_enter(&child_ud->usb_mutex);
2359 
2360 	usb_dev_descr = child_ud->usb_dev_descr;
2361 
2362 	/*
2363 	 * for each interface association, determine all compatible names
2364 	 */
2365 	USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2366 	    "usba_ready_ia_node: "
2367 	    "port %d, interface = %d, port_status = %x",
2368 	    child_ud->usb_port, first_if, child_ud->usb_port_status);
2369 
2370 	/* Parse the interface descriptor */
2371 	size = usb_parse_ia_descr(
2372 	    usb_cfg,
2373 	    usb_cfg_length,
2374 	    first_if,	/* interface index */
2375 	    &ia_descr,
2376 	    USB_IA_DESCR_SIZE);
2377 
2378 	*if_count = 1;
2379 	if (size != USB_IA_DESCR_SIZE) {
2380 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2381 		    "parsing ia: size (%lu) != USB_IA_DESCR_SIZE (%d)",
2382 		    size, USB_IA_DESCR_SIZE);
2383 		mutex_exit(&child_ud->usb_mutex);
2384 
2385 		return (NULL);
2386 	}
2387 
2388 	port_status = child_ud->usb_port_status;
2389 
2390 	/* create reg property */
2391 	reg[0] = first_if;
2392 	reg[1] = child_ud->usb_cfg_value;
2393 
2394 	mutex_exit(&child_ud->usb_mutex);
2395 
2396 	/* clone this dip */
2397 	rval =	usba_create_child_devi(dip,
2398 	    "interface-association",
2399 	    NULL,		/* usba_hcdi ops */
2400 	    NULL,		/* root hub dip */
2401 	    port_status,	/* port status */
2402 	    child_ud,	/* share this usba_device */
2403 	    &child_dip);
2404 
2405 	if (rval != USB_SUCCESS) {
2406 
2407 		goto fail;
2408 	}
2409 
2410 	rval = ndi_prop_update_int_array(
2411 	    DDI_DEV_T_NONE, child_dip, "reg", reg, 2);
2412 
2413 	if (rval != DDI_PROP_SUCCESS) {
2414 
2415 		goto fail;
2416 	}
2417 
2418 	usba_set_node_name(child_dip, ia_descr.bFunctionClass,
2419 	    ia_descr.bFunctionSubClass, ia_descr.bFunctionProtocol,
2420 	    FLAG_INTERFACE_ASSOCIATION_NODE);
2421 
2422 	/* check force binding */
2423 	if (usba_ugen_force_binding ==
2424 	    USBA_UGEN_INTERFACE_ASSOCIATION_BINDING) {
2425 		force_bind = "ugen";
2426 	}
2427 
2428 	/*
2429 	 * check whether there is another dip with this name and address
2430 	 */
2431 	ASSERT(usba_find_existing_node(child_dip) == NULL);
2432 
2433 	usba_name_buf = kmem_zalloc(USBA_MAX_COMPAT_NAMES *
2434 	    USBA_MAX_COMPAT_NAME_LEN, KM_SLEEP);
2435 
2436 	for (i = 0; i < USBA_MAX_COMPAT_NAMES; i++) {
2437 		usba_name[i] = usba_name_buf + (i * USBA_MAX_COMPAT_NAME_LEN);
2438 	}
2439 
2440 	n = 0;
2441 
2442 	if (force_bind) {
2443 		(void) ndi_devi_set_nodename(child_dip, force_bind, 0);
2444 		(void) strncpy(usba_name[n++], force_bind,
2445 		    USBA_MAX_COMPAT_NAME_LEN);
2446 	}
2447 
2448 	/* 1) usbiaVID,PID.REV.configCN.FN */
2449 	(void) sprintf(usba_name[n++],
2450 	    "usbia%x,%x.%x.config%x.%x",
2451 	    usb_dev_descr->idVendor,
2452 	    usb_dev_descr->idProduct,
2453 	    usb_dev_descr->bcdDevice,
2454 	    child_ud->usb_cfg_value,
2455 	    first_if);
2456 
2457 	/* 2) usbiaVID,PID.configCN.FN */
2458 	(void) sprintf(usba_name[n++],
2459 	    "usbia%x,%x.config%x.%x",
2460 	    usb_dev_descr->idVendor,
2461 	    usb_dev_descr->idProduct,
2462 	    child_ud->usb_cfg_value,
2463 	    first_if);
2464 
2465 
2466 	if (ia_descr.bFunctionClass) {
2467 		/* 3) usbiaVID,classFC.FSC.FPROTO */
2468 		(void) sprintf(usba_name[n++],
2469 		    "usbia%x,class%x.%x.%x",
2470 		    usb_dev_descr->idVendor,
2471 		    ia_descr.bFunctionClass,
2472 		    ia_descr.bFunctionSubClass,
2473 		    ia_descr.bFunctionProtocol);
2474 
2475 		/* 4) usbiaVID,classFC.FSC */
2476 		(void) sprintf(usba_name[n++],
2477 		    "usbia%x,class%x.%x",
2478 		    usb_dev_descr->idVendor,
2479 		    ia_descr.bFunctionClass,
2480 		    ia_descr.bFunctionSubClass);
2481 
2482 		/* 5) usbiaVID,classFC */
2483 		(void) sprintf(usba_name[n++],
2484 		    "usbia%x,class%x",
2485 		    usb_dev_descr->idVendor,
2486 		    ia_descr.bFunctionClass);
2487 
2488 		/* 6) usbia,classFC.FSC.FPROTO */
2489 		(void) sprintf(usba_name[n++],
2490 		    "usbia,class%x.%x.%x",
2491 		    ia_descr.bFunctionClass,
2492 		    ia_descr.bFunctionSubClass,
2493 		    ia_descr.bFunctionProtocol);
2494 
2495 		/* 7) usbia,classFC.FSC */
2496 		(void) sprintf(usba_name[n++],
2497 		    "usbia,class%x.%x",
2498 		    ia_descr.bFunctionClass,
2499 		    ia_descr.bFunctionSubClass);
2500 
2501 		/* 8) usbia,classFC */
2502 		(void) sprintf(usba_name[n++],
2503 		    "usbia,class%x",
2504 		    ia_descr.bFunctionClass);
2505 	}
2506 
2507 	if (usba_get_ugen_binding(child_dip) ==
2508 	    USBA_UGEN_INTERFACE_ASSOCIATION_BINDING) {
2509 		/* 9) ugen */
2510 		(void) sprintf(usba_name[n++], "ugen");
2511 	} else {
2512 
2513 		(void) sprintf(usba_name[n++], "usb,ia");
2514 	}
2515 
2516 	for (i = 0; i < n; i += 2) {
2517 		USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2518 		    "compatible name:\t%s\t%s", usba_name[i],
2519 		    (((i+1) < n)? usba_name[i+1] : ""));
2520 	}
2521 
2522 	/* create compatible property */
2523 	rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip,
2524 	    "compatible", (char **)usba_name, n);
2525 
2526 	kmem_free(usba_name_buf, USBA_MAX_COMPAT_NAMES *
2527 	    USBA_MAX_COMPAT_NAME_LEN);
2528 
2529 	if (rval != DDI_PROP_SUCCESS) {
2530 
2531 		goto fail;
2532 	}
2533 
2534 	/* update the address property */
2535 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2536 	    "assigned-address", child_ud->usb_addr);
2537 	if (rval != DDI_PROP_SUCCESS) {
2538 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2539 		    "usba_ready_interface_node: address update failed");
2540 	}
2541 
2542 	/* create property with first interface number */
2543 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2544 	    "interface", ia_descr.bFirstInterface);
2545 
2546 	if (rval != DDI_PROP_SUCCESS) {
2547 
2548 		goto fail;
2549 	}
2550 
2551 	/* create property with the count of interfaces in this ia */
2552 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2553 	    "interface-count", ia_descr.bInterfaceCount);
2554 
2555 	if (rval != DDI_PROP_SUCCESS) {
2556 
2557 		goto fail;
2558 	}
2559 
2560 	USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2561 	    "%s%d port %d: %s, dip = 0x%p",
2562 	    ddi_node_name(ddi_get_parent(dip)),
2563 	    ddi_get_instance(ddi_get_parent(dip)),
2564 	    child_ud->usb_port, ddi_node_name(child_dip), (void *)child_dip);
2565 
2566 	*if_count = ia_descr.bInterfaceCount;
2567 	usba_set_usba_device(child_dip, child_ud);
2568 	ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip)->usb_mutex)));
2569 
2570 	return (child_dip);
2571 
2572 fail:
2573 	(void) usba_destroy_child_devi(child_dip, NDI_DEVI_REMOVE);
2574 
2575 	return (NULL);
2576 }
2577 
2578 
2579 /*
2580  * driver binding at interface level, the first arg will be the
2581  * the parent dip
2582  */
2583 /*ARGSUSED*/
2584 dev_info_t *
2585 usba_ready_interface_node(dev_info_t *dip, uint_t intf)
2586 {
2587 	dev_info_t		*child_dip = NULL;
2588 	usba_device_t		*child_ud = usba_get_usba_device(dip);
2589 	usb_dev_descr_t	*usb_dev_descr;
2590 	size_t			usb_cfg_length;
2591 	uchar_t 		*usb_cfg;
2592 	usb_if_descr_t	if_descr;
2593 	int			i, n, rval;
2594 	int			reg[2];
2595 	size_t			size;
2596 	usb_port_status_t	port_status;
2597 	char			*force_bind = NULL;
2598 	char			*usba_name_buf = NULL;
2599 	char			*usba_name[USBA_MAX_COMPAT_NAMES];
2600 
2601 	usb_cfg = usb_get_raw_cfg_data(dip, &usb_cfg_length);
2602 
2603 	mutex_enter(&child_ud->usb_mutex);
2604 
2605 	usb_dev_descr = child_ud->usb_dev_descr;
2606 
2607 	/*
2608 	 * for each interface, determine all compatible names
2609 	 */
2610 	USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2611 	    "usba_ready_interface_node: "
2612 	    "port %d, interface = %d port status = %x",
2613 	    child_ud->usb_port, intf, child_ud->usb_port_status);
2614 
2615 	/* Parse the interface descriptor */
2616 	size = usb_parse_if_descr(
2617 	    usb_cfg,
2618 	    usb_cfg_length,
2619 	    intf,		/* interface index */
2620 	    0,		/* alt interface index */
2621 	    &if_descr,
2622 	    USB_IF_DESCR_SIZE);
2623 
2624 	if (size != USB_IF_DESCR_SIZE) {
2625 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2626 		    "parsing interface: size (%lu) != USB_IF_DESCR_SIZE (%d)",
2627 		    size, USB_IF_DESCR_SIZE);
2628 		mutex_exit(&child_ud->usb_mutex);
2629 
2630 		return (NULL);
2631 	}
2632 
2633 	port_status = child_ud->usb_port_status;
2634 
2635 	/* create reg property */
2636 	reg[0] = intf;
2637 	reg[1] = child_ud->usb_cfg_value;
2638 
2639 	mutex_exit(&child_ud->usb_mutex);
2640 
2641 	/* clone this dip */
2642 	rval =	usba_create_child_devi(dip,
2643 	    "interface",
2644 	    NULL,		/* usba_hcdi ops */
2645 	    NULL,		/* root hub dip */
2646 	    port_status,	/* port status */
2647 	    child_ud,	/* share this usba_device */
2648 	    &child_dip);
2649 
2650 	if (rval != USB_SUCCESS) {
2651 
2652 		goto fail;
2653 	}
2654 
2655 	rval = ndi_prop_update_int_array(
2656 	    DDI_DEV_T_NONE, child_dip, "reg", reg, 2);
2657 
2658 	if (rval != DDI_PROP_SUCCESS) {
2659 
2660 		goto fail;
2661 	}
2662 
2663 	usba_set_node_name(child_dip, if_descr.bInterfaceClass,
2664 	    if_descr.bInterfaceSubClass, if_descr.bInterfaceProtocol,
2665 	    FLAG_INTERFACE_NODE);
2666 
2667 	/* check force binding */
2668 	if (usba_ugen_force_binding == USBA_UGEN_INTERFACE_BINDING) {
2669 		force_bind = "ugen";
2670 	}
2671 
2672 	/*
2673 	 * check whether there is another dip with this name and address
2674 	 */
2675 	ASSERT(usba_find_existing_node(child_dip) == NULL);
2676 
2677 	usba_name_buf = kmem_zalloc(USBA_MAX_COMPAT_NAMES *
2678 	    USBA_MAX_COMPAT_NAME_LEN, KM_SLEEP);
2679 
2680 	for (i = 0; i < USBA_MAX_COMPAT_NAMES; i++) {
2681 		usba_name[i] = usba_name_buf + (i * USBA_MAX_COMPAT_NAME_LEN);
2682 	}
2683 
2684 	n = 0;
2685 
2686 	if (force_bind) {
2687 		(void) ndi_devi_set_nodename(child_dip, force_bind, 0);
2688 		(void) strncpy(usba_name[n++], force_bind,
2689 		    USBA_MAX_COMPAT_NAME_LEN);
2690 	}
2691 
2692 	/* 1) usbifVID,PID.REV.configCN.IN */
2693 	(void) sprintf(usba_name[n++],
2694 	    "usbif%x,%x.%x.config%x.%x",
2695 	    usb_dev_descr->idVendor,
2696 	    usb_dev_descr->idProduct,
2697 	    usb_dev_descr->bcdDevice,
2698 	    child_ud->usb_cfg_value,
2699 	    intf);
2700 
2701 	/* 2) usbifVID,PID.configCN.IN */
2702 	(void) sprintf(usba_name[n++],
2703 	    "usbif%x,%x.config%x.%x",
2704 	    usb_dev_descr->idVendor,
2705 	    usb_dev_descr->idProduct,
2706 	    child_ud->usb_cfg_value,
2707 	    intf);
2708 
2709 
2710 	if (if_descr.bInterfaceClass) {
2711 		/* 3) usbifVID,classIC.ISC.IPROTO */
2712 		(void) sprintf(usba_name[n++],
2713 		    "usbif%x,class%x.%x.%x",
2714 		    usb_dev_descr->idVendor,
2715 		    if_descr.bInterfaceClass,
2716 		    if_descr.bInterfaceSubClass,
2717 		    if_descr.bInterfaceProtocol);
2718 
2719 		/* 4) usbifVID,classIC.ISC */
2720 		(void) sprintf(usba_name[n++],
2721 		    "usbif%x,class%x.%x",
2722 		    usb_dev_descr->idVendor,
2723 		    if_descr.bInterfaceClass,
2724 		    if_descr.bInterfaceSubClass);
2725 
2726 		/* 5) usbifVID,classIC */
2727 		(void) sprintf(usba_name[n++],
2728 		    "usbif%x,class%x",
2729 		    usb_dev_descr->idVendor,
2730 		    if_descr.bInterfaceClass);
2731 
2732 		/* 6) usbif,classIC.ISC.IPROTO */
2733 		(void) sprintf(usba_name[n++],
2734 		    "usbif,class%x.%x.%x",
2735 		    if_descr.bInterfaceClass,
2736 		    if_descr.bInterfaceSubClass,
2737 		    if_descr.bInterfaceProtocol);
2738 
2739 		/* 7) usbif,classIC.ISC */
2740 		(void) sprintf(usba_name[n++],
2741 		    "usbif,class%x.%x",
2742 		    if_descr.bInterfaceClass,
2743 		    if_descr.bInterfaceSubClass);
2744 
2745 		/* 8) usbif,classIC */
2746 		(void) sprintf(usba_name[n++],
2747 		    "usbif,class%x",
2748 		    if_descr.bInterfaceClass);
2749 	}
2750 
2751 	if (usba_get_ugen_binding(child_dip) ==
2752 	    USBA_UGEN_INTERFACE_BINDING) {
2753 		/* 9) ugen */
2754 		(void) sprintf(usba_name[n++], "ugen");
2755 	}
2756 
2757 	for (i = 0; i < n; i += 2) {
2758 		USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
2759 		    "compatible name:\t%s\t%s", usba_name[i],
2760 		    (((i+1) < n)? usba_name[i+1] : ""));
2761 	}
2762 
2763 	/* create compatible property */
2764 	rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, child_dip,
2765 	    "compatible", (char **)usba_name, n);
2766 
2767 	kmem_free(usba_name_buf, USBA_MAX_COMPAT_NAMES *
2768 	    USBA_MAX_COMPAT_NAME_LEN);
2769 
2770 	if (rval != DDI_PROP_SUCCESS) {
2771 
2772 		goto fail;
2773 	}
2774 
2775 	/* update the address property */
2776 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2777 	    "assigned-address", child_ud->usb_addr);
2778 	if (rval != DDI_PROP_SUCCESS) {
2779 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2780 		    "usba_ready_interface_node: address update failed");
2781 	}
2782 
2783 	/* create property with if number */
2784 	rval = ndi_prop_update_int(DDI_DEV_T_NONE, child_dip,
2785 	    "interface", intf);
2786 
2787 	if (rval != DDI_PROP_SUCCESS) {
2788 
2789 		goto fail;
2790 	}
2791 
2792 	USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
2793 	    "%s%d port %d: %s, dip = 0x%p",
2794 	    ddi_node_name(ddi_get_parent(dip)),
2795 	    ddi_get_instance(ddi_get_parent(dip)),
2796 	    child_ud->usb_port, ddi_node_name(child_dip), (void *)child_dip);
2797 
2798 	usba_set_usba_device(child_dip, child_ud);
2799 	ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip)->usb_mutex)));
2800 
2801 	return (child_dip);
2802 
2803 fail:
2804 	(void) usba_destroy_child_devi(child_dip, NDI_DEVI_REMOVE);
2805 
2806 	return (NULL);
2807 }
2808 
2809 
2810 /*
2811  * retrieve string descriptors for manufacturer, vendor and serial
2812  * number
2813  */
2814 void
2815 usba_get_dev_string_descrs(dev_info_t *dip, usba_device_t *ud)
2816 {
2817 	char	*tmpbuf, *str;
2818 	int	l;
2819 	usb_dev_descr_t *usb_dev_descr = ud->usb_dev_descr;
2820 
2821 
2822 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
2823 	    "usba_get_usb_string_descr: m=%d, p=%d, s=%d",
2824 	    usb_dev_descr->iManufacturer,
2825 	    usb_dev_descr->iProduct,
2826 	    usb_dev_descr->iSerialNumber);
2827 
2828 	tmpbuf = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
2829 
2830 	/* fetch manufacturer string */
2831 	if ((ud->usb_mfg_str == NULL) && usb_dev_descr->iManufacturer &&
2832 	    (usb_get_string_descr(dip, USB_LANG_ID,
2833 	    usb_dev_descr->iManufacturer, tmpbuf, USB_MAXSTRINGLEN) ==
2834 	    USB_SUCCESS)) {
2835 
2836 		l = strlen(tmpbuf);
2837 		if (l > 0) {
2838 			str = kmem_zalloc(l + 1, KM_SLEEP);
2839 			mutex_enter(&ud->usb_mutex);
2840 			ud->usb_mfg_str = str;
2841 			(void) strcpy(ud->usb_mfg_str, tmpbuf);
2842 			mutex_exit(&ud->usb_mutex);
2843 		}
2844 	}
2845 
2846 	/* fetch product string */
2847 	if ((ud->usb_product_str == NULL) && usb_dev_descr->iProduct &&
2848 	    (usb_get_string_descr(dip, USB_LANG_ID, usb_dev_descr->iProduct,
2849 	    tmpbuf, USB_MAXSTRINGLEN) ==
2850 	    USB_SUCCESS)) {
2851 
2852 		l = strlen(tmpbuf);
2853 		if (l > 0) {
2854 			str = kmem_zalloc(l + 1, KM_SLEEP);
2855 			mutex_enter(&ud->usb_mutex);
2856 			ud->usb_product_str = str;
2857 			(void) strcpy(ud->usb_product_str, tmpbuf);
2858 			mutex_exit(&ud->usb_mutex);
2859 		}
2860 	}
2861 
2862 	/* fetch device serial number string */
2863 	if ((ud->usb_serialno_str == NULL) && usb_dev_descr->iSerialNumber &&
2864 	    (usb_get_string_descr(dip, USB_LANG_ID,
2865 	    usb_dev_descr->iSerialNumber, tmpbuf, USB_MAXSTRINGLEN) ==
2866 	    USB_SUCCESS)) {
2867 
2868 		l = strlen(tmpbuf);
2869 		if (l > 0) {
2870 			str = kmem_zalloc(l + 1, KM_SLEEP);
2871 			mutex_enter(&ud->usb_mutex);
2872 			ud->usb_serialno_str = str;
2873 			(void) strcpy(ud->usb_serialno_str, tmpbuf);
2874 			mutex_exit(&ud->usb_mutex);
2875 		}
2876 	}
2877 
2878 	kmem_free(tmpbuf, USB_MAXSTRINGLEN);
2879 }
2880 
2881 
2882 /*
2883  * usba_str_startcmp:
2884  *	Return the number of characters duplicated from the beginning of the
2885  *	string.  Return -1 if a complete duplicate.
2886  *
2887  * Arguments:
2888  *	Two strings to compare.
2889  */
2890 static int usba_str_startcmp(char *first, char *second)
2891 {
2892 	int num_same_chars = 0;
2893 	while (*first == *second++) {
2894 		if (*first++ == '\0') {
2895 			return (-1);
2896 		}
2897 		num_same_chars++;
2898 	}
2899 
2900 	return (num_same_chars);
2901 }
2902 
2903 
2904 /*
2905  * usba_get_mfg_prod_sn_str:
2906  *	Return a string containing mfg, product, serial number strings.
2907  *	Remove duplicates if some strings are the same.
2908  *
2909  * Arguments:
2910  *	dip	- pointer to dev info
2911  *	buffer	- Where string is returned
2912  *	buflen	- Length of buffer
2913  *
2914  * Returns:
2915  *	Same as second arg.
2916  */
2917 char *
2918 usba_get_mfg_prod_sn_str(
2919     dev_info_t	*dip,
2920     char	*buffer,
2921     int		buflen)
2922 {
2923 	usba_device_t *usba_device = usba_get_usba_device(dip);
2924 	int return_len = 0;
2925 	int len = 0;
2926 	int duplen;
2927 
2928 	buffer[0] = '\0';
2929 	buffer[buflen-1] = '\0';
2930 
2931 	if ((usba_device->usb_mfg_str) &&
2932 	    ((len = strlen(usba_device->usb_mfg_str)) != 0)) {
2933 		(void) strncpy(buffer, usba_device->usb_mfg_str, buflen - 1);
2934 		return_len = min(buflen - 1, len);
2935 	}
2936 
2937 	/* Product string exists to append. */
2938 	if ((usba_device->usb_product_str) &&
2939 	    ((len = strlen(usba_device->usb_product_str)) != 0)) {
2940 
2941 		/* Append only parts of string that don't match mfg string. */
2942 		duplen = usba_str_startcmp(buffer,
2943 		    usba_device->usb_product_str);
2944 
2945 		if (duplen != -1) {		/* Not a complete match. */
2946 			if (return_len > 0) {
2947 				buffer[return_len++] = ' ';
2948 			}
2949 
2950 			/* Skip over the dup part of the concat'ed string. */
2951 			len -= duplen;
2952 			(void) strncpy(&buffer[return_len],
2953 			    &usba_device->usb_product_str[duplen],
2954 			    buflen - return_len - 1);
2955 			return_len = min(buflen - 1, return_len + len);
2956 		}
2957 	}
2958 
2959 	if ((usba_device->usb_serialno_str) &&
2960 	    ((len = strlen(usba_device->usb_serialno_str)) != 0)) {
2961 		if (return_len > 0) {
2962 			buffer[return_len++] = ' ';
2963 		}
2964 		(void) strncpy(&buffer[return_len],
2965 		    usba_device->usb_serialno_str,
2966 		    buflen - return_len - 1);
2967 	}
2968 
2969 	return (buffer);
2970 }
2971 
2972 
2973 /*
2974  * USB enumeration statistic functions
2975  */
2976 
2977 /*
2978  * Increments the hotplug statistics based on flags.
2979  */
2980 void
2981 usba_update_hotplug_stats(dev_info_t *dip, usb_flags_t flags)
2982 {
2983 	usba_device_t	*usba_device = usba_get_usba_device(dip);
2984 	usba_hcdi_t	*hcdi =
2985 	    usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
2986 
2987 	mutex_enter(&hcdi->hcdi_mutex);
2988 	if (flags & USBA_TOTAL_HOTPLUG_SUCCESS) {
2989 		hcdi->hcdi_total_hotplug_success++;
2990 		HCDI_HOTPLUG_STATS_DATA(hcdi)->
2991 		    hcdi_hotplug_total_success.value.ui64++;
2992 	}
2993 	if (flags & USBA_HOTPLUG_SUCCESS) {
2994 		hcdi->hcdi_hotplug_success++;
2995 		HCDI_HOTPLUG_STATS_DATA(hcdi)->
2996 		    hcdi_hotplug_success.value.ui64++;
2997 	}
2998 	if (flags & USBA_TOTAL_HOTPLUG_FAILURE) {
2999 		hcdi->hcdi_total_hotplug_failure++;
3000 		HCDI_HOTPLUG_STATS_DATA(hcdi)->
3001 		    hcdi_hotplug_total_failure.value.ui64++;
3002 	}
3003 	if (flags & USBA_HOTPLUG_FAILURE) {
3004 		hcdi->hcdi_hotplug_failure++;
3005 		HCDI_HOTPLUG_STATS_DATA(hcdi)->
3006 		    hcdi_hotplug_failure.value.ui64++;
3007 	}
3008 	mutex_exit(&hcdi->hcdi_mutex);
3009 }
3010 
3011 
3012 /*
3013  * Retrieve the current enumeration statistics
3014  */
3015 void
3016 usba_get_hotplug_stats(dev_info_t *dip, ulong_t *total_success,
3017     ulong_t *success, ulong_t *total_failure, ulong_t *failure,
3018     uchar_t *device_count)
3019 {
3020 	usba_device_t	*usba_device = usba_get_usba_device(dip);
3021 	usba_hcdi_t	*hcdi =
3022 	    usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
3023 
3024 	mutex_enter(&hcdi->hcdi_mutex);
3025 	*total_success = hcdi->hcdi_total_hotplug_success;
3026 	*success = hcdi->hcdi_hotplug_success;
3027 	*total_failure = hcdi->hcdi_total_hotplug_failure;
3028 	*failure = hcdi->hcdi_hotplug_failure;
3029 	*device_count = hcdi->hcdi_device_count;
3030 	mutex_exit(&hcdi->hcdi_mutex);
3031 }
3032 
3033 
3034 /*
3035  * Reset the resetable hotplug stats
3036  */
3037 void
3038 usba_reset_hotplug_stats(dev_info_t *dip)
3039 {
3040 	usba_device_t	*usba_device = usba_get_usba_device(dip);
3041 	usba_hcdi_t	*hcdi =
3042 	    usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
3043 	hcdi_hotplug_stats_t *hsp;
3044 
3045 	mutex_enter(&hcdi->hcdi_mutex);
3046 	hcdi->hcdi_hotplug_success = 0;
3047 	hcdi->hcdi_hotplug_failure = 0;
3048 
3049 	hsp = HCDI_HOTPLUG_STATS_DATA(hcdi);
3050 	hsp->hcdi_hotplug_success.value.ui64 = 0;
3051 	hsp->hcdi_hotplug_failure.value.ui64 = 0;
3052 	mutex_exit(&hcdi->hcdi_mutex);
3053 }
3054 
3055 
3056 /*
3057  * usba_bind_driver():
3058  *	This function calls ndi_devi_bind_driver() which tries to
3059  *	bind a driver to the device.  If the driver binding fails
3060  *	we get an rval of NDI_UNBOUD and report an error to the
3061  *	syslog that the driver failed binding.
3062  *	If rval is something other than NDI_UNBOUND we report an
3063  *	error to the console.
3064  *
3065  *	This function returns USB_SUCCESS if no errors were
3066  *	encountered while binding.
3067  */
3068 int
3069 usba_bind_driver(dev_info_t *dip)
3070 {
3071 	int	rval;
3072 	char	*name;
3073 	uint8_t if_num = usba_get_ifno(dip);
3074 
3075 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
3076 	    "usba_bind_driver: dip = 0x%p, if_num = 0x%x", (void *)dip, if_num);
3077 
3078 	name = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
3079 
3080 	/* bind device to the driver */
3081 	if ((rval = ndi_devi_bind_driver(dip, 0)) != NDI_SUCCESS) {
3082 		/* if we fail to bind report an error */
3083 		(void) usba_get_mfg_prod_sn_str(dip, name, MAXNAMELEN);
3084 		if (name[0] != '\0') {
3085 			if (!usb_owns_device(dip)) {
3086 				USB_DPRINTF_L1(DPRINT_MASK_USBA,
3087 				    usba_log_handle,
3088 				    "no driver found for "
3089 				    "interface %d (nodename: '%s') of %s",
3090 				    if_num, ddi_node_name(dip), name);
3091 			} else {
3092 				USB_DPRINTF_L1(DPRINT_MASK_USBA,
3093 				    usba_log_handle,
3094 				    "no driver found for device %s", name);
3095 			}
3096 		} else {
3097 			(void) ddi_pathname(dip, name);
3098 			USB_DPRINTF_L1(DPRINT_MASK_USBA,
3099 			    usba_log_handle,
3100 			    "no driver found for device %s", name);
3101 		}
3102 
3103 		kmem_free(name, MAXNAMELEN);
3104 
3105 		return (USB_FAILURE);
3106 	}
3107 	kmem_free(name, MAXNAMELEN);
3108 
3109 	return ((rval == NDI_SUCCESS) ? USB_SUCCESS : USB_FAILURE);
3110 }
3111 
3112 
3113 /*
3114  * usba_get_hc_dma_attr:
3115  *	function returning dma attributes of the HCD
3116  *
3117  * Arguments:
3118  *	dip	- pointer to devinfo of the client
3119  *
3120  * Return Values:
3121  *	hcdi_dma_attr
3122  */
3123 ddi_dma_attr_t *
3124 usba_get_hc_dma_attr(dev_info_t *dip)
3125 {
3126 	usba_device_t *usba_device = usba_get_usba_device(dip);
3127 	usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip);
3128 
3129 	return (hcdi->hcdi_dma_attr);
3130 }
3131 
3132 
3133 /*
3134  * usba_check_for_leaks:
3135  *	check usba_device structure for leaks
3136  *
3137  * Arguments:
3138  *	usba_device	- usba_device structure pointer
3139  */
3140 void
3141 usba_check_for_leaks(usba_device_t *usba_device)
3142 {
3143 	int i, ph_open_cnt, req_wrp_leaks, iface;
3144 	int leaks = 0;
3145 
3146 	USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle,
3147 	    "usba_check_for_leaks: %s%d usba_device=0x%p",
3148 	    ddi_driver_name(usba_device->usb_dip),
3149 	    ddi_get_instance(usba_device->usb_dip), (void *)usba_device);
3150 
3151 	/*
3152 	 * default pipe is still open
3153 	 * all other pipes should be closed
3154 	 */
3155 	for (ph_open_cnt = 0, i = 1; i < USBA_N_ENDPOINTS; i++) {
3156 		usba_ph_impl_t *ph_impl =
3157 		    &usba_device->usb_ph_list[i];
3158 		if (ph_impl->usba_ph_data) {
3159 			USB_DPRINTF_L2(DPRINT_MASK_USBA,
3160 			    usba_log_handle,
3161 			    "%s%d: leaking pipehandle=0x%p (0x%p) ep_addr=0x%x",
3162 			    ddi_driver_name(ph_impl->usba_ph_data->p_dip),
3163 			    ddi_get_instance(ph_impl->usba_ph_data->p_dip),
3164 			    (void *)ph_impl,
3165 			    (void *)ph_impl->usba_ph_data,
3166 			    ph_impl->usba_ph_ep.bEndpointAddress);
3167 			ph_open_cnt++;
3168 			leaks++;
3169 #ifndef DEBUG
3170 			usb_pipe_close(ph_impl->usba_ph_data->p_dip,
3171 			    (usb_pipe_handle_t)ph_impl, USB_FLAGS_SLEEP,
3172 			    NULL, NULL);
3173 #endif
3174 		}
3175 	}
3176 	req_wrp_leaks =  usba_list_entry_leaks(&usba_device->
3177 	    usb_allocated, "request wrappers");
3178 
3179 	ASSERT(ph_open_cnt == 0);
3180 	ASSERT(req_wrp_leaks == 0);
3181 
3182 	if (req_wrp_leaks) {
3183 		usba_list_entry_t *entry;
3184 
3185 		while ((entry = usba_rm_first_from_list(
3186 		    &usba_device->usb_allocated)) != NULL) {
3187 			usba_req_wrapper_t *wrp;
3188 
3189 			mutex_enter(&entry->list_mutex);
3190 			wrp = (usba_req_wrapper_t *)entry->private;
3191 			mutex_exit(&entry->list_mutex);
3192 			leaks++;
3193 
3194 			USB_DPRINTF_L2(DPRINT_MASK_USBA,
3195 			    usba_log_handle,
3196 			    "%s%d: leaking request 0x%p",
3197 			    ddi_driver_name(wrp->wr_dip),
3198 			    ddi_get_instance(wrp->wr_dip),
3199 			    (void *)wrp->wr_req);
3200 
3201 			/*
3202 			 * put it back, usba_req_wrapper_free
3203 			 * expects it on the list
3204 			 */
3205 			usba_add_to_list(&usba_device->usb_allocated,
3206 			    &wrp->wr_allocated_list);
3207 
3208 			usba_req_wrapper_free(wrp);
3209 		}
3210 	}
3211 
3212 	mutex_enter(&usba_device->usb_mutex);
3213 	for (iface = 0; iface < usba_device->usb_n_ifs; iface++) {
3214 		USB_DPRINTF_L3(DPRINT_MASK_USBA, usba_log_handle,
3215 		    "usba_check_for_leaks: if=%d client_flags=0x%x",
3216 		    iface, usba_device->usb_client_flags[iface]);
3217 
3218 		if (usba_device->usb_client_flags[iface] &
3219 		    USBA_CLIENT_FLAG_DEV_DATA) {
3220 			usb_client_dev_data_list_t *entry =
3221 			    usba_device->usb_client_dev_data_list.cddl_next;
3222 			usb_client_dev_data_list_t *next;
3223 			usb_client_dev_data_t *dev_data;
3224 
3225 			while (entry) {
3226 				dev_info_t *dip = entry->cddl_dip;
3227 				next = entry->cddl_next;
3228 				dev_data = entry->cddl_dev_data;
3229 
3230 
3231 				if (!i_ddi_devi_attached(dip)) {
3232 					USB_DPRINTF_L2(DPRINT_MASK_USBA,
3233 					    usba_log_handle,
3234 					    "%s%d: leaking dev_data 0x%p",
3235 					    ddi_driver_name(dip),
3236 					    ddi_get_instance(dip),
3237 					    (void *)dev_data);
3238 
3239 					leaks++;
3240 
3241 					mutex_exit(&usba_device->usb_mutex);
3242 					usb_free_dev_data(dip, dev_data);
3243 					mutex_enter(&usba_device->usb_mutex);
3244 				}
3245 
3246 				entry = next;
3247 			}
3248 		}
3249 		if (usba_device->usb_client_flags[iface] &
3250 		    USBA_CLIENT_FLAG_ATTACH) {
3251 			dev_info_t *dip = usba_device->
3252 			    usb_client_attach_list[iface].dip;
3253 
3254 			USB_DPRINTF_L2(DPRINT_MASK_USBA,
3255 			    usba_log_handle,
3256 			    "%s%d: did no usb_client_detach",
3257 			    ddi_driver_name(dip), ddi_get_instance(dip));
3258 			leaks++;
3259 
3260 			mutex_exit(&usba_device->usb_mutex);
3261 			usb_client_detach(dip, NULL);
3262 			mutex_enter(&usba_device->usb_mutex);
3263 
3264 			usba_device->
3265 			    usb_client_attach_list[iface].dip = NULL;
3266 
3267 			usba_device->usb_client_flags[iface] &=
3268 			    ~USBA_CLIENT_FLAG_ATTACH;
3269 
3270 		}
3271 		if (usba_device->usb_client_flags[iface] &
3272 		    USBA_CLIENT_FLAG_EV_CBS) {
3273 			dev_info_t *dip =
3274 			    usba_device->usb_client_ev_cb_list[iface].
3275 			    dip;
3276 			usb_event_t *ev_data =
3277 			    usba_device->usb_client_ev_cb_list[iface].
3278 			    ev_data;
3279 
3280 			USB_DPRINTF_L2(DPRINT_MASK_USBA,
3281 			    usba_log_handle,
3282 			    "%s%d: did no usb_unregister_event_cbs",
3283 			    ddi_driver_name(dip), ddi_get_instance(dip));
3284 			leaks++;
3285 
3286 			mutex_exit(&usba_device->usb_mutex);
3287 			usb_unregister_event_cbs(dip, ev_data);
3288 			mutex_enter(&usba_device->usb_mutex);
3289 
3290 			usba_device->usb_client_ev_cb_list[iface].
3291 			    dip = NULL;
3292 			usba_device->usb_client_ev_cb_list[iface].
3293 			    ev_data = NULL;
3294 			usba_device->usb_client_flags[iface] &=
3295 			    ~USBA_CLIENT_FLAG_EV_CBS;
3296 		}
3297 	}
3298 	mutex_exit(&usba_device->usb_mutex);
3299 
3300 	if (leaks) {
3301 		USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle,
3302 		    "all %d leaks fixed", leaks);
3303 	}
3304 }
3305