d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * CDDL HEADER START
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * The contents of this file are subject to the terms of the
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Common Development and Distribution License (the "License").
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * You may not use this file except in compliance with the License.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * or http://www.opensolaris.org/os/licensing.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * See the License for the specific language governing permissions
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * and limitations under the License.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * When distributing Covered Code, include this CDDL HEADER in each
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * If applicable, add the following below this CDDL HEADER, with the
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * fields enclosed by brackets "[]" replaced with your own identifying
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * information: Portions Copyright [yyyy] [name of copyright owner]
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * CDDL HEADER END
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
be529ebc20c1845423cc7561286bd60dcc97f677Raymond Chen * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Use is subject to license terms.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore/*
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * usb interface association driver
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * this driver attempts to the interface association node and
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * creates/manages child nodes for the included interfaces.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#if defined(lint) && !defined(DEBUG)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#define DEBUG 1
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#endif
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#include <sys/usb/usba/usbai_version.h>
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#include <sys/usb/usba.h>
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#include <sys/usb/usba/usba_types.h>
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#include <sys/usb/usba/usba_impl.h>
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#include <sys/usb/usb_ia/usb_iavar.h>
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/* Debugging support */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcuint_t usb_ia_errlevel = USB_LOG_L4;
d73ae94e59c019f5cc3221ee0a0012d02091b40egcuint_t usb_ia_errmask = (uint_t)DPRINT_MASK_ALL;
d73ae94e59c019f5cc3221ee0a0012d02091b40egcuint_t usb_ia_instance_debug = (uint_t)-1;
d73ae94e59c019f5cc3221ee0a0012d02091b40egcuint_t usb_ia_bus_config_debug = 0;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_errlevel))
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_errmask))
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_instance_debug))
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_NOTE(SCHEME_PROTECTS_DATA("unique", msgb))
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_NOTE(SCHEME_PROTECTS_DATA("unique", dev_info))
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_NOTE(SCHEME_PROTECTS_DATA("unique", usb_pipe_policy))
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic struct cb_ops usb_ia_cb_ops = {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* open */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* close */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* strategy */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* print */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* dump */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* read */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* write */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* ioctl */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* devmap */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* mmap */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* segmap */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nochpoll, /* poll */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_prop_op, /* prop_op */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* aread */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc D_MP
d73ae94e59c019f5cc3221ee0a0012d02091b40egc};
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_busop_get_eventcookie(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *rdip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc char *eventname,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t *cookie);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_busop_add_eventcall(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *rdip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t cookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void (*callback)(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t cookie, void *arg,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *bus_impldata),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg, ddi_callback_id_t *cb_id);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_busop_remove_eventcall(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_callback_id_t cb_id);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_busop_post_event(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *rdip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t cookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_bus_config(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc uint_t flag,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_bus_config_op_t op,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t **child);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_bus_unconfig(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc uint_t flag,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_bus_config_op_t op,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * autoconfiguration data and routines.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_info(dev_info_t *, ddi_info_cmd_t,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *, void **);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_attach(dev_info_t *, ddi_attach_cmd_t);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_detach(dev_info_t *, ddi_detach_cmd_t);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/* other routines */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void usb_ia_create_pm_components(dev_info_t *, usb_ia_t *);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_bus_ctl(dev_info_t *, dev_info_t *,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_ctl_enum_t, void *, void *);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_power(dev_info_t *, int, int);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_restore_device_state(dev_info_t *, usb_ia_t *);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic usb_ia_t *usb_ia_obtain_state(dev_info_t *);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void usb_ia_event_cb(dev_info_t *, ddi_eventcookie_t, void *, void *);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/* prototypes */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void usb_ia_create_children(usb_ia_t *);
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int usb_ia_cleanup(usb_ia_t *);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Busops vector
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic struct bus_ops usb_ia_busops = {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc BUSO_REV,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nullbusmap, /* bus_map */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_get_intrspec */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_add_intrspec */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_remove_intrspec */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* XXXX bus_map_fault */
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore NULL, /* bus_dma_map */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_dma_allochdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_dma_freehdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_dma_bindhdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_dma_unbindhdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_dma_flush,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_dma_win,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_dma_mctl, /* bus_dma_ctl */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_bus_ctl, /* bus_ctl */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_bus_prop_op, /* bus_prop_op */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_busop_get_eventcookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_busop_add_eventcall,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_busop_remove_eventcall,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_busop_post_event, /* bus_post_event */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_intr_ctl */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_bus_config, /* bus_config */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_bus_unconfig, /* bus_unconfig */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_fm_init */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_fm_fini */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_fm_access_enter */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, /* bus_fm_access_exit */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL /* bus_power */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc};
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic struct dev_ops usb_ia_ops = {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc DEVO_REV, /* devo_rev, */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc 0, /* refcnt */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_info, /* info */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nulldev, /* identify */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nulldev, /* probe */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_attach, /* attach */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_detach, /* detach */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc nodev, /* reset */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc &usb_ia_cb_ops, /* driver operations */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc &usb_ia_busops, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore usb_ia_power, /* power */
be529ebc20c1845423cc7561286bd60dcc97f677Raymond Chen ddi_quiesce_not_needed, /* devo_quiesce */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc};
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic struct modldrv modldrv = {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc &mod_driverops, /* Type of module. This one is a driver */
77e515715b61e28fcf0c3f30936492888cecfd8bgongtian zhao - Sun Microsystems - Beijing China "USB Interface Association Driver", /* Name of the module. */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc &usb_ia_ops, /* driver ops */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc};
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic struct modlinkage modlinkage = {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc MODREV_1, (void *)&modldrv, NULL
d73ae94e59c019f5cc3221ee0a0012d02091b40egc};
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#define USB_IA_INITIAL_SOFT_SPACE 4
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void *usb_ia_statep;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * event definition
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic ndi_event_definition_t usb_ia_ndi_event_defs[] = {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc {USBA_EVENT_TAG_HOT_REMOVAL, DDI_DEVI_REMOVE_EVENT, EPL_KERNEL,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NDI_EVENT_POST_TO_ALL},
d73ae94e59c019f5cc3221ee0a0012d02091b40egc {USBA_EVENT_TAG_HOT_INSERTION, DDI_DEVI_INSERT_EVENT, EPL_KERNEL,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NDI_EVENT_POST_TO_ALL},
d73ae94e59c019f5cc3221ee0a0012d02091b40egc {USBA_EVENT_TAG_POST_RESUME, USBA_POST_RESUME_EVENT, EPL_KERNEL,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NDI_EVENT_POST_TO_ALL},
d73ae94e59c019f5cc3221ee0a0012d02091b40egc {USBA_EVENT_TAG_PRE_SUSPEND, USBA_PRE_SUSPEND_EVENT, EPL_KERNEL,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NDI_EVENT_POST_TO_ALL}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc};
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc#define USB_IA_N_NDI_EVENTS \
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (sizeof (usb_ia_ndi_event_defs) / sizeof (ndi_event_definition_t))
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic ndi_event_set_t usb_ia_ndi_events = {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NDI_EVENTS_REV1, USB_IA_N_NDI_EVENTS, usb_ia_ndi_event_defs};
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * standard driver entry points
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcint
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_init(void)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int rval;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rval = ddi_soft_state_init(&usb_ia_statep, sizeof (struct usb_ia),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_IA_INITIAL_SOFT_SPACE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (rval != 0) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if ((rval = mod_install(&modlinkage)) != 0) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_soft_state_fini(&usb_ia_statep);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcint
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_fini(void)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int rval;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rval = mod_remove(&modlinkage);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (rval) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_soft_state_fini(&usb_ia_statep);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcint
d73ae94e59c019f5cc3221ee0a0012d02091b40egc_info(struct modinfo *modinfop)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (mod_info(&modlinkage, modinfop));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*ARGSUSED*/
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int instance = getminor((dev_t)arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int error = DDI_FAILURE;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (infocmd) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_INFO_DEVT2DEVINFO:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if ((usb_ia = ddi_get_soft_state(usb_ia_statep,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc instance)) != NULL) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *result = (void *)usb_ia->ia_dip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (*result != NULL) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc error = DDI_SUCCESS;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc } else {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *result = NULL;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_INFO_DEVT2INSTANCE:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *result = (void *)(intptr_t)instance;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc error = DDI_SUCCESS;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc default:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (error);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * child post attach/detach notification
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_post_attach(usb_ia_t *usb_ia, uint8_t ifno, struct attachspec *as)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_post_attach: ifno = %d result = %d", ifno, as->result);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_post_detach(usb_ia_t *usb_ia, uint8_t ifno, struct detachspec *ds)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_post_detach: ifno = %d result = %d", ifno, ds->result);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * bus ctl support. we handle notifications here and the
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * rest goes up to root hub/hcd
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*ARGSUSED*/
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_bus_ctl(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *rdip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_ctl_enum_t op,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *result)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usba_device_t *hub_usba_device = usba_get_usba_device(rdip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *root_hub_dip = hub_usba_device->usb_root_hub_dip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc struct attachspec *as;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc struct detachspec *ds;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_bus_ctl:\n\t"
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "dip = 0x%p, rdip = 0x%p, op = 0x%x, arg = 0x%p",
112116d842e816e29d26a8fe28ed25d201063169fb (void *)dip, (void *)rdip, op, arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (op) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_CTLOPS_ATTACH:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc as = (struct attachspec *)arg;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (as->when) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_PRE :
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* nothing to do basically */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "DDI_PRE DDI_CTLOPS_ATTACH");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_POST :
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_post_attach(usb_ia, usba_get_ifno(rdip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (struct attachspec *)arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_CTLOPS_DETACH:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ds = (struct detachspec *)arg;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (ds->when) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_PRE :
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* nothing to do basically */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "DDI_PRE DDI_CTLOPS_DETACH");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_POST :
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_post_detach(usb_ia, usba_get_ifno(rdip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (struct detachspec *)arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc default:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* pass to root hub to handle */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (usba_bus_ctl(root_hub_dip, rdip, op, arg, result));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_SUCCESS);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * bus enumeration entry points
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg, dev_info_t **child)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int rval, circ;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_ALL, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_bus_config: op=%d", op);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia_bus_config_debug) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc flag |= NDI_DEVI_DEBUG;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_devi_enter(dip, &circ);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* enumerate each interface below us */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_create_children(usb_ia);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rval = ndi_busop_bus_config(dip, flag, op, arg, child, 0);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_devi_exit(dip, circ);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *cdip, *mdip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int interface, circular_count;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int rval = NDI_SUCCESS;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_ALL, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_bus_unconfig: op=%d", op);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia_bus_config_debug) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc flag |= NDI_DEVI_DEBUG;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * first offline and if offlining successful, then
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * remove children
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (op == BUS_UNCONFIG_ALL) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_devi_enter(dip, &circular_count);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rval = ndi_busop_bus_unconfig(dip, flag, op, arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (op == BUS_UNCONFIG_ALL && rval == NDI_SUCCESS &&
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (flag & NDI_AUTODETACH) == 0) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc flag |= NDI_DEVI_REMOVE;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rval = ndi_busop_bus_unconfig(dip, flag, op, arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* update children's list */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc for (interface = 0; usb_ia->ia_children_dips &&
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (interface < usb_ia->ia_n_ifs); interface++) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mdip = usb_ia->ia_children_dips[interface];
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* now search if this dip still exists */
112116d842e816e29d26a8fe28ed25d201063169fb for (cdip = ddi_get_child(dip); cdip && (cdip != mdip); )
112116d842e816e29d26a8fe28ed25d201063169fb cdip = ddi_get_next_sibling(cdip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (cdip != mdip) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* we lost the dip on this interface */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_children_dips[interface] = NULL;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc } else if (cdip) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * keep in DS_INITALIZED to prevent parent
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * from detaching
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ddi_initchild(ddi_get_parent(cdip), cdip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_devi_exit(dip, circular_count);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_ALL, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_bus_config: rval=%d", rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/* power entry point */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/* ARGSUSED */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_power(dev_info_t *dip, int comp, int level)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_common_power_t *pm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int rval = DDI_FAILURE;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
112116d842e816e29d26a8fe28ed25d201063169fb "usb_ia_power: Begin: usb_ia = %p, level = %d",
112116d842e816e29d26a8fe28ed25d201063169fb (void *)usb_ia, level);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc pm = usb_ia->ia_pm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* check if we are transitioning to a legal power level */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (USB_DEV_PWRSTATE_OK(pm->uc_pwr_states, level)) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_power: illegal power level = %d "
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "uc_pwr_states = %x", level, pm->uc_pwr_states);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
036aa26189b72905886e39d76d63352185cfd9d2gc rval = usba_common_power(dip, &(pm->uc_current_power),
036aa26189b72905886e39d76d63352185cfd9d2gc &(usb_ia->ia_dev_state), level);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * attach/resume entry point
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int instance = ddi_get_instance(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = NULL;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc uint_t n_ifs;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc size_t size;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (cmd) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_ATTACH:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_RESUME:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia = ddi_get_soft_state(usb_ia_statep, instance);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) usb_ia_restore_device_state(dip, usb_ia);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_SUCCESS);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc default:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_FAILURE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Attach:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc *
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Allocate soft state and initialize
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (ddi_soft_state_zalloc(usb_ia_statep, instance) != DDI_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto fail;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia = ddi_get_soft_state(usb_ia_statep, instance);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia == NULL) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto fail;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* allocate handle for logging of messages */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_log_handle = usb_alloc_log_hdl(dip, "ia",
112116d842e816e29d26a8fe28ed25d201063169fb &usb_ia_errlevel,
112116d842e816e29d26a8fe28ed25d201063169fb &usb_ia_errmask, &usb_ia_instance_debug,
112116d842e816e29d26a8fe28ed25d201063169fb 0);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dip = dip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_instance = instance;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_first_if = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc DDI_PROP_DONTPASS, "interface", -1);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_n_ifs = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc DDI_PROP_DONTPASS, "interface-count", -1);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_first_if < 0 || usb_ia->ia_n_ifs < 0) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "interface-association property failed");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto fail;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* attach client driver to USBA */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_client_attach failed");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto fail;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_get_dev_data(dip, &usb_ia->ia_dev_data, USB_PARSE_LVL_NONE,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc 0) != USB_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_get_dev_data failed");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto fail;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_init(&usb_ia->ia_mutex, NULL, MUTEX_DRIVER,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dev_data->dev_iblock_cookie);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_free_dev_data(dip, usb_ia->ia_dev_data);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dev_data = NULL;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_init_state |= USB_IA_LOCK_INIT;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (ddi_create_minor_node(dip, "usb_ia", S_IFCHR, instance,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "cannot create devctl minor node");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto fail;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_init_state |= USB_IA_MINOR_NODE_CREATED;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * allocate array for keeping track of child dips
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc n_ifs = usb_ia->ia_n_ifs;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_cd_list_length = size = (sizeof (dev_info_t *)) * n_ifs;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_children_dips = kmem_zalloc(size, KM_SLEEP);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_child_events = kmem_zalloc(sizeof (uint8_t) * n_ifs,
112116d842e816e29d26a8fe28ed25d201063169fb KM_SLEEP);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Event handling: definition and registration
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * get event handle for events that we have defined
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ndi_event_alloc_hdl(dip, 0, &usb_ia->ia_ndi_event_hdl,
112116d842e816e29d26a8fe28ed25d201063169fb NDI_SLEEP);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* bind event set to the handle */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (ndi_event_bind_set(usb_ia->ia_ndi_event_hdl, &usb_ia_ndi_events,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NDI_SLEEP)) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_attach: binding event set failed");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto fail;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dev_state = USB_DEV_ONLINE;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * now create components to power manage this device
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * before attaching children
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_create_pm_components(dip, usb_ia);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* event registration for events from our parent */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usba_common_register_events(dip, n_ifs, usb_ia_event_cb);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_init_state |= USB_IA_EVENTS_REGISTERED;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_report_dev(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_SUCCESS);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcfail:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_ATTA, NULL, "usb_ia%d cannot attach",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc instance);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) usb_ia_cleanup(usb_ia);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_FAILURE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/* detach or suspend this instance */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_detach: cmd = 0x%x", cmd);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (cmd) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_DETACH:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (usb_ia_cleanup(usb_ia));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case DDI_SUSPEND:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* nothing to do */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dev_state = USB_DEV_SUSPENDED;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_SUCCESS);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc default:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_FAILURE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc _NOTE(NOT_REACHED)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* NOTREACHED */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * usb_ia_cleanup:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * cleanup usb_ia and deallocate. this function is called for
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * handling attach failures and detaching including dynamic
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * reconfiguration
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*ARGSUSED*/
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_cleanup(usb_ia_t *usb_ia)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_common_power_t *iapm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int rval;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *dip = usb_ia->ia_dip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_cleanup:");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if ((usb_ia->ia_init_state & USB_IA_LOCK_INIT) == 0) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc goto done;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * deallocate events, if events are still registered
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * (ie. children still attached) then we have to fail the detach
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_ndi_event_hdl &&
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (ndi_event_free_hdl(usb_ia->ia_ndi_event_hdl) != NDI_SUCCESS)) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_cleanup: ndi_event_free_hdl failed");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_FAILURE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Disable the event callbacks, after this point, event
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * callbacks will never get called. Note we shouldn't hold
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * mutex while unregistering events because there may be a
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * competing event callback thread. Event callbacks are done
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * with ndi mutex held and this can cause a potential deadlock.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Note that cleanup can't fail after deregistration of events.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_init_state & USB_IA_EVENTS_REGISTERED) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usba_common_unregister_events(usb_ia->ia_dip, usb_ia->ia_n_ifs);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm = usb_ia->ia_pm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if ((iapm) && (usb_ia->ia_dev_state != USB_DEV_DISCONNECTED)) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_busy_component(dip, 0);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (iapm->uc_wakeup_enabled) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* First bring the device to full power */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rval = usb_handle_remote_wakeup(dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_REMOTE_WAKEUP_DISABLE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (rval != DDI_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_EVENTS,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_cleanup: disable remote "
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "wakeup failed, rval=%d", rval);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_lower_power(usb_ia->ia_dip, 0, USB_DEV_OS_PWR_OFF);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_idle_component(dip, 0);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc } else {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (iapm) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc kmem_free(iapm, sizeof (usb_common_power_t));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* free children list */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_children_dips) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc kmem_free(usb_ia->ia_children_dips,
112116d842e816e29d26a8fe28ed25d201063169fb usb_ia->ia_cd_list_length);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_child_events) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc kmem_free(usb_ia->ia_child_events, sizeof (uint8_t) *
112116d842e816e29d26a8fe28ed25d201063169fb usb_ia->ia_n_ifs);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_init_state & USB_IA_MINOR_NODE_CREATED) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_remove_minor_node(dip, NULL);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_destroy(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcdone:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_client_detach(dip, usb_ia->ia_dev_data);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_free_log_hdl(usb_ia->ia_log_handle);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_soft_state_free(usb_ia_statep, ddi_get_instance(dip));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_prop_remove_all(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (DDI_SUCCESS);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * usb_ia_create_children:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_create_children(usb_ia_t *usb_ia)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usba_device_t *usba_device;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc uint_t n_ifs, first_if;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc uint_t i;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *cdip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usba_device = usba_get_usba_device(usb_ia->ia_dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_attach_child_drivers: port = %d, address = %d",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usba_device->usb_port, usba_device->usb_addr);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc n_ifs = usb_ia->ia_n_ifs;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc first_if = usb_ia->ia_first_if;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * create all children if not already present
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc for (i = 0; i < n_ifs; i++) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_children_dips[i] != NULL) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc continue;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc cdip = usba_ready_interface_node(usb_ia->ia_dip, first_if + i);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (cdip != NULL) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) usba_bind_driver(cdip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_children_dips[i] = cdip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * event support
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_busop_get_eventcookie(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *rdip, char *eventname, ddi_eventcookie_t *cookie)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_busop_get_eventcookie: dip=0x%p, rdip=0x%p, "
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "event=%s", (void *)dip, (void *)rdip, eventname);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "(dip=%s%d rdip=%s%d)",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(dip), ddi_get_instance(dip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(rdip), ddi_get_instance(rdip));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* return event cookie, iblock cookie, and level */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (ndi_event_retrieve_cookie(usb_ia->ia_ndi_event_hdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rdip, eventname, cookie, NDI_EVENT_NOPASS));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_busop_add_eventcall(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *rdip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t cookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void (*callback)(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t cookie, void *arg,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *bus_impldata),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg, ddi_callback_id_t *cb_id)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int ifno;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ifno = usba_get_ifno(rdip)- usb_ia->ia_first_if;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (ifno < 0) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ifno = 0;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_busop_add_eventcall: dip=0x%p, rdip=0x%p "
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "cookie=0x%p, cb=0x%p, arg=0x%p",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void *)dip, (void *)rdip, (void *)cookie, (void *)callback, arg);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "(dip=%s%d rdip=%s%d event=%s)",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(dip), ddi_get_instance(dip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(rdip), ddi_get_instance(rdip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl, cookie));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* Set flag on children registering events */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (ndi_event_cookie_to_tag(usb_ia->ia_ndi_event_hdl, cookie)) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case USBA_EVENT_TAG_HOT_REMOVAL:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_child_events[ifno] |=
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_IA_CHILD_EVENT_DISCONNECT;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case USBA_EVENT_TAG_PRE_SUSPEND:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_child_events[ifno] |=
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_IA_CHILD_EVENT_PRESUSPEND;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc default:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* add callback (perform registration) */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (ndi_event_add_callback(usb_ia->ia_ndi_event_hdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rdip, cookie, callback, arg, NDI_SLEEP, cb_id));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_busop_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_event_callbacks_t *cb = (ndi_event_callbacks_t *)cb_id;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ASSERT(cb);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_busop_remove_eventcall: dip=0x%p, rdip=0x%p "
112116d842e816e29d26a8fe28ed25d201063169fb "cookie=0x%p", (void *)dip, (void *)cb->ndi_evtcb_dip,
112116d842e816e29d26a8fe28ed25d201063169fb (void *)cb->ndi_evtcb_cookie);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "(dip=%s%d rdip=%s%d event=%s)",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(dip), ddi_get_instance(dip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(cb->ndi_evtcb_dip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_get_instance(cb->ndi_evtcb_dip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc cb->ndi_evtcb_cookie));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* remove event registration from our event set */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (ndi_event_remove_callback(usb_ia->ia_ndi_event_hdl, cb_id));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_busop_post_event(dev_info_t *dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *rdip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t cookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *bus_impldata)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_busop_post_event: dip=0x%p, rdip=0x%p "
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "cookie=0x%p, impl=0x%p",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void *)dip, (void *)rdip, (void *)cookie, bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "(dip=%s%d rdip=%s%d event=%s)",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(dip), ddi_get_instance(dip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(rdip), ddi_get_instance(rdip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl, cookie));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* post event to all children registered for this event */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (ndi_event_run_callbacks(usb_ia->ia_ndi_event_hdl, rdip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc cookie, bus_impldata));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * usb_ia_restore_device_state
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * set the original configuration of the device
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic int
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_restore_device_state(dev_info_t *dip, usb_ia_t *usb_ia)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_common_power_t *iapm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
112116d842e816e29d26a8fe28ed25d201063169fb "usb_ia_restore_device_state: usb_ia = %p", (void *)usb_ia);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm = usb_ia->ia_pm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* First bring the device to full power */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_busy_component(dip, 0);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_check_same_device(dip, usb_ia->ia_log_handle, USB_LOG_L0,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc DPRINT_MASK_EVENTS, USB_CHK_VIDPID, NULL) != USB_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* change the device state from suspended to disconnected */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dev_state = USB_DEV_DISCONNECTED;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_idle_component(dip, 0);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (USB_FAILURE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * if the device had remote wakeup earlier,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * enable it again
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (iapm->uc_wakeup_enabled) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) usb_handle_remote_wakeup(usb_ia->ia_dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_REMOTE_WAKEUP_ENABLE);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dev_state = USB_DEV_ONLINE;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_idle_component(dip, 0);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (USB_SUCCESS);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * usb_ia_event_cb()
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * handle disconnect and connect events
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_event_cb(dev_info_t *dip, ddi_eventcookie_t cookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc void *arg, void *bus_impldata)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int i, tag;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *usb_ia = usb_ia_obtain_state(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc dev_info_t *child_dip;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_eventcookie_t rm_cookie, ins_cookie, suspend_cookie, resume_cookie;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_event_cb: dip=0x%p, cookie=0x%p, "
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "arg=0x%p, impl=0x%p",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void *)dip, (void *)cookie, arg, bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "(dip=%s%d event=%s)",
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ddi_driver_name(dip), ddi_get_instance(dip),
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl, cookie));
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc tag = NDI_EVENT_TAG(cookie);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rm_cookie = ndi_event_tag_to_cookie(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_HOT_REMOVAL);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc suspend_cookie = ndi_event_tag_to_cookie(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_PRE_SUSPEND);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ins_cookie = ndi_event_tag_to_cookie(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_HOT_INSERTION);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc resume_cookie = ndi_event_tag_to_cookie(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_POST_RESUME);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc switch (tag) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case USBA_EVENT_TAG_HOT_REMOVAL:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_dev_state == USB_DEV_DISCONNECTED) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L2(DPRINT_MASK_EVENTS,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_event_cb: Device already disconnected");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc } else {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* we are disconnected so set our state now */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_dev_state = USB_DEV_DISCONNECTED;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc for (i = 0; i < usb_ia->ia_n_ifs; i++) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_child_events[i] &= ~
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_IA_CHILD_EVENT_DISCONNECT;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* pass disconnect event to all the children */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ndi_event_run_callbacks(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl, NULL,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rm_cookie, bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case USBA_EVENT_TAG_PRE_SUSPEND:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* set our state *after* suspending children */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* pass pre_suspend event to all the children */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ndi_event_run_callbacks(usb_ia->ia_ndi_event_hdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, suspend_cookie, bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc for (i = 0; i < usb_ia->ia_n_ifs; i++) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_child_events[i] &= ~
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_IA_CHILD_EVENT_PRESUSPEND;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case USBA_EVENT_TAG_HOT_INSERTION:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia_restore_device_state(dip, usb_ia) == USB_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Check to see if this child has missed the disconnect
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * event before it registered for event cb
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc for (i = 0; i < usb_ia->ia_n_ifs; i++) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_child_events[i] &
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_IA_CHILD_EVENT_DISCONNECT) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_child_events[i] &=
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ~USB_IA_CHILD_EVENT_DISCONNECT;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc child_dip =
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_children_dips[i];
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* post the missed disconnect */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ndi_event_do_callback(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc child_dip,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc rm_cookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* pass reconnect event to all the children */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ndi_event_run_callbacks(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl, NULL,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ins_cookie, bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc case USBA_EVENT_TAG_POST_RESUME:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * Check to see if this child has missed the pre-suspend
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * event before it registered for event cb
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc for (i = 0; i < usb_ia->ia_n_ifs; i++) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_ia->ia_child_events[i] &
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_IA_CHILD_EVENT_PRESUSPEND) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_child_events[i] &=
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ~USB_IA_CHILD_EVENT_PRESUSPEND;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc child_dip = usb_ia->ia_children_dips[i];
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* post the missed pre-suspend event */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ndi_event_do_callback(
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_ndi_event_hdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc child_dip, suspend_cookie,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* pass post_resume event to all the children */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) ndi_event_run_callbacks(usb_ia->ia_ndi_event_hdl,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc NULL, resume_cookie, bus_impldata);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc break;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * create the pm components required for power management
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic void
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_create_pm_components(dev_info_t *dip, usb_ia_t *usb_ia)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_common_power_t *iapm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc uint_t pwr_states;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_create_pm_components: Begin");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /* Allocate the PM state structure */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm = kmem_zalloc(sizeof (usb_common_power_t), KM_SLEEP);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_enter(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia->ia_pm = iapm;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm->uc_usb_statep = usb_ia;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm->uc_pm_capabilities = 0; /* XXXX should this be 0?? */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm->uc_current_power = USB_DEV_OS_FULL_PWR;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc mutex_exit(&usb_ia->ia_mutex);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * By not enabling parental notification, PM enforces
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * "strict parental dependency" meaning, usb_ia won't
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * power off until any of its children are in full power.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc /*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * there are 3 scenarios:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * 1. a well behaved device should have remote wakeup
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * at interface and device level. If the interface
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * wakes up, usb_ia will wake up
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * 2. if the device doesn't have remote wake up and
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * the interface has, PM will still work, ie.
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * the interfaces wakes up and usb_ia wakes up
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * 3. if neither the interface nor device has remote
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * wakeup, the interface will wake up when it is opened
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * and goes to sleep after being closed for a while
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * In this case usb_ia should also go to sleep shortly
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * thereafter
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * In all scenarios it doesn't really matter whether
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * remote wakeup at the device level is enabled or not
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * but we do it anyways
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_handle_remote_wakeup(dip, USB_REMOTE_WAKEUP_ENABLE) ==
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L3(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_create_pm_components: "
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "Remote Wakeup Enabled");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm->uc_wakeup_enabled = 1;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc if (usb_create_pm_components(dip, &pwr_states) ==
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_SUCCESS) {
d73ae94e59c019f5cc3221ee0a0012d02091b40egc iapm->uc_pwr_states = (uint8_t)pwr_states;
d73ae94e59c019f5cc3221ee0a0012d02091b40egc (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc }
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
d73ae94e59c019f5cc3221ee0a0012d02091b40egc "usb_ia_create_pm_components: End");
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc/*
d73ae94e59c019f5cc3221ee0a0012d02091b40egc * usb_ia_obtain_state:
d73ae94e59c019f5cc3221ee0a0012d02091b40egc */
d73ae94e59c019f5cc3221ee0a0012d02091b40egcstatic usb_ia_t *
d73ae94e59c019f5cc3221ee0a0012d02091b40egcusb_ia_obtain_state(dev_info_t *dip)
d73ae94e59c019f5cc3221ee0a0012d02091b40egc{
d73ae94e59c019f5cc3221ee0a0012d02091b40egc int instance = ddi_get_instance(dip);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc usb_ia_t *statep = ddi_get_soft_state(usb_ia_statep, instance);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc ASSERT(statep != NULL);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc
d73ae94e59c019f5cc3221ee0a0012d02091b40egc return (statep);
d73ae94e59c019f5cc3221ee0a0012d02091b40egc}