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