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