269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER START
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The contents of this file are subject to the terms of the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Common Development and Distribution License (the "License").
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You may not use this file except in compliance with the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
269473047d747f7815af570197e4ef7322d3632cEvan Yan * or http://www.opensolaris.org/os/licensing.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * See the License for the specific language governing permissions
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and limitations under the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
269473047d747f7815af570197e4ef7322d3632cEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If applicable, add the following below this CDDL HEADER, with the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
269473047d747f7815af570197e4ef7322d3632cEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER END
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Use is subject to license terms.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Sun DDI hotplug implementation specific functions
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/sysmacros.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/types.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/file.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/param.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/systm.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/kmem.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/cmn_err.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/debug.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/avintr.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/autoconf.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/ddi.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/sunndi.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/ndi_impldefs.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/sysevent.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/sysevent/eventdefs.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/sysevent/dr.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/fs/dv_node.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Local function prototypes
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* Connector operations */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_cn_pre_change_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_cn_post_change_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t new_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_cn_handle_state_change(ddi_hp_cn_handle_t *hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_cn_change_children_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan boolean_t online);
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* Port operations */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_port_change_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_port_upgrade_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_port_downgrade_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* Misc routines */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void ddihp_update_last_change(ddi_hp_cn_handle_t *hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic boolean_t ddihp_check_status_prop(dev_info_t *dip);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Global functions (called within hotplug framework)
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Implement modctl() commands for hotplug.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Called by modctl_hp() in modctl.c
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_modctl(int hp_op, char *path, char *cn_name, uintptr_t arg,
269473047d747f7815af570197e4ef7322d3632cEvan Yan uintptr_t rval)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_handle_t *hdlp;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_op_t op = (ddi_hp_op_t)hp_op;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int count, rv, error;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Get the dip of nexus node */
269473047d747f7815af570197e4ef7322d3632cEvan Yan dip = e_ddi_hold_devi_by_path(path, 0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (dip == NULL)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENXIO);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_modctl: dip %p op %x path %s "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "cn_name %s arg %p rval %p\n", (void *)dip, hp_op, path, cn_name,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)arg, (void *)rval));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!NEXUS_HAS_HP_OP(dip)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_release_devi(dip);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ENOTSUP);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Lock before access */
269473047d747f7815af570197e4ef7322d3632cEvan Yan ndi_devi_enter(dip, &count);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp = ddihp_cn_name_to_handle(dip, cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hp_op == DDI_HPOP_CN_CREATE_PORT) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdlp != NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* this port already exists. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = EEXIST;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_hp_op))(
269473047d747f7815af570197e4ef7322d3632cEvan Yan dip, cn_name, op, NULL, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdlp == NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Invalid Connection name */
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = ENXIO;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hp_op == DDI_HPOP_CN_CHANGE_STATE) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state = (ddi_hp_cn_state_t)arg;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t result_state = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDIHP_CN_OPS(hdlp, op, (void *)&target_state,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)&result_state, rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_modctl: target_state="
269473047d747f7815af570197e4ef7322d3632cEvan Yan "%x, result_state=%x, rv=%x \n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan target_state, result_state, rv));
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDIHP_CN_OPS(hdlp, op, (void *)arg, (void *)rval, rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (rv) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_SUCCESS:
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_EINVAL:
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = EINVAL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_EBUSY:
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = EBUSY;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_ENOTSUP:
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = ENOTSUP;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_ENOMEM:
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = ENOMEM;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan error = EIO;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yandone:
269473047d747f7815af570197e4ef7322d3632cEvan Yan ndi_devi_exit(dip, count);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_release_devi(dip);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (error);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Return the state of Hotplug Connection (CN)
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_getstate(ddi_hp_cn_handle_t *hdlp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t new_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int ret;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_getstate: pdip %p hdlp %p\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)hdlp->cn_dip, (void *)hdlp));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(DEVI_BUSY_OWNED(hdlp->cn_dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDIHP_CN_OPS(hdlp, DDI_HPOP_CN_GET_STATE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan NULL, (void *)&new_state, ret);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ret != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_getstate: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "CN %p getstate command failed\n", (void *)hdlp));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ret);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_getstate: hdlp %p "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "current Connection state %x new Connection state %x\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)hdlp, hdlp->cn_info.cn_state, new_state));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (new_state != hdlp->cn_info.cn_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state = new_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddihp_update_last_change(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ret);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Implementation function for unregistering the Hotplug Connection (CN)
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_unregister(ddi_hp_cn_handle_t *hdlp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip = hdlp->cn_dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_unregister: hdlp %p\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)hdlp));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(DEVI_BUSY_OWNED(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) ddihp_cn_getstate(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdlp->cn_info.cn_state > DDI_HP_CN_STATE_OFFLINE) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_unregister: dip %p, hdlp %p "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "state %x. Device busy, failed to unregister connection!\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)dip, (void *)hdlp, hdlp->cn_info.cn_state));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (DDI_EBUSY);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* unlink the handle */
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDIHP_LIST_REMOVE(ddi_hp_cn_handle_t, (DEVI(dip)->devi_hp_hdlp), hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(hdlp->cn_info.cn_name, strlen(hdlp->cn_info.cn_name) + 1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(hdlp, sizeof (ddi_hp_cn_handle_t));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (DDI_SUCCESS);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * For a given Connection name and the dip node where the Connection is
269473047d747f7815af570197e4ef7322d3632cEvan Yan * supposed to be, find the corresponding hotplug handle.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanddi_hp_cn_handle_t *
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_name_to_handle(dev_info_t *dip, char *cn_name)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_handle_t *hdlp;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(DEVI_BUSY_OWNED(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_name_to_handle: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "dip %p cn_name to find: %s", (void *)dip, cn_name));
269473047d747f7815af570197e4ef7322d3632cEvan Yan for (hdlp = DEVI(dip)->devi_hp_hdlp; hdlp; hdlp = hdlp->next) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_name_to_handle: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "current cn_name: %s", hdlp->cn_info.cn_name));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (strcmp(cn_name, hdlp->cn_info.cn_name) == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* found */
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_name_to_handle: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "failed to find cn_name"));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Process the hotplug operations for Connector and also create Port
269473047d747f7815af570197e4ef7322d3632cEvan Yan * upon user command.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_connector_ops(ddi_hp_cn_handle_t *hdlp, ddi_hp_op_t op,
269473047d747f7815af570197e4ef7322d3632cEvan Yan void *arg, void *result)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip = hdlp->cn_dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(DEVI_BUSY_OWNED(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_connector_ops: pdip=%p op=%x "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "hdlp=%p arg=%p\n", (void *)dip, op, (void *)hdlp, arg));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (op == DDI_HPOP_CN_CHANGE_STATE) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state = *(ddi_hp_cn_state_t *)arg;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ddihp_cn_pre_change_state(hdlp, target_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* the state is not changed */
269473047d747f7815af570197e4ef7322d3632cEvan Yan *((ddi_hp_cn_state_t *)result) =
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(NEXUS_HAS_HP_OP(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_hp_op))(
269473047d747f7815af570197e4ef7322d3632cEvan Yan dip, hdlp->cn_info.cn_name, op, arg, result);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_connector_ops: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "bus_hp_op failed: pdip=%p cn_name:%s op=%x "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "hdlp=%p arg=%p\n", (void *)dip, hdlp->cn_info.cn_name,
269473047d747f7815af570197e4ef7322d3632cEvan Yan op, (void *)hdlp, arg));
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (op == DDI_HPOP_CN_CHANGE_STATE) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv_post;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_connector_ops: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "old_state=%x, new_state=%x, rv=%x\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state, *(ddi_hp_cn_state_t *)result, rv));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * After state change op is successfully done or
269473047d747f7815af570197e4ef7322d3632cEvan Yan * failed at some stages, continue to do some jobs.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv_post = ddihp_cn_post_change_state(hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan *(ddi_hp_cn_state_t *)result);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv_post != DDI_SUCCESS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = rv_post;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Process the hotplug op for Port
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_port_ops(ddi_hp_cn_handle_t *hdlp, ddi_hp_op_t op,
269473047d747f7815af570197e4ef7322d3632cEvan Yan void *arg, void *result)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan int ret = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(DEVI_BUSY_OWNED(hdlp->cn_dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_port_ops: pdip=%p op=%x hdlp=%p "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "arg=%p\n", (void *)hdlp->cn_dip, op, (void *)hdlp, arg));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (op) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HPOP_CN_GET_STATE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan {
269473047d747f7815af570197e4ef7322d3632cEvan Yan int state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdlp->cn_info.cn_child == NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* No child. Either present or empty. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (state >= DDI_HP_CN_STATE_PORT_PRESENT)
269473047d747f7815af570197e4ef7322d3632cEvan Yan state = DDI_HP_CN_STATE_PORT_PRESENT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan else
269473047d747f7815af570197e4ef7322d3632cEvan Yan state = DDI_HP_CN_STATE_PORT_EMPTY;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else { /* There is a child of this Port */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Check DEVI(dip)->devi_node_state */
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (i_ddi_node_state(hdlp->cn_info.cn_child)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_INVAL:
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_PROTO:
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_LINKED:
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_BOUND:
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_INITIALIZED:
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_PROBED:
269473047d747f7815af570197e4ef7322d3632cEvan Yan state = DDI_HP_CN_STATE_OFFLINE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_ATTACHED:
269473047d747f7815af570197e4ef7322d3632cEvan Yan state = DDI_HP_CN_STATE_MAINTENANCE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DS_READY:
269473047d747f7815af570197e4ef7322d3632cEvan Yan state = DDI_HP_CN_STATE_ONLINE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* should never reach here */
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT("unknown devinfo state");
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Check DEVI(dip)->devi_state in case the node is
269473047d747f7815af570197e4ef7322d3632cEvan Yan * downgraded or quiesced.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (state == DDI_HP_CN_STATE_ONLINE &&
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_get_devstate(hdlp->cn_info.cn_child) !=
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_DEVSTATE_UP)
269473047d747f7815af570197e4ef7322d3632cEvan Yan state = DDI_HP_CN_STATE_MAINTENANCE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan *((ddi_hp_cn_state_t *)result) = state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HPOP_CN_CHANGE_STATE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan {
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state = *(ddi_hp_cn_state_t *)arg;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ret = ddihp_port_change_state(hdlp, target_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (curr_state != hdlp->cn_info.cn_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddihp_update_last_change(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan *((ddi_hp_cn_state_t *)result) = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HPOP_CN_REMOVE_PORT:
269473047d747f7815af570197e4ef7322d3632cEvan Yan {
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) ddihp_cn_getstate(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdlp->cn_info.cn_state != DDI_HP_CN_STATE_PORT_EMPTY) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Only empty PORT can be removed by commands */
269473047d747f7815af570197e4ef7322d3632cEvan Yan ret = DDI_EBUSY;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ret = ddihp_cn_unregister(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan ret = DDI_ENOTSUP;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ret);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Generate the system event with a possible hint
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* ARGSUSED */
269473047d747f7815af570197e4ef7322d3632cEvan Yanvoid
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_gen_sysevent(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_sysevent_t event_sub_class, int hint, int kmflag)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip = hdlp->cn_dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *cn_path, *ap_id;
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *ev_subclass = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_t *ev_attr_list = NULL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan sysevent_id_t eid;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int ap_id_len, err;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan cn_path = kmem_zalloc(MAXPATHLEN, kmflag);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (cn_path == NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "%s%d: Failed to allocate memory for hotplug"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " connection: %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Minor device name will be bus path
269473047d747f7815af570197e4ef7322d3632cEvan Yan * concatenated with connection name.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * One of consumers of the sysevent will pass it
269473047d747f7815af570197e4ef7322d3632cEvan Yan * to cfgadm as AP ID.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) strcpy(cn_path, "/devices");
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) ddi_pathname(dip, cn_path + strlen("/devices"));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ap_id_len = strlen(cn_path) + strlen(":") +
269473047d747f7815af570197e4ef7322d3632cEvan Yan strlen(hdlp->cn_info.cn_name) + 1;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ap_id = kmem_zalloc(ap_id_len, kmflag);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ap_id == NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "%s%d: Failed to allocate memory for AP ID: %s:%s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan cn_path, hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(cn_path, MAXPATHLEN);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) strcpy(ap_id, cn_path);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) strcat(ap_id, ":");
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) strcat(ap_id, hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(cn_path, MAXPATHLEN);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan err = nvlist_alloc(&ev_attr_list, NV_UNIQUE_NAME_TYPE, kmflag);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (err != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "%s%d: Failed to allocate memory for event subclass %d\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan event_sub_class);
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(ap_id, ap_id_len);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (event_sub_class) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_CHANGE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan ev_subclass = ESC_DR_AP_STATE_CHANGE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (hint) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case SE_NO_HINT: /* fall through */
269473047d747f7815af570197e4ef7322d3632cEvan Yan case SE_HINT_INSERT: /* fall through */
269473047d747f7815af570197e4ef7322d3632cEvan Yan case SE_HINT_REMOVE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan err = nvlist_add_string(ev_attr_list, DR_HINT,
269473047d747f7815af570197e4ef7322d3632cEvan Yan SE_HINT2STR(hint));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (err != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN, "%s%d: Failed to add attr [%s]"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " for %s event\n", ddi_driver_name(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_get_instance(dip), DR_HINT,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ESC_DR_AP_STATE_CHANGE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN, "%s%d: Unknown hint on sysevent\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* event sub class: DDI_HP_CN_REQ */
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_REQ:
269473047d747f7815af570197e4ef7322d3632cEvan Yan ev_subclass = ESC_DR_REQ;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (hint) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case SE_INVESTIGATE_RES: /* fall through */
269473047d747f7815af570197e4ef7322d3632cEvan Yan case SE_INCOMING_RES: /* fall through */
269473047d747f7815af570197e4ef7322d3632cEvan Yan case SE_OUTGOING_RES: /* fall through */
269473047d747f7815af570197e4ef7322d3632cEvan Yan err = nvlist_add_string(ev_attr_list, DR_REQ_TYPE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan SE_REQ2STR(hint));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (err != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "%s%d: Failed to add attr [%s] for %s \n"
269473047d747f7815af570197e4ef7322d3632cEvan Yan "event", ddi_driver_name(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan DR_REQ_TYPE, ESC_DR_REQ);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN, "%s%d: Unknown hint on sysevent\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN, "%s%d: Unknown Event subclass\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Add Hotplug Connection (CN) as attribute (common attribute)
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan err = nvlist_add_string(ev_attr_list, DR_AP_ID, ap_id);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (err != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN, "%s%d: Failed to add attr [%s] for %s event\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan DR_AP_ID, EC_DR);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan goto done;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Log this event with sysevent framework.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, EC_DR,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ev_subclass, ev_attr_list, &eid,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ((kmflag == KM_SLEEP) ? DDI_SLEEP : DDI_NOSLEEP));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (err != 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN, "%s%d: Failed to log %s event\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip), EC_DR);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yandone:
269473047d747f7815af570197e4ef7322d3632cEvan Yan nvlist_free(ev_attr_list);
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(ap_id, ap_id_len);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Local functions (called within this file)
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Connector operations
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Prepare to change state for a Connector: offline, unprobe, etc.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_pre_change_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip = hdlp->cn_dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (curr_state > target_state &&
269473047d747f7815af570197e4ef7322d3632cEvan Yan curr_state == DDI_HP_CN_STATE_ENABLED) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If the Connection goes to a lower state from ENABLED,
269473047d747f7815af570197e4ef7322d3632cEvan Yan * then offline all children under it.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ddihp_cn_change_children_state(hdlp, B_FALSE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "(%s%d): "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "failed to unconfigure the device in the"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " Connection %s\n", ddi_driver_name(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(NEXUS_HAS_HP_OP(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Remove all the children and their ports
269473047d747f7815af570197e4ef7322d3632cEvan Yan * after they are offlined.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_hp_op))(
269473047d747f7815af570197e4ef7322d3632cEvan Yan dip, hdlp->cn_info.cn_name, DDI_HPOP_CN_UNPROBE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan NULL, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "(%s%d): failed"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " to unprobe the device in the Connector"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " %s\n", ddi_driver_name(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "ddihp_connector_ops (%s%d): device"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " is unconfigured and unprobed in Connector %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name));
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Jobs after change state of a Connector: update last change time,
269473047d747f7815af570197e4ef7322d3632cEvan Yan * probe, online, sysevent, etc.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_post_change_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t new_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Update the state in handle */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (new_state != curr_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state = new_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddihp_update_last_change(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (curr_state < new_state &&
269473047d747f7815af570197e4ef7322d3632cEvan Yan new_state == DDI_HP_CN_STATE_ENABLED) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Probe and online devices if state is
269473047d747f7815af570197e4ef7322d3632cEvan Yan * upgraded to ENABLED.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ddihp_cn_handle_state_change(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (curr_state != hdlp->cn_info.cn_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * For Connector, generate a sysevent on
269473047d747f7815af570197e4ef7322d3632cEvan Yan * state change.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddihp_cn_gen_sysevent(hdlp, DDI_HP_CN_STATE_CHANGE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan SE_NO_HINT, KM_SLEEP);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Handle Connector state change.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * This function is called after connector is upgraded to ENABLED sate.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * It probes the device plugged in the connector to setup devinfo nodes
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and then online the nodes.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_handle_state_change(ddi_hp_cn_handle_t *hdlp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip = hdlp->cn_dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(DEVI_BUSY_OWNED(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(NEXUS_HAS_HP_OP(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If the Connection went to state ENABLED from a lower state,
269473047d747f7815af570197e4ef7322d3632cEvan Yan * probe it.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_hp_op))(
269473047d747f7815af570197e4ef7322d3632cEvan Yan dip, hdlp->cn_info.cn_name, DDI_HPOP_CN_PROBE, NULL, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state = DDI_HP_CN_STATE_POWERED;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t result_state = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Probe failed. Disable the connector so that it can
269473047d747f7815af570197e4ef7322d3632cEvan Yan * be enabled again by a later try from userland.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_hp_op))(
269473047d747f7815af570197e4ef7322d3632cEvan Yan dip, hdlp->cn_info.cn_name, DDI_HPOP_CN_CHANGE_STATE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)&target_state, (void *)&result_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (result_state && result_state != hdlp->cn_info.cn_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state = result_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddihp_update_last_change(hdlp);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "(%s%d): failed to probe the Connection %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Try to online all the children of CN.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) ddihp_cn_change_children_state(hdlp, B_TRUE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_event_handler (%s%d): "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "device is configured in the Connection %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Online/Offline all the children under the Hotplug Connection (CN)
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Do online operation when the online parameter is true; otherwise do offline.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_cn_change_children_state(ddi_hp_cn_handle_t *hdlp, boolean_t online)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip = hdlp->cn_dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *cdip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_handle_t *h;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_change_children_state:"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " dip %p hdlp %p, online %x\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)dip, (void *)hdlp, online));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(DEVI_BUSY_OWNED(dip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Return invalid if Connection state is < DDI_HP_CN_STATE_ENABLED
269473047d747f7815af570197e4ef7322d3632cEvan Yan * when try to online children.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (online && hdlp->cn_info.cn_state < DDI_HP_CN_STATE_ENABLED) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_cn_change_children_state: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "Connector %p is not in probed state\n", (void *)hdlp));
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (DDI_EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Now, online/offline all the devices depending on the Connector */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!online) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * For offline operation we need to firstly clean up devfs
269473047d747f7815af570197e4ef7322d3632cEvan Yan * so as not to prevent driver detach.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) devfs_clean(dip, NULL, DV_CLEAN_FORCE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan for (h = DEVI(dip)->devi_hp_hdlp; h; h = h->next) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (h->cn_info.cn_type != DDI_HP_CN_TYPE_VIRTUAL_PORT)
269473047d747f7815af570197e4ef7322d3632cEvan Yan continue;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (h->cn_info.cn_num_dpd_on !=
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_num)
269473047d747f7815af570197e4ef7322d3632cEvan Yan continue;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan cdip = h->cn_info.cn_child;
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(cdip);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (online) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* online children */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!ddihp_check_status_prop(dip))
269473047d747f7815af570197e4ef7322d3632cEvan Yan continue;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ndi_devi_online(cdip,
269473047d747f7815af570197e4ef7322d3632cEvan Yan NDI_ONLINE_ATTACH | NDI_CONFIG) != NDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "(%s%d):"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " failed to attach driver for a device"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " (%s%d) under the Connection %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(cdip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_get_instance(cdip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * One of the devices failed to online, but we
269473047d747f7815af570197e4ef7322d3632cEvan Yan * want to continue to online the rest siblings
269473047d747f7815af570197e4ef7322d3632cEvan Yan * after mark the failure here.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = DDI_FAILURE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan continue;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* offline children */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ndi_devi_offline(cdip, NDI_UNCONFIG) !=
269473047d747f7815af570197e4ef7322d3632cEvan Yan NDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "(%s%d):"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " failed to dettach driver for the device"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " (%s%d) in the Connection %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(cdip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_get_instance(cdip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (DDI_EBUSY);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Port operations
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Change Port state to target_state.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_port_change_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (target_state < DDI_HP_CN_STATE_PORT_EMPTY ||
269473047d747f7815af570197e4ef7322d3632cEvan Yan target_state > DDI_HP_CN_STATE_ONLINE) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (DDI_EINVAL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (curr_state < target_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ddihp_port_upgrade_state(hdlp, target_state));
269473047d747f7815af570197e4ef7322d3632cEvan Yan else if (curr_state > target_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (ddihp_port_downgrade_state(hdlp, target_state));
269473047d747f7815af570197e4ef7322d3632cEvan Yan else
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (DDI_SUCCESS);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Upgrade port state to target_state.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_port_upgrade_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t curr_state, new_state, result_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *cdip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan while (curr_state < target_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (curr_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_PORT_EMPTY:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Check the existence of the corresponding hardware */
269473047d747f7815af570197e4ef7322d3632cEvan Yan new_state = DDI_HP_CN_STATE_PORT_PRESENT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ddihp_connector_ops(hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HPOP_CN_CHANGE_STATE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)&new_state, (void *)&result_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv == DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state =
269473047d747f7815af570197e4ef7322d3632cEvan Yan result_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_PORT_PRESENT:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Read-only probe the corresponding hardware. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan new_state = DDI_HP_CN_STATE_OFFLINE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ddihp_connector_ops(hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HPOP_CN_CHANGE_STATE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)&new_state, &cdip);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv == DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state =
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_CN_STATE_OFFLINE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT(hdlp->cn_info.cn_child == NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_child = cdip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_OFFLINE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* fall through */
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_MAINTENANCE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan cdip = hdlp->cn_info.cn_child;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ndi_devi_online(cdip,
269473047d747f7815af570197e4ef7322d3632cEvan Yan NDI_ONLINE_ATTACH | NDI_CONFIG);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv == NDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state =
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_CN_STATE_ONLINE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = DDI_FAILURE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "ddihp_port_upgrade_state: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "failed to online device %p at port: %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)cdip, hdlp->cn_info.cn_name));
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_ONLINE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* should never reach here */
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT("unknown devinfo state");
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_port_upgrade_state: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "failed curr_state=%x, target_state=%x \n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan curr_state, target_state));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Downgrade state to target_state
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_port_downgrade_state(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t target_state)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_hp_cn_state_t curr_state, new_state, result_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *dip = hdlp->cn_dip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan dev_info_t *cdip;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan while (curr_state > target_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (curr_state) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_PORT_EMPTY:
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_PORT_PRESENT:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Check the existence of the corresponding hardware */
269473047d747f7815af570197e4ef7322d3632cEvan Yan new_state = DDI_HP_CN_STATE_PORT_EMPTY;
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ddihp_connector_ops(hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HPOP_CN_CHANGE_STATE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)&new_state, (void *)&result_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv == DDI_SUCCESS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state =
269473047d747f7815af570197e4ef7322d3632cEvan Yan result_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_OFFLINE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Read-only unprobe the corresponding hardware:
269473047d747f7815af570197e4ef7322d3632cEvan Yan * 1. release the assigned resource;
269473047d747f7815af570197e4ef7322d3632cEvan Yan * 2. remove the node pointed by the port's cn_child
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan new_state = DDI_HP_CN_STATE_PORT_PRESENT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ddihp_connector_ops(hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HPOP_CN_CHANGE_STATE,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)&new_state, (void *)&result_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv == DDI_SUCCESS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state =
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_CN_STATE_PORT_PRESENT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_MAINTENANCE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* fall through. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan case DDI_HP_CN_STATE_ONLINE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan cdip = hdlp->cn_info.cn_child;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) devfs_clean(dip, NULL, DV_CLEAN_FORCE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = ndi_devi_offline(cdip, NDI_UNCONFIG);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv == NDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_state =
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_CN_STATE_OFFLINE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = DDI_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = DDI_EBUSY;
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "ddihp_port_downgrade_state: failed "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "to offline node, rv=%x, cdip=%p \n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv, (void *)cdip));
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* should never reach here */
269473047d747f7815af570197e4ef7322d3632cEvan Yan ASSERT("unknown devinfo state");
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan curr_state = hdlp->cn_info.cn_state;
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (rv != DDI_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "ddihp_port_downgrade_state: failed "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "curr_state=%x, target_state=%x \n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan curr_state, target_state));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Misc routines
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* Update the last state change time */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_update_last_change(ddi_hp_cn_handle_t *hdlp)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan time_t time;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (drv_getparm(TIME, (void *)&time) != DDI_SUCCESS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_last_change = (time_t)-1;
269473047d747f7815af570197e4ef7322d3632cEvan Yan else
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_last_change = (time32_t)time;
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Check the device for a 'status' property. A conforming device
269473047d747f7815af570197e4ef7322d3632cEvan Yan * should have a status of "okay", "disabled", "fail", or "fail-xxx".
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Return FALSE for a conforming device that is disabled or faulted.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Return TRUE in every other case.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * 'status' property is NOT a bus specific property. It is defined in page 184,
269473047d747f7815af570197e4ef7322d3632cEvan Yan * IEEE 1275 spec. The full name of the spec is "IEEE Standard for
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Boot (Initialization Configuration) Firmware: Core Requirements and
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Practices".
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic boolean_t
269473047d747f7815af570197e4ef7322d3632cEvan Yanddihp_check_status_prop(dev_info_t *dip)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan char *status_prop;
269473047d747f7815af570197e4ef7322d3632cEvan Yan boolean_t rv = B_TRUE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* try to get the 'status' property */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "status", &status_prop) == DDI_PROP_SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * test if the status is "disabled", "fail", or
269473047d747f7815af570197e4ef7322d3632cEvan Yan * "fail-xxx".
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (strcmp(status_prop, "disabled") == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = B_FALSE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_IMPLDBG((CE_CONT, "ddihp_check_status_prop "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "(%s%d): device is in disabled state",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip)));
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else if (strncmp(status_prop, "fail", 4) == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = B_FALSE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan cmn_err(CE_WARN,
269473047d747f7815af570197e4ef7322d3632cEvan Yan "hotplug (%s%d): device is in fault state (%s)\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_driver_name(dip), ddi_get_instance(dip),
269473047d747f7815af570197e4ef7322d3632cEvan Yan status_prop);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan ddi_prop_free(status_prop);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}