driver_lyr.c revision 349dcea37d1dc6e491c49c864c5e3773a4e3cae6
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Common Development and Distribution License (the "License").
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling * Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Layered driver support.
99653d4ee642c6528e88224f12409a5f23060994eschrock * Device contract related
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson * Define macros to manipulate snode, vnode, and open device flags
99653d4ee642c6528e88224f12409a5f23060994eschrock#define VTYP_VALID(i) (((i) == VCHR) || ((i) == VBLK))
99653d4ee642c6528e88224f12409a5f23060994eschrock#define VTYP_TO_OTYP(i) (((i) == VCHR) ? OTYP_CHR : OTYP_BLK)
99653d4ee642c6528e88224f12409a5f23060994eschrock#define VTYP_TO_STYP(i) (((i) == VCHR) ? S_IFCHR : S_IFBLK)
99653d4ee642c6528e88224f12409a5f23060994eschrock#define OTYP_VALID(i) (((i) == OTYP_CHR) || ((i) == OTYP_BLK))
99653d4ee642c6528e88224f12409a5f23060994eschrock#define OTYP_TO_VTYP(i) (((i) == OTYP_CHR) ? VCHR : VBLK)
99653d4ee642c6528e88224f12409a5f23060994eschrock#define OTYP_TO_STYP(i) (((i) == OTYP_CHR) ? S_IFCHR : S_IFBLK)
99653d4ee642c6528e88224f12409a5f23060994eschrock#define STYP_VALID(i) (((i) == S_IFCHR) || ((i) == S_IFBLK))
99653d4ee642c6528e88224f12409a5f23060994eschrock#define STYP_TO_VTYP(i) (((i) == S_IFCHR) ? VCHR : VBLK)
99653d4ee642c6528e88224f12409a5f23060994eschrock * Define macros for accessing layered driver hash structures
99653d4ee642c6528e88224f12409a5f23060994eschrock#define LH_HASH(vp) (handle_hash_func(vp) % LH_HASH_SZ)
99653d4ee642c6528e88224f12409a5f23060994eschrock#define LI_HASH(mid, dip, dev) (ident_hash_func(mid, dip, dev) % LI_HASH_SZ)
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson * Define layered handle flags used in the lh_type field
99653d4ee642c6528e88224f12409a5f23060994eschrock#define LH_STREAM (0x1) /* handle to a streams device */
99653d4ee642c6528e88224f12409a5f23060994eschrock#define LH_CBDEV (0x2) /* handle to a char/block device */
99653d4ee642c6528e88224f12409a5f23060994eschrock * Define macro for devid property lookups
99653d4ee642c6528e88224f12409a5f23060994eschrock * Dummy string for NDI events
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic void ldi_ev_lock(void);
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic void ldi_ev_unlock(void);
99653d4ee642c6528e88224f12409a5f23060994eschrockint ldi_remove_event_handler(ldi_handle_t lh, ldi_callback_id_t id);
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic struct ldi_ident *ldi_ident_hash[LI_HASH_SZ];
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic struct ldi_handle *ldi_handle_hash[LH_HASH_SZ];
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic struct ldi_ev_callback_list ldi_ev_callback_list;
99653d4ee642c6528e88224f12409a5f23060994eschrock for (i = 0; i < LH_HASH_SZ; i++) {
99653d4ee642c6528e88224f12409a5f23060994eschrock mutex_init(&ldi_handle_hash_lock[i], NULL, MUTEX_DEFAULT, NULL);
99653d4ee642c6528e88224f12409a5f23060994eschrock for (i = 0; i < LI_HASH_SZ; i++) {
99653d4ee642c6528e88224f12409a5f23060994eschrock mutex_init(&ldi_ident_hash_lock[i], NULL, MUTEX_DEFAULT, NULL);
b1b8ab34de515a5e83206da22c3d7e563241b021lling * Initialize the LDI event subsystem
b1b8ab34de515a5e83206da22c3d7e563241b021lling mutex_init(&ldi_ev_callback_list.le_lock, NULL, MUTEX_DEFAULT, NULL);
b1b8ab34de515a5e83206da22c3d7e563241b021lling cv_init(&ldi_ev_callback_list.le_cv, NULL, CV_DEFAULT, NULL);
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor * LDI ident manipulation functions
8488aeb5df27784d479c16cde06a9e25cd9a1152taylorident_hash_func(modid_t modid, dev_info_t *dip, dev_t dev)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return ((uint_t)k);
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrockstatic struct ldi_ident **
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendanident_find_ref_nolock(modid_t modid, dev_info_t *dip, dev_t dev, major_t major)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Altstatic struct ldi_ident *
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Altident_alloc(char *mod_name, dev_info_t *dip, dev_t dev, major_t major)
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling /* get the module id */
99d5e173470cf967aa87653364ed614299e7b511Tim Haley /* allocate a new ident in case we need it */
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson /* search the hash for a matching ident */
99653d4ee642c6528e88224f12409a5f23060994eschrock lipp = ident_find_ref_nolock(modid, dip, dev, major);
c08432ebe688ed6410b302771a9afd8e23e2a7cceschrock /* we found an ident in the hash */
99653d4ee642c6528e88224f12409a5f23060994eschrock ASSERT(strcmp((*lipp)->li_modname, mod_name) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* initialize the new ident */
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) strncpy(lip->li_modname, mod_name, sizeof (lip->li_modname) - 1);
99653d4ee642c6528e88224f12409a5f23060994eschrock /* add it to the ident hash */
99653d4ee642c6528e88224f12409a5f23060994eschrock index = LI_HASH(lip->li_modid, lip->li_dip, lip->li_dev);
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling index = LI_HASH(lip->li_modid, lip->li_dip, lip->li_dev);
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling /* there are more references to this ident */
99653d4ee642c6528e88224f12409a5f23060994eschrock /* this was the last reference/open for this ident. free it. */
99653d4ee642c6528e88224f12409a5f23060994eschrock lip->li_modid, lip->li_dip, lip->li_dev, lip->li_major);
99653d4ee642c6528e88224f12409a5f23060994eschrock * LDI handle manipulation functions
99653d4ee642c6528e88224f12409a5f23060994eschrock return ((uint_t)k);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic struct ldi_handle **
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarkshandle_find_ref_nolock(vnode_t *vp, struct ldi_ident *ident)
ece3d9b3bacef51a5f34d993935eedbb7bb87059llingstatic struct ldi_handle *
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic struct ldi_handle *
97d9e3a676d96208790c885c4766194423e84b24ck /* allocate a new handle in case we need it */
99653d4ee642c6528e88224f12409a5f23060994eschrock /* search the hash for a matching handle */
99653d4ee642c6528e88224f12409a5f23060994eschrock /* we found a handle in the hash */
99653d4ee642c6528e88224f12409a5f23060994eschrock "lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x",
99653d4ee642c6528e88224f12409a5f23060994eschrock /* initialize the new handle */
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson mutex_init(lhp->lh_lock, NULL, MUTEX_DEFAULT, NULL);
b7661ccca92e6bf5160f4d5d2601efaeaa1f5161mmusante /* set the device type for this handle */
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson /* get holds on other objects */
99653d4ee642c6528e88224f12409a5f23060994eschrock /* add it to the handle hash */
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling "lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x",
99653d4ee642c6528e88224f12409a5f23060994eschrock "lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x",
99653d4ee642c6528e88224f12409a5f23060994eschrock (void *)lhp, (void *)lhp->lh_ident, (void *)lhp->lh_vp,
99653d4ee642c6528e88224f12409a5f23060994eschrock /* there are more references to this handle */
99653d4ee642c6528e88224f12409a5f23060994eschrock /* this was the last reference/open for this handle. free it. */
99653d4ee642c6528e88224f12409a5f23060994eschrock lhpp = handle_find_ref_nolock(lhp->lh_vp, lhp->lh_ident);
99653d4ee642c6528e88224f12409a5f23060994eschrock * LDI event manipulation functions
fa9e4066f08beec538e775443c5be79dd423fcabahrensi_ldi_callback(dev_info_t *dip, ddi_eventcookie_t event_cookie,
fa9e4066f08beec538e775443c5be79dd423fcabahrens "event_cookie=0x%p, ldi_eventp=0x%p", "i_ldi_callback",
fa9e4066f08beec538e775443c5be79dd423fcabahrens lep->le_handler(lep->le_lhp, event_cookie, lep->le_arg, bus_impldata);
99d5e173470cf967aa87653364ed614299e7b511Tim Haley * LDI open helper functions
99d5e173470cf967aa87653364ed614299e7b511Tim Haley/* get a vnode to a device by dev_t and otyp */
99d5e173470cf967aa87653364ed614299e7b511Tim Haleyldi_vp_from_dev(dev_t dev, int otyp, vnode_t **vpp)
99d5e173470cf967aa87653364ed614299e7b511Tim Haley /* sanity check required input parameters */
99d5e173470cf967aa87653364ed614299e7b511Tim Haley if ((dev == DDI_DEV_T_NONE) || (!OTYP_VALID(otyp)) || (vpp == NULL))
99d5e173470cf967aa87653364ed614299e7b511Tim Haley if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
99d5e173470cf967aa87653364ed614299e7b511Tim Haley ddi_release_devi(dip); /* from e_ddi_hold_devi_by_dev */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock return (0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock/* get a vnode to a device by pathname */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /* sanity check required input parameters */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* we don't want lookupname to fail because of credentials */
99653d4ee642c6528e88224f12409a5f23060994eschrock * all lookups should be done in the global zone. but
fa9e4066f08beec538e775443c5be79dd423fcabahrens * lookupnameat() won't actually do this if an absolute
fa9e4066f08beec538e775443c5be79dd423fcabahrens * path is passed in. since the ldi interfaces require an
fa9e4066f08beec538e775443c5be79dd423fcabahrens * absolute path we pass lookupnameat() a pointer to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the character after the leading '/' and tell it to
99653d4ee642c6528e88224f12409a5f23060994eschrock * start searching at the current system root directory.
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = lookupnameat(path + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* restore this threads credentials */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ret == 0) {
5c7098917783942b65876f681a21342761227dadeschrock * Root is not mounted, the minor node is not specified,
5c7098917783942b65876f681a21342761227dadeschrock * or an OBP path has been specified.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Determine if path can be pruned to produce an
5c7098917783942b65876f681a21342761227dadeschrock * OBP or devfs path for resolve_pathname.
5c7098917783942b65876f681a21342761227dadeschrock * if no minor node was specified the DEFAULT minor node
5c7098917783942b65876f681a21342761227dadeschrock * will be returned. if there is no DEFAULT minor node
5c7098917783942b65876f681a21342761227dadeschrock * one will be fabricated of type S_IFCHR with the minor
5c7098917783942b65876f681a21342761227dadeschrock * number equal to the instance number.
5c7098917783942b65876f681a21342761227dadeschrock ret = resolve_pathname(path, &dip, &dev, &spec_type);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrockldi_devid_match(ddi_devid_t devid, dev_info_t *dip, dev_t dev)
99653d4ee642c6528e88224f12409a5f23060994eschrock /* convert devid as a string property */
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((devidstr = ddi_devid_str_encode(devid, NULL)) == NULL)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrock * Search for the devid. For speed and ease in locking this
99653d4ee642c6528e88224f12409a5f23060994eschrock * code directly uses the property implementation. See
99653d4ee642c6528e88224f12409a5f23060994eschrock * ddi_common_devid_to_devlist() for a comment as to why.
99653d4ee642c6528e88224f12409a5f23060994eschrock /* check if there is a DDI_DEV_T_NONE devid property */
99653d4ee642c6528e88224f12409a5f23060994eschrock DEVID_PROP_NAME, DEVID_PROP_FLAGS, &DEVI(dip)->devi_hw_prop_ptr);
99653d4ee642c6528e88224f12409a5f23060994eschrock if (ddi_devid_str_compare(propp->prop_val, devidstr) == 0) {
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens /* a DDI_DEV_T_NONE devid exists and matchs */
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens /* a DDI_DEV_T_NONE devid exists and doesn't match */
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens return (0);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens /* check if there is a devt specific devid property */
99653d4ee642c6528e88224f12409a5f23060994eschrock DEVID_PROP_NAME, DEVID_PROP_FLAGS, &(DEVI(dip)->devi_hw_prop_ptr));
99653d4ee642c6528e88224f12409a5f23060994eschrock if (ddi_devid_str_compare(propp->prop_val, devidstr) == 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock /* a devt specific devid exists and matchs */
99653d4ee642c6528e88224f12409a5f23060994eschrock return (1);
99653d4ee642c6528e88224f12409a5f23060994eschrock /* a devt specific devid exists and doesn't match */
29ab75c9a733dad2978c4860efd954b5625e3467rm return (0);
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens /* we didn't find any devids associated with the device */
99653d4ee642c6528e88224f12409a5f23060994eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrock/* get a handle to a device by devid and minor name */
99653d4ee642c6528e88224f12409a5f23060994eschrockldi_vp_from_devid(ddi_devid_t devid, char *minor_name, vnode_t **vpp)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /* sanity check required input parameters */
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris if ((devid == NULL) || (minor_name == NULL) || (vpp == NULL))
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris ret = ddi_lyr_devid_to_devlist(devid, minor_name, &ndevs, &devs);
5aba80db367b061758a29154d304977d00d8e4f4ck for (i = 0; i < ndevs; i++) {
5aba80db367b061758a29154d304977d00d8e4f4ck * now we have to verify that the devid of the disk
5aba80db367b061758a29154d304977d00d8e4f4ck * still matches what was requested.
5aba80db367b061758a29154d304977d00d8e4f4ck * we have to do this because the devid could have
5aba80db367b061758a29154d304977d00d8e4f4ck * changed between the call to ddi_lyr_devid_to_devlist()
5aba80db367b061758a29154d304977d00d8e4f4ck * and e_ddi_hold_devi_by_dev(). this is because when
5aba80db367b061758a29154d304977d00d8e4f4ck * ddi_lyr_devid_to_devlist() returns a list of devts
5aba80db367b061758a29154d304977d00d8e4f4ck * there is no kind of hold on those devts so a device
5aba80db367b061758a29154d304977d00d8e4f4ck * could have been replaced out from under us in the
5aba80db367b061758a29154d304977d00d8e4f4ck * interim.
5aba80db367b061758a29154d304977d00d8e4f4ck ddi_release_devi(dip); /* from e_ddi_hold_devi_by_dev() */
5aba80db367b061758a29154d304977d00d8e4f4ck return (0);
5aba80db367b061758a29154d304977d00d8e4f4ck/* given a vnode, open a device */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /* if the vnode passed in is not a device, then bail */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (!vn_matchops(vp, spec_getvnodeops()) || !VTYP_VALID(vp->v_type))
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * the caller may have specified a node that
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * doesn't have cb_ops defined. the ldi doesn't yet
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * support opening devices without a valid cb_ops.
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (devopsp[getmajor(vp->v_rdev)]->devo_cb_ops == NULL)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /* open the device */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if ((err = VOP_OPEN(&vp, flag | FKLYR, cr, NULL)) != 0)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /* possible clone open, make sure that we still have a spec node */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * allocating the layered handle took a new hold on the vnode
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * so we can release the hold that was returned by the clone
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock/* Call a drivers prop_op(9E) interface */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrocki_ldi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock int flags, char *name, caddr_t valuep, int *lengthp)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * we can only be invoked after a driver has been opened and
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * someone has a layered handle to it, so there had better be
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * a valid ops vector.
990b4856d0eaada6f8140335733a1b1771ed2746lling * Some nexus drivers incorrectly set cb_prop_op to nodev,
990b4856d0eaada6f8140335733a1b1771ed2746lling * nulldev or even NULL.
990b4856d0eaada6f8140335733a1b1771ed2746lling /* check if this is actually DDI_DEV_T_ANY query */
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock res = cdev_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp);
990b4856d0eaada6f8140335733a1b1771ed2746lling pdd_size = sizeof (struct prop_driver_data) + prop_len;
b1b8ab34de515a5e83206da22c3d7e563241b021lling * i_ldi_prop_op_typed() is a wrapper for i_ldi_prop_op that is used
b1b8ab34de515a5e83206da22c3d7e563241b021lling * by the typed ldi property lookup interfaces.
b1b8ab34de515a5e83206da22c3d7e563241b021llingi_ldi_prop_op_typed(dev_t dev, dev_info_t *dip, int flags, char *name,
b1b8ab34de515a5e83206da22c3d7e563241b021lling * first call the drivers prop_op() interface to allow it
b1b8ab34de515a5e83206da22c3d7e563241b021lling * it to override default property values.
deb8317b8f5925e3f6dd7cb6ed0cdd035f546a5aMark J Musante /* sanity check the property length */
b1b8ab34de515a5e83206da22c3d7e563241b021lling * the ddi typed interfaces don't allow a drivers to
b1b8ab34de515a5e83206da22c3d7e563241b021lling * create properties with a length of 0. so we should
b1b8ab34de515a5e83206da22c3d7e563241b021lling * prevent drivers from returning 0 length dynamic
b1b8ab34de515a5e83206da22c3d7e563241b021lling * properties for typed property lookups.
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* sanity check the property length against the element size */
990b4856d0eaada6f8140335733a1b1771ed2746lling * got it. now allocate a prop_driver_data struct so that the
990b4856d0eaada6f8140335733a1b1771ed2746lling * user can free the property via ddi_prop_free().
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* lookup the property again, this time get the value */
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* sanity check the property length */
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* sanity check the property length against the element size */
deb8317b8f5925e3f6dd7cb6ed0cdd035f546a5aMark J Musante if (elem_size && ((prop_len % elem_size) != 0)) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * return the prop_driver_data struct and, optionally, the length
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * of the data.
b1b8ab34de515a5e83206da22c3d7e563241b021lling * i_check_string looks at a string property and makes sure its
b1b8ab34de515a5e83206da22c3d7e563241b021lling * a valid null terminated string
b1b8ab34de515a5e83206da22c3d7e563241b021lling for (i = 0; i < prop_len; i++) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (0);
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (1);
b1b8ab34de515a5e83206da22c3d7e563241b021lling * i_pack_string_array takes a a string array property that is represented
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * as a concatenation of strings (with the NULL character included for
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * each string) and converts it into a format that can be returned by
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * ldi_prop_lookup_string_array.
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * first we need to sanity check the input string array.
b1b8ab34de515a5e83206da22c3d7e563241b021lling * in essence this can be done my making sure that the last
b1b8ab34de515a5e83206da22c3d7e563241b021lling * character of the array passed in is null. (meaning the last
b1b8ab34de515a5e83206da22c3d7e563241b021lling * string in the array is NULL terminated.
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (1);
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* now let's count the number of strings in the array */
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* now let's allocate memory for the new packed property */
b1b8ab34de515a5e83206da22c3d7e563241b021lling pack_size = (sizeof (char *) * (nelem + 1)) + prop_len;
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson /* let's copy the actual string data into the new property */
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* now initialize the string array pointers */
b1b8ab34de515a5e83206da22c3d7e563241b021lling for (i = 0; i < nelem; i++) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* set the return values */
b1b8ab34de515a5e83206da22c3d7e563241b021lling * LDI Project private device usage interfaces
b1b8ab34de515a5e83206da22c3d7e563241b021lling * Get a count of how many devices are currentl open by different consumers
b1b8ab34de515a5e83206da22c3d7e563241b021llingldi_usage_walker_tgt_helper(ldi_usage_t *ldi_usage, vnode_t *vp)
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* get the target devt */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* try to get the target dip */
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* set the target information */
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson ldi_usage->tgt_name = mod_major_to_name(getmajor(dev));
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson ldi_usage->tgt_modid = mod_name_to_modid(ldi_usage->tgt_name);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Ericksonldi_usage_walker_helper(struct ldi_ident *lip, vnode_t *vp,
b1b8ab34de515a5e83206da22c3d7e563241b021lling void *arg, int (*callback)(const ldi_usage_t *, void *))
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* set the target device information */
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* get the source devt */
b1b8ab34de515a5e83206da22c3d7e563241b021lling /* try to get the source dip */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* set the valid source information */
990b4856d0eaada6f8140335733a1b1771ed2746lling * if the source ident represents either:
990b4856d0eaada6f8140335733a1b1771ed2746lling * - a kernel module (and not a device or device driver)
990b4856d0eaada6f8140335733a1b1771ed2746lling * - a device node
990b4856d0eaada6f8140335733a1b1771ed2746lling * then we currently have all the info we need to report the
990b4856d0eaada6f8140335733a1b1771ed2746lling * usage information so invoke the callback function.
990b4856d0eaada6f8140335733a1b1771ed2746lling if (((lip->li_major == -1) && (dev == DDI_DEV_T_NONE)) ||
990b4856d0eaada6f8140335733a1b1771ed2746lling * now this is kinda gross.
990b4856d0eaada6f8140335733a1b1771ed2746lling * what we do here is attempt to associate every device instance
990b4856d0eaada6f8140335733a1b1771ed2746lling * of the source driver on the system with the open target driver.
990b4856d0eaada6f8140335733a1b1771ed2746lling * we do this because we don't know which instance of the device
990b4856d0eaada6f8140335733a1b1771ed2746lling * could potentially access the lower device so we assume that all
990b4856d0eaada6f8140335733a1b1771ed2746lling * the instances could access it.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * there are two ways we could have gotten here:
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * 1) this layered ident represents one created using only a
990b4856d0eaada6f8140335733a1b1771ed2746lling * major number or a driver module name. this means that when
990b4856d0eaada6f8140335733a1b1771ed2746lling * it was created we could not associate it with a particular
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * dev_t or device instance.
990b4856d0eaada6f8140335733a1b1771ed2746lling * when could this possibly happen you ask?
990b4856d0eaada6f8140335733a1b1771ed2746lling * a perfect example of this is streams persistent links.
990b4856d0eaada6f8140335733a1b1771ed2746lling * when a persistant streams link is formed we can't associate
990b4856d0eaada6f8140335733a1b1771ed2746lling * the lower device stream with any particular upper device
990b4856d0eaada6f8140335733a1b1771ed2746lling * stream or instance. this is because any particular upper
990b4856d0eaada6f8140335733a1b1771ed2746lling * device stream could be closed, then another could be
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * opened with a different dev_t and device instance, and it
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * would still have access to the lower linked stream.
990b4856d0eaada6f8140335733a1b1771ed2746lling * since any instance of the upper streams driver could
f67f35c39aa272d43489ee49625b4965cc83add2Eric Schrock * potentially access the lower stream whenever it wants,
990b4856d0eaada6f8140335733a1b1771ed2746lling * we represent that here by associating the opened lower
990b4856d0eaada6f8140335733a1b1771ed2746lling * device with every existing device instance of the upper
990b4856d0eaada6f8140335733a1b1771ed2746lling * streams driver.
990b4856d0eaada6f8140335733a1b1771ed2746lling * 2) This case should really never happen but we'll include it
990b4856d0eaada6f8140335733a1b1771ed2746lling * for completeness.
990b4856d0eaada6f8140335733a1b1771ed2746lling * it's possible that we could have gotten here because we
990b4856d0eaada6f8140335733a1b1771ed2746lling * have a dev_t for the upper device but we couldn't find a
990b4856d0eaada6f8140335733a1b1771ed2746lling * dip associated with that dev_t.
990b4856d0eaada6f8140335733a1b1771ed2746lling * the only types of devices that have dev_t without an
990b4856d0eaada6f8140335733a1b1771ed2746lling * associated dip are unbound DLPIv2 network devices. These
990b4856d0eaada6f8140335733a1b1771ed2746lling * types of devices exist to be able to attach a stream to any
990b4856d0eaada6f8140335733a1b1771ed2746lling * instance of a hardware network device. since these types of
990b4856d0eaada6f8140335733a1b1771ed2746lling * devices are usually hardware devices they should never
990b4856d0eaada6f8140335733a1b1771ed2746lling * really have other devices open.
990b4856d0eaada6f8140335733a1b1771ed2746lling /* set the source dip */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* invoke the callback function */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* if there was a target dip, release it */
990b4856d0eaada6f8140335733a1b1771ed2746lling * ldi_usage_walker() - this walker reports LDI kernel device usage
990b4856d0eaada6f8140335733a1b1771ed2746lling * information via the callback() callback function. the LDI keeps track
990b4856d0eaada6f8140335733a1b1771ed2746lling * of what devices are being accessed in its own internal data structures.
990b4856d0eaada6f8140335733a1b1771ed2746lling * this function walks those data structures to determine device usage.
990b4856d0eaada6f8140335733a1b1771ed2746llingldi_usage_walker(void *arg, int (*callback)(const ldi_usage_t *, void *))
990b4856d0eaada6f8140335733a1b1771ed2746lling for (i = 0; i < LH_HASH_SZ; i++) {
990b4856d0eaada6f8140335733a1b1771ed2746lling while ((lhp != NULL) && (ret == LDI_USAGE_CONTINUE)) {
990b4856d0eaada6f8140335733a1b1771ed2746lling /* invoke the devinfo callback function */
990b4856d0eaada6f8140335733a1b1771ed2746lling ret = ldi_usage_walker_helper(lip, vp, arg, callback);
990b4856d0eaada6f8140335733a1b1771ed2746lling * LDI Project private interfaces (streams linking interfaces)
990b4856d0eaada6f8140335733a1b1771ed2746lling * Streams supports a type of built in device layering via linking.
990b4856d0eaada6f8140335733a1b1771ed2746lling * Certain types of streams drivers can be streams multiplexors.
990b4856d0eaada6f8140335733a1b1771ed2746lling * A streams multiplexor supports the I_LINK/I_PLINK operation.
990b4856d0eaada6f8140335733a1b1771ed2746lling * These operations allows other streams devices to be linked under the
990b4856d0eaada6f8140335733a1b1771ed2746lling * multiplexor. By definition all streams multiplexors are devices
990b4856d0eaada6f8140335733a1b1771ed2746lling * so this linking is a type of device layering where the multiplexor
990b4856d0eaada6f8140335733a1b1771ed2746lling * device is layered on top of the device linked below it.
990b4856d0eaada6f8140335733a1b1771ed2746lling * ldi_mlink_lh() is invoked when streams are linked using LDI handles.
990b4856d0eaada6f8140335733a1b1771ed2746lling * It is not used for normal I_LINKs and I_PLINKs using file descriptors.
990b4856d0eaada6f8140335733a1b1771ed2746lling * The streams framework keeps track of links via the file_t of the lower
990b4856d0eaada6f8140335733a1b1771ed2746lling * stream. The LDI keeps track of devices using a vnode. In the case
990b4856d0eaada6f8140335733a1b1771ed2746lling * of a streams link created via an LDI handle, fnk_lh() allocates
990b4856d0eaada6f8140335733a1b1771ed2746lling * a file_t that the streams framework can use to track the linkage.
990b4856d0eaada6f8140335733a1b1771ed2746llingldi_mlink_lh(vnode_t *vp, int cmd, intptr_t arg, cred_t *crp, int *rvalp)
990b4856d0eaada6f8140335733a1b1771ed2746lling * create a new lower vnode and a file_t that points to it,
a9799022bd90b13722204e80112efaa5bf573099ck * streams linking requires a file_t. falloc() returns with
990b4856d0eaada6f8140335733a1b1771ed2746lling * fpdown locked.
a2afb611b30628fb74ad9eade4ae465f9031e262Jerry Jelinek (void) falloc(vpdown, FREAD|FWRITE, &fpdown, NULL);
a2afb611b30628fb74ad9eade4ae465f9031e262Jerry Jelinek /* try to establish the link */
a2afb611b30628fb74ad9eade4ae465f9031e262Jerry Jelinek err = mlink_file(vp, I_PLINK, fpdown, crp, rvalp, 1);
a2afb611b30628fb74ad9eade4ae465f9031e262Jerry Jelinek /* the link failed, free the file_t and release the vnode */
990b4856d0eaada6f8140335733a1b1771ed2746lling * ldi_mlink_fp() is invoked for all successful streams linkages created
a9799022bd90b13722204e80112efaa5bf573099ck * via I_LINK and I_PLINK. ldi_mlink_fp() records the linkage information
a9799022bd90b13722204e80112efaa5bf573099ck * in its internal state so that the devinfo snapshot code has some
990b4856d0eaada6f8140335733a1b1771ed2746lling * observability into streams device linkage information.
990b4856d0eaada6f8140335733a1b1771ed2746llingldi_mlink_fp(struct stdata *stp, file_t *fpdown, int lhlink, int type)
990b4856d0eaada6f8140335733a1b1771ed2746lling /* if the lower stream is not a device then return */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* check if this was a plink via a layered handle */
990b4856d0eaada6f8140335733a1b1771ed2746lling * increment the common snode s_count.
990b4856d0eaada6f8140335733a1b1771ed2746lling * this is done because after the link operation there
990b4856d0eaada6f8140335733a1b1771ed2746lling * are two ways that s_count can be decremented.
990b4856d0eaada6f8140335733a1b1771ed2746lling * when the layered handle used to create the link is
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * closed, spec_close() is called and it will decrement
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * s_count in the common snode. if we don't increment
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * s_count here then this could cause spec_close() to
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * actually close the device while it's still linked
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * under a multiplexer.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * also, when the lower stream is unlinked, closef() is
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * called for the file_t associated with this snode.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * closef() will call spec_close(), which will decrement
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * s_count. if we dont't increment s_count here then this
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * could cause spec_close() to actually close the device
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * while there may still be valid layered handles
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * pointing to it.
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden * decrement the f_count.
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden * this is done because the layered driver framework does
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * not actually cache a copy of the file_t allocated to
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * do the link. this is done here instead of in ldi_mlink_lh()
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * because there is a window in ldi_mlink_lh() between where
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * milnk_file() returns and we would decrement the f_count
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * when the stream could be unlinked.
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden * NOTE: here we rely on the streams subsystem not allowing
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * a stream to be multiplexed more than once. if this
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * changes, we break.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * mark the snode/stream as multiplexed
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens /* get a layered ident for the upper stream */
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * if the link is not persistant then we can associate
990b4856d0eaada6f8140335733a1b1771ed2746lling * the upper stream with a dev_t. this is because the
990b4856d0eaada6f8140335733a1b1771ed2746lling * upper stream is associated with a vnode, which is
990b4856d0eaada6f8140335733a1b1771ed2746lling * associated with a dev_t and this binding can't change
990b4856d0eaada6f8140335733a1b1771ed2746lling * during the life of the stream. since the link isn't
990b4856d0eaada6f8140335733a1b1771ed2746lling * persistant once the stream is destroyed the link is
990b4856d0eaada6f8140335733a1b1771ed2746lling * destroyed. so the dev_t will be valid for the life
990b4856d0eaada6f8140335733a1b1771ed2746lling * of the link.
990b4856d0eaada6f8140335733a1b1771ed2746lling ret = ldi_ident_from_stream(getendq(stp->sd_wrq), &li);
990b4856d0eaada6f8140335733a1b1771ed2746lling * if the link is persistant we can only associate the
990b4856d0eaada6f8140335733a1b1771ed2746lling * link with a driver (and not a dev_t.) this is
990b4856d0eaada6f8140335733a1b1771ed2746lling * because subsequent opens of the upper device may result
990b4856d0eaada6f8140335733a1b1771ed2746lling * in a different stream (and dev_t) having access to
990b4856d0eaada6f8140335733a1b1771ed2746lling * the lower stream.
990b4856d0eaada6f8140335733a1b1771ed2746lling * for example, if the upper stream is closed after the
990b4856d0eaada6f8140335733a1b1771ed2746lling * persistant link operation is compleated, a subsequent
990b4856d0eaada6f8140335733a1b1771ed2746lling * open of the upper device will create a new stream which
990b4856d0eaada6f8140335733a1b1771ed2746lling * may have a different dev_t and an unlink operation
990b4856d0eaada6f8140335733a1b1771ed2746lling * can be performed using this new upper stream.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrensldi_munlink_fp(struct stdata *stp, file_t *fpdown, int type)
990b4856d0eaada6f8140335733a1b1771ed2746lling /* if the lower stream is not a device then return */
990b4856d0eaada6f8140335733a1b1771ed2746lling ASSERT((type == LINKNORMAL) || (type == LINKPERSIST));
990b4856d0eaada6f8140335733a1b1771ed2746lling * NOTE: here we rely on the streams subsystem not allowing
990b4856d0eaada6f8140335733a1b1771ed2746lling * a stream to be multiplexed more than once. if this
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * changes, we break.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * mark the snode/stream as not multiplexed
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * clear the owner for this snode
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * see the comment in ldi_mlink_fp() for information about how
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * the ident is allocated
990b4856d0eaada6f8140335733a1b1771ed2746lling ret = ldi_ident_from_stream(getendq(stp->sd_wrq), &li);
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens lhp = handle_find(vp, (struct ldi_ident *)li);
990b4856d0eaada6f8140335733a1b1771ed2746lling * LDI Consolidation private interfaces
990b4856d0eaada6f8140335733a1b1771ed2746llingldi_ident_from_mod(struct modlinkage *modlp, ldi_ident_t *lip)
990b4856d0eaada6f8140335733a1b1771ed2746lling *lip = (ldi_ident_t)ident_alloc(name, NULL, DDI_DEV_T_NONE, major);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746lling lip = (ldi_ident_t)ident_alloc("genunix", NULL, DDI_DEV_T_NONE, -1);
990b4856d0eaada6f8140335733a1b1771ed2746lling * LDI Public interfaces
990b4856d0eaada6f8140335733a1b1771ed2746llingldi_ident_from_stream(struct queue *sq, ldi_ident_t *lip)
990b4856d0eaada6f8140335733a1b1771ed2746lling "%s: li=0x%p, mod=%s, minor=0x%x, stp=0x%p",
990b4856d0eaada6f8140335733a1b1771ed2746lling "ldi_ident_from_stream", (void *)*lip, name, getminor(dev),
990b4856d0eaada6f8140335733a1b1771ed2746lling (void *)stp));
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
return (EINVAL);
return (EINVAL);
char *name;
return (EINVAL);
return (EINVAL);
char *name;
return (EINVAL);
return (EINVAL);
char *name;
int ret;
return (EINVAL);
return (ret);
return (ret);
int ret;
return (EINVAL);
return (ret);
return (ret);
int ret;
return (EINVAL);
return (ret);
return (ret);
int err = 0;
int notify = 0;
return (EINVAL);
#ifdef LDI_OBSOLETE_EVENT
if (err) {
ldi_ev_lock();
if (!notify) {
if (notify)
return (err);
int ret;
return (EINVAL);
return (ENOTSUP);
return (ret);
int ret;
return (EINVAL);
return (ENOTSUP);
return (ret);
int otyp;
int blkshift;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_SUCCESS);
return (DDI_SUCCESS);
return (DDI_FAILURE);
return (EINVAL);
return (ENOTSUP);
return (ret);
int ret;
return (EINVAL);
return (ENOTSUP);
return (ret);
int ret;
return (DDI_PROP_INVAL_ARG);
return (DDI_PROP_INVAL_ARG);
return (DDI_PROP_INVAL_ARG);
return (DDI_PROP_NOT_FOUND);
return (ret);
return (EINVAL);
return (ENOTSUP);
return (EINVAL);
return (ENOTSUP);
return (EINVAL);
return (ENOTSUP);
return (EINVAL);
return (ENOTSUP);
return (ENOTSUP);
return (ENOTSUP);
return (EINVAL);
return (ENOTSUP);
return (ENOTSUP);
return (ENOTSUP);
int ret;
return (EINVAL);
return (ENOTSUP);
return (ret);
return (EINVAL);
return (ENOTSUP);
return (EINVAL);
pri = 0;
return (ret);
return (EINVAL);
return (EINVAL);
int ret;
return (EINVAL);
return (ENOTSUP);
return (EINVAL);
return (ENOTSUP);
int res;
return (DDI_PROP_INVAL_ARG);
return (res);
return (res);
int res;
return (DDI_PROP_INVAL_ARG);
int prop_len;
return (res);
return (res);
int res;
return (DDI_PROP_INVAL_ARG);
char *prop_val;
int prop_len;
char **str_array;
int nelem;
return (res);
return (res);
int res;
return (DDI_PROP_INVAL_ARG);
char *prop_val;
int prop_len;
return (res);
#ifdef DEBUG
int pdd_prop_size;
sizeof (struct prop_driver_data);
return (res);
int res;
return (DDI_PROP_INVAL_ARG);
int prop_len;
return (res);
return (res);
int res;
return (defvalue);
int prop_val;
int prop_len;
prop_len = sizeof (int);
(prop_len == sizeof (int))) {
return (res);
return (res);
return (defvalue);
int prop_len;
return (res);
return (res);
return (res);
#ifdef LDI_OBSOLETE_EVENT
int res;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (res);
int res;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (res);
return (res);
int res;
return (DDI_FAILURE);
!= DDI_SUCCESS) {
return (res);
return (res);
static uint_t
static uint_t
return (NDI_EVENT_SERVICE);
static ldi_ev_cookie_t
return (NULL);
ldi_ev_lock(void)
ldi_ev_unlock(void)
int res;
return (LDI_EV_FAILURE);
if (tcookie) {
return (LDI_EV_SUCCESS);
return (LDI_EV_FAILURE);
return (LDI_EV_SUCCESS);
return (LDI_EV_FAILURE);
int ddi_event;
return (LDI_EV_FAILURE);
return (LDI_EV_FAILURE);
return (LDI_EV_FAILURE);
*id = 0;
return (LDI_EV_FAILURE);
ddi_event = 0;
return (LDI_EV_FAILURE);
!= DDI_SUCCESS) {
return (LDI_EV_FAILURE);
ldi_ev_lock();
if (!ddi_event)
return (LDI_EV_SUCCESS);
void *ev_data)
int ret;
char *lec_event;
ldi_ev_lock();
goto out;
out:
return (ret);
int retc;
int retl;
return (LDI_EV_SUCCESS);
return (LDI_EV_FAILURE);
return (LDI_EV_FAILURE);
return (LDI_EV_FAILURE);
return (LDI_EV_SUCCESS);
char *lec_event;
int found = 0;
ldi_ev_lock();
if (found)
char *evname;
if (id == 0) {
return (LDI_EV_FAILURE);
(void *)id));
ldi_ev_lock();
(void *)id);
return (LDI_EV_SUCCESS);
!= DDI_SUCCESS) {
ldi_ev_lock();
return (LDI_EV_FAILURE);
return (LDI_EV_SUCCESS);