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