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