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