driver_lyr.c revision 86f07f8f16054fb11b7f08b96913a9a66435b99a
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Layered driver support.
*/
#include <sys/sysmacros.h>
#include <sys/bootconf.h>
#include <sys/pathname.h>
#include <sys/dditypes.h>
#include <sys/ddi_impldefs.h>
#include <sys/autoconf.h>
#include <sys/sunldi_impl.h>
#include <sys/socketvar.h>
/*
* Define macros to manipulate snode, vnode, and open device flags
*/
/*
* Define macros for accessing layered driver hash structures
*/
/*
* Define layered handle flags used in the lh_type field
*/
/*
* Define marco for devid property lookups
*/
#define DEVID_PROP_FLAGS (DDI_PROP_DONTPASS | \
/*
* globals
*/
static size_t ldi_handle_hash_count;
void
ldi_init(void)
{
int i;
for (i = 0; i < LH_HASH_SZ; i++) {
ldi_handle_hash[i] = NULL;
}
for (i = 0; i < LI_HASH_SZ; i++) {
ldi_ident_hash[i] = NULL;
}
}
/*
* LDI ident manipulation functions
*/
static uint_t
{
return ((uint_t)k);
} else if (dev != DDI_DEV_T_NONE) {
} else {
return (modid);
}
}
static struct ldi_ident **
{
break;
}
return (lipp);
}
static struct ldi_ident *
{
/* get the module id */
/* allocate a new ident in case we need it */
/* search the hash for a matching ident */
/* we found an indent in the hash */
return (*lipp);
}
/* initialize the new ident */
/* add it to the ident hash */
return (lip);
}
static void
{
}
static void
{
/* there are more references to this ident */
return;
}
}
/*
* LDI handle manipulation functions
*/
static uint_t
handle_hash_func(void *vp)
{
return ((uint_t)k);
}
static struct ldi_handle **
{
break;
}
return (lhpp);
}
static struct ldi_handle *
{
struct ldi_handle **lhpp;
return (*lhpp);
}
static struct ldi_handle *
{
/* allocate a new handle in case we need it */
/* search the hash for a matching handle */
/* we found a handle in the hash */
"lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x",
return (*lhpp);
}
/* initialize the new handle */
/* set the device type for this handle */
} else {
}
/* get holds on other objects */
ident_hold(ident);
/* add it to the handle hash */
"lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x",
return (lhp);
}
static void
{
struct ldi_handle **lhpp;
"lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x",
/* there are more references to this handle */
return;
}
}
/*
* LDI event manipulation functions
*/
static void
{
return;
}
}
static void
{
}
static void
void *arg, void *bus_impldata)
{
"event_cookie=0x%p, ldi_eventp=0x%p", "i_ldi_callback",
}
/*
* LDI open helper functions
*/
/* get a vnode to a device by dev_t and otyp */
static int
{
/* sanity check required input parameters */
return (EINVAL);
return (ENODEV);
return (ENXIO);
}
return (0);
}
/* get a vnode to a device by pathname */
static int
{
int ret;
/* sanity check required input parameters */
return (EINVAL);
if (modrootloaded) {
/* we don't want lookupname to fail because of credentials */
/*
* all lookups should be done in the global zone. but
* lookupnameat() won't actually do this if an absolute
* path is passed in. since the ldi interfaces require an
* absolute path we pass lookupnameat() a pointer to
* the character after the leading '/' and tell it to
* start searching at the current system root directory.
*/
/* restore this threads credentials */
if (ret == 0) {
return (ENXIO);
}
}
}
int spec_type;
/*
* Root is not mounted, the minor node is not specified,
* or an OBP path has been specified.
*/
/*
* Determine if path can be pruned to produce an
* OBP or devfs path for resolve_pathname.
*/
/*
* if no minor node was specified the DEFAULT minor node
* will be returned. if there is no DEFAULT minor node
* one will be fabricated of type S_IFCHR with the minor
* number equal to the instance number.
*/
if (ret != 0)
return (ENODEV);
}
return (0);
}
static int
{
char *devidstr;
/* convert devid as a string property */
return (0);
/*
* Search for the devid. For speed and ease in locking this
* code directly uses the property implementation. See
* ddi_common_devid_to_devlist() for a comment as to why.
*/
/* check if there is a DDI_DEV_T_NONE devid property */
/* a DDI_DEV_T_NONE devid exists and matchs */
return (1);
} else {
/* a DDI_DEV_T_NONE devid exists and doesn't match */
return (0);
}
}
/* check if there is a devt specific devid property */
/* a devt specific devid exists and matchs */
return (1);
} else {
/* a devt specific devid exists and doesn't match */
return (0);
}
}
/* we didn't find any devids associated with the device */
return (0);
}
/* get a handle to a device by devid and minor name */
static int
{
/* sanity check required input parameters */
return (EINVAL);
return (ENODEV);
for (i = 0; i < ndevs; i++) {
continue;
/*
* now we have to verify that the devid of the disk
* still matches what was requested.
*
* we have to do this because the devid could have
* changed between the call to ddi_lyr_devid_to_devlist()
* and e_ddi_hold_devi_by_dev(). this is because when
* ddi_lyr_devid_to_devlist() returns a list of devts
* there is no kind of hold on those devts so a device
* could have been replaced out from under us in the
* interim.
*/
break;
}
if (i == ndevs)
return (ENODEV);
return (0);
}
/* given a vnode, open a device */
static int
{
struct ldi_handle *nlhp;
int err;
/* if the vnode passed in is not a device, then bail */
return (ENXIO);
/*
* the caller may have specified a node that
* doesn't have cb_ops defined. the ldi doesn't yet
* support opening devices without a valid cb_ops.
*/
return (ENXIO);
/* open the device */
return (err);
/* possible clone open, make sure that we still have a spec node */
/*
* allocating the layered handle took a new hold on the vnode
* so we can release the hold that was returned by the clone
* open
*/
"ldi clone open", (void *)nlhp));
} else {
"ldi open", (void *)nlhp));
}
/* Flush back any dirty pages associated with the device. */
}
return (0);
}
/* Call a drivers prop_op(9E) interface */
static int
{
int res;
/*
* we can only be invoked after a driver has been opened and
* someone has a layered handle to it, so there had better be
* a valid ops vector.
*/
/*
* Some nexus drivers incorrectly set cb_prop_op to nodev,
* nulldev or even NULL.
*/
return (DDI_PROP_NOT_FOUND);
}
/* check if this is actually DDI_DEV_T_ANY query */
if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
return (res);
}
static void
{
}
static caddr_t
{
struct prop_driver_data *pdd;
int pdd_size;
}
/*
* i_ldi_prop_op_typed() is a wrapper for i_ldi_prop_op that is used
* by the typed ldi property lookup interfaces.
*/
static int
{
/*
* first call the drivers prop_op() interface to allow it
* it to override default property values.
*/
if (res != DDI_PROP_SUCCESS)
return (DDI_PROP_NOT_FOUND);
/* sanity check the property length */
if (prop_len == 0) {
/*
* the ddi typed interfaces don't allow a drivers to
* create properties with a length of 0. so we should
* prevent drivers from returning 0 length dynamic
* properties for typed property lookups.
*/
return (DDI_PROP_NOT_FOUND);
}
/* sanity check the property length against the element size */
return (DDI_PROP_NOT_FOUND);
/*
* got it. now allocate a prop_driver_data struct so that the
* user can free the property via ddi_prop_free().
*/
/* lookup the property again, this time get the value */
if (res != DDI_PROP_SUCCESS) {
return (DDI_PROP_NOT_FOUND);
}
/* sanity check the property length */
if (prop_len == 0) {
return (DDI_PROP_NOT_FOUND);
}
/* sanity check the property length against the element size */
return (DDI_PROP_NOT_FOUND);
}
/*
* return the prop_driver_data struct and, optionally, the length
* of the data.
*/
return (DDI_PROP_SUCCESS);
}
/*
* i_check_string looks at a string property and makes sure its
* a valid null terminated string
*/
static int
{
int i;
for (i = 0; i < prop_len; i++) {
if (str[i] == '\0')
return (0);
}
return (1);
}
/*
* i_pack_string_array takes a a string array property that is represented
* as a concatination of strings (with the NULL character included for
* each string) and converts it into a format that can be returned by
* ldi_prop_lookup_string_array.
*/
static int
char ***str_arrayp, int *nelemp)
{
/*
* first we need to sanity check the input string array.
* in essence this can be done my making sure that the last
* character of the array passed in is null. (meaning the last
* string in the array is NULL terminated.
*/
return (1);
/* now let's count the number of strings in the array */
if (str_concat[i] == '\0')
nelem++;
/* now let's allocate memory for the new packed property */
/* let's copy the actual string data into the new property */
/* now initialize the string array pointers */
for (i = 0; i < nelem; i++) {
}
/* set the return values */
*str_arrayp = str_array;
return (0);
}
/*
* LDI Project private device usage interfaces
*/
/*
* Get a count of how many devices are currentl open by different consumers
*/
int
{
return (ldi_handle_hash_count);
}
static void
{
/* get the target devt */
/* try to get the target dip */
} else if (dev != DDI_DEV_T_NONE) {
}
/* set the target information */
}
static int
{
int ret = LDI_USAGE_CONTINUE;
/* set the target device information */
/* get the source devt */
/* try to get the source dip */
} else if (dev != DDI_DEV_T_NONE) {
}
/* set the valid source information */
/*
* if the source ident represents either:
*
* - a kernel module (and not a device or device driver)
* - a device node
*
* then we currently have all the info we need to report the
* usage information so invoke the callback function.
*/
return (ret);
}
/*
* now this is kinda gross.
*
* what we do here is attempt to associate every device instance
* of the source driver on the system with the open target driver.
* we do this because we don't know which instance of the device
* could potentially access the lower device so we assume that all
* the instances could access it.
*
* there are two ways we could have gotten here:
*
* 1) this layered ident represents one created using only a
* major number or a driver module name. this means that when
* it was created we could not associate it with a particular
* dev_t or device instance.
*
* when could this possibly happen you ask?
*
* a perfect example of this is streams persistent links.
* when a persistant streams link is formed we can't associate
* the lower device stream with any particular upper device
* stream or instance. this is because any particular upper
* device stream could be closed, then another could be
* opened with a different dev_t and device instance, and it
* would still have access to the lower linked stream.
*
* since any instance of the upper streams driver could
* potentially access the lower stream whenever it wants,
* we represent that here by associating the opened lower
* device with every existing device instance of the upper
* streams driver.
*
* 2) This case should really never happen but we'll include it
* for completeness.
*
* it's possible that we could have gotten here because we
* have a dev_t for the upper device but we couldn't find a
* dip associated with that dev_t.
*
* the only types of devices that have dev_t without an
* associated dip are unbound DLPIv2 network devices. These
* types of devices exist to be able to attach a stream to any
* instance of a hardware network device. since these types of
* devices are usually hardware devices they should never
* really have other devices open.
*/
if (dev != DDI_DEV_T_NONE)
else
/* set the source dip */
/* invoke the callback function */
}
/* if there was a target dip, release it */
return (ret);
}
/*
* ldi_usage_walker() - this walker reports LDI kernel device usage
* information via the callback() callback function. the LDI keeps track
* of what devices are being accessed in its own internal data structures.
* this function walks those data structures to determine device usage.
*/
void
{
struct ldi_handle *lhp;
int i;
int ret = LDI_USAGE_CONTINUE;
for (i = 0; i < LH_HASH_SZ; i++) {
lhp = ldi_handle_hash[i];
/* invoke the devinfo callback function */
}
if (ret != LDI_USAGE_CONTINUE)
break;
}
}
/*
* LDI Project private interfaces (streams linking interfaces)
*
* Streams supports a type of built in device layering via linking.
* Certain types of streams drivers can be streams multiplexors.
* These operations allows other streams devices to be linked under the
* multiplexor. By definition all streams multiplexors are devices
* so this linking is a type of device layering where the multiplexor
* device is layered on top of the device linked below it.
*/
/*
* ldi_mlink_lh() is invoked when streams are linked using LDI handles.
* It is not used for normal I_LINKs and I_PLINKs using file descriptors.
*
* The streams framework keeps track of links via the file_t of the lower
* stream. The LDI keeps track of devices using a vnode. In the case
* of a streams link created via an LDI handle, fnk_lh() allocates
* a file_t that the streams framework can use to track the linkage.
*/
int
{
int err;
return (EINVAL);
/*
* create a new lower vnode and a file_t that points to it,
* streams linking requires a file_t. falloc() returns with
* fpdown locked.
*/
/* try to establish the link */
if (err != 0) {
/* the link failed, free the file_t and release the vnode */
}
return (err);
}
/*
* ldi_mlink_fp() is invoked for all successfull streams linkages created
* via I_LINK and I_PLINK. ldi_mlink_fp() records the linkage information
* in its internal state so that the devinfo snapshot code has some
* observability into streams device linkage information.
*/
void
{
int ret;
/* if the lower stream is not a device then return */
return;
"stp=0x%p, fpdown=0x%p", "ldi_mlink_fp",
/* check if this was a plink via a layered handle */
if (lhlink) {
/*
* increment the common snode s_count.
*
* this is done because after the link operation there
* are two ways that s_count can be decremented.
*
* when the layered handle used to create the link is
* closed, spec_close() is called and it will decrement
* s_count in the common snode. if we don't increment
* s_count here then this could cause spec_close() to
* actually close the device while it's still linked
* under a multiplexer.
*
* also, when the lower stream is unlinked, closef() is
* called for the file_t associated with this snode.
* closef() will call spec_close(), which will decrement
* s_count. if we dont't increment s_count here then this
* could cause spec_close() to actually close the device
* while there may still be valid layered handles
* pointing to it.
*/
/*
* decrement the f_count.
* this is done because the layered driver framework does
* not actually cache a copy of the file_t allocated to
* do the link. this is done here instead of in ldi_mlink_lh()
* because there is a window in ldi_mlink_lh() between where
* milnk_file() returns and we would decrement the f_count
* when the stream could be unlinked.
*/
}
/*
* NOTE: here we rely on the streams subsystem not allowing
* a stream to be multiplexed more than once. if this
* changes, we break.
*
*/
/* get a layered ident for the upper stream */
if (type == LINKNORMAL) {
/*
* if the link is not persistant then we can associate
* the upper stream with a dev_t. this is because the
* upper stream is associated with a vnode, which is
* associated with a dev_t and this binding can't change
* during the life of the stream. since the link isn't
* persistant once the stream is destroyed the link is
* destroyed. so the dev_t will be valid for the life
* of the link.
*/
} else {
/*
* if the link is persistant we can only associate the
* link with a driver (and not a dev_t.) this is
* because subsequent opens of the upper device may result
* in a different stream (and dev_t) having access to
* the lower stream.
*
* for example, if the upper stream is closed after the
* persistant link operation is compleated, a subsequent
* open of the upper device will create a new stream which
* may have a different dev_t and an unlink operation
* can be performed using this new upper stream.
*/
}
}
void
{
struct ldi_handle *lhp;
int ret;
/* if the lower stream is not a device then return */
return;
"stp=0x%p, fpdown=0x%p", "ldi_munlink_fp",
/*
* NOTE: here we rely on the streams subsystem not allowing
* a stream to be multiplexed more than once. if this
* changes, we break.
*
*/
/*
* clear the owner for this snode
* see the comment in ldi_mlink_fp() for information about how
* the ident is allocated
*/
if (type == LINKNORMAL) {
} else {
}
}
/*
* LDI Consolidation private interfaces
*/
int
{
char *name;
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (0);
}
{
return (lip);
}
/*
* LDI Public interfaces
*/
int
{
char *name;
return (EINVAL);
return (EINVAL);
return (EINVAL);
"%s: li=0x%p, mod=%s, minor=0x%x, stp=0x%p",
(void *)stp));
return (0);
}
int
{
char *name;
return (EINVAL);
return (EINVAL);
"%s: li=0x%p, mod=%s, minor=0x%x",
return (0);
}
int
{
char *name;
return (EINVAL);
return (EINVAL);
"%s: li=0x%p, mod=%s, dip=0x%p",
return (0);
}
int
{
char *name;
return (EINVAL);
return (EINVAL);
"%s: li=0x%p, mod=%s",
return (0);
}
void
{
char *name;
return;
name = ident->li_modname;
"%s: li=0x%p, mod=%s",
}
/* get a handle to a device by dev_t and otyp */
int
{
int ret;
/* sanity check required input parameters */
return (EINVAL);
return (ret);
}
return (ret);
}
/* get a handle to a device by pathname */
int
{
int ret;
/* sanity check required input parameters */
return (EINVAL);
return (ret);
return (ret);
}
/* get a handle to a device by devid and minor_name */
int
{
int ret;
/* sanity check required input parameters */
return (EINVAL);
return (ret);
return (ret);
}
int
{
int err = 0;
return (EINVAL);
/* Flush back any dirty pages associated with the device. */
}
/*
* Any event handlers should have been unregistered by the
* time ldi_close() is called. If they haven't then it's a
* bug.
*
* In a debug kernel we'll panic to make the problem obvious.
*/
/*
* On a production kernel we'll "do the right thing" (unregister
* the event handlers) and then complain about having to do the
* work ourselves.
*/
err = 1;
}
if (err) {
"failed to unregister layered event handlers before "
}
/* do a layered close on the device */
/*
* Free the handle even if the device close failed. why?
*
* If the device close failed we can't really make assumptions
* about the devices state so we shouldn't allow access to the
* device via this handle any more. If the device consumer wants
* to access the device again they should open it again.
*
* in other places like spec_close() and closeandsetf().
*/
return (err);
}
int
{
int ret;
return (EINVAL);
} else {
return (ENOTSUP);
}
return (ret);
}
int
{
int ret;
return (EINVAL);
} else {
return (ENOTSUP);
}
return (ret);
}
int
{
int otyp;
return (DDI_FAILURE);
return (DDI_FAILURE);
/*
* Determine device type (char or block).
* property value. Block devices may support
*/
return (DDI_FAILURE);
if (ldi_prop_exists(lh,
"Nblocks", 0);
return (DDI_SUCCESS);
}
if (ldi_prop_exists(lh,
"nblocks", 0);
return (DDI_SUCCESS);
}
}
if (ldi_prop_exists(lh,
return (DDI_SUCCESS);
}
if (ldi_prop_exists(lh,
return (DDI_SUCCESS);
}
/* unable to determine device size */
return (DDI_FAILURE);
}
int
{
return (EINVAL);
/*
* if the data pointed to by arg is located in the kernel then
* make sure the FNATIVE flag is set.
*/
/*
* if we get an I_PLINK from within the kernel the
* arg is a layered handle pointer instead of
* a file descriptor, so we translate this ioctl
* into a private one that can handle this.
*/
cmd = _I_PLINK_LH;
} else {
return (ENOTSUP);
}
return (ret);
}
int
{
int ret;
return (EINVAL);
} else {
return (ENOTSUP);
}
return (ret);
}
int
{
int ret;
return (DDI_PROP_INVAL_ARG);
return (DDI_PROP_INVAL_ARG);
return (DDI_PROP_INVAL_ARG);
/*
* try to find the associated dip,
* this places a hold on the driver
*/
return (DDI_PROP_NOT_FOUND);
return (ret);
}
int
{
return (EINVAL);
/* this entry point is only supported for cb devices */
return (ENOTSUP);
return (bdev_strategy(bp));
}
int
{
return (EINVAL);
/* this entry point is only supported for cb devices */
return (ENOTSUP);
}
int
{
return (EINVAL);
/* this entry point is only supported for cb devices */
return (ENOTSUP);
}
int
{
return (EINVAL);
/* this entry point is only supported for cb devices */
return (ENOTSUP);
/*
* Kaio is only supported on block devices.
*/
return (ENOTSUP);
return (ENOTSUP);
}
int
{
return (EINVAL);
/* this entry point is only supported for cb devices */
return (ENOTSUP);
/*
* Kaio is only supported on block devices.
*/
return (ENOTSUP);
return (ENOTSUP);
}
int
{
int ret;
return (EINVAL);
return (ENOTSUP);
}
/* Send message while honoring flow control */
return (ret);
}
int
{
return (EINVAL);
return (ENOTSUP);
/* Convert from nanoseconds to milliseconds */
return (EINVAL);
} else
timout = -1;
/* Wait for timeout millseconds for a message */
pri = 0;
return (ret);
}
int
{
return (EINVAL);
return (0);
}
int
{
return (EINVAL);
return (0);
}
int
{
int ret;
return (EINVAL);
if (ret != DDI_SUCCESS)
return (ENOTSUP);
return (0);
}
int
{
return (EINVAL);
if (ret != DDI_SUCCESS)
return (ENOTSUP);
return (0);
}
int
{
int res;
return (DDI_PROP_INVAL_ARG);
flags |= DDI_UNBND_DLPI2;
} else if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
/* if we got it then return it */
if (res == DDI_PROP_SUCCESS) {
return (res);
}
}
/* call the normal property interfaces */
return (res);
}
int
{
int res;
return (DDI_PROP_INVAL_ARG);
flags |= DDI_UNBND_DLPI2;
} else if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
int prop_len;
/* if we got it then return it */
if (res == DDI_PROP_SUCCESS) {
return (res);
}
}
/* call the normal property interfaces */
return (res);
}
int
{
int res;
return (DDI_PROP_INVAL_ARG);
flags |= DDI_UNBND_DLPI2;
} else if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
char *prop_val;
int prop_len;
/* if we got it then return it */
if (res == DDI_PROP_SUCCESS) {
char **str_array;
int nelem;
/*
* pack the returned string array into the format
* our callers expect
*/
return (res);
}
/*
* the format of the returned property must have
* been bad so throw it out
*/
}
}
/* call the normal property interfaces */
return (res);
}
int
{
int res;
return (DDI_PROP_INVAL_ARG);
flags |= DDI_UNBND_DLPI2;
} else if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
char *prop_val;
int prop_len;
/* if we got it then return it */
if (res == DDI_PROP_SUCCESS) {
/*
* sanity check the vaule returned.
*/
} else {
return (res);
}
}
}
/* call the normal property interfaces */
#ifdef DEBUG
if (res == DDI_PROP_SUCCESS) {
/*
* keep ourselves honest
* make sure the framework returns strings in the
* same format as we're demanding from drivers.
*/
struct prop_driver_data *pdd;
int pdd_prop_size;
sizeof (struct prop_driver_data);
}
#endif /* DEBUG */
return (res);
}
int
{
int res;
return (DDI_PROP_INVAL_ARG);
flags |= DDI_UNBND_DLPI2;
} else if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
int prop_len;
/* if we got it then return it */
if (res == DDI_PROP_SUCCESS) {
return (res);
}
}
/* call the normal property interfaces */
return (res);
}
int
{
int res;
return (defvalue);
flags |= DDI_UNBND_DLPI2;
} else if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
int prop_val;
int prop_len;
/*
* first call the drivers prop_op interface to allow it
* it to override default property values.
*/
prop_len = sizeof (int);
/* if we got it then return it */
if ((res == DDI_PROP_SUCCESS) &&
(prop_len == sizeof (int))) {
return (res);
}
}
/* call the normal property interfaces */
return (res);
}
{
return (defvalue);
flags |= DDI_UNBND_DLPI2;
} else if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
int prop_len;
/*
* first call the drivers prop_op interface to allow it
* it to override default property values.
*/
/* if we got it then return it */
if ((res == DDI_PROP_SUCCESS) &&
return (res);
}
}
/* call the normal property interfaces */
return (res);
}
int
{
return (0);
/* if NULL dip, prop does NOT exist */
return (0);
if (flags & LDI_DEV_T_ANY) {
flags &= ~LDI_DEV_T_ANY;
dev = DDI_DEV_T_ANY;
}
/*
* first call the drivers prop_op interface to allow it
* it to override default property values.
*/
if (res == DDI_PROP_SUCCESS) {
return (1);
}
/* call the normal property interfaces */
return (res);
}
int
{
int res;
return (DDI_FAILURE);
}
return (DDI_FAILURE);
"dip=0x%p, event_cookiep=0x%p", "ldi_get_eventcookie",
return (res);
}
int
{
int res;
return (DDI_FAILURE);
return (DDI_FAILURE);
"event callback", "ldi_add_event_handler"));
return (res);
}
"ldi_eventp=0x%p, cb_id=0x%p", "ldi_add_event_handler",
return (res);
}
int
{
int res;
return (DDI_FAILURE);
!= DDI_SUCCESS) {
"event callback", "ldi_remove_event_handler"));
return (res);
}
return (res);
}