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