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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26 * Copyright 2016 James S. Blachly, MD <james.blachly@gmail.com>
31 * USBA: Solaris USB Architecture support
33 #define USBA_FRAMEWORK
34 #include <sys/usb/usba/usba_impl.h>
35 #include <sys/usb/usba/hcdi_impl.h>
36 #include <sys/usb/hubd/hub.h>
37 #include <sys/fs/dv_node.h>
40 * USBA private variables and tunables
42 static kmutex_t usba_mutex
;
44 /* mutex to protect usba_root_hubs */
45 static kmutex_t usba_hub_mutex
;
47 typedef struct usba_root_hub_ent
{
49 struct usba_root_hub_ent
*next
;
52 static usba_root_hub_ent_t
*usba_root_hubs
= NULL
;
55 * ddivs forced binding:
57 * usbc usbc_xhubs usbc_xaddress node name
59 * 0 x x class name or "device"
62 * 1 0 >1 ddivs_usbc except device
64 * 1 1 0 ddivs_usbc except hubs
65 * 1 1 >1 ddivs_usbc except hubs and
66 * device at usbc_xaddress
68 uint_t usba_ddivs_usbc
;
69 uint_t usba_ddivs_usbc_xhubs
;
70 uint_t usba_ddivs_usbc_xaddress
;
72 uint_t usba_ugen_force_binding
;
75 * compatible name handling
78 * allowing for 15 compat names, plus one force bind name and
79 * one possible specified client driver name
81 #define USBA_MAX_COMPAT_NAMES 17
82 #define USBA_MAX_COMPAT_NAME_LEN 64
84 /* double linked list for usba_devices */
85 usba_list_entry_t usba_device_list
;
87 _NOTE(MUTEX_PROTECTS_DATA(usba_mutex
, usba_device_list
))
93 static struct modlmisc modlmisc
= {
94 &mod_miscops
, /* Type of module */
95 "USBA: USB Architecture 2.0 1.66"
98 static struct modlinkage modlinkage
= {
99 MODREV_1
, (void *)&modlmisc
, NULL
103 static usb_log_handle_t usba_log_handle
;
104 uint_t usba_errlevel
= USB_LOG_L4
;
105 uint_t usba_errmask
= (uint_t
)-1;
107 extern usb_log_handle_t hubdi_log_handle
;
115 * usbai providing log support needs to be init'ed first
118 usba_usbai_initialization();
119 usba_usba_initialization();
120 usba_usbai_register_initialization();
121 usba_hcdi_initialization();
122 usba_hubdi_initialization();
123 usba_devdb_initialization();
125 if ((rval
= mod_install(&modlinkage
)) != 0) {
126 usba_devdb_destroy();
127 usba_hubdi_destroy();
129 usba_usbai_register_destroy();
131 usba_usbai_destroy();
142 if ((rval
= mod_remove(&modlinkage
)) == 0) {
143 usba_devdb_destroy();
144 usba_hubdi_destroy();
146 usba_usbai_register_destroy();
148 usba_usbai_destroy();
155 _info(struct modinfo
*modinfop
)
157 return (mod_info(&modlinkage
, modinfop
));
161 usba_owns_ia(dev_info_t
*dip
)
163 int if_count
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
164 "interface-count", 0);
166 return ((if_count
) ? B_TRUE
: B_FALSE
);
170 * common bus ctl for hcd, usb_mid, and hubd
173 usba_bus_ctl(dev_info_t
*dip
,
179 dev_info_t
*child_dip
= (dev_info_t
*)arg
;
180 usba_device_t
*usba_device
;
181 usba_hcdi_t
*usba_hcdi
;
182 usba_hcdi_ops_t
*usba_hcdi_ops
;
184 USB_DPRINTF_L4(DPRINT_MASK_USBA
, hubdi_log_handle
,
185 "usba_bus_ctl: %s%d %s%d op=%d", ddi_node_name(rdip
),
186 ddi_get_instance(rdip
), ddi_node_name(dip
),
187 ddi_get_instance(dip
), op
);
191 case DDI_CTLOPS_REPORTDEV
:
193 char *name
, compat_name
[64], *speed
;
194 usba_device_t
*hub_usba_device
;
197 usba_device
= usba_get_usba_device(rdip
);
199 /* find the parent hub */
200 hubdip
= ddi_get_parent(rdip
);
201 while ((strcmp(ddi_driver_name(hubdip
), "hubd") != 0) &&
202 !(usba_is_root_hub(hubdip
))) {
203 hubdip
= ddi_get_parent(hubdip
);
206 hub_usba_device
= usba_get_usba_device(hubdip
);
209 if (usb_owns_device(rdip
)) {
210 (void) snprintf(compat_name
,
211 sizeof (compat_name
),
213 usba_device
->usb_dev_descr
->idVendor
,
214 usba_device
->usb_dev_descr
->idProduct
);
215 } else if (usba_owns_ia(rdip
)) {
216 (void) snprintf(compat_name
,
217 sizeof (compat_name
),
218 "usbia%x,%x.config%x.%x",
219 usba_device
->usb_dev_descr
->idVendor
,
220 usba_device
->usb_dev_descr
->idProduct
,
221 usba_device
->usb_cfg_value
,
222 usb_get_if_number(rdip
));
224 (void) snprintf(compat_name
,
225 sizeof (compat_name
),
226 "usbif%x,%x.config%x.%x",
227 usba_device
->usb_dev_descr
->idVendor
,
228 usba_device
->usb_dev_descr
->idProduct
,
229 usba_device
->usb_cfg_value
,
230 usb_get_if_number(rdip
));
232 switch (usba_device
->usb_port_status
) {
233 case USBA_SUPER_SPEED_DEV
:
234 speed
= "super speed (USB 3.x)";
236 case USBA_HIGH_SPEED_DEV
:
237 speed
= "hi speed (USB 2.x)";
239 case USBA_LOW_SPEED_DEV
:
240 speed
= "low speed (USB 1.x)";
242 case USBA_FULL_SPEED_DEV
:
244 speed
= "full speed (USB 1.x)";
249 "?USB %x.%x %s (%s) operating at %s on "
251 "%s@%s, %s%d at bus address %d\n",
252 (usba_device
->usb_dev_descr
->bcdUSB
& 0xff00) >> 8,
253 usba_device
->usb_dev_descr
->bcdUSB
& 0xff,
254 (usb_owns_device(rdip
) ? "device" :
255 ((usba_owns_ia(rdip
) ? "interface-association" :
258 (hub_usba_device
->usb_dev_descr
->bcdUSB
&
260 hub_usba_device
->usb_dev_descr
->bcdUSB
& 0xff,
261 usba_is_root_hub(hubdip
) ? "root" : "external",
262 ddi_node_name(rdip
), ddi_get_name_addr(rdip
),
263 ddi_driver_name(rdip
),
264 ddi_get_instance(rdip
), usba_device
->usb_addr
);
266 name
= kmem_alloc(MAXNAMELEN
, KM_SLEEP
);
267 (void) usba_get_mfg_prod_sn_str(rdip
, name
, MAXNAMELEN
);
268 if (name
[0] != '\0') {
269 cmn_err(CE_CONT
, "?%s\n", name
);
271 kmem_free(name
, MAXNAMELEN
);
273 } else { /* harden USBA against this case; if it happens */
276 "?USB-device: %s@%s, %s%d\n",
277 ddi_node_name(rdip
), ddi_get_name_addr(rdip
),
278 ddi_driver_name(rdip
), ddi_get_instance(rdip
));
281 return (DDI_SUCCESS
);
284 case DDI_CTLOPS_INITCHILD
:
291 int len
= sizeof (usb_addr
);
293 usba_hcdi
= usba_hcdi_get_hcdi(dip
);
294 usba_hcdi_ops
= usba_hcdi
->hcdi_ops
;
295 ASSERT(usba_hcdi_ops
!= NULL
);
298 * as long as the dip exists, it should have
299 * usba_device structure associated with it
301 usba_device
= usba_get_usba_device(child_dip
);
302 if (usba_device
== NULL
) {
304 USB_DPRINTF_L2(DPRINT_MASK_USBA
, hubdi_log_handle
,
305 "usba_bus_ctl: DDI_NOT_WELL_FORMED (%s (0x%p))",
306 ddi_node_name(child_dip
), (void *)child_dip
);
308 return (DDI_NOT_WELL_FORMED
);
311 /* the dip should have an address and reg property */
312 if (ddi_prop_op(DDI_DEV_T_NONE
, child_dip
, PROP_LEN_AND_VAL_BUF
,
313 DDI_PROP_DONTPASS
| DDI_PROP_CANSLEEP
, "assigned-address",
314 (caddr_t
)&usb_addr
, &len
) != DDI_SUCCESS
) {
316 USB_DPRINTF_L2(DPRINT_MASK_USBA
, hubdi_log_handle
,
318 "%s%d %s%d op=%d rdip = 0x%p dip = 0x%p",
319 ddi_node_name(rdip
), ddi_get_instance(rdip
),
320 ddi_node_name(dip
), ddi_get_instance(dip
), op
,
321 (void *)rdip
, (void *)dip
);
323 USB_DPRINTF_L2(DPRINT_MASK_USBA
, hubdi_log_handle
,
324 "usba_bus_ctl: DDI_NOT_WELL_FORMED (%s (0x%p))",
325 ddi_node_name(child_dip
), (void *)child_dip
);
327 return (DDI_NOT_WELL_FORMED
);
330 if ((rval
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, child_dip
,
331 DDI_PROP_DONTPASS
, "reg",
332 &data
, &n
)) != DDI_SUCCESS
) {
334 USB_DPRINTF_L2(DPRINT_MASK_USBA
, hubdi_log_handle
,
335 "usba_bus_ctl: %d, DDI_NOT_WELL_FORMED", rval
);
337 return (DDI_NOT_WELL_FORMED
);
342 * if the configuration is 1, the unit address is
343 * just the interface number
345 if ((n
== 1) || ((n
> 1) && (data
[1] == 1))) {
346 (void) sprintf(name
, "%x", data
[0]);
348 (void) sprintf(name
, "%x,%x", data
[0], data
[1]);
351 USB_DPRINTF_L3(DPRINT_MASK_USBA
,
352 hubdi_log_handle
, "usba_bus_ctl: name = %s", name
);
355 ddi_set_name_addr(child_dip
, name
);
358 * increment the reference count for each child using this
359 * usba_device structure
361 mutex_enter(&usba_device
->usb_mutex
);
362 usba_device
->usb_ref_count
++;
364 USB_DPRINTF_L3(DPRINT_MASK_USBA
, hubdi_log_handle
,
365 "usba_bus_ctl: init usba_device = 0x%p ref_count = %d",
366 (void *)usba_device
, usba_device
->usb_ref_count
);
368 mutex_exit(&usba_device
->usb_mutex
);
370 return (DDI_SUCCESS
);
373 case DDI_CTLOPS_UNINITCHILD
:
375 usba_device
= usba_get_usba_device(child_dip
);
377 if (usba_device
!= NULL
) {
379 * decrement the reference count for each child
380 * using this usba_device structure
382 mutex_enter(&usba_device
->usb_mutex
);
383 usba_device
->usb_ref_count
--;
385 USB_DPRINTF_L3(DPRINT_MASK_USBA
, hubdi_log_handle
,
386 "usba_hcdi_bus_ctl: uninit usba_device=0x%p "
388 (void *)usba_device
, usba_device
->usb_ref_count
);
390 mutex_exit(&usba_device
->usb_mutex
);
392 ddi_set_name_addr(child_dip
, NULL
);
394 return (DDI_SUCCESS
);
397 case DDI_CTLOPS_IOMIN
:
399 return (DDI_SUCCESS
);
402 * These ops correspond to functions that "shouldn't" be called
403 * by a USB client driver. So we whine when we're called.
405 case DDI_CTLOPS_DMAPMAPC
:
406 case DDI_CTLOPS_REPORTINT
:
407 case DDI_CTLOPS_REGSIZE
:
408 case DDI_CTLOPS_NREGS
:
409 case DDI_CTLOPS_SIDDEV
:
410 case DDI_CTLOPS_SLAVEONLY
:
411 case DDI_CTLOPS_AFFINITY
:
412 case DDI_CTLOPS_POKE
:
413 case DDI_CTLOPS_PEEK
:
414 cmn_err(CE_CONT
, "%s%d: invalid op (%d) from %s%d",
415 ddi_node_name(dip
), ddi_get_instance(dip
),
416 op
, ddi_node_name(rdip
), ddi_get_instance(rdip
));
417 return (DDI_FAILURE
);
420 * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
423 return (ddi_ctlops(dip
, rdip
, op
, arg
, result
));
429 * initialize and destroy USBA module
432 usba_usba_initialization()
434 usba_log_handle
= usb_alloc_log_hdl(NULL
, "usba", &usba_errlevel
,
435 &usba_errmask
, NULL
, 0);
437 USB_DPRINTF_L4(DPRINT_MASK_USBA
,
438 usba_log_handle
, "usba_usba_initialization");
440 mutex_init(&usba_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
441 mutex_init(&usba_hub_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
442 usba_init_list(&usba_device_list
, NULL
, NULL
);
449 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
, "usba_usba_destroy");
451 mutex_destroy(&usba_hub_mutex
);
452 mutex_destroy(&usba_mutex
);
453 usba_destroy_list(&usba_device_list
);
455 usb_free_log_hdl(usba_log_handle
);
460 * usba_set_usb_address:
461 * set usb address in usba_device structure
464 usba_set_usb_address(usba_device_t
*usba_device
)
469 char *usb_address_in_use
;
471 mutex_enter(&usba_device
->usb_mutex
);
473 hcdi
= usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
);
475 mutex_enter(&hcdi
->hcdi_mutex
);
476 usb_address_in_use
= hcdi
->hcdi_usb_address_in_use
;
478 for (address
= ROOT_HUB_ADDR
+ 1;
479 address
<= USBA_MAX_ADDRESS
; address
++) {
480 if (usb_address_in_use
[address
/s
] & (1 << (address
% s
))) {
483 usb_address_in_use
[address
/s
] |= (1 << (address
% s
));
484 hcdi
->hcdi_device_count
++;
485 HCDI_HOTPLUG_STATS_DATA(hcdi
)->hcdi_device_count
.value
.ui64
++;
486 mutex_exit(&hcdi
->hcdi_mutex
);
488 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
489 "usba_set_usb_address: %d", address
);
491 usba_device
->usb_addr
= address
;
493 mutex_exit(&usba_device
->usb_mutex
);
495 return (USB_SUCCESS
);
498 usba_device
->usb_addr
= 0;
500 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
501 "no usb address available");
503 mutex_exit(&hcdi
->hcdi_mutex
);
504 mutex_exit(&usba_device
->usb_mutex
);
506 return (USB_FAILURE
);
511 * usba_unset_usb_address:
512 * unset usb_address in usba_device structure
515 usba_unset_usb_address(usba_device_t
*usba_device
)
520 char *usb_address_in_use
;
522 mutex_enter(&usba_device
->usb_mutex
);
523 address
= usba_device
->usb_addr
;
524 hcdi
= usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
);
526 if (address
> ROOT_HUB_ADDR
) {
527 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
528 "usba_unset_usb_address: address=%d", address
);
530 mutex_enter(&hcdi
->hcdi_mutex
);
531 usb_address_in_use
= hcdi
->hcdi_usb_address_in_use
;
533 ASSERT(usb_address_in_use
[address
/s
] & (1 << (address
% s
)));
535 usb_address_in_use
[address
/s
] &= ~(1 << (address
% s
));
537 hcdi
->hcdi_device_count
--;
538 HCDI_HOTPLUG_STATS_DATA(hcdi
)->hcdi_device_count
.value
.ui64
--;
540 mutex_exit(&hcdi
->hcdi_mutex
);
542 usba_device
->usb_addr
= 0;
544 mutex_exit(&usba_device
->usb_mutex
);
549 usba_get_evdata(dev_info_t
*dip
)
551 usba_evdata_t
*evdata
;
552 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
554 /* called when dip attaches */
555 ASSERT(usba_device
!= NULL
);
557 mutex_enter(&usba_device
->usb_mutex
);
558 evdata
= usba_device
->usb_evdata
;
560 if (evdata
->ev_dip
== dip
) {
561 mutex_exit(&usba_device
->usb_mutex
);
565 evdata
= evdata
->ev_next
;
568 evdata
= kmem_zalloc(sizeof (usba_evdata_t
), KM_SLEEP
);
569 evdata
->ev_dip
= dip
;
570 evdata
->ev_next
= usba_device
->usb_evdata
;
571 usba_device
->usb_evdata
= evdata
;
572 mutex_exit(&usba_device
->usb_mutex
);
579 * allocate a usb device structure and link it in the list
582 usba_alloc_usba_device(dev_info_t
*root_hub_dip
)
584 usba_device_t
*usba_device
;
586 ddi_iblock_cookie_t iblock_cookie
=
587 usba_hcdi_get_hcdi(root_hub_dip
)->hcdi_iblock_cookie
;
590 * create a new usba_device structure
592 usba_device
= kmem_zalloc(sizeof (usba_device_t
), KM_SLEEP
);
595 * initialize usba_device
597 mutex_init(&usba_device
->usb_mutex
, NULL
, MUTEX_DRIVER
,
600 usba_init_list(&usba_device
->usb_device_list
, (usb_opaque_t
)usba_device
,
602 usba_init_list(&usba_device
->usb_allocated
, (usb_opaque_t
)usba_device
,
604 mutex_enter(&usba_device
->usb_mutex
);
605 usba_device
->usb_root_hub_dip
= root_hub_dip
;
608 * add to list of usba_devices
610 usba_add_to_list(&usba_device_list
, &usba_device
->usb_device_list
);
612 /* init mutex in each usba_ph_impl structure */
613 for (ep_idx
= 0; ep_idx
< USBA_N_ENDPOINTS
; ep_idx
++) {
614 mutex_init(&usba_device
->usb_ph_list
[ep_idx
].usba_ph_mutex
,
615 NULL
, MUTEX_DRIVER
, iblock_cookie
);
618 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
619 "allocated usba_device 0x%p", (void *)usba_device
);
621 mutex_exit(&usba_device
->usb_mutex
);
623 return (usba_device
);
627 /* free NDI event data associated with usba_device */
629 usba_free_evdata(usba_evdata_t
*evdata
)
634 next
= evdata
->ev_next
;
635 kmem_free(evdata
, sizeof (usba_evdata_t
));
642 * free usb device structure
645 usba_free_usba_device(usba_device_t
*usba_device
)
648 usb_pipe_handle_t def_ph
;
650 if (usba_device
== NULL
) {
655 mutex_enter(&usba_device
->usb_mutex
);
656 if (usba_device
->usb_ref_count
) {
657 mutex_exit(&usba_device
->usb_mutex
);
662 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
663 "usba_free_usba_device 0x%p, address=0x%x, ref cnt=%d",
664 (void *)usba_device
, usba_device
->usb_addr
,
665 usba_device
->usb_ref_count
);
667 usba_free_evdata(usba_device
->usb_evdata
);
668 mutex_exit(&usba_device
->usb_mutex
);
670 def_ph
= usba_usbdev_to_dflt_pipe_handle(usba_device
);
671 if (def_ph
!= NULL
) {
672 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data(def_ph
);
675 usb_pipe_close(ph_data
->p_dip
, def_ph
,
676 USB_FLAGS_SLEEP
| USBA_FLAGS_PRIVILEGED
,
682 * Give the HCD a chance to clean up this child device before we finish
683 * tearing things down.
685 if (usba_device
->usb_hcdi_ops
->usba_hcdi_device_fini
!= NULL
) {
686 usba_device
->usb_hcdi_ops
->usba_hcdi_device_fini(
687 usba_device
, usba_device
->usb_hcd_private
);
688 usba_device
->usb_hcd_private
= NULL
;
691 mutex_enter(&usba_mutex
);
693 /* destroy mutex in each usba_ph_impl structure */
694 for (ep_idx
= 0; ep_idx
< USBA_N_ENDPOINTS
; ep_idx
++) {
695 mutex_destroy(&usba_device
->usb_ph_list
[ep_idx
].usba_ph_mutex
);
698 (void) usba_rm_from_list(&usba_device_list
,
699 &usba_device
->usb_device_list
);
701 mutex_exit(&usba_mutex
);
703 usba_destroy_list(&usba_device
->usb_device_list
);
704 usba_destroy_list(&usba_device
->usb_allocated
);
706 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
707 "deallocating usba_device = 0x%p, address = 0x%x",
708 (void *)usba_device
, usba_device
->usb_addr
);
711 * ohci allocates descriptors for root hub so we can't
712 * deallocate these here
715 if (usba_device
->usb_addr
!= ROOT_HUB_ADDR
) {
716 if (usba_device
->usb_cfg_array
) {
717 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
718 "deallocating usb_config_array: 0x%p",
719 (void *)usba_device
->usb_cfg_array
);
720 mutex_enter(&usba_device
->usb_mutex
);
722 i
< usba_device
->usb_dev_descr
->bNumConfigurations
;
724 if (usba_device
->usb_cfg_array
[i
]) {
726 usba_device
->usb_cfg_array
[i
],
727 usba_device
->usb_cfg_array_len
[i
]);
731 /* free the array pointers */
732 kmem_free(usba_device
->usb_cfg_array
,
733 usba_device
->usb_cfg_array_length
);
734 kmem_free(usba_device
->usb_cfg_array_len
,
735 usba_device
->usb_cfg_array_len_length
);
737 mutex_exit(&usba_device
->usb_mutex
);
740 if (usba_device
->usb_cfg_str_descr
) {
741 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
742 "deallocating usb_cfg_str_descr: 0x%p",
743 (void *)usba_device
->usb_cfg_str_descr
);
745 i
< usba_device
->usb_dev_descr
->bNumConfigurations
;
747 if (usba_device
->usb_cfg_str_descr
[i
]) {
749 usba_device
->usb_cfg_str_descr
[i
],
751 usb_cfg_str_descr
[i
]) + 1);
754 /* free the array pointers */
755 kmem_free(usba_device
->usb_cfg_str_descr
,
756 sizeof (uchar_t
*) * usba_device
->usb_n_cfgs
);
759 if (usba_device
->usb_dev_descr
) {
760 kmem_free(usba_device
->usb_dev_descr
,
761 sizeof (usb_dev_descr_t
));
764 if (usba_device
->usb_mfg_str
) {
765 kmem_free(usba_device
->usb_mfg_str
,
766 strlen(usba_device
->usb_mfg_str
) + 1);
769 if (usba_device
->usb_product_str
) {
770 kmem_free(usba_device
->usb_product_str
,
771 strlen(usba_device
->usb_product_str
) + 1);
774 if (usba_device
->usb_serialno_str
) {
775 kmem_free(usba_device
->usb_serialno_str
,
776 strlen(usba_device
->usb_serialno_str
) + 1);
779 usba_unset_usb_address(usba_device
);
782 ASSERT(usba_device
->usb_client_dev_data_list
.cddl_next
== NULL
);
784 if (usba_device
->usb_client_flags
) {
787 for (i
= 0; i
< usba_device
->usb_n_ifs
; i
++) {
788 ASSERT(usba_device
->usb_client_flags
[i
] == 0);
790 kmem_free(usba_device
->usb_client_flags
,
791 usba_device
->usb_n_ifs
* USBA_CLIENT_FLAG_SIZE
);
795 if (usba_device
->usb_client_attach_list
) {
796 kmem_free(usba_device
->usb_client_attach_list
,
797 usba_device
->usb_n_ifs
*
798 sizeof (*usba_device
->usb_client_attach_list
));
800 if (usba_device
->usb_client_ev_cb_list
) {
801 kmem_free(usba_device
->usb_client_ev_cb_list
,
802 usba_device
->usb_n_ifs
*
803 sizeof (*usba_device
->usb_client_ev_cb_list
));
807 * finally ready to destroy the structure
809 mutex_destroy(&usba_device
->usb_mutex
);
811 kmem_free((caddr_t
)usba_device
, sizeof (usba_device_t
));
815 /* clear the data toggle for all endpoints on this device */
817 usba_clear_data_toggle(usba_device_t
*usba_device
)
821 if (usba_device
!= NULL
) {
822 mutex_enter(&usba_device
->usb_mutex
);
823 for (i
= 0; i
< USBA_N_ENDPOINTS
; i
++) {
824 usba_device
->usb_ph_list
[i
].usba_ph_flags
&=
825 ~USBA_PH_DATA_TOGGLE
;
827 mutex_exit(&usba_device
->usb_mutex
);
833 * usba_create_child_devi():
834 * create a child devinfo node, usba_device, attach properties.
835 * the usba_device structure is shared between all interfaces
838 usba_create_child_devi(dev_info_t
*dip
,
840 usba_hcdi_ops_t
*usba_hcdi_ops
,
841 dev_info_t
*usb_root_hub_dip
,
842 usb_port_status_t port_status
,
843 usba_device_t
*usba_device
,
844 dev_info_t
**child_dip
)
846 int rval
= USB_FAILURE
;
847 int usba_device_allocated
= 0;
850 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
851 "usba_create_child_devi: %s usba_device=0x%p "
852 "port status=0x%x", node_name
,
853 (void *)usba_device
, port_status
);
855 ndi_devi_alloc_sleep(dip
, node_name
, (pnode_t
)DEVI_SID_NODEID
,
858 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
859 "child dip=0x%p", (void *)*child_dip
);
861 if (usba_device
== NULL
) {
863 usba_device
= usba_alloc_usba_device(usb_root_hub_dip
);
865 /* grab the mutex to keep warlock happy */
866 mutex_enter(&usba_device
->usb_mutex
);
867 usba_device
->usb_hcdi_ops
= usba_hcdi_ops
;
868 usba_device
->usb_port_status
= port_status
;
869 mutex_exit(&usba_device
->usb_mutex
);
871 usba_device_allocated
++;
873 mutex_enter(&usba_device
->usb_mutex
);
875 ASSERT(usba_device
->usb_hcdi_ops
== usba_hcdi_ops
);
877 if (usb_root_hub_dip
) {
878 ASSERT(usba_device
->usb_root_hub_dip
==
882 usba_device
->usb_port_status
= port_status
;
884 mutex_exit(&usba_device
->usb_mutex
);
887 if (usba_device
->usb_addr
== 0) {
888 if (usba_set_usb_address(usba_device
) == USB_FAILURE
) {
891 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
892 "cannot set usb address for dip=0x%p",
898 address
= usba_device
->usb_addr
;
900 /* attach properties */
901 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, *child_dip
,
902 "assigned-address", address
);
903 if (rval
!= DDI_PROP_SUCCESS
) {
904 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
905 "cannot set usb address property for dip=0x%p",
913 * store the usba_device point in the dip
915 usba_set_usba_device(*child_dip
, usba_device
);
917 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
918 "usba_create_child_devi: devi=0x%p (%s) ud=0x%p",
919 (void *)*child_dip
, ddi_driver_name(*child_dip
),
920 (void *)usba_device
);
922 return (USB_SUCCESS
);
926 int rval
= usba_destroy_child_devi(*child_dip
, NDI_DEVI_REMOVE
);
927 ASSERT(rval
== USB_SUCCESS
);
931 if (usba_device_allocated
) {
932 usba_free_usba_device(usba_device
);
933 } else if (address
&& usba_device
) {
934 usba_unset_usb_address(usba_device
);
937 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
938 "usba_create_child_devi failed: rval=%d", rval
);
945 usba_destroy_child_devi(dev_info_t
*dip
, uint_t flag
)
947 usba_device_t
*usba_device
;
948 int rval
= NDI_SUCCESS
;
950 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
951 "usba_destroy_child_devi: %s%d (0x%p)",
952 ddi_driver_name(dip
), ddi_get_instance(dip
), (void *)dip
);
954 usba_device
= usba_get_usba_device(dip
);
957 * if the child hasn't been bound yet, we can just
960 if (i_ddi_node_state(dip
) < DS_INITIALIZED
) {
962 * do not call ndi_devi_free() since it might
965 rval
= ddi_remove_child(dip
, 0);
968 char *devnm
= kmem_alloc(MAXNAMELEN
+ 1, KM_SLEEP
);
969 dev_info_t
*pdip
= ddi_get_parent(dip
);
971 (void) ddi_deviname(dip
, devnm
);
973 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
974 "usba_destroy_child_devi:\n\t"
975 "offlining dip 0x%p usba_device=0x%p (%s)", (void *)dip
,
976 (void *)usba_device
, devnm
);
978 (void) devfs_clean(pdip
, NULL
, DV_CLEAN_FORCE
);
979 rval
= ndi_devi_unconfig_one(pdip
, devnm
+ 1, NULL
,
980 flag
| NDI_UNCONFIG
| NDI_DEVI_OFFLINE
);
981 if (rval
!= NDI_SUCCESS
) {
982 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
983 " ndi_devi_unconfig_one %s%d failed (%d)",
984 ddi_driver_name(dip
), ddi_get_instance(dip
),
987 kmem_free(devnm
, MAXNAMELEN
+ 1);
990 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
991 "usba_destroy_child_devi: rval=%d", rval
);
993 return (rval
== NDI_SUCCESS
? USB_SUCCESS
: USB_FAILURE
);
1001 usba_init_list(usba_list_entry_t
*element
, usb_opaque_t
private,
1002 ddi_iblock_cookie_t iblock_cookie
)
1004 mutex_init(&element
->list_mutex
, NULL
, MUTEX_DRIVER
,
1006 mutex_enter(&element
->list_mutex
);
1007 element
->private = private;
1008 mutex_exit(&element
->list_mutex
);
1013 usba_destroy_list(usba_list_entry_t
*head
)
1015 mutex_enter(&head
->list_mutex
);
1016 ASSERT(head
->next
== NULL
);
1017 ASSERT(head
->prev
== NULL
);
1018 mutex_exit(&head
->list_mutex
);
1020 mutex_destroy(&head
->list_mutex
);
1025 usba_add_to_list(usba_list_entry_t
*head
, usba_list_entry_t
*element
)
1027 usba_list_entry_t
*next
;
1030 mutex_enter(&head
->list_mutex
);
1031 mutex_enter(&element
->list_mutex
);
1033 remaining
= head
->count
;
1035 /* check if it is not in another list */
1036 ASSERT(element
->next
== NULL
);
1037 ASSERT(element
->prev
== NULL
);
1041 * only verify the list when not in interrupt context, we
1042 * have to trust the HCD
1044 if (!servicing_interrupt()) {
1046 /* check if not already in this list */
1047 for (next
= head
->next
; (next
!= NULL
);
1048 next
= next
->next
) {
1049 if (next
== element
) {
1050 USB_DPRINTF_L0(DPRINT_MASK_USBA
,
1052 "Attempt to corrupt USB list at 0x%p",
1054 ASSERT(next
== element
);
1061 * Detect incorrect circ links or found
1062 * unexpected elements.
1064 if ((next
->next
&& (remaining
== 0)) ||
1065 ((next
->next
== NULL
) && remaining
)) {
1066 panic("Corrupted USB list at 0x%p",
1074 if (head
->next
== NULL
) {
1075 head
->prev
= head
->next
= element
;
1078 head
->prev
->next
= element
;
1079 element
->prev
= head
->prev
;
1080 head
->prev
= element
;
1085 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
1086 "usba_add_to_list: head=0x%p element=0x%p count=%d",
1087 (void *)head
, (void *)element
, head
->count
);
1090 mutex_exit(&head
->list_mutex
);
1091 mutex_exit(&element
->list_mutex
);
1096 usba_rm_from_list(usba_list_entry_t
*head
, usba_list_entry_t
*element
)
1098 usba_list_entry_t
*e
;
1102 /* find the element in the list first */
1103 mutex_enter(&head
->list_mutex
);
1105 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
1106 "usba_rm_from_list: head=0x%p element=0x%p count=%d",
1107 (void *)head
, (void *)element
, head
->count
);
1109 remaining
= head
->count
;
1121 /* Detect incorrect circ links or found unexpected elements. */
1122 if ((e
&& (remaining
== 0)) ||
1123 ((e
== NULL
) && (remaining
))) {
1124 panic("Corrupted USB list at 0x%p", (void *)head
);
1130 mutex_exit(&head
->list_mutex
);
1132 return (USB_FAILURE
);
1135 /* now remove the element */
1136 mutex_enter(&element
->list_mutex
);
1138 if (element
->next
) {
1139 element
->next
->prev
= element
->prev
;
1141 if (element
->prev
) {
1142 element
->prev
->next
= element
->next
;
1144 if (head
->next
== element
) {
1145 head
->next
= element
->next
;
1147 if (head
->prev
== element
) {
1148 head
->prev
= element
->prev
;
1151 element
->prev
= element
->next
= NULL
;
1152 if (head
->next
== NULL
) {
1153 ASSERT(head
->prev
== NULL
);
1155 ASSERT(head
->next
->prev
== NULL
);
1157 if (head
->prev
== NULL
) {
1158 ASSERT(head
->next
== NULL
);
1160 ASSERT(head
->prev
->next
== NULL
);
1165 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
1166 "usba_rm_from_list success: head=0x%p element=0x%p cnt=%d",
1167 (void *)head
, (void *)element
, head
->count
);
1169 mutex_exit(&element
->list_mutex
);
1170 mutex_exit(&head
->list_mutex
);
1172 return (USB_SUCCESS
);
1177 usba_rm_first_from_list(usba_list_entry_t
*head
)
1179 usba_list_entry_t
*element
= NULL
;
1182 mutex_enter(&head
->list_mutex
);
1183 element
= head
->next
;
1185 /* now remove the element */
1186 mutex_enter(&element
->list_mutex
);
1187 head
->next
= element
->next
;
1189 head
->next
->prev
= NULL
;
1191 if (head
->prev
== element
) {
1192 head
->prev
= element
->next
;
1194 element
->prev
= element
->next
= NULL
;
1195 mutex_exit(&element
->list_mutex
);
1198 if (head
->next
== NULL
) {
1199 ASSERT(head
->prev
== NULL
);
1201 ASSERT(head
->next
->prev
== NULL
);
1203 if (head
->prev
== NULL
) {
1204 ASSERT(head
->next
== NULL
);
1206 ASSERT(head
->prev
->next
== NULL
);
1208 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
1209 "usba_rm_first_from_list: head=0x%p el=0x%p cnt=%d",
1210 (void *)head
, (void *)element
, head
->count
);
1212 mutex_exit(&head
->list_mutex
);
1220 usba_rm_first_pvt_from_list(usba_list_entry_t
*head
)
1222 usba_list_entry_t
*element
= usba_rm_first_from_list(head
);
1223 usb_opaque_t
private = NULL
;
1226 mutex_enter(&element
->list_mutex
);
1227 private = element
->private;
1228 mutex_exit(&element
->list_mutex
);
1236 * move list to new list and zero original list
1239 usba_move_list(usba_list_entry_t
*head
, usba_list_entry_t
*new,
1240 ddi_iblock_cookie_t iblock_cookie
)
1242 usba_init_list(new, NULL
, iblock_cookie
);
1243 mutex_enter(&head
->list_mutex
);
1244 mutex_enter(&new->list_mutex
);
1246 new->next
= head
->next
;
1247 new->prev
= head
->prev
;
1248 new->count
= head
->count
;
1249 new->private = head
->private;
1254 head
->private = NULL
;
1255 mutex_exit(&head
->list_mutex
);
1256 mutex_exit(&new->list_mutex
);
1261 usba_check_in_list(usba_list_entry_t
*head
, usba_list_entry_t
*element
)
1263 int rval
= USB_FAILURE
;
1265 usba_list_entry_t
*next
;
1267 mutex_enter(&head
->list_mutex
);
1268 remaining
= head
->count
;
1270 mutex_enter(&element
->list_mutex
);
1271 for (next
= head
->next
; next
!= NULL
; next
= next
->next
) {
1272 if (next
== element
) {
1278 /* Detect incorrect circ links or found unexpected elements. */
1279 if ((next
->next
&& (remaining
== 0)) ||
1280 ((next
->next
== NULL
) && remaining
)) {
1281 panic("Corrupted USB list at 0x%p", (void *)head
);
1285 mutex_exit(&element
->list_mutex
);
1286 mutex_exit(&head
->list_mutex
);
1293 usba_list_entry_leaks(usba_list_entry_t
*head
, char *what
)
1297 usba_list_entry_t
*next
;
1299 mutex_enter(&head
->list_mutex
);
1300 remaining
= head
->count
;
1301 for (next
= head
->next
; next
!= NULL
; next
= next
->next
) {
1302 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, usba_log_handle
,
1303 "leaking %s 0x%p", what
, (void *)next
->private);
1308 /* Detect incorrect circ links or found unexpected elements. */
1309 if ((next
->next
&& (remaining
== 0)) ||
1310 ((next
->next
== NULL
) && remaining
)) {
1311 panic("Corrupted USB list at 0x%p", (void *)head
);
1315 ASSERT(count
== head
->count
);
1316 mutex_exit(&head
->list_mutex
);
1319 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, usba_log_handle
,
1320 "usba_list_entry_count: leaking %d", count
);
1328 usba_list_entry_count(usba_list_entry_t
*head
)
1332 mutex_enter(&head
->list_mutex
);
1333 count
= head
->count
;
1334 mutex_exit(&head
->list_mutex
);
1339 /* add a new root hub to the usba_root_hubs list */
1342 usba_add_root_hub(dev_info_t
*dip
)
1344 usba_root_hub_ent_t
*hub
;
1346 hub
= (usba_root_hub_ent_t
*)
1347 kmem_zalloc(sizeof (usba_root_hub_ent_t
), KM_SLEEP
);
1349 mutex_enter(&usba_hub_mutex
);
1351 hub
->next
= usba_root_hubs
;
1352 usba_root_hubs
= hub
;
1353 mutex_exit(&usba_hub_mutex
);
1356 /* remove a root hub from the usba_root_hubs list */
1359 usba_rem_root_hub(dev_info_t
*dip
)
1361 usba_root_hub_ent_t
**hubp
, *hub
;
1363 mutex_enter(&usba_hub_mutex
);
1364 hubp
= &usba_root_hubs
;
1366 if ((*hubp
)->dip
== dip
) {
1369 kmem_free(hub
, sizeof (struct usba_root_hub_ent
));
1370 mutex_exit(&usba_hub_mutex
);
1374 hubp
= &(*hubp
)->next
;
1376 mutex_exit(&usba_hub_mutex
);
1380 * check whether this dip is the root hub. Any root hub known by
1381 * usba is recorded in the linked list pointed to by usba_root_hubs
1384 usba_is_root_hub(dev_info_t
*dip
)
1386 usba_root_hub_ent_t
*hub
;
1388 mutex_enter(&usba_hub_mutex
);
1389 hub
= usba_root_hubs
;
1391 if (hub
->dip
== dip
) {
1392 mutex_exit(&usba_hub_mutex
);
1398 mutex_exit(&usba_hub_mutex
);
1404 * get and store usba_device pointer in the devi
1407 usba_get_usba_device(dev_info_t
*dip
)
1410 * we cannot use parent_data in the usb node because its
1411 * bus parent (eg. PCI nexus driver) uses this data
1413 * we cannot use driver data in the other usb nodes since
1414 * usb drivers may need to use this
1416 if (usba_is_root_hub(dip
)) {
1417 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(dip
);
1419 return (hcdi
->hcdi_usba_device
);
1422 return (ddi_get_parent_data(dip
));
1428 * Retrieve the usba_device pointer from the dev without checking for
1429 * the root hub first. This function is only used in polled mode.
1432 usba_polled_get_usba_device(dev_info_t
*dip
)
1435 * Don't call usba_is_root_hub() to find out if this is
1436 * the root hub usba_is_root_hub() calls into the DDI
1437 * where there are locking issues. The dip sent in during
1438 * polled mode will never be the root hub, so just get
1439 * the usba_device pointer from the dip.
1441 return (ddi_get_parent_data(dip
));
1446 usba_set_usba_device(dev_info_t
*dip
, usba_device_t
*usba_device
)
1448 if (usba_is_root_hub(dip
)) {
1449 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(dip
);
1450 /* no locking is needed here */
1451 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(hcdi
->hcdi_usba_device
))
1452 hcdi
->hcdi_usba_device
= usba_device
;
1453 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(hcdi
->hcdi_usba_device
))
1455 ddi_set_parent_data(dip
, usba_device
);
1461 * usba_set_node_name() according to class, subclass, and protocol
1462 * following the 1275 USB binding tables.
1465 /* device node table, refer to section 3.2.2.1 of 1275 binding */
1466 static node_name_entry_t device_node_name_table
[] = {
1467 { USB_CLASS_COMM
, DONTCARE
, DONTCARE
, "communications" },
1468 { USB_CLASS_HUB
, DONTCARE
, DONTCARE
, "hub" },
1469 { USB_CLASS_DIAG
, DONTCARE
, DONTCARE
, "diagnostics" },
1470 { USB_CLASS_MISC
, DONTCARE
, DONTCARE
, "miscellaneous" },
1471 { DONTCARE
, DONTCARE
, DONTCARE
, "device" }
1474 /* interface-association node table */
1475 static node_name_entry_t ia_node_name_table
[] = {
1476 { USB_CLASS_AUDIO
, DONTCARE
, DONTCARE
, "audio" },
1477 { USB_CLASS_VIDEO
, DONTCARE
, DONTCARE
, "video" },
1478 { USB_CLASS_WIRELESS
, USB_SUBCLS_WUSB_2
, USB_PROTO_WUSB_DWA
,
1479 "device-wire-adaptor" },
1480 { USB_CLASS_WIRELESS
, DONTCARE
, DONTCARE
, "wireless-controller" },
1481 { DONTCARE
, DONTCARE
, DONTCARE
, "interface-association" }
1484 /* interface node table, refer to section 3.3.2.1 */
1485 static node_name_entry_t if_node_name_table
[] = {
1486 { USB_CLASS_AUDIO
, USB_SUBCLS_AUD_CONTROL
, DONTCARE
, "sound-control" },
1487 { USB_CLASS_AUDIO
, USB_SUBCLS_AUD_STREAMING
, DONTCARE
, "sound" },
1488 { USB_CLASS_AUDIO
, USB_SUBCLS_AUD_MIDI_STREAMING
, DONTCARE
, "midi" },
1489 { USB_CLASS_AUDIO
, DONTCARE
, DONTCARE
, "sound" },
1491 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_DIRECT_LINE
, DONTCARE
, "line" },
1492 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ABSTRCT_CTRL
, DONTCARE
, "modem" },
1493 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_PHONE_CTRL
, DONTCARE
, "telephone" },
1494 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_MULTCNL_ISDN
, DONTCARE
, "isdn" },
1495 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ISDN
, DONTCARE
, "isdn" },
1496 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ETHERNET
, DONTCARE
, "ethernet" },
1497 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ATM_NETWORK
, DONTCARE
, "atm-network" },
1498 { USB_CLASS_COMM
, DONTCARE
, DONTCARE
, "communications" },
1500 { USB_CLASS_HID
, USB_SUBCLS_HID_1
, USB_PROTO_HID_KEYBOARD
, "keyboard" },
1501 { USB_CLASS_HID
, USB_SUBCLS_HID_1
, USB_PROTO_HID_MOUSE
, "mouse" },
1502 { USB_CLASS_HID
, DONTCARE
, DONTCARE
, "input" },
1504 { USB_CLASS_HUB
, DONTCARE
, DONTCARE
, "hub" },
1506 { USB_CLASS_PHYSICAL
, DONTCARE
, DONTCARE
, "physical" },
1508 { USB_CLASS_IMAGE
, DONTCARE
, DONTCARE
, "image" },
1510 { USB_CLASS_PRINTER
, DONTCARE
, DONTCARE
, "printer" },
1512 { USB_CLASS_MASS_STORAGE
, DONTCARE
, DONTCARE
, "storage" },
1514 { USB_CLASS_CDC_DATA
, DONTCARE
, DONTCARE
, "data" },
1516 { USB_CLASS_SECURITY
, DONTCARE
, DONTCARE
, "security" },
1518 { USB_CLASS_VIDEO
, USB_SUBCLS_VIDEO_CONTROL
, DONTCARE
, "video-control" },
1519 { USB_CLASS_VIDEO
, USB_SUBCLS_VIDEO_STREAM
, DONTCARE
, "video-stream" },
1520 { USB_CLASS_VIDEO
, DONTCARE
, DONTCARE
, "video" },
1522 { USB_CLASS_APP
, USB_SUBCLS_APP_FIRMWARE
, DONTCARE
, "firmware" },
1523 { USB_CLASS_APP
, USB_SUBCLS_APP_IRDA
, DONTCARE
, "IrDa" },
1524 { USB_CLASS_APP
, USB_SUBCLS_APP_TEST
, DONTCARE
, "test" },
1526 { USB_CLASS_MISC
, USB_SUBCLS_CBAF
, USB_PROTO_CBAF
, "wusb_ca"},
1527 { USB_CLASS_WIRELESS
, USB_SUBCLS_WUSB_1
, USB_PROTO_WUSB_RC
, "hwa-radio" },
1528 { USB_CLASS_WIRELESS
, USB_SUBCLS_WUSB_2
, USB_PROTO_WUSB_HWA
, "hwa-host" },
1529 { USB_CLASS_WIRELESS
, USB_SUBCLS_WUSB_2
, USB_PROTO_WUSB_DWA
, "dwa-control" },
1530 { USB_CLASS_WIRELESS
, USB_SUBCLS_WUSB_2
, USB_PROTO_WUSB_DWA_ISO
, "dwa-isoc" },
1531 { USB_CLASS_WIRELESS
, DONTCARE
, DONTCARE
, "wireless" },
1533 { DONTCARE
, DONTCARE
, DONTCARE
, "interface" },
1537 /* combined node table, refer to section 3.4.2.1 */
1538 static node_name_entry_t combined_node_name_table
[] = {
1539 { USB_CLASS_AUDIO
, USB_SUBCLS_AUD_CONTROL
, DONTCARE
, "sound-control" },
1540 { USB_CLASS_AUDIO
, USB_SUBCLS_AUD_STREAMING
, DONTCARE
, "sound" },
1541 { USB_CLASS_AUDIO
, USB_SUBCLS_AUD_MIDI_STREAMING
, DONTCARE
, "midi" },
1542 { USB_CLASS_AUDIO
, DONTCARE
, DONTCARE
, "sound" },
1544 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_DIRECT_LINE
, DONTCARE
, "line" },
1545 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ABSTRCT_CTRL
, DONTCARE
, "modem" },
1546 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_PHONE_CTRL
, DONTCARE
, "telephone" },
1547 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_MULTCNL_ISDN
, DONTCARE
, "isdn" },
1548 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ISDN
, DONTCARE
, "isdn" },
1549 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ETHERNET
, DONTCARE
, "ethernet" },
1550 { USB_CLASS_COMM
, USB_SUBCLS_CDCC_ATM_NETWORK
, DONTCARE
, "atm-network" },
1551 { USB_CLASS_COMM
, DONTCARE
, DONTCARE
, "communications" },
1553 { USB_CLASS_HID
, USB_SUBCLS_HID_1
, USB_PROTO_HID_KEYBOARD
, "keyboard" },
1554 { USB_CLASS_HID
, USB_SUBCLS_HID_1
, USB_PROTO_HID_MOUSE
, "mouse" },
1555 { USB_CLASS_HID
, DONTCARE
, DONTCARE
, "input" },
1557 { USB_CLASS_PHYSICAL
, DONTCARE
, DONTCARE
, "physical" },
1559 { USB_CLASS_IMAGE
, DONTCARE
, DONTCARE
, "image" },
1561 { USB_CLASS_PRINTER
, DONTCARE
, DONTCARE
, "printer" },
1563 { USB_CLASS_MASS_STORAGE
, USB_SUBCLS_MS_RBC_T10
, DONTCARE
, "storage" },
1564 { USB_CLASS_MASS_STORAGE
, USB_SUBCLS_MS_SFF8020I
, DONTCARE
, "cdrom" },
1565 { USB_CLASS_MASS_STORAGE
, USB_SUBCLS_MS_QIC_157
, DONTCARE
, "tape" },
1566 { USB_CLASS_MASS_STORAGE
, USB_SUBCLS_MS_UFI
, DONTCARE
, "floppy" },
1567 { USB_CLASS_MASS_STORAGE
, USB_SUBCLS_MS_SFF8070I
, DONTCARE
, "storage" },
1568 { USB_CLASS_MASS_STORAGE
, USB_SUBCLS_MS_SCSI
, DONTCARE
, "storage" },
1569 { USB_CLASS_MASS_STORAGE
, DONTCARE
, DONTCARE
, "storage" },
1571 { USB_CLASS_CDC_DATA
, DONTCARE
, DONTCARE
, "data" },
1573 { USB_CLASS_SECURITY
, DONTCARE
, DONTCARE
, "security" },
1575 { USB_CLASS_VIDEO
, USB_SUBCLS_VIDEO_CONTROL
, DONTCARE
, "video-control" },
1576 { USB_CLASS_VIDEO
, USB_SUBCLS_VIDEO_STREAM
, DONTCARE
, "video-stream" },
1577 { USB_CLASS_VIDEO
, DONTCARE
, DONTCARE
, "video" },
1579 { USB_CLASS_APP
, USB_SUBCLS_APP_FIRMWARE
, DONTCARE
, "firmware" },
1580 { USB_CLASS_APP
, USB_SUBCLS_APP_IRDA
, DONTCARE
, "IrDa" },
1581 { USB_CLASS_APP
, USB_SUBCLS_APP_TEST
, DONTCARE
, "test" },
1583 { USB_CLASS_COMM
, DONTCARE
, DONTCARE
, "communications" },
1584 { USB_CLASS_HUB
, DONTCARE
, DONTCARE
, "hub" },
1585 { USB_CLASS_DIAG
, DONTCARE
, DONTCARE
, "diagnostics" },
1586 { USB_CLASS_MISC
, DONTCARE
, DONTCARE
, "miscellaneous" },
1587 { DONTCARE
, DONTCARE
, DONTCARE
, "device" }
1590 static size_t device_node_name_table_size
=
1591 sizeof (device_node_name_table
)/sizeof (struct node_name_entry
);
1592 static size_t ia_node_name_table_size
=
1593 sizeof (ia_node_name_table
)/sizeof (struct node_name_entry
);
1594 static size_t if_node_name_table_size
=
1595 sizeof (if_node_name_table
)/sizeof (struct node_name_entry
);
1596 static size_t combined_node_name_table_size
=
1597 sizeof (combined_node_name_table
)/sizeof (struct node_name_entry
);
1601 usba_set_node_name(dev_info_t
*dip
, uint8_t class, uint8_t subclass
,
1602 uint8_t protocol
, uint_t flag
)
1606 node_name_entry_t
*node_name_table
;
1609 /* interface share node names with interface-association */
1610 case FLAG_INTERFACE_ASSOCIATION_NODE
:
1611 node_name_table
= ia_node_name_table
;
1612 size
= ia_node_name_table_size
;
1614 case FLAG_INTERFACE_NODE
:
1615 node_name_table
= if_node_name_table
;
1616 size
= if_node_name_table_size
;
1618 case FLAG_DEVICE_NODE
:
1619 node_name_table
= device_node_name_table
;
1620 size
= device_node_name_table_size
;
1622 case FLAG_COMBINED_NODE
:
1623 node_name_table
= combined_node_name_table
;
1624 size
= combined_node_name_table_size
;
1631 for (i
= 0; i
< size
; i
++) {
1632 int16_t c
= node_name_table
[i
].class;
1633 int16_t s
= node_name_table
[i
].subclass
;
1634 int16_t p
= node_name_table
[i
].protocol
;
1636 if (((c
== DONTCARE
) || (c
== class)) &&
1637 ((s
== DONTCARE
) || (s
== subclass
)) &&
1638 ((p
== DONTCARE
) || (p
== protocol
))) {
1639 char *name
= node_name_table
[i
].name
;
1641 (void) ndi_devi_set_nodename(dip
, name
, 0);
1650 * walk the children of the parent of this devi and compare the
1651 * name and reg property of each child. If there is a match
1655 usba_find_existing_node(dev_info_t
*odip
)
1657 dev_info_t
*ndip
, *child
, *pdip
;
1659 uint_t n_odata
, n_ndata
;
1662 pdip
= ddi_get_parent(odip
);
1663 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
,
1664 odip
, DDI_PROP_DONTPASS
, "reg",
1665 &odata
, &n_odata
) != DDI_SUCCESS
) {
1666 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, usba_log_handle
,
1667 "usba_find_existing_node: "
1668 "%s: DDI_NOT_WELL_FORMED", ddi_driver_name(odip
));
1673 ndi_devi_enter(pdip
, &circular
);
1674 ndip
= (dev_info_t
*)(DEVI(pdip
)->devi_child
);
1675 while ((child
= ndip
) != NULL
) {
1677 ndip
= (dev_info_t
*)(DEVI(child
)->devi_sibling
);
1679 if (child
== odip
) {
1683 if (strcmp(DEVI(child
)->devi_node_name
,
1684 DEVI(odip
)->devi_node_name
)) {
1688 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
,
1689 child
, DDI_PROP_DONTPASS
, "reg",
1690 &ndata
, &n_ndata
) != DDI_SUCCESS
) {
1692 USB_DPRINTF_L2(DPRINT_MASK_HCDI
, usba_log_handle
,
1693 "usba_find_existing_node: "
1694 "%s DDI_NOT_WELL_FORMED", ddi_driver_name(child
));
1696 } else if (n_ndata
&& n_odata
&& (bcmp(odata
, ndata
,
1697 max(n_odata
, n_ndata
) * sizeof (int)) == 0)) {
1699 USB_DPRINTF_L3(DPRINT_MASK_HCDI
, usba_log_handle
,
1700 "usba_find_existing_node: found %s%d (%p)",
1701 ddi_driver_name(child
),
1702 ddi_get_instance(child
), (void *)child
);
1704 USB_DPRINTF_L3(DPRINT_MASK_HCDI
, usba_log_handle
,
1705 "usba_find_existing_node: "
1706 "reg: %x %x %x - %x %x %x",
1707 n_odata
, odata
[0], odata
[1],
1708 n_ndata
, ndata
[0], ndata
[1]);
1710 ddi_prop_free(ndata
);
1714 ddi_prop_free(ndata
);
1718 ndi_devi_exit(pdip
, circular
);
1720 ddi_prop_free(odata
);
1726 /* change all unprintable characters to spaces */
1728 usba_filter_string(char *instr
, char *outstr
)
1731 if ((*instr
>= ' ') && (*instr
<= '~')) {
1744 * lookup ugen binding specified in property in
1748 usba_get_ugen_binding(dev_info_t
*dip
)
1750 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
1752 usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
);
1754 return (hcdi
->hcdi_ugen_default_binding
);
1759 * driver binding support at device level
1762 usba_ready_device_node(dev_info_t
*child_dip
)
1766 usba_device_t
*usba_device
= usba_get_usba_device(child_dip
);
1767 usb_dev_descr_t
*usb_dev_descr
;
1768 uint_t n_cfgs
; /* number of configs */
1769 uint_t n_ifs
; /* number of interfaces */
1770 uint_t port
, bus_num
;
1771 size_t usb_config_length
;
1772 uchar_t
*usb_config
;
1774 usb_addr_t address
= usb_get_addr(child_dip
);
1775 usb_if_descr_t if_descr
;
1777 int combined_node
= 0;
1780 char *force_bind
= NULL
;
1781 char *usba_name_buf
= NULL
;
1782 char *usba_name
[USBA_MAX_COMPAT_NAMES
];
1784 usb_config
= usb_get_raw_cfg_data(child_dip
, &usb_config_length
);
1786 mutex_enter(&usba_device
->usb_mutex
);
1787 mutex_enter(&usba_mutex
);
1789 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
1790 "usba_ready_device_node: child=0x%p", (void *)child_dip
);
1792 port
= usba_device
->usb_port
;
1793 usb_dev_descr
= usba_device
->usb_dev_descr
;
1794 n_cfgs
= usba_device
->usb_n_cfgs
;
1795 n_ifs
= usba_device
->usb_n_ifs
;
1796 bus_num
= usba_device
->usb_addr
;
1798 if (address
!= ROOT_HUB_ADDR
) {
1799 size
= usb_parse_if_descr(
1802 0, /* interface index */
1803 0, /* alt interface index */
1807 if (size
!= USB_IF_DESCR_SIZE
) {
1808 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
1809 "parsing interface: "
1810 "size (%lu) != USB_IF_DESCR_SIZE (%d)",
1811 size
, USB_IF_DESCR_SIZE
);
1813 mutex_exit(&usba_mutex
);
1814 mutex_exit(&usba_device
->usb_mutex
);
1819 /* fake an interface descriptor for the root hub */
1820 bzero(&if_descr
, sizeof (if_descr
));
1822 if_descr
.bInterfaceClass
= USB_CLASS_HUB
;
1827 mutex_exit(&usba_mutex
);
1828 mutex_exit(&usba_device
->usb_mutex
);
1830 rval
= ndi_prop_update_int_array(
1831 DDI_DEV_T_NONE
, child_dip
, "reg", reg
, 1);
1833 if (rval
!= DDI_PROP_SUCCESS
) {
1834 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
1835 "usba_ready_device_node: property update failed");
1840 combined_node
= ((n_cfgs
== 1) && (n_ifs
== 1) &&
1841 ((usb_dev_descr
->bDeviceClass
== USB_CLASS_HUB
) ||
1842 (usb_dev_descr
->bDeviceClass
== 0)));
1844 is_hub
= (if_descr
.bInterfaceClass
== USB_CLASS_HUB
) ||
1845 (usb_dev_descr
->bDeviceClass
== USB_CLASS_HUB
);
1848 if (combined_node
) {
1849 usba_set_node_name(child_dip
,
1850 if_descr
.bInterfaceClass
,
1851 if_descr
.bInterfaceSubClass
,
1852 if_descr
.bInterfaceProtocol
,
1853 FLAG_COMBINED_NODE
);
1855 usba_set_node_name(child_dip
,
1856 usb_dev_descr
->bDeviceClass
,
1857 usb_dev_descr
->bDeviceSubClass
,
1858 usb_dev_descr
->bDeviceProtocol
,
1863 * check force binding rules
1865 if ((address
!= ROOT_HUB_ADDR
) && usba_ddivs_usbc
&&
1866 (address
!= usba_ddivs_usbc_xaddress
) &&
1867 (!(usba_ddivs_usbc_xhubs
&& is_hub
))) {
1868 force_bind
= "ddivs_usbc";
1869 (void) ndi_devi_set_nodename(child_dip
, "ddivs_usbc", 0);
1871 } else if (usba_device
->usb_preferred_driver
) {
1872 force_bind
= usba_device
->usb_preferred_driver
;
1874 } else if ((address
!= ROOT_HUB_ADDR
) &&
1875 ((usba_ugen_force_binding
== USBA_UGEN_DEVICE_BINDING
) ||
1876 ((usba_ugen_force_binding
== USBA_UGEN_INTERFACE_BINDING
) &&
1877 combined_node
)) && (!is_hub
)) {
1878 force_bind
= "ugen";
1883 * check whether there is another dip with this name and address
1884 * If the dip contains usba_device, it is held by the previous
1885 * round of configuration.
1887 ASSERT(usba_find_existing_node(child_dip
) == NULL
);
1890 usba_name_buf
= kmem_zalloc(USBA_MAX_COMPAT_NAMES
*
1891 USBA_MAX_COMPAT_NAME_LEN
, KM_SLEEP
);
1893 for (i
= 0; i
< USBA_MAX_COMPAT_NAMES
; i
++) {
1894 usba_name
[i
] = usba_name_buf
+ (i
* USBA_MAX_COMPAT_NAME_LEN
);
1898 (void) ndi_devi_set_nodename(child_dip
, force_bind
, 0);
1899 (void) strncpy(usba_name
[n
++], force_bind
,
1900 USBA_MAX_COMPAT_NAME_LEN
);
1904 * If the callback function of specified driver is registered,
1905 * it will be called here to check whether to take over the device.
1907 if (usb_cap
.usba_dev_driver_cb
!= NULL
) {
1908 char *dev_drv
= NULL
;
1909 usb_dev_str_t dev_str
;
1910 char *pathname
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
1912 dev_str
.usb_mfg
= usba_device
->usb_mfg_str
;
1913 dev_str
.usb_product
= usba_device
->usb_product_str
;
1914 dev_str
.usb_serialno
= usba_device
->usb_serialno_str
;
1916 (void) ddi_pathname(child_dip
, pathname
);
1918 if ((usb_cap
.usba_dev_driver_cb(usb_dev_descr
, &dev_str
,
1919 pathname
, bus_num
, port
, &dev_drv
, NULL
) == USB_SUCCESS
) &&
1920 (dev_drv
!= NULL
)) {
1921 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
1922 "usba_ready_device_node: dev_driver=%s, port =%d,"
1923 "bus =%d, path=%s\n\t",
1924 dev_drv
, port
, bus_num
, pathname
);
1926 (void) strncpy(usba_name
[n
++], dev_drv
,
1927 USBA_MAX_COMPAT_NAME_LEN
);
1929 kmem_free(pathname
, MAXPATHLEN
);
1932 /* create compatible names */
1933 if (combined_node
) {
1935 /* 1. usbVID,PID.REV */
1936 (void) sprintf(usba_name
[n
++],
1938 usb_dev_descr
->idVendor
,
1939 usb_dev_descr
->idProduct
,
1940 usb_dev_descr
->bcdDevice
);
1943 (void) sprintf(usba_name
[n
++],
1945 usb_dev_descr
->idVendor
,
1946 usb_dev_descr
->idProduct
);
1948 if (usb_dev_descr
->bDeviceClass
!= 0) {
1949 /* 3. usbVID,classDC.DSC.DPROTO */
1950 (void) sprintf(usba_name
[n
++],
1951 "usb%x,class%x.%x.%x",
1952 usb_dev_descr
->idVendor
,
1953 usb_dev_descr
->bDeviceClass
,
1954 usb_dev_descr
->bDeviceSubClass
,
1955 usb_dev_descr
->bDeviceProtocol
);
1957 /* 4. usbVID,classDC.DSC */
1958 (void) sprintf(usba_name
[n
++],
1960 usb_dev_descr
->idVendor
,
1961 usb_dev_descr
->bDeviceClass
,
1962 usb_dev_descr
->bDeviceSubClass
);
1964 /* 5. usbVID,classDC */
1965 (void) sprintf(usba_name
[n
++],
1967 usb_dev_descr
->idVendor
,
1968 usb_dev_descr
->bDeviceClass
);
1970 /* 6. usb,classDC.DSC.DPROTO */
1971 (void) sprintf(usba_name
[n
++],
1972 "usb,class%x.%x.%x",
1973 usb_dev_descr
->bDeviceClass
,
1974 usb_dev_descr
->bDeviceSubClass
,
1975 usb_dev_descr
->bDeviceProtocol
);
1977 /* 7. usb,classDC.DSC */
1978 (void) sprintf(usba_name
[n
++],
1980 usb_dev_descr
->bDeviceClass
,
1981 usb_dev_descr
->bDeviceSubClass
);
1983 /* 8. usb,classDC */
1984 (void) sprintf(usba_name
[n
++],
1986 usb_dev_descr
->bDeviceClass
);
1989 if (if_descr
.bInterfaceClass
!= 0) {
1990 /* 9. usbifVID,classIC.ISC.IPROTO */
1991 (void) sprintf(usba_name
[n
++],
1992 "usbif%x,class%x.%x.%x",
1993 usb_dev_descr
->idVendor
,
1994 if_descr
.bInterfaceClass
,
1995 if_descr
.bInterfaceSubClass
,
1996 if_descr
.bInterfaceProtocol
);
1998 /* 10. usbifVID,classIC.ISC */
1999 (void) sprintf(usba_name
[n
++],
2000 "usbif%x,class%x.%x",
2001 usb_dev_descr
->idVendor
,
2002 if_descr
.bInterfaceClass
,
2003 if_descr
.bInterfaceSubClass
);
2005 /* 11. usbifVID,classIC */
2006 (void) sprintf(usba_name
[n
++],
2008 usb_dev_descr
->idVendor
,
2009 if_descr
.bInterfaceClass
);
2011 /* 12. usbif,classIC.ISC.IPROTO */
2012 (void) sprintf(usba_name
[n
++],
2013 "usbif,class%x.%x.%x",
2014 if_descr
.bInterfaceClass
,
2015 if_descr
.bInterfaceSubClass
,
2016 if_descr
.bInterfaceProtocol
);
2018 /* 13. usbif,classIC.ISC */
2019 (void) sprintf(usba_name
[n
++],
2021 if_descr
.bInterfaceClass
,
2022 if_descr
.bInterfaceSubClass
);
2024 /* 14. usbif,classIC */
2025 (void) sprintf(usba_name
[n
++],
2027 if_descr
.bInterfaceClass
);
2030 /* 15. ugen or usb_mid */
2031 if (usba_get_ugen_binding(child_dip
) ==
2032 USBA_UGEN_DEVICE_BINDING
) {
2033 (void) sprintf(usba_name
[n
++], "ugen");
2035 (void) sprintf(usba_name
[n
++], "usb,device");
2040 /* 1. usbVID,PID.REV.configCN */
2041 (void) sprintf(usba_name
[n
++],
2042 "usb%x,%x.%x.config%x",
2043 usb_dev_descr
->idVendor
,
2044 usb_dev_descr
->idProduct
,
2045 usb_dev_descr
->bcdDevice
,
2046 usba_device
->usb_cfg_value
);
2049 /* 2. usbVID,PID.REV */
2050 (void) sprintf(usba_name
[n
++],
2052 usb_dev_descr
->idVendor
,
2053 usb_dev_descr
->idProduct
,
2054 usb_dev_descr
->bcdDevice
);
2056 /* 3. usbVID,PID.configCN */
2058 (void) sprintf(usba_name
[n
++],
2060 usb_dev_descr
->idVendor
,
2061 usb_dev_descr
->idProduct
,
2062 usba_device
->usb_cfg_value
);
2066 (void) sprintf(usba_name
[n
++],
2068 usb_dev_descr
->idVendor
,
2069 usb_dev_descr
->idProduct
);
2071 if (usb_dev_descr
->bDeviceClass
!= 0) {
2072 /* 5. usbVID,classDC.DSC.DPROTO */
2073 (void) sprintf(usba_name
[n
++],
2074 "usb%x,class%x.%x.%x",
2075 usb_dev_descr
->idVendor
,
2076 usb_dev_descr
->bDeviceClass
,
2077 usb_dev_descr
->bDeviceSubClass
,
2078 usb_dev_descr
->bDeviceProtocol
);
2080 /* 6. usbVID,classDC.DSC */
2081 (void) sprintf(usba_name
[n
++],
2083 usb_dev_descr
->idVendor
,
2084 usb_dev_descr
->bDeviceClass
,
2085 usb_dev_descr
->bDeviceSubClass
);
2087 /* 7. usbVID,classDC */
2088 (void) sprintf(usba_name
[n
++],
2090 usb_dev_descr
->idVendor
,
2091 usb_dev_descr
->bDeviceClass
);
2093 /* 8. usb,classDC.DSC.DPROTO */
2094 (void) sprintf(usba_name
[n
++],
2095 "usb,class%x.%x.%x",
2096 usb_dev_descr
->bDeviceClass
,
2097 usb_dev_descr
->bDeviceSubClass
,
2098 usb_dev_descr
->bDeviceProtocol
);
2100 /* 9. usb,classDC.DSC */
2101 (void) sprintf(usba_name
[n
++],
2103 usb_dev_descr
->bDeviceClass
,
2104 usb_dev_descr
->bDeviceSubClass
);
2106 /* 10. usb,classDC */
2107 (void) sprintf(usba_name
[n
++],
2109 usb_dev_descr
->bDeviceClass
);
2112 if (usba_get_ugen_binding(child_dip
) ==
2113 USBA_UGEN_DEVICE_BINDING
) {
2115 (void) sprintf(usba_name
[n
++], "ugen");
2117 /* 11. usb,device */
2118 (void) sprintf(usba_name
[n
++], "usb,device");
2122 for (i
= 0; i
< n
; i
+= 2) {
2123 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
2124 "compatible name:\t%s\t%s", usba_name
[i
],
2125 (((i
+1) < n
)? usba_name
[i
+1] : ""));
2128 rval
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, child_dip
,
2129 "compatible", (char **)usba_name
, n
);
2131 kmem_free(usba_name_buf
, USBA_MAX_COMPAT_NAMES
*
2132 USBA_MAX_COMPAT_NAME_LEN
);
2134 if (rval
!= DDI_PROP_SUCCESS
) {
2136 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2137 "usba_ready_device_node: property update failed");
2142 /* update the address property */
2143 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2144 "assigned-address", usba_device
->usb_addr
);
2145 if (rval
!= DDI_PROP_SUCCESS
) {
2146 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2147 "usba_ready_device_node: address update failed");
2150 /* update the usb device properties (PSARC/2000/454) */
2151 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2152 "usb-vendor-id", usb_dev_descr
->idVendor
);
2153 if (rval
!= DDI_PROP_SUCCESS
) {
2154 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2155 "usba_ready_device_node: usb-vendor-id update failed");
2158 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2159 "usb-product-id", usb_dev_descr
->idProduct
);
2160 if (rval
!= DDI_PROP_SUCCESS
) {
2161 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2162 "usba_ready_device_node: usb-product-id update failed");
2165 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2166 "usb-revision-id", usb_dev_descr
->bcdDevice
);
2167 if (rval
!= DDI_PROP_SUCCESS
) {
2168 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2169 "usba_ready_device_node: usb-revision-id update failed");
2172 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2173 "usb-num-configs", usb_dev_descr
->bNumConfigurations
);
2174 if (rval
!= DDI_PROP_SUCCESS
) {
2175 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2176 "usba_ready_device_node: usb-num-configs update failed");
2179 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2180 "usb-release", usb_dev_descr
->bcdUSB
);
2181 if (rval
!= DDI_PROP_SUCCESS
) {
2182 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2183 "usba_ready_device_node: usb-release update failed");
2186 rval
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, child_dip
,
2187 "usb-dev-descriptor", (uchar_t
*)usb_dev_descr
,
2188 sizeof (usb_dev_descr_t
));
2189 if (rval
!= DDI_PROP_SUCCESS
) {
2190 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2191 "usba_ready_device_node: usb-descriptor update failed");
2194 rval
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, child_dip
,
2195 "usb-raw-cfg-descriptors", usb_config
, usb_config_length
);
2196 if (rval
!= DDI_PROP_SUCCESS
) {
2197 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2198 "usba_ready_device_node: usb-raw-cfg-descriptors update "
2202 devprop_str
= kmem_zalloc(USB_MAXSTRINGLEN
, KM_SLEEP
);
2204 if (usba_device
->usb_serialno_str
) {
2205 usba_filter_string(usba_device
->usb_serialno_str
, devprop_str
);
2206 rval
= ndi_prop_update_string(DDI_DEV_T_NONE
, child_dip
,
2207 "usb-serialno", devprop_str
);
2208 if (rval
!= DDI_PROP_SUCCESS
) {
2209 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2210 "usba_ready_device_node: "
2211 "usb-serialno update failed");
2215 if (usba_device
->usb_mfg_str
) {
2216 usba_filter_string(usba_device
->usb_mfg_str
, devprop_str
);
2217 rval
= ndi_prop_update_string(DDI_DEV_T_NONE
, child_dip
,
2218 "usb-vendor-name", devprop_str
);
2219 if (rval
!= DDI_PROP_SUCCESS
) {
2220 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2221 "usba_ready_device_node: "
2222 "usb-vendor-name update failed");
2226 if (usba_device
->usb_product_str
) {
2227 usba_filter_string(usba_device
->usb_product_str
, devprop_str
);
2228 rval
= ndi_prop_update_string(DDI_DEV_T_NONE
, child_dip
,
2229 "usb-product-name", devprop_str
);
2230 if (rval
!= DDI_PROP_SUCCESS
) {
2231 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2232 "usba_ready_device_node: "
2233 "usb-product-name update failed");
2237 kmem_free(devprop_str
, USB_MAXSTRINGLEN
);
2239 if (!combined_node
) {
2240 /* update the configuration property */
2241 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2242 "configuration#", usba_device
->usb_cfg_value
);
2243 if (rval
!= DDI_PROP_SUCCESS
) {
2244 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2245 "usba_ready_device_node: "
2246 "config prop update failed");
2250 if (usba_device
->usb_port_status
== USBA_LOW_SPEED_DEV
) {
2251 /* create boolean property */
2252 rval
= ndi_prop_create_boolean(DDI_DEV_T_NONE
, child_dip
,
2254 if (rval
!= DDI_PROP_SUCCESS
) {
2255 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2256 "usba_ready_device_node: "
2257 "low speed prop update failed");
2261 if (usba_device
->usb_port_status
== USBA_HIGH_SPEED_DEV
) {
2262 /* create boolean property */
2263 rval
= ndi_prop_create_boolean(DDI_DEV_T_NONE
, child_dip
,
2265 if (rval
!= DDI_PROP_SUCCESS
) {
2266 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2267 "usba_ready_device_node: "
2268 "high speed prop update failed");
2272 if (usba_device
->usb_port_status
== USBA_SUPER_SPEED_DEV
) {
2273 rval
= ndi_prop_create_boolean(DDI_DEV_T_NONE
, child_dip
,
2275 if (rval
!= DDI_PROP_SUCCESS
) {
2276 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2277 "usba_ready_device_node: "
2278 "super speed prop update failed");
2282 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
2283 "%s%d at port %d: %s, dip=0x%p",
2284 ddi_node_name(ddi_get_parent(child_dip
)),
2285 ddi_get_instance(ddi_get_parent(child_dip
)),
2286 port
, ddi_node_name(child_dip
), (void *)child_dip
);
2288 usba_set_usba_device(child_dip
, usba_device
);
2290 ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip
)->usb_mutex
)));
2297 * driver binding at interface association level. the first arg is the parent
2298 * dip. if_count returns amount of interfaces which are associated within
2299 * this interface-association that starts from first_if.
2303 usba_ready_interface_association_node(dev_info_t
*dip
,
2307 dev_info_t
*child_dip
= NULL
;
2308 usba_device_t
*child_ud
= usba_get_usba_device(dip
);
2309 usb_dev_descr_t
*usb_dev_descr
;
2310 size_t usb_cfg_length
;
2312 usb_ia_descr_t ia_descr
;
2316 usb_port_status_t port_status
;
2317 char *force_bind
= NULL
;
2318 char *usba_name_buf
= NULL
;
2319 char *usba_name
[USBA_MAX_COMPAT_NAMES
];
2321 usb_cfg
= usb_get_raw_cfg_data(dip
, &usb_cfg_length
);
2323 mutex_enter(&child_ud
->usb_mutex
);
2325 usb_dev_descr
= child_ud
->usb_dev_descr
;
2328 * for each interface association, determine all compatible names
2330 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
2331 "usba_ready_ia_node: "
2332 "port %d, interface = %d, port_status = %x",
2333 child_ud
->usb_port
, first_if
, child_ud
->usb_port_status
);
2335 /* Parse the interface descriptor */
2336 size
= usb_parse_ia_descr(
2339 first_if
, /* interface index */
2344 if (size
!= USB_IA_DESCR_SIZE
) {
2345 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2346 "parsing ia: size (%lu) != USB_IA_DESCR_SIZE (%d)",
2347 size
, USB_IA_DESCR_SIZE
);
2348 mutex_exit(&child_ud
->usb_mutex
);
2353 port_status
= child_ud
->usb_port_status
;
2355 /* create reg property */
2357 reg
[1] = child_ud
->usb_cfg_value
;
2359 mutex_exit(&child_ud
->usb_mutex
);
2361 /* clone this dip */
2362 rval
= usba_create_child_devi(dip
,
2363 "interface-association",
2364 NULL
, /* usba_hcdi ops */
2365 NULL
, /* root hub dip */
2366 port_status
, /* port status */
2367 child_ud
, /* share this usba_device */
2370 if (rval
!= USB_SUCCESS
) {
2375 rval
= ndi_prop_update_int_array(
2376 DDI_DEV_T_NONE
, child_dip
, "reg", reg
, 2);
2378 if (rval
!= DDI_PROP_SUCCESS
) {
2383 usba_set_node_name(child_dip
, ia_descr
.bFunctionClass
,
2384 ia_descr
.bFunctionSubClass
, ia_descr
.bFunctionProtocol
,
2385 FLAG_INTERFACE_ASSOCIATION_NODE
);
2387 /* check force binding */
2388 if (usba_ugen_force_binding
==
2389 USBA_UGEN_INTERFACE_ASSOCIATION_BINDING
) {
2390 force_bind
= "ugen";
2394 * check whether there is another dip with this name and address
2396 ASSERT(usba_find_existing_node(child_dip
) == NULL
);
2398 usba_name_buf
= kmem_zalloc(USBA_MAX_COMPAT_NAMES
*
2399 USBA_MAX_COMPAT_NAME_LEN
, KM_SLEEP
);
2401 for (i
= 0; i
< USBA_MAX_COMPAT_NAMES
; i
++) {
2402 usba_name
[i
] = usba_name_buf
+ (i
* USBA_MAX_COMPAT_NAME_LEN
);
2408 (void) ndi_devi_set_nodename(child_dip
, force_bind
, 0);
2409 (void) strncpy(usba_name
[n
++], force_bind
,
2410 USBA_MAX_COMPAT_NAME_LEN
);
2413 /* 1) usbiaVID,PID.REV.configCN.FN */
2414 (void) sprintf(usba_name
[n
++],
2415 "usbia%x,%x.%x.config%x.%x",
2416 usb_dev_descr
->idVendor
,
2417 usb_dev_descr
->idProduct
,
2418 usb_dev_descr
->bcdDevice
,
2419 child_ud
->usb_cfg_value
,
2422 /* 2) usbiaVID,PID.configCN.FN */
2423 (void) sprintf(usba_name
[n
++],
2424 "usbia%x,%x.config%x.%x",
2425 usb_dev_descr
->idVendor
,
2426 usb_dev_descr
->idProduct
,
2427 child_ud
->usb_cfg_value
,
2431 if (ia_descr
.bFunctionClass
) {
2432 /* 3) usbiaVID,classFC.FSC.FPROTO */
2433 (void) sprintf(usba_name
[n
++],
2434 "usbia%x,class%x.%x.%x",
2435 usb_dev_descr
->idVendor
,
2436 ia_descr
.bFunctionClass
,
2437 ia_descr
.bFunctionSubClass
,
2438 ia_descr
.bFunctionProtocol
);
2440 /* 4) usbiaVID,classFC.FSC */
2441 (void) sprintf(usba_name
[n
++],
2442 "usbia%x,class%x.%x",
2443 usb_dev_descr
->idVendor
,
2444 ia_descr
.bFunctionClass
,
2445 ia_descr
.bFunctionSubClass
);
2447 /* 5) usbiaVID,classFC */
2448 (void) sprintf(usba_name
[n
++],
2450 usb_dev_descr
->idVendor
,
2451 ia_descr
.bFunctionClass
);
2453 /* 6) usbia,classFC.FSC.FPROTO */
2454 (void) sprintf(usba_name
[n
++],
2455 "usbia,class%x.%x.%x",
2456 ia_descr
.bFunctionClass
,
2457 ia_descr
.bFunctionSubClass
,
2458 ia_descr
.bFunctionProtocol
);
2460 /* 7) usbia,classFC.FSC */
2461 (void) sprintf(usba_name
[n
++],
2463 ia_descr
.bFunctionClass
,
2464 ia_descr
.bFunctionSubClass
);
2466 /* 8) usbia,classFC */
2467 (void) sprintf(usba_name
[n
++],
2469 ia_descr
.bFunctionClass
);
2472 if (usba_get_ugen_binding(child_dip
) ==
2473 USBA_UGEN_INTERFACE_ASSOCIATION_BINDING
) {
2475 (void) sprintf(usba_name
[n
++], "ugen");
2478 (void) sprintf(usba_name
[n
++], "usb,ia");
2481 for (i
= 0; i
< n
; i
+= 2) {
2482 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
2483 "compatible name:\t%s\t%s", usba_name
[i
],
2484 (((i
+1) < n
)? usba_name
[i
+1] : ""));
2487 /* create compatible property */
2488 rval
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, child_dip
,
2489 "compatible", (char **)usba_name
, n
);
2491 kmem_free(usba_name_buf
, USBA_MAX_COMPAT_NAMES
*
2492 USBA_MAX_COMPAT_NAME_LEN
);
2494 if (rval
!= DDI_PROP_SUCCESS
) {
2499 /* update the address property */
2500 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2501 "assigned-address", child_ud
->usb_addr
);
2502 if (rval
!= DDI_PROP_SUCCESS
) {
2503 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2504 "usba_ready_interface_node: address update failed");
2507 /* create property with first interface number */
2508 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2509 "interface", ia_descr
.bFirstInterface
);
2511 if (rval
!= DDI_PROP_SUCCESS
) {
2516 /* create property with the count of interfaces in this ia */
2517 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2518 "interface-count", ia_descr
.bInterfaceCount
);
2520 if (rval
!= DDI_PROP_SUCCESS
) {
2525 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2526 "%s%d port %d: %s, dip = 0x%p",
2527 ddi_node_name(ddi_get_parent(dip
)),
2528 ddi_get_instance(ddi_get_parent(dip
)),
2529 child_ud
->usb_port
, ddi_node_name(child_dip
), (void *)child_dip
);
2531 *if_count
= ia_descr
.bInterfaceCount
;
2532 usba_set_usba_device(child_dip
, child_ud
);
2533 ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip
)->usb_mutex
)));
2538 (void) usba_destroy_child_devi(child_dip
, NDI_DEVI_REMOVE
);
2545 * driver binding at interface level, the first arg will be the
2550 usba_ready_interface_node(dev_info_t
*dip
, uint_t intf
)
2552 dev_info_t
*child_dip
= NULL
;
2553 usba_device_t
*child_ud
= usba_get_usba_device(dip
);
2554 usb_dev_descr_t
*usb_dev_descr
;
2555 size_t usb_cfg_length
;
2557 usb_if_descr_t if_descr
;
2561 usb_port_status_t port_status
;
2562 char *force_bind
= NULL
;
2563 char *usba_name_buf
= NULL
;
2564 char *usba_name
[USBA_MAX_COMPAT_NAMES
];
2566 usb_cfg
= usb_get_raw_cfg_data(dip
, &usb_cfg_length
);
2568 mutex_enter(&child_ud
->usb_mutex
);
2570 usb_dev_descr
= child_ud
->usb_dev_descr
;
2573 * for each interface, determine all compatible names
2575 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
2576 "usba_ready_interface_node: "
2577 "port %d, interface = %d port status = %x",
2578 child_ud
->usb_port
, intf
, child_ud
->usb_port_status
);
2580 /* Parse the interface descriptor */
2581 size
= usb_parse_if_descr(
2584 intf
, /* interface index */
2585 0, /* alt interface index */
2589 if (size
!= USB_IF_DESCR_SIZE
) {
2590 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2591 "parsing interface: size (%lu) != USB_IF_DESCR_SIZE (%d)",
2592 size
, USB_IF_DESCR_SIZE
);
2593 mutex_exit(&child_ud
->usb_mutex
);
2598 port_status
= child_ud
->usb_port_status
;
2600 /* create reg property */
2602 reg
[1] = child_ud
->usb_cfg_value
;
2604 mutex_exit(&child_ud
->usb_mutex
);
2606 /* clone this dip */
2607 rval
= usba_create_child_devi(dip
,
2609 NULL
, /* usba_hcdi ops */
2610 NULL
, /* root hub dip */
2611 port_status
, /* port status */
2612 child_ud
, /* share this usba_device */
2615 if (rval
!= USB_SUCCESS
) {
2620 rval
= ndi_prop_update_int_array(
2621 DDI_DEV_T_NONE
, child_dip
, "reg", reg
, 2);
2623 if (rval
!= DDI_PROP_SUCCESS
) {
2628 usba_set_node_name(child_dip
, if_descr
.bInterfaceClass
,
2629 if_descr
.bInterfaceSubClass
, if_descr
.bInterfaceProtocol
,
2630 FLAG_INTERFACE_NODE
);
2632 /* check force binding */
2633 if (usba_ugen_force_binding
== USBA_UGEN_INTERFACE_BINDING
) {
2634 force_bind
= "ugen";
2638 * check whether there is another dip with this name and address
2640 ASSERT(usba_find_existing_node(child_dip
) == NULL
);
2642 usba_name_buf
= kmem_zalloc(USBA_MAX_COMPAT_NAMES
*
2643 USBA_MAX_COMPAT_NAME_LEN
, KM_SLEEP
);
2645 for (i
= 0; i
< USBA_MAX_COMPAT_NAMES
; i
++) {
2646 usba_name
[i
] = usba_name_buf
+ (i
* USBA_MAX_COMPAT_NAME_LEN
);
2652 (void) ndi_devi_set_nodename(child_dip
, force_bind
, 0);
2653 (void) strncpy(usba_name
[n
++], force_bind
,
2654 USBA_MAX_COMPAT_NAME_LEN
);
2657 /* 1) usbifVID,PID.REV.configCN.IN */
2658 (void) sprintf(usba_name
[n
++],
2659 "usbif%x,%x.%x.config%x.%x",
2660 usb_dev_descr
->idVendor
,
2661 usb_dev_descr
->idProduct
,
2662 usb_dev_descr
->bcdDevice
,
2663 child_ud
->usb_cfg_value
,
2666 /* 2) usbifVID,PID.configCN.IN */
2667 (void) sprintf(usba_name
[n
++],
2668 "usbif%x,%x.config%x.%x",
2669 usb_dev_descr
->idVendor
,
2670 usb_dev_descr
->idProduct
,
2671 child_ud
->usb_cfg_value
,
2675 if (if_descr
.bInterfaceClass
) {
2676 /* 3) usbifVID,classIC.ISC.IPROTO */
2677 (void) sprintf(usba_name
[n
++],
2678 "usbif%x,class%x.%x.%x",
2679 usb_dev_descr
->idVendor
,
2680 if_descr
.bInterfaceClass
,
2681 if_descr
.bInterfaceSubClass
,
2682 if_descr
.bInterfaceProtocol
);
2684 /* 4) usbifVID,classIC.ISC */
2685 (void) sprintf(usba_name
[n
++],
2686 "usbif%x,class%x.%x",
2687 usb_dev_descr
->idVendor
,
2688 if_descr
.bInterfaceClass
,
2689 if_descr
.bInterfaceSubClass
);
2691 /* 5) usbifVID,classIC */
2692 (void) sprintf(usba_name
[n
++],
2694 usb_dev_descr
->idVendor
,
2695 if_descr
.bInterfaceClass
);
2697 /* 6) usbif,classIC.ISC.IPROTO */
2698 (void) sprintf(usba_name
[n
++],
2699 "usbif,class%x.%x.%x",
2700 if_descr
.bInterfaceClass
,
2701 if_descr
.bInterfaceSubClass
,
2702 if_descr
.bInterfaceProtocol
);
2704 /* 7) usbif,classIC.ISC */
2705 (void) sprintf(usba_name
[n
++],
2707 if_descr
.bInterfaceClass
,
2708 if_descr
.bInterfaceSubClass
);
2710 /* 8) usbif,classIC */
2711 (void) sprintf(usba_name
[n
++],
2713 if_descr
.bInterfaceClass
);
2716 if (usba_get_ugen_binding(child_dip
) ==
2717 USBA_UGEN_INTERFACE_BINDING
) {
2719 (void) sprintf(usba_name
[n
++], "ugen");
2722 for (i
= 0; i
< n
; i
+= 2) {
2723 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
2724 "compatible name:\t%s\t%s", usba_name
[i
],
2725 (((i
+1) < n
)? usba_name
[i
+1] : ""));
2728 /* create compatible property */
2729 rval
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, child_dip
,
2730 "compatible", (char **)usba_name
, n
);
2732 kmem_free(usba_name_buf
, USBA_MAX_COMPAT_NAMES
*
2733 USBA_MAX_COMPAT_NAME_LEN
);
2735 if (rval
!= DDI_PROP_SUCCESS
) {
2740 /* update the address property */
2741 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2742 "assigned-address", child_ud
->usb_addr
);
2743 if (rval
!= DDI_PROP_SUCCESS
) {
2744 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2745 "usba_ready_interface_node: address update failed");
2748 /* create property with if number */
2749 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, child_dip
,
2752 if (rval
!= DDI_PROP_SUCCESS
) {
2757 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
2758 "%s%d port %d: %s, dip = 0x%p",
2759 ddi_node_name(ddi_get_parent(dip
)),
2760 ddi_get_instance(ddi_get_parent(dip
)),
2761 child_ud
->usb_port
, ddi_node_name(child_dip
), (void *)child_dip
);
2763 usba_set_usba_device(child_dip
, child_ud
);
2764 ASSERT(!mutex_owned(&(usba_get_usba_device(child_dip
)->usb_mutex
)));
2769 (void) usba_destroy_child_devi(child_dip
, NDI_DEVI_REMOVE
);
2776 * retrieve string descriptors for manufacturer, vendor and serial
2780 usba_get_dev_string_descrs(dev_info_t
*dip
, usba_device_t
*ud
)
2784 usb_dev_descr_t
*usb_dev_descr
= ud
->usb_dev_descr
;
2787 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
2788 "usba_get_usb_string_descr: m=%d, p=%d, s=%d",
2789 usb_dev_descr
->iManufacturer
,
2790 usb_dev_descr
->iProduct
,
2791 usb_dev_descr
->iSerialNumber
);
2793 tmpbuf
= kmem_zalloc(USB_MAXSTRINGLEN
, KM_SLEEP
);
2795 /* fetch manufacturer string */
2796 if ((ud
->usb_mfg_str
== NULL
) && usb_dev_descr
->iManufacturer
&&
2797 (usb_get_string_descr(dip
, USB_LANG_ID
,
2798 usb_dev_descr
->iManufacturer
, tmpbuf
, USB_MAXSTRINGLEN
) ==
2803 str
= kmem_zalloc(l
+ 1, KM_SLEEP
);
2804 mutex_enter(&ud
->usb_mutex
);
2805 ud
->usb_mfg_str
= str
;
2806 (void) strcpy(ud
->usb_mfg_str
, tmpbuf
);
2807 mutex_exit(&ud
->usb_mutex
);
2811 /* fetch product string */
2812 if ((ud
->usb_product_str
== NULL
) && usb_dev_descr
->iProduct
&&
2813 (usb_get_string_descr(dip
, USB_LANG_ID
, usb_dev_descr
->iProduct
,
2814 tmpbuf
, USB_MAXSTRINGLEN
) ==
2819 str
= kmem_zalloc(l
+ 1, KM_SLEEP
);
2820 mutex_enter(&ud
->usb_mutex
);
2821 ud
->usb_product_str
= str
;
2822 (void) strcpy(ud
->usb_product_str
, tmpbuf
);
2823 mutex_exit(&ud
->usb_mutex
);
2827 /* fetch device serial number string */
2828 if ((ud
->usb_serialno_str
== NULL
) && usb_dev_descr
->iSerialNumber
&&
2829 (usb_get_string_descr(dip
, USB_LANG_ID
,
2830 usb_dev_descr
->iSerialNumber
, tmpbuf
, USB_MAXSTRINGLEN
) ==
2835 str
= kmem_zalloc(l
+ 1, KM_SLEEP
);
2836 mutex_enter(&ud
->usb_mutex
);
2837 ud
->usb_serialno_str
= str
;
2838 (void) strcpy(ud
->usb_serialno_str
, tmpbuf
);
2839 mutex_exit(&ud
->usb_mutex
);
2843 kmem_free(tmpbuf
, USB_MAXSTRINGLEN
);
2848 * usba_get_mfg_prod_sn_str:
2849 * Return a string containing mfg, product, serial number strings.
2850 * Remove duplicates if some strings are the same.
2853 * dip - pointer to dev info
2854 * buffer - Where string is returned
2855 * buflen - Length of buffer
2858 * Same as second arg.
2861 usba_get_mfg_prod_sn_str(
2866 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
2871 buffer
[buflen
-1] = '\0';
2873 /* Manufacturer string exists. */
2874 if ((usba_device
->usb_mfg_str
) &&
2875 ((len
= strlen(usba_device
->usb_mfg_str
)) != 0)) {
2876 (void) strncpy(buffer
, usba_device
->usb_mfg_str
, buflen
- 1);
2877 return_len
= min(buflen
- 1, len
);
2880 /* Product string exists to append. */
2881 if ((usba_device
->usb_product_str
) &&
2882 ((len
= strlen(usba_device
->usb_product_str
)) != 0)) {
2883 if (return_len
> 0) {
2884 buffer
[return_len
++] = ' ';
2886 (void) strncpy(&buffer
[return_len
],
2887 usba_device
->usb_product_str
, buflen
- return_len
- 1);
2888 return_len
= min(buflen
- 1, return_len
+ len
);
2891 /* Serial number string exists to append. */
2892 if ((usba_device
->usb_serialno_str
) &&
2893 ((len
= strlen(usba_device
->usb_serialno_str
)) != 0)) {
2894 if (return_len
> 0) {
2895 buffer
[return_len
++] = ' ';
2897 (void) strncpy(&buffer
[return_len
],
2898 usba_device
->usb_serialno_str
,
2899 buflen
- return_len
- 1);
2907 * USB enumeration statistic functions
2911 * Increments the hotplug statistics based on flags.
2914 usba_update_hotplug_stats(dev_info_t
*dip
, usb_flags_t flags
)
2916 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
2918 usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
);
2920 mutex_enter(&hcdi
->hcdi_mutex
);
2921 if (flags
& USBA_TOTAL_HOTPLUG_SUCCESS
) {
2922 hcdi
->hcdi_total_hotplug_success
++;
2923 HCDI_HOTPLUG_STATS_DATA(hcdi
)->
2924 hcdi_hotplug_total_success
.value
.ui64
++;
2926 if (flags
& USBA_HOTPLUG_SUCCESS
) {
2927 hcdi
->hcdi_hotplug_success
++;
2928 HCDI_HOTPLUG_STATS_DATA(hcdi
)->
2929 hcdi_hotplug_success
.value
.ui64
++;
2931 if (flags
& USBA_TOTAL_HOTPLUG_FAILURE
) {
2932 hcdi
->hcdi_total_hotplug_failure
++;
2933 HCDI_HOTPLUG_STATS_DATA(hcdi
)->
2934 hcdi_hotplug_total_failure
.value
.ui64
++;
2936 if (flags
& USBA_HOTPLUG_FAILURE
) {
2937 hcdi
->hcdi_hotplug_failure
++;
2938 HCDI_HOTPLUG_STATS_DATA(hcdi
)->
2939 hcdi_hotplug_failure
.value
.ui64
++;
2941 mutex_exit(&hcdi
->hcdi_mutex
);
2946 * Retrieve the current enumeration statistics
2949 usba_get_hotplug_stats(dev_info_t
*dip
, ulong_t
*total_success
,
2950 ulong_t
*success
, ulong_t
*total_failure
, ulong_t
*failure
,
2951 uchar_t
*device_count
)
2953 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
2955 usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
);
2957 mutex_enter(&hcdi
->hcdi_mutex
);
2958 *total_success
= hcdi
->hcdi_total_hotplug_success
;
2959 *success
= hcdi
->hcdi_hotplug_success
;
2960 *total_failure
= hcdi
->hcdi_total_hotplug_failure
;
2961 *failure
= hcdi
->hcdi_hotplug_failure
;
2962 *device_count
= hcdi
->hcdi_device_count
;
2963 mutex_exit(&hcdi
->hcdi_mutex
);
2968 * Reset the resetable hotplug stats
2971 usba_reset_hotplug_stats(dev_info_t
*dip
)
2973 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
2975 usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
);
2976 hcdi_hotplug_stats_t
*hsp
;
2978 mutex_enter(&hcdi
->hcdi_mutex
);
2979 hcdi
->hcdi_hotplug_success
= 0;
2980 hcdi
->hcdi_hotplug_failure
= 0;
2982 hsp
= HCDI_HOTPLUG_STATS_DATA(hcdi
);
2983 hsp
->hcdi_hotplug_success
.value
.ui64
= 0;
2984 hsp
->hcdi_hotplug_failure
.value
.ui64
= 0;
2985 mutex_exit(&hcdi
->hcdi_mutex
);
2990 * usba_bind_driver():
2991 * This function calls ndi_devi_bind_driver() which tries to
2992 * bind a driver to the device. If the driver binding fails
2993 * we get an rval of NDI_UNBOUD and report an error to the
2994 * syslog that the driver failed binding.
2995 * If rval is something other than NDI_UNBOUND we report an
2996 * error to the console.
2998 * This function returns USB_SUCCESS if no errors were
2999 * encountered while binding.
3002 usba_bind_driver(dev_info_t
*dip
)
3006 uint8_t if_num
= usba_get_ifno(dip
);
3008 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
3009 "usba_bind_driver: dip = 0x%p, if_num = 0x%x", (void *)dip
, if_num
);
3011 name
= kmem_zalloc(MAXNAMELEN
, KM_SLEEP
);
3013 /* bind device to the driver */
3014 if ((rval
= ndi_devi_bind_driver(dip
, 0)) != NDI_SUCCESS
) {
3015 /* if we fail to bind report an error */
3016 (void) usba_get_mfg_prod_sn_str(dip
, name
, MAXNAMELEN
);
3017 if (name
[0] != '\0') {
3018 if (!usb_owns_device(dip
)) {
3019 USB_DPRINTF_L1(DPRINT_MASK_USBA
,
3021 "no driver found for "
3022 "interface %d (nodename: '%s') of %s",
3023 if_num
, ddi_node_name(dip
), name
);
3025 USB_DPRINTF_L1(DPRINT_MASK_USBA
,
3027 "no driver found for device %s", name
);
3030 (void) ddi_pathname(dip
, name
);
3031 USB_DPRINTF_L1(DPRINT_MASK_USBA
,
3033 "no driver found for device %s", name
);
3036 kmem_free(name
, MAXNAMELEN
);
3038 return (USB_FAILURE
);
3040 kmem_free(name
, MAXNAMELEN
);
3042 return ((rval
== NDI_SUCCESS
) ? USB_SUCCESS
: USB_FAILURE
);
3047 * usba_get_hc_dma_attr:
3048 * function returning dma attributes of the HCD
3051 * dip - pointer to devinfo of the client
3057 usba_get_hc_dma_attr(dev_info_t
*dip
)
3059 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
3060 usba_hcdi_t
*hcdi
= usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
);
3062 return (hcdi
->hcdi_dma_attr
);
3067 * usba_check_for_leaks:
3068 * check usba_device structure for leaks
3071 * usba_device - usba_device structure pointer
3074 usba_check_for_leaks(usba_device_t
*usba_device
)
3076 int i
, ph_open_cnt
, req_wrp_leaks
, iface
;
3079 USB_DPRINTF_L4(DPRINT_MASK_USBA
, usba_log_handle
,
3080 "usba_check_for_leaks: %s%d usba_device=0x%p",
3081 ddi_driver_name(usba_device
->usb_dip
),
3082 ddi_get_instance(usba_device
->usb_dip
), (void *)usba_device
);
3085 * default pipe is still open
3086 * all other pipes should be closed
3088 for (ph_open_cnt
= 0, i
= 1; i
< USBA_N_ENDPOINTS
; i
++) {
3089 usba_ph_impl_t
*ph_impl
=
3090 &usba_device
->usb_ph_list
[i
];
3091 if (ph_impl
->usba_ph_data
) {
3092 USB_DPRINTF_L2(DPRINT_MASK_USBA
,
3094 "%s%d: leaking pipehandle=0x%p (0x%p) ep_addr=0x%x",
3095 ddi_driver_name(ph_impl
->usba_ph_data
->p_dip
),
3096 ddi_get_instance(ph_impl
->usba_ph_data
->p_dip
),
3098 (void *)ph_impl
->usba_ph_data
,
3099 ph_impl
->usba_ph_ep
.bEndpointAddress
);
3103 usb_pipe_close(ph_impl
->usba_ph_data
->p_dip
,
3104 (usb_pipe_handle_t
)ph_impl
, USB_FLAGS_SLEEP
,
3105 (void (*)())NULL
, NULL
);
3109 req_wrp_leaks
= usba_list_entry_leaks(&usba_device
->
3110 usb_allocated
, "request wrappers");
3112 ASSERT(ph_open_cnt
== 0);
3113 ASSERT(req_wrp_leaks
== 0);
3115 if (req_wrp_leaks
) {
3116 usba_list_entry_t
*entry
;
3118 while ((entry
= usba_rm_first_from_list(
3119 &usba_device
->usb_allocated
)) != NULL
) {
3120 usba_req_wrapper_t
*wrp
;
3122 mutex_enter(&entry
->list_mutex
);
3123 wrp
= (usba_req_wrapper_t
*)entry
->private;
3124 mutex_exit(&entry
->list_mutex
);
3127 USB_DPRINTF_L2(DPRINT_MASK_USBA
,
3129 "%s%d: leaking request 0x%p",
3130 ddi_driver_name(wrp
->wr_dip
),
3131 ddi_get_instance(wrp
->wr_dip
),
3132 (void *)wrp
->wr_req
);
3135 * put it back, usba_req_wrapper_free
3136 * expects it on the list
3138 usba_add_to_list(&usba_device
->usb_allocated
,
3139 &wrp
->wr_allocated_list
);
3141 usba_req_wrapper_free(wrp
);
3145 mutex_enter(&usba_device
->usb_mutex
);
3146 for (iface
= 0; iface
< usba_device
->usb_n_ifs
; iface
++) {
3147 USB_DPRINTF_L3(DPRINT_MASK_USBA
, usba_log_handle
,
3148 "usba_check_for_leaks: if=%d client_flags=0x%x",
3149 iface
, usba_device
->usb_client_flags
[iface
]);
3151 if (usba_device
->usb_client_flags
[iface
] &
3152 USBA_CLIENT_FLAG_DEV_DATA
) {
3153 usb_client_dev_data_list_t
*entry
=
3154 usba_device
->usb_client_dev_data_list
.cddl_next
;
3155 usb_client_dev_data_list_t
*next
;
3156 usb_client_dev_data_t
*dev_data
;
3159 dev_info_t
*dip
= entry
->cddl_dip
;
3160 next
= entry
->cddl_next
;
3161 dev_data
= entry
->cddl_dev_data
;
3164 if (!i_ddi_devi_attached(dip
)) {
3165 USB_DPRINTF_L2(DPRINT_MASK_USBA
,
3167 "%s%d: leaking dev_data 0x%p",
3168 ddi_driver_name(dip
),
3169 ddi_get_instance(dip
),
3174 mutex_exit(&usba_device
->usb_mutex
);
3175 usb_free_dev_data(dip
, dev_data
);
3176 mutex_enter(&usba_device
->usb_mutex
);
3182 if (usba_device
->usb_client_flags
[iface
] &
3183 USBA_CLIENT_FLAG_ATTACH
) {
3184 dev_info_t
*dip
= usba_device
->
3185 usb_client_attach_list
[iface
].dip
;
3187 USB_DPRINTF_L2(DPRINT_MASK_USBA
,
3189 "%s%d: did no usb_client_detach",
3190 ddi_driver_name(dip
), ddi_get_instance(dip
));
3193 mutex_exit(&usba_device
->usb_mutex
);
3194 usb_client_detach(dip
, NULL
);
3195 mutex_enter(&usba_device
->usb_mutex
);
3198 usb_client_attach_list
[iface
].dip
= NULL
;
3200 usba_device
->usb_client_flags
[iface
] &=
3201 ~USBA_CLIENT_FLAG_ATTACH
;
3204 if (usba_device
->usb_client_flags
[iface
] &
3205 USBA_CLIENT_FLAG_EV_CBS
) {
3207 usba_device
->usb_client_ev_cb_list
[iface
].
3209 usb_event_t
*ev_data
=
3210 usba_device
->usb_client_ev_cb_list
[iface
].
3213 USB_DPRINTF_L2(DPRINT_MASK_USBA
,
3215 "%s%d: did no usb_unregister_event_cbs",
3216 ddi_driver_name(dip
), ddi_get_instance(dip
));
3219 mutex_exit(&usba_device
->usb_mutex
);
3220 usb_unregister_event_cbs(dip
, ev_data
);
3221 mutex_enter(&usba_device
->usb_mutex
);
3223 usba_device
->usb_client_ev_cb_list
[iface
].
3225 usba_device
->usb_client_ev_cb_list
[iface
].
3227 usba_device
->usb_client_flags
[iface
] &=
3228 ~USBA_CLIENT_FLAG_EV_CBS
;
3231 mutex_exit(&usba_device
->usb_mutex
);
3234 USB_DPRINTF_L2(DPRINT_MASK_USBA
, usba_log_handle
,
3235 "all %d leaks fixed", leaks
);