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