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