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