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