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