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