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