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