fc_subr.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* 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 (c) 2000-2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Kernel framework functions for the fcode interpreter
*/
#ifdef DEBUG
int fcode_debug = 0;
#else
int fcode_debug = 0;
#endif
static kmutex_t fc_request_lock;
static kmutex_t fc_resource_lock;
static kmutex_t fc_hash_lock;
static kmutex_t fc_device_tree_lock;
static kmutex_t fc_phandle_lock;
static kcondvar_t fc_request_cv;
static struct fc_request *fc_request_head;
static int fc_initialized;
static void fcode_timer(void *);
int fcodem_unloadable;
extern int hz;
/*
* Initialize the fcode interpreter framework ... must be called
* prior to activating any of the fcode interpreter framework including
* the driver.
*/
static void
fcode_init(void)
{
if (fc_initialized)
return;
}
static void
fcode_fini(void)
{
fc_initialized = 0;
}
/*
* Module linkage information for the kernel.
*/
&mod_miscops, "FCode framework 1.13"
};
static struct modlinkage modlinkage = {
};
int
_init(void)
{
int error;
fcode_init();
fcode_fini();
return (error);
}
int
_fini(void)
{
if (fcodem_unloadable)
fcode_fini();
return (error);
}
int
{
}
/*
* Framework function to invoke the interpreter. Wait and return when the
* interpreter is done. See fcode.h for details.
*/
int
{
int error;
/*
* Create a request structure
*/
/*
* Add the request to the end of the request list.
*/
if (fc_request_head == NULL)
else {
/* empty */;
}
/*
* log a message (ie: i_ddi_log_event) indicating that a request
* has been queued to start the userland fcode interpreter.
* This call is the glue to the eventd and automates the process.
*/
/*
* Signal the driver if it's waiting for a request to be queued.
*/
/*
* Wait for the request to be serviced
*/
}
/*
* Remove the request from the queue (while still holding the lock)
*/
if (fc_request_head == fp)
else {
/* empty */;
}
fp);
/*
* Free the request structure and return any errors.
*/
return (error);
}
/*
* Timeout requests thet don't get picked up by the interpreter. This
* would happen if the daemon is not running. If the timer goes off
* and it's state is not FC_R_INIT, then the interpreter has picked up the
* request.
*/
static void
fcode_timer(void *arg)
{
"interpreter - Interpreter did not pick up request\n");
return;
} else {
"interpreter - Interpreter is executing request\n");
}
}
/*
* This is the function the driver calls to wait for and get
* a request. The call should be interruptable since it's done
* at read(2) time, so allow for signals to interrupt us.
*
* Return NULL if the wait was interrupted, else return a pointer
* to the fc_request structure (marked as busy).
*
* Note that we have to check for a request first, before waiting,
* in case the request is already queued. In this case, the signal
* may have already been delivered.
*/
struct fc_request *
fc_get_request(void)
{
struct fc_request *fp;
/*CONSTANTCONDITION*/
while (1) {
return (fp);
}
}
return (NULL);
}
}
/*NOTREACHED*/
}
/*
* This is the function the driver calls when it's finished with
* a request. Mark the request as done and signal the thread that
* enqueued the request.
*/
void
{
}
/*
* Generic resource list management subroutines
*/
void
{
}
void
{
struct fc_resource *fp;
return;
}
return;
}
/* empty */;
return;
}
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
}
/*
* Common helper ops and subroutines
*/
/*ARGSUSED*/
int
{
return (0);
}
/*ARGSUSED*/
int
{
return (0);
}
/*ARGSUSED*/
int
{
return (0);
}
/*
* fc_fail_op: This 'handles' a request by specifically failing it,
* as opposed to not handling it and returning '-1' to indicate
* 'service unknown' and allowing somebody else in the chain to
* handle it.
*/
/*ARGSUSED*/
int
{
return (0);
}
/*
* Functions to manage the set of handles we give to the interpreter.
* The handles are opaque and internally represent dev_info_t pointers.
*/
struct fc_phandle_entry **
{
while (rp->next_handle)
}
/*ARGSUSED*/
void
{
}
void
{
/*
* Free each entry in the table.
*/
}
}
{
struct fc_phandle_entry *ip;
break;
}
{
fc_phandle_t h;
/*
* Just in case, allocate a new entry ...
*/
/*
* If we already have this dip in the table, just return the handle
*/
return (h);
}
}
/*
* Insert this entry to the list of known entries
*/
np->h = h;
return (h);
}
/*
* We won't need this function once the ddi is modified to handle
* unique non-prom nodeids. For now, this allows us to add a given
* nodeid to the device tree without dereferencing the value in the
* devinfo node, so we have a parallel mechanism.
*/
void
fc_phandle_t h)
{
/*
* Just in case, allocate a new entry ...
*/
/*
* If we already have this dip in the table, just return the handle
*/
return;
}
}
/*
* Insert this entry to the list of known entries
*/
np->h = h;
}
/*
* Functions to manage our copy of our subtree.
*
* The head of the device tree is always stored in the last 'handle'
* in the handle chain.
*/
struct fc_device_tree **
{
while (rp->next_handle)
}
struct fc_device_tree *
{
return (*head);
}
/*
* The root of the subtree is the attachment point ...
* Thus, there is never an empty device tree.
*/
void
{
struct fc_device_tree *dp;
}
#ifdef notdef
static void
{
struct fc_device_tree *np;
}
/*
* Remove each peer node, working our way backwards from the
* last peer node to the first peer node.
*/
/* empty */;
}
}
}
void
{
}
#endif /* notdef */
void
{
struct fc_device_tree *dp;
}
struct fc_device_tree *
{
struct fc_device_tree *p;
while (hp) {
return (hp);
return (p);
}
return (NULL);
}
void
{
struct fc_device_tree *p, *q;
#ifdef DEBUG
/* XXX: Revisit ASSERT vs PANIC */
#endif
p->child = q;
}
void
{
struct fc_device_tree *p, *c, *n;
/*
* Find the child within the parent's subtree ...
*/
c = fc_find_node(child, p);
/*
* If it's the first child, remove it, otherwise
* remove it from the child's peer list.
*/
if (p->child == c) {
} else {
int found = 0;
if (n->peer == c) {
found = 1;
break;
}
}
if (!found)
}
kmem_free(c, sizeof (struct fc_device_tree));
}
{
struct fc_device_tree *p;
if (p && p->child)
return (dip);
}
{
struct fc_device_tree *p;
if (p && p->peer)
return (dip);
}