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