Home | History | Annotate | Download | only in os
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"@(#)dacf.c	1.9	05/06/08 SMI"
     28 
     29 /*
     30  * DACF: device autoconfiguration support
     31  *
     32  * DACF provides a fast, lightweight policy engine for the I/O subsystem.
     33  * This policy engine provides a mechanism for auto-configuring and
     34  * auto-unconfiguring devices.
     35  *
     36  * After a device is attach(9E)ed, additional configuration may be needed in
     37  * order to make the device available for use by the system.  For example,
     38  * STREAMS modules may need to be pushed atop the driver in order to create
     39  * a STREAMS stack.  If the device is to be removed from the system, these
     40  * configuration operations need to be undone, and the device prepared for
     41  * detach(9E).
     42  *
     43  * It is desirable to move the implementation of such policies outside of the
     44  * kernel proper, since such operations are typically infrequent.  To this end,
     45  * DACF manages kernel modules in (module_path)/dacf directories.  These adhere
     46  * to the api defined in sys/dacf.h, and register sets of configuration
     47  * operations.  The kernel loads these modules when the operations they
     48  * implement are needed, and can unload them at any time thereafter.
     49  * Implementing configuration operations in external modules can also increase
     50  * code reuse.
     51  *
     52  * DACF provides a policy database which associates
     53  *
     54  *   (device descr., kernel action) --> (configuration operation, parameters)
     55  *
     56  * - Device description is matching rule, for example:
     57  * 	minor-nodetype="ddi_keyboard"
     58  * - Kernel action is a reference to a dacf kernel hook.
     59  *      currently supported are "post-attach" and "pre-detach"
     60  * - Configuration action is a reference to a module and a set of operations
     61  *      within the module, for example:  consconfig:kbd_config
     62  * - Parameters is a list of name="value" parameters to be passed to the
     63  *      configuration operation when invoked.
     64  *
     65  * The contents of the rules database are loaded from /etc/dacf.conf upon boot.
     66  *
     67  * DACF kernel hooks are comprised of a call into the rule-matching engine,
     68  * using parameters from the hook in order find a matching rule.  If one is
     69  * found, the framework can invoke the configuration operation immediately, or
     70  * defer doing so until later, by putting the rule on a 'reservation list.'
     71  */
     72 
     73 #include <sys/param.h>
     74 #include <sys/modctl.h>
     75 #include <sys/sysmacros.h>
     76 #include <sys/kmem.h>
     77 #include <sys/cmn_err.h>
     78 #include <sys/pathname.h>
     79 #include <sys/ddi_impldefs.h>
     80 #include <sys/sunddi.h>
     81 #include <sys/autoconf.h>
     82 #include <sys/modhash.h>
     83 #include <sys/dacf.h>
     84 #include <sys/dacf_impl.h>
     85 #include <sys/systm.h>
     86 #include <sys/varargs.h>
     87 #include <sys/debug.h>
     88 #include <sys/log.h>
     89 #include <sys/fs/snode.h>
     90 
     91 /*
     92  * Enumeration of the ops exported by the dacf framework.
     93  *
     94  * To add a new op to the framework, add it to this list, update dacf.h,
     95  * (don't miss DACF_NUM_OPIDS) and modify dacf_rule_matrix.
     96  *
     97  */
     98 typedef struct dacf_opmap {
     99 	const char *name;
    100 	dacf_opid_t id;
    101 } dacf_opmap_t;
    102 
    103 static dacf_opmap_t dacf_ops[] = {
    104 	{ "post-attach",	DACF_OPID_POSTATTACH		},
    105 	{ "pre-detach",		DACF_OPID_PREDETACH		},
    106 	{ NULL,			0				},
    107 };
    108 
    109 /*
    110  * Enumeration of the options exported by the dacf framework (currently none).
    111  *
    112  * To add a new option, add it to this array.
    113  */
    114 typedef struct dacf_opt {
    115 	const char *optname;
    116 	uint_t optmask;
    117 } dacf_opt_t;
    118 
    119 static dacf_opt_t dacf_options[] = {
    120 #ifdef DEBUG
    121 	{ "testopt", 		1		},
    122 	{ "testopt2", 		2		},
    123 #endif
    124 	{ NULL, 		0		},
    125 };
    126 
    127 static char kmod_name[] = "__kernel";
    128 
    129 /*
    130  * Enumeration of the device specifiers exported by the dacf framework.
    131  *
    132  * To add a new devspec to the framework, add it to this list, update dacf.h,
    133  * (don't miss DACF_NUM_DEVSPECS), modify dacf_rule_matrix, and modify
    134  * dacf_match().
    135  */
    136 typedef struct dacf_ds {
    137 	const char *name;
    138 	dacf_devspec_t id;
    139 } dacf_ds_t;
    140 
    141 static dacf_ds_t dacf_devspecs[] = {
    142 	{ "minor-nodetype", 	DACF_DS_MIN_NT 		},
    143 	{ "driver-minorname", 	DACF_DS_DRV_MNAME	},
    144 	{ "device-path",	DACF_DS_DEV_PATH	},
    145 	{ NULL,			NULL			},
    146 };
    147 
    148 mod_hash_t *posta_mntype, *posta_mname, *posta_devname;	/* post-attach */
    149 mod_hash_t *pred_mntype, *pred_mname, *pred_devname;	/* pre-detach */
    150 
    151 mod_hash_t *dacf_module_hash;
    152 mod_hash_t *dacf_info_hash;
    153 
    154 /*
    155  * This is the lookup table for the hash tables that dacf manages.  Given an
    156  * op id and devspec type, one can obtain the hash for that type of data.
    157  */
    158 mod_hash_t **dacf_rule_matrix[DACF_NUM_OPIDS][DACF_NUM_DEVSPECS] = {
    159 	{ &posta_mntype, 	&posta_mname,	&posta_devname	},
    160 	{ &pred_mntype,		&pred_mname,	&pred_devname	},
    161 };
    162 
    163 kmutex_t dacf_lock;
    164 kmutex_t dacf_module_lock;
    165 
    166 int dacfdebug = 0;
    167 
    168 static dacf_rule_t *dacf_rule_ctor(char *, char *, char *, dacf_opid_t,
    169     uint_t, dacf_arg_t *);
    170 static mod_hash_t *dacf_get_op_hash(dacf_opid_t, dacf_devspec_t);
    171 static void dacf_rule_val_dtor(mod_hash_val_t);
    172 static void dacf_destroy_opsets(dacf_module_t *module);
    173 static void dacf_opset_copy(dacf_opset_t *dst, dacf_opset_t *src);
    174 static void dprintf(const char *, ...) __KPRINTFLIKE(1);
    175 
    176 /*PRINTFLIKE1*/
    177 static void
    178 dprintf(const char *format, ...)
    179 {
    180 	va_list alist;
    181 	char dp_buf[256], *dpbp;
    182 	if (dacfdebug & DACF_DBG_MSGS) {
    183 		va_start(alist, format);
    184 		/*
    185 		 * sprintf up the string that is 'dacf debug: <the message>'
    186 		 */
    187 		(void) sprintf(dp_buf, "dacf debug: ");
    188 		dpbp = &(dp_buf[strlen(dp_buf)]);
    189 		(void) vsnprintf(dpbp, sizeof (dp_buf) - strlen(dp_buf),
    190 		    format, alist);
    191 		printf(dp_buf);
    192 		va_end(alist);
    193 	}
    194 }
    195 
    196 /*
    197  * dacf_init()
    198  * 	initialize the dacf framework by creating the various hash tables.
    199  */
    200 void
    201 dacf_init()
    202 {
    203 	int i, j;
    204 	char hbuf[40];
    205 
    206 	mutex_enter(&dacf_lock);
    207 
    208 	dprintf("dacf_init: creating hashmatrix\n");
    209 
    210 #ifdef DEBUG
    211 	/*
    212 	 * Sanity check that DACF_NUM_DEVSPECS and the devspecs are in sync
    213 	 */
    214 	for (i = 0; dacf_devspecs[i].name != NULL; i++)
    215 		continue;
    216 	ASSERT(i == DACF_NUM_DEVSPECS);
    217 
    218 	/*
    219 	 * Sanity check that DACF_NUM_OPIDS and the dacf_ops are in sync
    220 	 */
    221 	for (i = 0; dacf_ops[i].name != NULL; i++)
    222 		continue;
    223 	ASSERT(i == DACF_NUM_OPIDS);
    224 #endif
    225 
    226 	for (i = 0; i < DACF_NUM_OPIDS; i++) {
    227 		for (j = 0; j < DACF_NUM_DEVSPECS; j++) {
    228 			if (dacf_rule_matrix[i][j] == NULL) {
    229 				continue;
    230 			}
    231 			/*
    232 			 * Set up a hash table with no key destructor.  The
    233 			 * keys are carried in the rule_t, so the val_dtor
    234 			 * will take care of the key as well.
    235 			 */
    236 			(void) snprintf(hbuf, sizeof (hbuf),
    237 			    "dacf hashmatrix [%d][%d]", i, j);
    238 			*(dacf_rule_matrix[i][j]) = mod_hash_create_extended(
    239 			    hbuf,			/* hash name */
    240 			    DACF_RULE_HASHSIZE,		/* # hash elems */
    241 			    mod_hash_null_keydtor,	/* key dtor */
    242 			    dacf_rule_val_dtor,		/* value dtor */
    243 			    mod_hash_bystr, NULL, 	/* hash alg & data */
    244 			    mod_hash_strkey_cmp,	/* key comparator */
    245 			    KM_SLEEP);
    246 		}
    247 	}
    248 
    249 	dprintf("dacf_init: creating module_hash\n");
    250 	/*
    251 	 * dacf_module_hash stores the currently registered dacf modules
    252 	 * by name.
    253 	 */
    254 	dacf_module_hash = mod_hash_create_strhash("dacf module hash",
    255 	    DACF_MODULE_HASHSIZE, mod_hash_null_valdtor);
    256 
    257 	dprintf("dacf_init: creating info_hash\n");
    258 	/*
    259 	 * dacf_info_hash stores pointers to data that modules can associate
    260 	 * on a per minornode basis.  The type of data stored is opaque to the
    261 	 * framework-- thus there is no destructor supplied.
    262 	 */
    263 	dacf_info_hash = mod_hash_create_ptrhash("dacf info hash",
    264 	    DACF_INFO_HASHSIZE, mod_hash_null_valdtor,
    265 	    sizeof (struct ddi_minor_data));
    266 
    267 	mutex_exit(&dacf_lock);
    268 
    269 	/*
    270 	 * Register the '__kernel' module.
    271 	 *
    272 	 * These are operations that are provided by the kernel, not by a
    273 	 * module.  We just feed the framework a dacfsw structure; it will get
    274 	 * marked as 'loaded' by dacf_module_register(), and will always be
    275 	 * available.
    276 	 */
    277 	(void) dacf_module_register(kmod_name, &kmod_dacfsw);
    278 
    279 	(void) read_dacf_binding_file(NULL);
    280 
    281 	dprintf("dacf_init: dacf is ready\n");
    282 }
    283 
    284 /*
    285  * dacf_clear_rules()
    286  * 	clear the dacf rule database.  This is typically done in advance of
    287  * 	rereading the dacf binding file.
    288  */
    289 void
    290 dacf_clear_rules()
    291 {
    292 	int i, j;
    293 	ASSERT(MUTEX_HELD(&dacf_lock));
    294 
    295 	for (i = 0; i < DACF_NUM_OPIDS; i++) {
    296 		for (j = 0; j < DACF_NUM_DEVSPECS; j++) {
    297 			if ((dacf_rule_matrix[i][j] != NULL) &&
    298 			    (*(dacf_rule_matrix[i][j]) != NULL)) {
    299 				mod_hash_clear(*(dacf_rule_matrix[i][j]));
    300 			}
    301 		}
    302 	}
    303 }
    304 
    305 /*
    306  * dacf_rule_insert()
    307  *	Create an entry in the dacf rule database.
    308  *	If 'module' is null, the kernel is the 'module'. (see dacf_rule_ctor()).
    309  */
    310 int
    311 dacf_rule_insert(dacf_devspec_t devspec_type, char *devspec_data,
    312     char *module, char *opset, dacf_opid_t opid, uint_t opts,
    313     dacf_arg_t *op_args)
    314 {
    315 	dacf_rule_t *rule;
    316 	mod_hash_t *hash;
    317 
    318 	ASSERT(devspec_type != DACF_DS_ERROR);
    319 	ASSERT(devspec_data);
    320 	ASSERT(opset);
    321 	ASSERT(MUTEX_HELD(&dacf_lock));
    322 
    323 	dprintf("dacf_rule_insert called: %s=\"%s\", %s:%s, %s\n",
    324 	    dacf_devspec_to_str(devspec_type), devspec_data,
    325 	    module ? module : "[kernel]", opset, dacf_opid_to_str(opid));
    326 
    327 	/*
    328 	 * Fetch the hash table associated with this op-name and devspec-type.
    329 	 * Some ops may not support all devspec-types, since they may be
    330 	 * meaningless, so hash may be null.
    331 	 */
    332 	hash = dacf_get_op_hash(opid, devspec_type);
    333 	if (hash == NULL) {
    334 		cmn_err(CE_WARN, "!dacf dev-spec '%s' does not support op '%s'",
    335 		    dacf_devspec_to_str(devspec_type), dacf_opid_to_str(opid));
    336 		return (-1);
    337 	}
    338 
    339 	/*
    340 	 * Allocate a rule  and fill it in, take a hold on it.
    341 	 */
    342 	rule = dacf_rule_ctor(devspec_data, module, opset, opid, opts,
    343 	    op_args);
    344 	dacf_rule_hold(rule);
    345 
    346 	if (mod_hash_insert(hash, (mod_hash_key_t)rule->r_devspec_data,
    347 	    (mod_hash_val_t)rule) != 0) {
    348 		/*
    349 		 * We failed, so release hold.  This will cause the rule and
    350 		 * associated data to get nuked.
    351 		 */
    352 		dacf_rule_rele(rule);
    353 
    354 		cmn_err(CE_WARN, "!dacf rule %s='%s' %s:%s %s duplicates "
    355 		    "another rule, ignored", dacf_devspec_to_str(devspec_type),
    356 		    devspec_data, module, opset, dacf_opid_to_str(opid));
    357 		return (-1);
    358 	}
    359 	return (0);
    360 }
    361 
    362 /*
    363  * dacf_rule_ctor()
    364  * 	Allocate and fill out entries in a dacf_rule_t.
    365  */
    366 static dacf_rule_t *
    367 dacf_rule_ctor(char *device_spec, char *module, char *opset, dacf_opid_t opid,
    368     uint_t opts, dacf_arg_t *op_args)
    369 {
    370 	dacf_rule_t *rule;
    371 	dacf_arg_t *p;
    372 
    373 	rule = kmem_alloc(sizeof (dacf_rule_t), KM_SLEEP);
    374 
    375 	/*
    376 	 * Fill in the entries
    377 	 */
    378 	rule->r_devspec_data = kmem_alloc(strlen(device_spec) + 1, KM_SLEEP);
    379 	(void) strcpy(rule->r_devspec_data, device_spec);
    380 
    381 	/*
    382 	 * If module is 'null' we set it to __kernel, meaning that this op
    383 	 * is implemented by the kernel.
    384 	 */
    385 	if (module == NULL) {
    386 		module = kmod_name;
    387 	}
    388 
    389 	rule->r_module = kmem_alloc(strlen(module) + 1, KM_SLEEP);
    390 	(void) strcpy(rule->r_module, module);
    391 
    392 	rule->r_opset = kmem_alloc(strlen(opset) + 1, KM_SLEEP);
    393 	(void) strcpy(rule->r_opset, opset);
    394 
    395 	rule->r_refs = 0;	/* no refs yet */
    396 	rule->r_opts = opts;
    397 	rule->r_opid = opid;
    398 
    399 	rule->r_args = NULL;
    400 	p = op_args;
    401 	while (p != NULL) {
    402 		ASSERT(p->arg_name);
    403 		ASSERT(p->arg_val);
    404 		/*
    405 		 * dacf_arg_insert() should always succeed, since we're copying
    406 		 * another (already duplicate-free) list.
    407 		 */
    408 		(void) dacf_arg_insert(&rule->r_args, p->arg_name, p->arg_val);
    409 		p = p->arg_next;
    410 	}
    411 
    412 	return (rule);
    413 }
    414 
    415 /*
    416  * dacf_rule_val_dtor()
    417  * 	This is the destructor for dacf_rule_t's in the rule database.  It
    418  * 	simply does a dacf_rule_rele() on the rule.  This function will take
    419  * 	care of destroying the rule if its ref count has dropped to 0.
    420  */
    421 static void
    422 dacf_rule_val_dtor(mod_hash_val_t val)
    423 {
    424 	ASSERT((void *)val != NULL);
    425 	dacf_rule_rele((dacf_rule_t *)val);
    426 }
    427 
    428 /*
    429  * dacf_rule_destroy()
    430  * 	destroy a dacf_rule_t
    431  */
    432 void
    433 dacf_rule_destroy(dacf_rule_t *rule)
    434 {
    435 	ASSERT(rule->r_refs == 0);
    436 	/*
    437 	 * Free arguments.
    438 	 */
    439 	dacf_arglist_delete(&(rule->r_args));
    440 	kmem_free(rule->r_devspec_data, strlen(rule->r_devspec_data) + 1);
    441 	/*
    442 	 * Module may be null for a kernel-managed op-set
    443 	 */
    444 	kmem_free(rule->r_module, strlen(rule->r_module) + 1);
    445 	kmem_free(rule->r_opset, strlen(rule->r_opset) + 1);
    446 	kmem_free(rule, sizeof (dacf_rule_t));
    447 }
    448 
    449 /*
    450  * dacf_rule_hold()
    451  * 	dacf rules are ref-counted.  This function increases the reference
    452  * 	count on an rule.
    453  */
    454 void
    455 dacf_rule_hold(dacf_rule_t *rule)
    456 {
    457 	ASSERT(MUTEX_HELD(&dacf_lock));
    458 
    459 	rule->r_refs++;
    460 }
    461 
    462 /*
    463  * dacf_rule_rele()
    464  * 	drop the ref count on an rule, and destroy the rule if its
    465  * 	ref count drops to 0.
    466  */
    467 void
    468 dacf_rule_rele(dacf_rule_t *rule)
    469 {
    470 	ASSERT(MUTEX_HELD(&dacf_lock));
    471 	ASSERT(rule->r_refs > 0);
    472 
    473 	rule->r_refs--;
    474 	if (rule->r_refs == 0) {
    475 		dacf_rule_destroy(rule);
    476 	}
    477 }
    478 
    479 /*
    480  * dacf_rsrv_make()
    481  * 	add an rule to a reservation list to be processed later.
    482  */
    483 void
    484 dacf_rsrv_make(dacf_rsrvlist_t *rsrv, dacf_rule_t *rule, void *info,
    485     dacf_rsrvlist_t **list)
    486 {
    487 	dacf_infohdl_t ihdl = info;
    488 	ASSERT(MUTEX_HELD(&dacf_lock));
    489 	ASSERT(info && rule && list);
    490 
    491 	/*
    492 	 * Bump the ref count on rule, so it won't get freed as long as it's on
    493 	 * this reservation list.
    494 	 */
    495 	dacf_rule_hold(rule);
    496 
    497 	rsrv->rsrv_rule = rule;
    498 	rsrv->rsrv_ihdl = ihdl;
    499 	rsrv->rsrv_result = DDI_SUCCESS;
    500 	rsrv->rsrv_next = *list;
    501 	*list = rsrv;
    502 
    503 	dprintf("dacf: reservation made\n");
    504 }
    505 
    506 /*
    507  * dacf_clr_rsrvs()
    508  * 	clear reservation list of operations of type 'op'
    509  */
    510 void
    511 dacf_clr_rsrvs(dev_info_t *devi, dacf_opid_t op)
    512 {
    513 	dacf_process_rsrvs(&(DEVI(devi)->devi_dacf_tasks), op, DACF_PROC_RELE);
    514 }
    515 
    516 /*
    517  * dacf_process_rsrvs()
    518  * 	iterate across a locked reservation list, processing each element
    519  * 	which matches 'op' according to 'flags'.
    520  *
    521  * 	if DACF_PROC_INVOKE is specified, the elements that match 'op'
    522  * 	will have their operations invoked.  The return value from that
    523  * 	operation is placed in the rsrv_result field of the dacf_rsrvlist_t
    524  */
    525 void
    526 dacf_process_rsrvs(dacf_rsrvlist_t **list, dacf_opid_t op, int flags)
    527 {
    528 	dacf_rsrvlist_t *p, *dp;
    529 	dacf_rsrvlist_t **prevptr;
    530 
    531 	ASSERT(MUTEX_HELD(&dacf_lock));
    532 	ASSERT(list);
    533 	ASSERT(flags != 0);
    534 
    535 	if (*list == NULL)
    536 		return;
    537 
    538 	dprintf("dacf_process_rsrvs: opid = %d, flags = 0x%x\n", op, flags);
    539 
    540 	/*
    541 	 * Walk the list, finding rules whose opid's match op, and performing
    542 	 * the work described by 'flags'.
    543 	 */
    544 	prevptr = list;
    545 	for (p = *list; p != NULL; ) {
    546 
    547 		if (p->rsrv_rule->r_opid != op) {
    548 			prevptr = &(p->rsrv_next);
    549 			p = p->rsrv_next;
    550 			continue;
    551 		}
    552 
    553 		if (flags & DACF_PROC_INVOKE) {
    554 			p->rsrv_result = dacf_op_invoke(p->rsrv_rule,
    555 			    p->rsrv_ihdl, 0);
    556 		}
    557 
    558 		if (flags & DACF_PROC_RELE) {
    559 			*prevptr = p->rsrv_next;
    560 			dp = p;
    561 			p = p->rsrv_next;
    562 			dacf_rule_rele(dp->rsrv_rule);
    563 			kmem_free(dp, sizeof (dacf_rsrvlist_t));
    564 		} else {
    565 			prevptr = &(p->rsrv_next);
    566 			p = p->rsrv_next;
    567 		}
    568 	}
    569 }
    570 
    571 /*
    572  * dacf_get_op_hash()
    573  * 	Given an op name, (i.e. "post-attach" or "pre-detach") and a
    574  * 	devspec-type, return the hash that represents that op indexed
    575  * 	by that devspec.
    576  */
    577 static mod_hash_t *
    578 dacf_get_op_hash(dacf_opid_t op, dacf_devspec_t ds_type)
    579 {
    580 	ASSERT(op <= DACF_NUM_OPIDS && op > 0);
    581 	ASSERT(ds_type <= DACF_NUM_DEVSPECS && ds_type > 0);
    582 
    583 	/*
    584 	 * dacf_rule_matrix is an array of pointers to pointers to hashes.
    585 	 */
    586 	if (dacf_rule_matrix[op - 1][ds_type - 1] == NULL) {
    587 		return (NULL);
    588 	}
    589 	return (*(dacf_rule_matrix[op - 1][ds_type - 1]));
    590 }
    591 
    592 /*
    593  * dacf_arg_insert()
    594  * 	Create and insert an entry in an argument list.
    595  * 	Returns -1 if the argument name is a duplicate of another already
    596  * 	present in the hash.
    597  */
    598 int
    599 dacf_arg_insert(dacf_arg_t **list, char *name, char *val)
    600 {
    601 	dacf_arg_t *arg;
    602 
    603 	/*
    604 	 * Don't allow duplicates.
    605 	 */
    606 	for (arg = *list; arg != NULL; arg = arg->arg_next) {
    607 		if (strcmp(arg->arg_name, name) == 0) {
    608 			return (-1);
    609 		}
    610 	}
    611 
    612 	arg = kmem_alloc(sizeof (dacf_arg_t), KM_SLEEP);
    613 	arg->arg_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
    614 	(void) strcpy(arg->arg_name, name);
    615 	arg->arg_val = kmem_alloc(strlen(val) + 1, KM_SLEEP);
    616 	(void) strcpy(arg->arg_val, val);
    617 
    618 	arg->arg_next = *list;
    619 	*list = arg;
    620 
    621 	return (0);
    622 }
    623 
    624 /*
    625  * dacf_arglist_delete()
    626  * 	free all the elements of a list of dacf_arg_t's.
    627  */
    628 void
    629 dacf_arglist_delete(dacf_arg_t **list)
    630 {
    631 	dacf_arg_t *arg, *narg;
    632 	arg = *list;
    633 	while (arg != NULL) {
    634 		narg = arg->arg_next;
    635 		kmem_free(arg->arg_name, strlen(arg->arg_name) + 1);
    636 		kmem_free(arg->arg_val, strlen(arg->arg_val) + 1);
    637 		kmem_free(arg, sizeof (dacf_arg_t));
    638 		arg = narg;
    639 	}
    640 	*list = NULL;
    641 }
    642 
    643 /*
    644  * dacf_match()
    645  * 	Match a device-spec to a rule.
    646  */
    647 dacf_rule_t *
    648 dacf_match(dacf_opid_t op, dacf_devspec_t ds, void *match_info)
    649 {
    650 	dacf_rule_t *rule;
    651 
    652 	ASSERT(MUTEX_HELD(&dacf_lock));
    653 
    654 	if (mod_hash_find(dacf_get_op_hash(op, ds), (mod_hash_key_t)match_info,
    655 	    (mod_hash_val_t *)&rule) == 0) {
    656 		return (rule);
    657 	}
    658 
    659 	return (NULL);	/* Not Found */
    660 }
    661 
    662 /*
    663  * dacf_module_register()
    664  * 	register a module with the framework.  Use when a module gets loaded,
    665  * 	or for the kernel to register a "virtual" module (i.e. a "module"
    666  * 	which the kernel provides).  Makes a copy of the interface description
    667  * 	provided by the module.
    668  */
    669 int
    670 dacf_module_register(char *mod_name, struct dacfsw *sw)
    671 {
    672 	char *str;
    673 	size_t i, nelems;
    674 	dacf_module_t *module;
    675 	dacf_opset_t *opsarray;
    676 
    677 	if (sw == NULL) {
    678 		return (EINVAL);
    679 	}
    680 
    681 	if (sw->dacf_rev != DACF_MODREV_1) {
    682 		cmn_err(CE_WARN, "dacf: module '%s' exports unsupported "
    683 		    "version %d interface, not registered\n", mod_name,
    684 		    sw->dacf_rev);
    685 		return (EINVAL);
    686 	}
    687 
    688 	/*
    689 	 * count how many opsets are provided.
    690 	 */
    691 	for (nelems = 0; sw->dacf_opsets[nelems].opset_name != NULL; nelems++)
    692 		;
    693 
    694 	dprintf("dacf_module_register: found %lu opsets\n", nelems);
    695 
    696 	/*
    697 	 * Temporary: It's ok for the kernel dacf_sw to have no opsets, since
    698 	 * we don't have any opsets to export yet (in NON-DEBUG).
    699 	 */
    700 	if ((nelems == 0) && (sw != &kmod_dacfsw)) {
    701 		cmn_err(CE_WARN, "dacf module %s exports no opsets, "
    702 		    "not registered.\n", mod_name);
    703 		return (EINVAL);
    704 	}
    705 
    706 	/*
    707 	 * Look to see if the module has been previously registered with the
    708 	 * framework.  If so, we can fail with EBUSY.
    709 	 */
    710 	if (mod_hash_find(dacf_module_hash, (mod_hash_key_t)mod_name,
    711 	    (mod_hash_val_t)&module) == 0) {
    712 		/*
    713 		 * See if it is loaded currently
    714 		 */
    715 		rw_enter(&module->dm_lock, RW_WRITER);
    716 		if (module->dm_loaded) {
    717 			rw_exit(&module->dm_lock);
    718 			cmn_err(CE_WARN, "dacf module '%s' is "
    719 			    "already registered.", mod_name);
    720 			return (EBUSY);
    721 		}
    722 	} else {
    723 		/*
    724 		 * This is the first time we've ever seen the module; stick
    725 		 * it into the module hash.  If that fails, we've had a
    726 		 * race between two threads, both trying to insert the same
    727 		 * new module.  It's safe to stick the module into the
    728 		 * hash only partly filled in, since dm_lock protects the
    729 		 * structure, and we've got that write-locked.
    730 		 */
    731 		module = kmem_zalloc(sizeof (dacf_module_t), KM_SLEEP);
    732 		str = kmem_alloc(strlen(mod_name) + 1, KM_SLEEP);
    733 		(void) strcpy(str, mod_name);
    734 		rw_enter(&module->dm_lock, RW_WRITER);
    735 
    736 		if (mod_hash_insert(dacf_module_hash, (mod_hash_key_t)str,
    737 		    (mod_hash_val_t)module) != 0) {
    738 			rw_exit(&module->dm_lock);
    739 			kmem_free(str, strlen(str) + 1);
    740 			kmem_free(module, sizeof (dacf_module_t));
    741 			cmn_err(CE_WARN, "dacf module '%s' is "
    742 			    "already registered.", mod_name);
    743 			return (EBUSY);
    744 		}
    745 	}
    746 	/*
    747 	 * In either case (first time we've seen it or not), the module is
    748 	 * not loaded, and we hold it write-locked.
    749 	 */
    750 	ASSERT(RW_WRITE_HELD(&module->dm_lock));
    751 
    752 	/*
    753 	 * Alloc array of opsets for this module.  Add one for the final
    754 	 * NULL entry
    755 	 */
    756 	opsarray = kmem_zalloc(sizeof (dacf_opset_t) * (nelems + 1), KM_SLEEP);
    757 
    758 	for (i = 0; i < nelems; i++) {
    759 		dacf_opset_copy(&(opsarray[i]), &(sw->dacf_opsets[i]));
    760 		ASSERT(opsarray[i].opset_name != NULL);
    761 		ASSERT(opsarray[i].opset_ops != NULL);
    762 	}
    763 	opsarray[nelems].opset_name = NULL;
    764 	opsarray[nelems].opset_ops = NULL;
    765 
    766 	ASSERT(module->dm_opsets == NULL);	/* see dacf_destroy_opsets() */
    767 	module->dm_opsets = opsarray;
    768 
    769 	if (dacfdebug & DACF_DBG_MSGS) {
    770 		dprintf("%s registered.\n", mod_name);
    771 		for (i = 0; i < nelems; i++) {
    772 			dprintf("registered %s\n", opsarray[i].opset_name);
    773 		}
    774 	}
    775 
    776 	module->dm_loaded = 1;
    777 	rw_exit(&module->dm_lock);
    778 
    779 	return (0);
    780 }
    781 
    782 /*
    783  * dacf_module_unregister()
    784  * 	remove a module from the framework, and free framework-allocated
    785  * 	resources.
    786  */
    787 int
    788 dacf_module_unregister(char *mod_name)
    789 {
    790 	dacf_module_t *module;
    791 
    792 	/*
    793 	 * Can't unregister __kernel, since there is no real way to get it
    794 	 * back-- Once it gets marked with dm_loaded == 0, the kernel will
    795 	 * try to modload() if it is ever needed, which will fail utterly,
    796 	 * and send op_invoke into a loop in it's modload logic
    797 	 *
    798 	 * If this is behavior is ever needed in the future, we can just
    799 	 * add a flag indicating that this module is really a fake.
    800 	 */
    801 	ASSERT(strcmp(mod_name, kmod_name) != 0);
    802 
    803 	dprintf("dacf_module_unregister: called for '%s'!\n", mod_name);
    804 
    805 	/*
    806 	 * If NOAUL_DACF is set, or we try to get a write-lock on dm_lock and
    807 	 * that fails, return EBUSY, and fail to unregister.
    808 	 */
    809 	if (mod_hash_find(dacf_module_hash, (mod_hash_key_t)mod_name,
    810 	    (mod_hash_val_t)&module) == 0) {
    811 		if ((moddebug & MODDEBUG_NOAUL_DACF) ||
    812 		    !rw_tryenter(&module->dm_lock, RW_WRITER)) {
    813 			return (EBUSY);
    814 		}
    815 	} else {
    816 		return (EINVAL);
    817 	}
    818 
    819 	ASSERT(RW_WRITE_HELD(&module->dm_lock));
    820 	dacf_destroy_opsets(module);
    821 	module->dm_loaded = 0;
    822 	rw_exit(&module->dm_lock);
    823 	return (0);
    824 }
    825 
    826 /*
    827  * dacf_destroy_opsets()
    828  * 	given a module, destroy all of it's associated op-sets.
    829  */
    830 static void
    831 dacf_destroy_opsets(dacf_module_t *module)
    832 {
    833 	dacf_opset_t *array = module->dm_opsets;
    834 	dacf_opset_t *p;
    835 	int i;
    836 	size_t nelems;
    837 
    838 	ASSERT(RW_WRITE_HELD(&module->dm_lock));
    839 	ASSERT(module->dm_loaded == 1);
    840 
    841 	for (i = 0; array[i].opset_name != NULL; i++) {
    842 		p = &(array[i]);
    843 		kmem_free(p->opset_name, strlen(p->opset_name) + 1);
    844 		/*
    845 		 * count nelems in opset_ops
    846 		 */
    847 		for (nelems = 0; ; nelems++) {
    848 			if (p->opset_ops[nelems].op_id == DACF_OPID_END) {
    849 				break;
    850 			}
    851 		}
    852 		/*
    853 		 * Free the array of op ptrs.
    854 		 */
    855 		kmem_free(p->opset_ops, sizeof (dacf_op_t) * (nelems + 1));
    856 	}
    857 
    858 	/*
    859 	 * i has counted how big array is; +1 to account for the last element.
    860 	 */
    861 	kmem_free(array, (sizeof (dacf_opset_t)) * (i + 1));
    862 	module->dm_opsets = NULL;
    863 }
    864 
    865 /*
    866  * dacf_opset_copy()
    867  * 	makes a copy of a dacf_opset_t.
    868  */
    869 static void
    870 dacf_opset_copy(dacf_opset_t *dst, dacf_opset_t *src)
    871 {
    872 	size_t nelems, i;
    873 	ASSERT(src && dst);
    874 
    875 	dprintf("dacf_opset_copy: called\n");
    876 
    877 	dst->opset_name = kmem_alloc(strlen(src->opset_name) + 1, KM_SLEEP);
    878 	(void) strcpy(dst->opset_name, src->opset_name);
    879 
    880 	dprintf("dacf_opset_copy: counting ops\n");
    881 
    882 	for (nelems = 0; ; nelems++) {
    883 		if ((src->opset_ops[nelems].op_id == DACF_OPID_END) ||
    884 		    (src->opset_ops[nelems].op_func == NULL)) {
    885 			break;
    886 		}
    887 	}
    888 
    889 	dprintf("dacf_opset_copy: found %lu ops\n", nelems);
    890 
    891 	dst->opset_ops = kmem_alloc(sizeof (dacf_op_t) * (nelems + 1),
    892 	    KM_SLEEP);
    893 
    894 	dprintf("dacf_opset_copy: copying ops\n");
    895 	for (i = 0; i < nelems; i++) {
    896 		dst->opset_ops[i].op_id = src->opset_ops[i].op_id;
    897 		dst->opset_ops[i].op_func = src->opset_ops[i].op_func;
    898 	}
    899 	dst->opset_ops[nelems].op_id = DACF_OPID_END;
    900 	dst->opset_ops[nelems].op_func = NULL;
    901 
    902 	dprintf("dacf_opset_copy: done copying ops\n");
    903 }
    904 
    905 int dacf_modload_laps = 0;	/* just a diagnostic aid */
    906 
    907 /*
    908  * dacf_op_invoke()
    909  *	Invoke a op in a opset in a module given the rule to invoke.
    910  *
    911  *	If the return value of dacf_op_invoke is 0, then rval contains the
    912  *	return value of the _op_ being invoked. Otherwise, dacf_op_invoke's
    913  *	return value indicates why the op invocation failed.
    914  */
    915 int
    916 dacf_op_invoke(dacf_rule_t *rule, dacf_infohdl_t info_hdl, int flags)
    917 {
    918 	dacf_module_t *module;
    919 	dacf_opset_t *opsarray;
    920 	dacf_opset_t *opset;
    921 	dacf_op_t *op = NULL;
    922 	dacf_opid_t op_id;
    923 	dacf_arghdl_t arg_hdl;
    924 	dev_info_t *dip;
    925 	int i, rval = -1;
    926 
    927 	ASSERT(rule);
    928 	ASSERT(MUTEX_HELD(&dacf_lock));
    929 
    930 	op_id = rule->r_opid;
    931 	dprintf("dacf_op_invoke: opid=%d\n", op_id);
    932 
    933 	/*
    934 	 * Take laps, trying to load the dacf module.  For the case of kernel-
    935 	 * provided operations, __kernel will be found in the hash table, and
    936 	 * no modload will be needed.
    937 	 */
    938 	for (;;) {
    939 		if (mod_hash_find(dacf_module_hash,
    940 		    (mod_hash_key_t)rule->r_module,
    941 		    (mod_hash_val_t *)&module) == 0) {
    942 			rw_enter(&module->dm_lock, RW_READER);
    943 			/*
    944 			 * Found the module, and it is loaded.
    945 			 */
    946 			if (module->dm_loaded != 0) {
    947 				break;
    948 			}
    949 			rw_exit(&module->dm_lock);
    950 		}
    951 
    952 		/*
    953 		 * If we're here, either: 1) it's not in the hash, or 2) it is,
    954 		 * but dm_loaded is 0, meaning the module needs to be loaded.
    955 		 */
    956 		dprintf("dacf_op_invoke: calling modload\n");
    957 		if (modload("dacf", rule->r_module) < 0) {
    958 			return (DACF_ERR_MOD_NOTFOUND);
    959 		}
    960 		dacf_modload_laps++;
    961 	}
    962 
    963 	ASSERT(RW_READ_HELD(&module->dm_lock));
    964 
    965 	opsarray = module->dm_opsets;
    966 
    967 	/*
    968 	 * Loop through the opsets exported by this module, and find the one
    969 	 * we care about.
    970 	 */
    971 	opset = NULL;
    972 	for (i = 0; opsarray[i].opset_name != NULL; i++) {
    973 		if (strcmp(opsarray[i].opset_name, rule->r_opset) == 0) {
    974 			opset = &opsarray[i];
    975 			break;
    976 		}
    977 	}
    978 
    979 	if (opset == NULL) {
    980 		cmn_err(CE_WARN, "!dacf: couldn't invoke op, opset '%s' not "
    981 		    "found in module '%s'", rule->r_opset, rule->r_module);
    982 		rw_exit(&module->dm_lock);
    983 		return (DACF_ERR_OPSET_NOTFOUND);
    984 	}
    985 
    986 	arg_hdl = (dacf_arghdl_t)rule->r_args;
    987 
    988 	/*
    989 	 * Call the appropriate routine in the target by looping across the
    990 	 * ops until we find the one whose id matches opid.
    991 	 */
    992 	op = NULL;
    993 	for (i = 0; opset->opset_ops[i].op_id != DACF_OPID_END; i++) {
    994 		if (opset->opset_ops[i].op_id == op_id) {
    995 			op = &(opset->opset_ops[i]);
    996 			break;
    997 		}
    998 	}
    999 
   1000 	if (op == NULL) {
   1001 		cmn_err(CE_WARN, "!dacf: couldn't invoke op, op '%s' not found "
   1002 		    "in opset '%s' in module '%s'", dacf_opid_to_str(op_id),
   1003 		    rule->r_opset, rule->r_module);
   1004 		rw_exit(&module->dm_lock);
   1005 		return (DACF_ERR_OP_NOTFOUND);
   1006 	}
   1007 
   1008 	dprintf("dacf_op_invoke: found op, invoking...\n");
   1009 
   1010 	/*
   1011 	 * Drop dacf_lock here, so that op_func's that cause drivers to
   1012 	 * get loaded don't wedge the system when they try to acquire dacf_lock
   1013 	 * to do matching.
   1014 	 *
   1015 	 * Mark that an invoke is happening to prevent recursive invokes
   1016 	 */
   1017 	dip = ((struct ddi_minor_data *)info_hdl)->dip;
   1018 
   1019 	mutex_enter(&(DEVI(dip)->devi_lock));
   1020 	DEVI_SET_INVOKING_DACF(dip);
   1021 	mutex_exit(&(DEVI(dip)->devi_lock));
   1022 
   1023 	mutex_exit(&dacf_lock);
   1024 
   1025 	rval = op->op_func(info_hdl, arg_hdl, flags);
   1026 
   1027 	mutex_enter(&dacf_lock);
   1028 
   1029 	/*
   1030 	 * Completed the invocation against module, so let go of it.
   1031 	 */
   1032 	mutex_enter(&(DEVI(dip)->devi_lock));
   1033 	DEVI_CLR_INVOKING_DACF(dip);
   1034 	mutex_exit(&(DEVI(dip)->devi_lock));
   1035 
   1036 	/*
   1037 	 * Drop our r-lock on the module, now that we no longer need the module
   1038 	 * to stay loaded.
   1039 	 */
   1040 	rw_exit(&module->dm_lock);
   1041 
   1042 	if (rval == DACF_SUCCESS) {
   1043 		return (DACF_SUCCESS);
   1044 	} else {
   1045 		return (DACF_ERR_OP_FAILED);
   1046 	}
   1047 }
   1048 
   1049 /*
   1050  * dacf_get_devspec()
   1051  * 	given a devspec-type as a string, return a corresponding dacf_devspec_t
   1052  */
   1053 dacf_devspec_t
   1054 dacf_get_devspec(char *name)
   1055 {
   1056 	dacf_ds_t *p = &dacf_devspecs[0];
   1057 
   1058 	while (p->name != NULL) {
   1059 		if (strcmp(p->name, name) == 0) {
   1060 			return (p->id);
   1061 		}
   1062 		p++;
   1063 	}
   1064 	return (DACF_DS_ERROR);
   1065 }
   1066 
   1067 /*
   1068  * dacf_devspec_to_str()
   1069  * 	given a dacf_devspec_t, return a pointer to the human readable string
   1070  * 	representation of that device specifier.
   1071  */
   1072 const char *
   1073 dacf_devspec_to_str(dacf_devspec_t ds)
   1074 {
   1075 	dacf_ds_t *p = &dacf_devspecs[0];
   1076 
   1077 	while (p->name != NULL) {
   1078 		if (p->id == ds) {
   1079 			return (p->name);
   1080 		}
   1081 		p++;
   1082 	}
   1083 	return (NULL);
   1084 }
   1085 
   1086 /*
   1087  * dacf_get_op()
   1088  * 	given a op name, returns the corresponding dacf_opid_t.
   1089  */
   1090 dacf_opid_t
   1091 dacf_get_op(char *name)
   1092 {
   1093 	dacf_opmap_t *p = &dacf_ops[0];
   1094 
   1095 	while (p->name != NULL) {
   1096 		if (strcmp(p->name, name) == 0) {
   1097 			return (p->id);
   1098 		}
   1099 		p++;
   1100 	}
   1101 	return (DACF_OPID_ERROR);
   1102 }
   1103 
   1104 /*
   1105  * dacf_opid_to_str()
   1106  * 	given a dacf_opid_t, return the human-readable op-name.
   1107  */
   1108 const char *
   1109 dacf_opid_to_str(dacf_opid_t tid)
   1110 {
   1111 	dacf_opmap_t *p = &dacf_ops[0];
   1112 
   1113 	while (p->name != NULL) {
   1114 		if (p->id == tid) {
   1115 			return (p->name);
   1116 		}
   1117 		p++;
   1118 	}
   1119 	return (NULL);
   1120 }
   1121 
   1122 /*
   1123  * dacf_getopt()
   1124  * 	given an option specified as a string, add it to the bit-field of
   1125  * 	options given.  Returns -1 if the option is unrecognized.
   1126  */
   1127 int
   1128 dacf_getopt(char *opt_str, uint_t *opts)
   1129 {
   1130 	dacf_opt_t *p = &dacf_options[0];
   1131 
   1132 	/*
   1133 	 * Look through the list for the option given
   1134 	 */
   1135 	while (p->optname != NULL) {
   1136 		if (strcmp(opt_str, p->optname) == 0) {
   1137 			*opts |= p->optmask;
   1138 			return (0);
   1139 		}
   1140 		p++;
   1141 	}
   1142 	return (-1);
   1143 }
   1144 
   1145 
   1146 
   1147 /*
   1148  * This family of functions forms the dacf interface which is exported to
   1149  * kernel/dacf modules.  Modules _should_not_ use any dacf_* functions
   1150  * presented above this point.
   1151  *
   1152  * Note: These routines use a dacf_infohdl_t to struct ddi_minor_data * and
   1153  * assume that the resulting pointer is not to an alias node.  That is true
   1154  * because dacf_op_invoke guarantees it by first resolving the alias.
   1155  */
   1156 
   1157 /*
   1158  * dacf_minor_name()
   1159  * 	given a dacf_infohdl_t, obtain the minor name of the device instance
   1160  * 	being configured.
   1161  */
   1162 const char *
   1163 dacf_minor_name(dacf_infohdl_t info_hdl)
   1164 {
   1165 	struct ddi_minor_data *dmdp = (struct ddi_minor_data *)info_hdl;
   1166 
   1167 	return (dmdp->ddm_name);
   1168 }
   1169 
   1170 /*
   1171  * dacf_minor_number()
   1172  * 	given a dacf_infohdl_t, obtain the device minor number of the instance
   1173  * 	being configured.
   1174  */
   1175 minor_t
   1176 dacf_minor_number(dacf_infohdl_t info_hdl)
   1177 {
   1178 	struct ddi_minor_data *dmdp = (struct ddi_minor_data *)info_hdl;
   1179 
   1180 	return (getminor(dmdp->ddm_dev));
   1181 }
   1182 
   1183 /*
   1184  * dacf_driver_name()
   1185  * 	given a dacf_infohdl_t, obtain the device driver name of the device
   1186  * 	instance being configured.
   1187  */
   1188 const char *
   1189 dacf_driver_name(dacf_infohdl_t info_hdl)
   1190 {
   1191 	struct ddi_minor_data *dmdp = (struct ddi_minor_data *)info_hdl;
   1192 
   1193 	return (ddi_driver_name(dmdp->dip));
   1194 }
   1195 
   1196 /*
   1197  * dacf_devinfo_node()
   1198  * 	given a dacf_infohdl_t, obtain the dev_info_t of the device instance
   1199  * 	being configured.
   1200  */
   1201 dev_info_t *
   1202 dacf_devinfo_node(dacf_infohdl_t info_hdl)
   1203 {
   1204 	struct ddi_minor_data *dmdp = (struct ddi_minor_data *)info_hdl;
   1205 
   1206 	return<