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