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