/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Sun NDI hotplug interfaces
*/
#include <sys/sysmacros.h>
#include <sys/autoconf.h>
#include <sys/ndi_impldefs.h>
#include <sys/sysevent.h>
/* Local functions prototype */
static void ddihp_cn_run_event(void *arg);
/*
* Global functions (called by hotplug controller or nexus drivers)
*/
/*
* Register the Hotplug Connection (CN)
*/
int
{
int count;
if (servicing_interrupt())
return (NDI_FAILURE);
/* Validate the arguments */
return (NDI_EINVAL);
if (!NEXUS_HAS_HP_OP(dip)) {
return (NDI_ENOTSUP);
}
/* Lock before access */
if (hdlp) {
/* This cn_name is already registered. */
return (NDI_SUCCESS);
}
/*
* Create and initialize hotplug Connection handle
*/
(sizeof (ddi_hp_cn_handle_t)), KM_SLEEP);
/* Copy the Connection information */
/* Copy cn_name */
goto fail;
}
/*
* Append the handle to the list
*/
hdlp);
return (NDI_SUCCESS);
fail:
return (NDI_FAILURE);
}
/*
* Unregister a Hotplug Connection (CN)
*/
int
{
int count;
int ret;
if (servicing_interrupt())
return (NDI_FAILURE);
/* Validate the arguments */
return (NDI_EINVAL);
return (NDI_EINVAL);
}
switch (ddihp_cn_unregister(hdlp)) {
case DDI_SUCCESS:
ret = NDI_SUCCESS;
break;
case DDI_EINVAL:
ret = NDI_EINVAL;
break;
case DDI_EBUSY:
break;
default:
ret = NDI_FAILURE;
break;
}
return (ret);
}
/*
* Notify the Hotplug Connection (CN) to change state.
* Flag:
* DDI_HP_REQ_SYNC Return after the change is finished.
* DDI_HP_REQ_ASYNC Return after the request is dispatched.
*/
int
{
"cn_name: %s, state %x, flag %x\n",
/* Validate the arguments */
return (NDI_EINVAL);
if (!NEXUS_HAS_HP_OP(dip)) {
return (NDI_ENOTSUP);
}
/*
* If the request is to handle the event synchronously, then call
* the event handler without queuing the event.
*/
if (flag & DDI_HP_REQ_SYNC) {
int count;
int ret;
if (servicing_interrupt())
return (NDI_FAILURE);
return (NDI_EINVAL);
}
"calling ddihp_cn_req_handler() directly to handle "
return (ret);
}
return (NDI_NOMEM);
return (NDI_NOMEM);
}
/*
* Hold the parent's ref so that it won't disappear when the taskq is
* scheduled to run.
*/
TQ_NOSLEEP)) {
"taskq_dispatch failed! dip %p "
return (NDI_NOMEM);
}
return (NDI_CLAIMED);
}
/*
* Walk the link of Hotplug Connection handles of a dip:
* DEVI(dip)->devi_hp_hdlp->[link of connections]
*/
void
void *), void *arg)
{
int count;
if (servicing_interrupt())
return;
/* Validate the arguments */
return;
"current cn_name: %s\n",
case DDI_WALK_TERMINATE:
return;
case DDI_WALK_CONTINUE:
default:
/*
* The current node is head and it is removed
* by last call to (*f)()
*/
/*
* The current node is a middle node or tail
* node and it is removed by last call to
* (*f)()
*/
} else {
/* no removal accurred on curr node */
}
}
}
}
/*
* Local functions (called within this file)
*/
/*
* Wrapper function for ddihp_cn_req_handler() called from taskq
*/
static void
{
int count;
/* Lock before access */
if (hdlp) {
} else {
"cn_name: %s dip %p. Request for target_state %x is"
" dropped. \n",
}
/* Release the devi's ref that is held from interrupt context. */
}
/*
* Handle state change request of a Hotplug Connection (CN)
*/
static int
{
" hdlp %p, target_state %x\n",
(void *)hdlp, target_state));
"hdlp %p ddi_cn_getstate failed\n", (void *)dip,
(void *)hdlp));
return (NDI_UNCLAIMED);
}
"hdlp %p changed state to %x, ret=%x\n",
}
if (ret == DDI_SUCCESS)
return (NDI_CLAIMED);
else
return (NDI_UNCLAIMED);
}