/*
* 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.
*/
#include <sys/autoconf.h>
#include <sys/ndi_impldefs.h>
#include <sys/pathname.h>
#include <sys/bootconf.h>
#include <sys/dacf_impl.h>
#include <sys/sunldi_impl.h>
#ifdef __sparc
#endif
/*
* ndi property handling
*/
int
{
}
int
{
}
int
char *name)
{
}
int
{
}
int
{
}
int
{
}
int
{
}
int
{
if (nelements == 0)
return (DDI_PROP_INVAL_ARG);
}
int
{
}
void
{
}
/*
* Post an event notification to nexus driver responsible for handling
* the event. The responsible nexus is defined in the cookie passed in as
* the third parameter.
* The dip parameter is an artifact of an older implementation in which all
* requests to remove an eventcall would bubble up the tree. Today, this
* parameter is ignored.
* Input Parameters:
* dip - Ignored.
* rdip - device driver posting the event
* cookie - valid ddi_eventcookie_t, obtained by caller prior to
* invocation of this routine
* impl_data - used by framework
*/
/*ARGSUSED*/
int
{
/*
* perform sanity checks. These conditions should never be true.
*/
/*
* post the event to the responsible ancestor
*/
}
/*
* Calls the bus nexus driver's implementation of the
* (*bus_remove_eventcall)() interface.
*/
int
{
/* check for a correct revno before calling up the device tree. */
return (DDI_FAILURE);
/*
* request responsible nexus to remove the eventcall
*/
}
/*
* Calls the bus nexus driver's implementation of the
* (*bus_add_eventcall)() interface. The dip parameter is an
* artifact of an older implementation in which all requests to
* add an eventcall would bubble up the tree. Today, this parameter is
* ignored.
*/
/*ARGSUSED*/
int
{
/*
* check for a correct revno before calling up the device tree.
*/
return (DDI_FAILURE);
/*
* request responsible ancestor to add the eventcall
*/
}
/*
* Calls the bus nexus driver's implementation of the
* (*bus_get_eventcookie)() interface up the device tree hierarchy.
*/
int
{
/* Can not be called from rootnex. */
/*
* check for a correct revno before calling up the device tree.
*/
#ifdef DEBUG
BUSO_REV_3) &&
"Warning: %s%d busops_rev=%d no longer supported"
" by the NDI event framework.\nBUSO_REV_6 or "
"greater must be used.",
}
#endif /* DEBUG */
}
}
/*
* Copy in the devctl IOCTL data and return a handle to
* the data.
*/
int
{
char *cpybuf;
if (get_udatamodel() == DATAMODEL_NATIVE) {
return (NDI_FAULT);
}
}
#ifdef _SYSCALL32_IMPL
else {
return (NDI_FAULT);
}
}
#endif
return (NDI_FAULT);
}
}
return (NDI_FAULT);
}
}
/*
* copyin and unpack a user defined nvlist if one was passed
*/
if ((dcp->nvl_usersz == 0) ||
return (NDI_FAILURE);
}
return (NDI_FAULT);
}
KM_SLEEP)) {
return (NDI_FAULT);
}
/*
* free the buffer containing the packed nvlist
*/
}
return (NDI_SUCCESS);
}
/*
* free all space allocated to a handle.
*/
void
{
}
char *
{
return (dcp->c_nodename);
}
char *
{
return (dcp->c_unitaddr);
}
nvlist_t *
{
}
/*
* Transition the child named by "devname@devaddr" to the online state.
* For use by a driver's DEVCTL_DEVICE_ONLINE handler.
*/
int
{
int rval;
char *name;
return (EINVAL);
/*
* Invalidate devfs cached directory contents. For the checks
* in the "if" condition see the comment in ndi_devi_online().
*/
} else if (rval == NDI_FAILURE) {
}
return (rval);
}
/*
* Transition the child named by "devname@devaddr" to the offline state.
* For use by a driver's DEVCTL_DEVICE_OFFLINE handler.
*/
int
{
int rval;
char *name;
return (EINVAL);
} else if (rval == NDI_FAILURE) {
}
return (rval);
}
/*
* Remove the child named by "devname@devaddr".
* For use by a driver's DEVCTL_DEVICE_REMOVE handler.
*/
int
{
int rval;
char *name;
return (EINVAL);
} else if (rval == NDI_FAILURE) {
}
return (rval);
}
/*
* Return devctl state of the child named by "name@addr".
* For use by a driver's DEVCTL_DEVICE_GETSTATE handler.
*/
int
{
char *devname;
int devnamelen;
int circ;
return (NDI_FAILURE);
} else {
}
return (NDI_FAILURE);
}
if (DEVI_IS_DEVICE_OFFLINE(dip)) {
*state = DEVICE_OFFLINE;
} else if (DEVI_IS_DEVICE_DOWN(dip)) {
*state = DEVICE_DOWN;
} else {
*state = DEVICE_ONLINE;
*state |= DEVICE_BUSY;
}
return (NDI_SUCCESS);
}
/*
* return the current state of the device "dip"
*
* recommend using ndi_devctl_ioctl() or
* ndi_devctl_device_getstate() instead
*/
int
{
int circ;
return (NDI_FAILURE);
if (DEVI_IS_DEVICE_OFFLINE(dip)) {
} else if (DEVI_IS_DEVICE_DOWN(dip)) {
} else {
devstate |= DEVICE_BUSY;
}
return (NDI_FAULT);
return (NDI_SUCCESS);
}
/*
* Return device's bus state
* For use by a driver's DEVCTL_BUS_GETSTATE handler.
*/
int
{
return (NDI_FAILURE);
}
/*
* Generic devctl ioctl handler
*/
int
{
struct devctl_iocdata *dcp;
/*
* read devctl ioctl data
*/
return (EFAULT);
switch (cmd) {
case DEVCTL_BUS_GETSTATE:
if (rval == NDI_SUCCESS) {
sizeof (uint_t)) != 0)
}
break;
case DEVCTL_DEVICE_ONLINE:
break;
case DEVCTL_DEVICE_OFFLINE:
break;
case DEVCTL_DEVICE_GETSTATE:
if (rval == NDI_SUCCESS) {
sizeof (uint_t)) != 0)
}
break;
case DEVCTL_DEVICE_REMOVE:
break;
case DEVCTL_BUS_DEV_CREATE:
break;
/*
* ioctls for which a generic implementation makes no sense
*/
case DEVCTL_BUS_RESET:
case DEVCTL_BUS_RESETALL:
case DEVCTL_DEVICE_RESET:
case DEVCTL_AP_CONNECT:
case DEVCTL_AP_DISCONNECT:
case DEVCTL_AP_INSERT:
case DEVCTL_AP_REMOVE:
case DEVCTL_AP_CONFIGURE:
case DEVCTL_AP_UNCONFIGURE:
case DEVCTL_AP_GETSTATE:
case DEVCTL_AP_CONTROL:
case DEVCTL_BUS_QUIESCE:
case DEVCTL_BUS_UNQUIESCE:
break;
}
return (rval);
}
/*
* Copyout the state of the Attachment Point "ap" to the requesting
* user process.
*/
int
{
return (NDI_FAILURE);
if (get_udatamodel() == DATAMODEL_NATIVE) {
sizeof (devctl_ap_state_t)) != 0)
return (NDI_FAULT);
}
#ifdef _SYSCALL32_IMPL
else {
sizeof (devctl_ap_state32_t)) != 0)
return (NDI_FAULT);
}
#endif
return (NDI_SUCCESS);
}
/*
* Copyout the bus state of the bus nexus device "dip" to the requesting
* user process.
*/
int
{
return (NDI_FAILURE);
return (NDI_FAILURE);
return (NDI_FAULT);
return (NDI_SUCCESS);
}
static int
/*
* create a child device node given the property definitions
* supplied by the userland process
*/
int
dev_info_t **rdip)
{
int nmlen;
/*
* The child device may have been pre-constructed by an earlier
* call to this function with the flag DEVCTL_CONSTRUCT set.
*/
return (rv);
/*
* Return the device node partially constructed if the
* DEVCTL_CONSTRUCT flag is set.
*/
if (flags & DEVCTL_CONSTRUCT) {
(void) ndi_devi_free(cdip);
return (EINVAL);
}
return (0);
}
/*
* Bring the node up to a named but OFFLINE state. The calling
* application will need to manage the node from here on.
*/
/*
* In the unlikely event that the dip was somehow attached by
* the userland process (and device contracts or LDI opens
* were registered against the dip) after it was created by
* a previous DEVCTL_CONSTRUCT call, we start notify
* proceedings on this dip. Note that we don't need to
* return the dip after a failure of the notify since
* for a contract or LDI handle to be created the dip was
* already available to the user.
*/
return (EBUSY);
}
/*
* hand set the OFFLINE flag to prevent any asynchronous
* autoconfiguration operations from attaching this node.
*/
if (rv != NDI_SUCCESS) {
return (ENXIO);
}
/*
* remove the dev_info node if it failed to bind to a
* driver above.
*/
return (ENXIO);
}
/*
* add the node to the per-driver list and INITCHILD it
* to give it a name.
*/
return (EINVAL);
}
} else {
/*
* Attempt to bring the device ONLINE. If the request to
* fails, remove the dev_info node.
*/
return (ENXIO);
}
/*
* if the node was successfully added but there was
* no driver available for the device, remove the node
*/
return (ENODEV);
}
}
/*
* return a handle to the child device
* copy out the name of the newly attached child device if
* the IOCTL request has provided a copyout buffer.
*/
return (0);
return (EFAULT);
}
return (0);
}
static int
dev_info_t **rdip)
{
char *np;
int rv = 0;
return (EINVAL);
/*
* construct a new dev_info node with a user-provided nodename
*/
/*
* create hardware properties for each member in the property
* list.
*/
/*
* skip the nodename property
*/
continue;
switch (nvpair_type(npp)) {
case DATA_TYPE_INT32: {
break;
(int)prop_val);
break;
}
case DATA_TYPE_STRING: {
char *prop_val;
break;
break;
}
case DATA_TYPE_BYTE_ARRAY: {
&nelms)) != 0)
break;
break;
}
case DATA_TYPE_INT32_ARRAY: {
&nelms)) != 0)
break;
break;
}
case DATA_TYPE_STRING_ARRAY: {
char **val;
&nelms)) != 0)
break;
break;
}
/*
* unsupported property data type
*/
default:
}
}
/*
* something above failed
* destroy the partially child device and abort the request
*/
if (rv != 0) {
(void) ndi_devi_free(cdip);
return (rv);
}
return (0);
}
/*
* return current soft bus state of bus nexus "dip"
*/
int
{
return (NDI_FAILURE);
return (NDI_FAILURE);
if (DEVI_IS_BUS_QUIESCED(dip))
*rstate = BUS_QUIESCED;
else if (DEVI_IS_BUS_DOWN(dip))
*rstate = BUS_SHUTDOWN;
else
*rstate = BUS_ACTIVE;
return (NDI_SUCCESS);
}
/*
* Set the soft state of bus nexus "dip"
*/
int
{
return (NDI_FAILURE);
switch (state) {
case BUS_QUIESCED:
break;
case BUS_ACTIVE:
break;
case BUS_SHUTDOWN:
break;
default:
rv = NDI_FAILURE;
}
return (rv);
}
/*
* These dummy functions are obsolete and may be removed.
* Retained for existing driver compatibility only.
* Drivers should be fixed not to use these functions.
* Don't write new code using these obsolete interfaces.
*/
/*ARGSUSED*/
void
{
/* obsolete dummy function */
}
/*ARGSUSED*/
void
{
/* obsolete dummy function */
}
/*
* Single thread entry into per-driver list
*/
/*ARGSUSED*/
void
{
/* obsolete dummy function */
}
/*
* release the per-driver list
*/
/*ARGSUSED*/
void
{
/* obsolete dummy function */
}
/*
* Attempt to enter driver list
*/
/*ARGSUSED*/
int
{
return (1); /* obsolete dummy function */
}
/*
* ndi event handling support functions:
* The NDI event support model is as follows:
*
* The nexus driver defines a set of events using some static structures (so
* these structures can be shared by all instances of the nexus driver).
* The nexus driver allocates an event handle and binds the event set
* to this handle. The nexus driver's event busop functions can just
* call the appropriate NDI event support function using this handle
* as the first argument.
*
* The reasoning for tying events to the device tree is that the entity
* generating the callback will typically be one of the device driver's
* ancestors in the tree.
*/
static int ndi_event_debug = 0;
#ifdef DEBUG
#endif /* DEBUG */
/*
* allocate a new ndi event handle
*/
int
{
if (!ndi_event_hdl) {
return (NDI_FAILURE);
}
MUTEX_DRIVER, (void *)cookie);
MUTEX_DRIVER, (void *)cookie);
return (NDI_SUCCESS);
}
/*
* free the ndi event handle
*/
int
{
/* deallocate all defined cookies */
}
/* destroy mutexes */
/* free event handle */
return (NDI_SUCCESS);
}
/*
* ndi_event_bind_set() adds a set of events to the NDI event
* handle.
*
* Events generated by high level interrupts should not
* be mixed in the same event set with events generated by
* normal interrupts or kernel events.
*
* This function can be called multiple times to bind
* additional sets to the event handle.
* However, events generated by high level interrupts cannot
* be bound to a handle that already has bound events generated
* by normal interrupts or from kernel context and vice versa.
*/
int
{
/*
*/
"attach or detach");
return (NDI_FAILURE);
}
/*
* if it is not the correct version or the event set is
* empty, bail out
*/
return (NDI_FAILURE);
high_plevels = other_plevels = 0;
/* check for mixing events at high level with the other types */
for (i = 0; i < ndi_events->ndi_n_events; i++) {
high_plevels++;
} else {
}
}
/*
* bail out if high level events are mixed with other types in this
* event set or the set is incompatible with the set in the handle
*/
if ((high_plevels && other_plevels) ||
return (NDI_FAILURE);
}
/*
* check for duplicate events in both the existing handle
* and the event set, add events if not duplicates
*/
for (i = 0; i < ndi_events->ndi_n_events; i++) {
dup = 1;
break;
}
}
if (dup == 0) {
km_flag);
if (!new_cookie)
return (NDI_FAILURE);
if (ndi_event_hdl->ndi_evthdl_n_events == 0) {
} else {
}
/*
* set up new cookie
*/
} else {
/*
* event not added, must correct plevel numbers
*/
if (ndi_event_defs[i].ndi_event_plevel ==
high_plevels--;
} else {
}
}
dup = 0;
}
(ndi_event_hdl->ndi_evthdl_other_plevels == 0));
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
}
#endif /* NDI_EVENT_DEBUG */
return (NDI_SUCCESS);
}
/*
* ndi_event_unbind_set() unbinds a set of events, previously
* bound using ndi_event_bind_set(), from the NDI event
* handle.
*
* This routine will unbind all events in the event set. If an event,
* specified in the event set, is not found in the handle, this
* routine will proceed onto the next member of the set as if the event
* was never specified.
*
* The event set may be a subset of the set of events that
* was previously bound to the handle. For example, events
* can be individually unbound.
*
* An event cannot be unbound if callbacks are still
* registered against the event.
*/
/*ARGSUSED*/
int
{
int len;
uint_t i;
int rval;
/*
*/
"attach or detach");
return (NDI_FAILURE);
}
/* bail out if ndi_event_set is outdated */
return (NDI_FAILURE);
}
/*
* Verify that all events in the event set are eligible
* for unbinding(ie. there are no outstanding callbacks).
* If any one of the events are ineligible, fail entire
* operation.
*/
for (i = 0; i < ndi_events->ndi_n_events; i++) {
while (cookie_list != NULL) {
if (cookie_list->callback_list) {
rval = NDI_FAILURE;
goto done;
}
break;
} else {
}
}
}
/*
* remove all events found within the handle
* If an event is not found, this function will proceed as if the event
* was never specified.
*/
for (i = 0; i < ndi_events->ndi_n_events; i++) {
while (cookie_list != NULL) {
/*
* can not unbind an event definition with
* outstanding callbacks
*/
if (cookie_list->callback_list) {
rval = NDI_FAILURE;
goto done;
}
/* remove this cookie from the list */
prev->next_cookie =
} else {
}
/* adjust plevel counts */
if (NDI_EVENT_PLEVEL(cookie_list) ==
} else {
}
/* adjust cookie count */
/* free the cookie */
sizeof (ndi_event_cookie_t));
break;
} else {
prev = cookie_list;
}
}
}
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
}
#endif /* NDI_EVENT_DEBUG */
rval = NDI_SUCCESS;
done:
return (rval);
}
/*
* ndi_event_retrieve_cookie():
* Return an event cookie for eventname if this nexus driver
* has defined the named event. The event cookie returned
* by this function is used to register callback handlers
* for the event.
*
* ndi_event_retrieve_cookie() is intended to be used in the
* nexus driver's bus_get_eventcookie busop routine.
*
* If the event is not defined by this bus nexus driver, and flag
* does not include NDI_EVENT_NOPASS, then ndi_event_retrieve_cookie()
* will pass the request up the device tree hierarchy by calling
* ndi_busop_get_eventcookie(9N).
* If the event is not defined by this bus nexus driver, and flag
* does include NDI_EVENT_NOPASS, ndi_event_retrieve_cookie()
* will return NDI_FAILURE. The caller may then determine what further
* action to take, such as using a different handle, passing the
* request up the device tree using ndi_busop_get_eventcookie(9N),
* or returning the failure to the caller, thus blocking the
* progress of the request up the tree.
*/
int
char *eventname,
{
int len;
/*
* search the cookie list for the event name and return
* cookie if found.
*/
while (cookie_list != NULL) {
len) == 0) {
return (NDI_SUCCESS);
}
}
/*
* event was not found, pass up or return failure
*/
if ((flag & NDI_EVENT_NOPASS) == 0) {
return (ndi_busop_get_eventcookie(
} else {
return (NDI_FAILURE);
}
}
/*
* check whether this nexus defined this event and look up attributes
*/
static int
{
while (cookie_list != NULL) {
if (attributes)
*attributes =
return (NDI_SUCCESS);
}
}
return (NDI_FAILURE);
}
/*
* ndi_event_add_callback(): adds an event callback registration
* to the event cookie defining this event.
*
* Refer also to bus_add_eventcall(9n) and ndi_busop_add_eventcall(9n).
*
* ndi_event_add_callback(9n) is intended to be used in
* the nexus driver's bus_add_eventcall(9n) busop function.
*
* If the event is not defined by this bus nexus driver,
* ndi_event_add_callback() will return NDI_FAILURE.
*/
int
void (*event_callback)(dev_info_t *,
void *arg,
{
/*
* if the event was not bound to this handle, return failure
*/
return (NDI_FAILURE);
}
/*
* allocate space for a callback structure
*/
return (NDI_FAILURE);
}
/* initialize callback structure */
/* add this callback structure to the list */
} else {
}
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
}
#endif /* NDI_EVENT_DEBUG */
return (NDI_SUCCESS);
}
/*
* ndi_event_remove_callback():
*
* ndi_event_remove_callback() removes a callback that was
* previously registered using ndi_event_add_callback(9N).
* Refer also to bus_remove_eventcall(9n) and
* ndi_busop_remove_eventcall(9n).
* ndi_event_remove_callback(9n) is intended to be used in
* the nexus driver's bus_remove_eventcall (9n) busop function.
* If the event is not defined by this bus nexus driver,
* ndi_event_remove_callback() will return NDI_FAILURE.
*/
int
{
return (NDI_SUCCESS);
}
/*ARGSUSED*/
static void
{
/* remove from callback linked list */
if (cb->ndi_evtcb_prev) {
}
if (cb->ndi_evtcb_next) {
}
}
}
/*
* ndi_event_run_callbacks() performs event callbacks for the event
* specified by cookie, if this is among those bound to the
* supplied handle.
* If the event is among those bound to the handle, none,
* some, or all of the handlers registered for the event
* will be called, according to the delivery attributes of
* the event.
* If the event attributes include NDI_EVENT_POST_TO_ALL
* (the default), all the handlers for the event will be
* called in an unspecified order.
* If the event attributes include NDI_EVENT_POST_TO_TGT, only
* the handlers (if any) registered by the driver identified by
* rdip will be called.
* If the event identified by cookie is not bound to the handle,
* NDI_FAILURE will be returned.
*/
int
{
int attributes;
/* if this is not our event, fail */
NDI_SUCCESS) {
return (NDI_FAILURE);
}
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
"producer dip=%p (%s%d): cookie = %p, name = %s\n",
(void *)ndi_event_hdl->ndi_evthdl_dip,
(void *)cookie,
}
#endif /* #ifdef NDI_EVENT_DEBUG */
/*
* The callback handlers may call conversion functions. The conversion
* functions may hold the ndi_evthdl_mutex during execution. Thus, to
* avoid a recursive mutex problem, only the ndi_evthdl_cb_mutex is
* held. The ndi_evthdl_mutex is not held when running the callbacks.
*/
/* perform callbacks */
if (attributes == NDI_EVENT_POST_TO_TGT &&
continue;
}
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
"\t\tconsumer dip=%p (%s%d)\n",
(void *)cb->ndi_evtcb_dip,
}
#endif
}
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
}
#endif /* NDI_EVENT_DEBUG */
return (NDI_SUCCESS);
}
/*
* perform one callback for a specified cookie and just one target
*/
int
{
int attributes;
/* if this is not our event, fail */
NDI_SUCCESS) {
return (NDI_FAILURE);
}
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
"producer dip=%p (%s%d): cookie = %p, name = %s\n",
(void *)ndi_event_hdl->ndi_evthdl_dip,
(void *)cookie,
}
#endif
/*
* we only grab the cb mutex because the callback handlers
* may call the conversion functions which would cause a recursive
* mutex problem
*/
/* perform callbacks */
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
"\t\tconsumer dip=%p (%s%d)\n",
(void *)cb->ndi_evtcb_dip,
}
#endif
break;
}
}
#ifdef NDI_EVENT_DEBUG
if (ndi_event_debug) {
}
#endif /* NDI_EVENT_DEBUG */
return (NDI_SUCCESS);
}
/*
* ndi_event_tag_to_cookie: utility function to find an event cookie
* given an event tag
*/
{
return ((ddi_eventcookie_t)list);
}
}
return (NULL);
}
/*
* ndi_event_cookie_to_tag: utility function to find a event tag
* given an event_cookie
*/
int
{
return (NDI_EVENT_TAG(list));
}
}
return (NDI_FAILURE);
}
/*
* ndi_event_cookie_to_name: utility function to find an event name
* given an event_cookie
*/
char *
{
return (NDI_EVENT_NAME(list));
}
}
return (NULL);
}
/*
* ndi_event_tag_to_name: utility function to find an event name
* given an event tag
*/
char *
{
while (list) {
return (NDI_EVENT_NAME(list));
}
}
return (NULL);
}
#ifdef NDI_EVENT_DEBUG
void
{
while (list) {
(void *)NDI_EVENT_DDIP(list));
"\t\t dip=%p (%s%d) cookie=%p arg=%p\n",
(void*)next->ndi_evtcb_dip,
(void *)next->ndi_evtcb_cookie,
}
}
}
#endif
int
{
}
int
{
/*
* NOTE: this does NOT mean the pseudo branch of the device tree,
* it means the node was created by software (DEVI_SID_NODEID ||
* DEVI_PSEUDO_NODEID || DEVI_SID_HIDDEN_NODEID) instead of being
* generated from a PROM node.
*/
}
int
{
}
int
{
}
int
{
}
void
{
}
void
{
}
int
{
DDI_AUTO_ASSIGNED_NODEID) != 0);
}
void
{
}
{
}
void
{
}
int
{
}
void
{
}
void
{
}
void
{
}
void
{
}
void
{
}
/*
* The default fault-handler, called when the event posted by
* ddi_dev_report_fault() reaches rootnex.
*/
static void
{
if (!DEVI_IS_DEVICE_OFFLINE(dip)) {
case DDI_SERVICE_LOST:
break;
case DDI_SERVICE_DEGRADED:
break;
case DDI_SERVICE_UNAFFECTED:
default:
break;
case DDI_SERVICE_RESTORED:
break;
}
}
}
/*
* The default fault-logger, called when the event posted by
* ddi_dev_report_fault() reaches rootnex.
*/
/*ARGSUSED*/
static void
{
const char *action;
const char *servstate;
const char *location;
int bad;
int changed;
int level;
int still;
bad = 0;
switch (fedp->f_location) {
case DDI_DATAPATH_FAULT:
location = "in datapath to";
break;
case DDI_DEVICE_FAULT:
location = "in";
break;
case DDI_EXTERNAL_FAULT:
location = "external to";
break;
default:
location = "somewhere near";
bad = 1;
break;
}
switch (newstate) {
case DDI_DEVSTATE_OFFLINE:
servstate = "unavailable";
break;
case DDI_DEVSTATE_DOWN:
servstate = "unavailable";
break;
case DDI_DEVSTATE_QUIESCED:
servstate = "suspended";
break;
case DDI_DEVSTATE_DEGRADED:
servstate = "degraded";
break;
default:
servstate = "available";
break;
}
case DDI_SERVICE_LOST:
case DDI_SERVICE_DEGRADED:
case DDI_SERVICE_UNAFFECTED:
/* fault detected; service [still] <servstate> */
action = "fault detected";
break;
case DDI_SERVICE_RESTORED:
if (newstate != DDI_DEVSTATE_UP) {
/* fault cleared; service still <servstate> */
action = "fault cleared";
still = 1;
} else if (changed) {
/* fault cleared; service <servstate> */
action = "fault cleared";
still = 0;
} else {
/* no fault; service <servstate> */
action = "no fault";
still = 0;
}
break;
default:
bad = 1;
break;
}
}
/*
* Platform-settable pointers to fault handler and logger functions.
* These are called by the default rootnex event-posting code when
* a fault event reaches rootnex.
*/
/*
* Rootnex event definitions ...
*/
enum rootnex_event_tags {
};
{
}
};
sizeof (rootnex_event_set) / sizeof (rootnex_event_set[0]),
};
/*
* Initialize rootnex event handle
*/
void
{
(void) ndi_event_free_hdl(rootnex_event_hdl);
}
}
}
/*
* Event-handling functions for rootnex
* These provide the standard implementation of fault handling
*/
/*ARGSUSED*/
int
{
if (rootnex_event_hdl == NULL)
return (NDI_FAILURE);
}
/*ARGSUSED*/
int
{
if (rootnex_event_hdl == NULL)
return (NDI_FAILURE);
}
/*ARGSUSED*/
int
{
if (rootnex_event_hdl == NULL)
return (NDI_FAILURE);
}
/*ARGSUSED*/
int
{
int tag;
if (rootnex_event_hdl == NULL)
return (NDI_FAILURE);
if (tag == ROOTNEX_FAULT_EVENT) {
}
}
/*
*/
void
void *data)
{
if (up) {
} else {
}
}
void *
{
if (up)
else
}
{
if (up) {
} else {
}
}
void
{
}
{
}
/*
* Interfaces to maintain flavor-specific private data of flavored
* children of self.
*
* The flavor count always includes the default (0) vanilla flavor,
* but storage for the vanilla flavor data pointer is in the same
* place that ddi_[sg]et_driver_private uses, so the flavorv
* storage is just for flavors 1..{nflavors-1}.
*/
void
{
return;
}
}
void
{
if (child_flavor == NDI_FLAVOR_VANILLA) {
} else {
return;
}
}
}
void *
{
if (child_flavor == NDI_FLAVOR_VANILLA) {
return (ddi_get_driver_private(self));
} else {
return (NULL);
}
}
}