/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/sysmacros.h>
#include <ipp/ipp_impl.h>
/*
* Debug switch.
*/
#if defined(DEBUG)
#define IPP_DBG
#endif
/*
* Globals
*/
/*
* ipp_action_count is not static because it is imported by inet/ipp_common.h
*/
/*
* Prototypes
*/
void ipp_init(void);
int ipp_list_mods(ipp_mod_id_t **, int *);
ipp_mod_id_t ipp_mod_lookup(const char *);
int ipp_mod_name(ipp_mod_id_t, char **);
int ipp_mod_register(const char *, ipp_ops_t *);
int *);
ipp_action_id_t ipp_action_lookup(const char *);
int ipp_action_name(ipp_action_id_t, char **);
int ipp_action_create(ipp_mod_id_t, const char *,
void *), void *, ipp_flags_t);
void ipp_action_set_ptr(ipp_action_id_t, void *);
void *ipp_action_get_ptr(ipp_action_id_t);
int ipp_packet_alloc(ipp_packet_t **, const char *,
void ipp_packet_free(ipp_packet_t *);
int ipp_packet_add_class(ipp_packet_t *, const char *,
int ipp_packet_process(ipp_packet_t **);
void ipp_packet_set_private(ipp_packet_t *, void *,
void (*)(void *));
void *ipp_packet_get_private(ipp_packet_t *);
int ipp_stat_create(ipp_action_id_t, const char *, int,
int (*)(ipp_stat_t *, void *, int), void *, ipp_stat_t **);
void ipp_stat_install(ipp_stat_t *);
void ipp_stat_destroy(ipp_stat_t *);
ipp_named_t *);
int ipp_stat_named_op(ipp_named_t *, void *, int);
static int is_mod_busy(ipp_mod_t *);
static ipp_mod_id_t find_mod(const char *);
static int alloc_mod(const char *, ipp_mod_id_t *);
static ipp_mod_id_t get_mid(void);
static int is_action_refd(ipp_action_t *);
static ipp_action_id_t find_action(const char *);
static int alloc_action(const char *, ipp_action_id_t *);
static void free_action(ipp_action_t *);
static void rele_action(ipp_action_t *);
static ipp_action_id_t get_aid(void);
static int alloc_packet(const char *, ipp_action_id_t,
ipp_packet_t **);
static int realloc_packet(ipp_packet_t *);
static void free_packet(ipp_packet_t *);
static int hash(const char *);
static int update_stats(kstat_t *, int);
static void init_mods(void);
static void init_actions(void);
static void init_packets(void);
static int mod_constructor(void *, void *, int);
static void mod_destructor(void *, void *);
static int action_constructor(void *, void *, int);
static void action_destructor(void *, void *);
static int packet_constructor(void *, void *, int);
static void packet_destructor(void *, void *);
/*
* Debug message macros
*/
#ifdef IPP_DBG
/*
* DBG_PACKET |
* DBG_STATS |
* DBG_LIST |
* DBG_MOD |
* DBG_ACTION |
*/
0;
/*PRINTFLIKE3*/
__KPRINTFLIKE(3);
(_a3));
#else /* IPP_DBG */
#endif /* IPP_DBG */
/*
* Lock macros
*/
/*
* Exported functions
*/
void
void)
{
#ifdef IPP_DBG
(void *)ipltospl(LOCK_LEVEL));
#endif /* IPP_DBG */
/*
* Initialize module and action structure caches and associated locks.
*/
init_mods();
init_actions();
init_packets();
}
int
ipp_mod_id_t **bufp,
int *neltp)
{
}
/*
* Module manipulation interface.
*/
const char *modname)
{
#define FIRST_TIME 0
/*
* Sanity check the module name.
*/
return (IPP_MOD_INVAL);
/*
* Module not installed.
*/
if (try++ == FIRST_TIME) {
/*
* This is the first attempt to find the module so
* try to 'demand load' it.
*/
goto try_again;
}
}
return (mid);
}
int
char **modnamep)
{
char *modname;
char *buf;
/*
* Translate the module id into the module pointer.
*/
return (ENOENT);
/*
* Allocate a buffer to pass back to the caller.
*/
return (ENOMEM);
}
/*
* Copy the module name into the buffer.
*/
return (0);
}
int
const char *modname,
{
int rc;
/*
* Sanity check the module name.
*/
return (EINVAL);
/*
* Allocate a module structure.
*/
return (rc);
/*
* Make module available for use.
*/
return (0);
}
int
{
/*
* Translate the module id into the module pointer.
*/
return (ENOENT);
/*
* Check to see if there are any actions that reference the module.
*/
if (is_mod_busy(imp)) {
return (EBUSY);
}
/*
* Prevent further use of the module.
*/
/*
* Free the module structure.
*/
return (0);
}
int
int *neltp)
{
int rc;
/*
* Translate the module id into the module pointer.
*/
return (ENOENT);
/*
* Get the list of actions referencing the module.
*/
return (rc);
}
/*
* Action manipulation interface.
*/
const char *aname)
{
return (IPP_ACTION_INVAL);
/*
* Check for special case 'virtual action' names.
*/
return (IPP_ACTION_CONT);
return (IPP_ACTION_DEFER);
return (IPP_ACTION_DROP);
/*
* Now check real actions.
*/
return (find_action(aname));
}
int
char **anamep)
{
char *aname;
char *buf;
int rc;
/*
* Check for special case 'virtual action' ids.
*/
switch (aid) {
case IPP_ACTION_CONT:
break;
case IPP_ACTION_DEFER:
break;
case IPP_ACTION_DROP:
break;
default:
/*
* Not a special case. Check for a real action.
*/
return (ENOENT);
break;
}
/*
* Allocate a buffer to pass back to the caller.
*/
goto done;
}
/*
* Copy the action name into the buffer.
*/
rc = 0;
done:
/*
* Unlock the action if necessary (i.e. it wasn't a virtual action).
*/
}
return (rc);
}
int
{
/*
* Return an error for 'virtual action' ids.
*/
switch (aid) {
case IPP_ACTION_CONT:
/*FALLTHRU*/
case IPP_ACTION_DEFER:
/*FALLTHRU*/
case IPP_ACTION_DROP:
return (EINVAL);
default:
break;
}
/*
* This is a real action.
*/
return (ENOENT);
/*
* Check that the action is not in prototype state.
*/
return (ENOENT);
}
return (0);
}
int
const char *aname,
{
int rc;
/*
* Sanity check the action name (NULL means the framework chooses the
* name).
*/
return (EINVAL);
/*
* Translate the module id into the module pointer.
*/
return (ENOENT);
/*
* Allocate an action.
*/
return (rc);
}
/*
* Note that the action is in the process of creation/destruction.
*/
/*
* Reference the module for which the action is being created.
*/
return (rc);
}
/*
* Call into the module to create the action context.
*/
return (rc);
}
/*
* Make the action available for use.
*/
return (0);
}
int
{
int rc;
/*
* Translate the action id into the action pointer.
*/
return (ENOENT);
/*
* Set the condemned action list pointer and destroy the action.
*/
/*
* Destroy any other actions condemned by the destruction of
* the first action.
*/
}
} else {
/*
* Unreference any condemned actions since the destruction of
* the first action failed.
*/
}
}
/*
* Clean up the condemned list.
*/
}
return (rc);
}
int
{
int rc;
/*
* Translate the action id into the action pointer.
*/
return (ENOENT);
/*
* Check that the action is either available for use or is in the
* process of creation/destruction.
*
* NOTE: It is up to the module to lock multiple configuration
* operations against each other if necessary.
*/
return (EPROTO);
}
/*
* Call into the module to modify the action context.
*/
return (rc);
}
int
void *arg,
{
int rc;
/*
* Translate the action id into the action pointer.
*/
return (ENOENT);
/*
* Check that the action is available for use. We don't want to
* read back parameters while the action is in the process of
*/
return (EPROTO);
}
/*
* Call into the module to get the action configuration information.
*/
"getting configuration information from action '%s'\n",
return (rc);
}
return (0);
}
void
void *ptr)
{
/*
* Translate the action id into the action pointer.
*/
/*
* Set the private data pointer.
*/
}
void *
{
void *ptr;
/*
* Translate the action id into the action pointer.
*/
/*
* Return the private data pointer.
*/
return (ptr);
}
/*ARGSUSED*/
int
{
int rc;
/*
* Actions are not allowed to reference themselves.
*/
return (EINVAL);
/*
* Check for a special case 'virtual action' id.
*/
switch (ref_aid) {
case IPP_ACTION_CONT:
/*FALLTHRU*/
case IPP_ACTION_DEFER:
/*FALLTHRU*/
case IPP_ACTION_DROP:
return (0);
default:
break;
}
/*
* Translate the action ids into action pointers.
*/
return (ENOENT);
return (ENOENT);
}
return (EPROTO);
}
/*
* Create references between the two actions.
*/
return (rc);
}
int
{
int ref_is_busy;
int rc;
return (EINVAL);
/*
* Check for a special case 'virtual action' id.
*/
switch (ref_aid) {
case IPP_ACTION_CONT:
/*FALLTHRU*/
case IPP_ACTION_DEFER:
/*FALLTHRU*/
case IPP_ACTION_DROP:
return (0);
default:
break;
}
/*
* Translate the action ids into action pointers.
*/
return (ENOENT);
return (ENOENT);
}
/*
* Remove the reference between the actions.
*/
return (rc);
}
if (flags & IPP_DESTROY_REF) {
if (!ref_is_busy) {
/*
* Condemn the action so that it will be destroyed.
*/
return (0);
}
}
return (0);
}
/*
* Packet manipulation interface.
*/
int
ipp_packet_t **ppp,
const char *name,
{
int rc;
/*
* A name is required.
*/
return (EINVAL);
/*
* Allocate a packet structure from the cache.
*/
return (rc);
/*
* Logging is turned on but there's no log buffer. We need
* to allocate one.
*/
ipp_packet_log_entries * sizeof (ipp_log_t),
KM_NOSLEEP)) != NULL) {
pp->ippp_log_windex = 0;
}
/*
* A log buffer is present but logging has been turned off.
* Free the buffer now,
*/
pp->ippp_log_limit = 0;
pp->ippp_log_windex = 0;
}
return (0);
}
void
{
/*
* If there is a private structure pointer set, call its free
* function.
*/
if (pp->ippp_private) {
}
/*
* Free the packet structure back to the cache.
*/
}
int
const char *name,
{
int rc;
/*
* A name is required.
*/
return (EINVAL);
/*
* Check if there is an available class structure.
*/
/*
* No more structures. Re-allocate the array.
*/
return (rc);
}
/*
* Set up a new class structure.
*/
return (0);
}
int
ipp_packet_t **ppp)
{
int rc;
/*
* Walk the class list.
*/
/*
* While there is a real action to invoke...
*/
while (aid != IPP_ACTION_CONT &&
aid != IPP_ACTION_DEFER &&
aid != IPP_ACTION_DROP) {
/*
* Translate the action id to the action pointer.
*/
"action id '%d' not found\n", aid);
return (ENOENT);
}
/*
* Check that the action is available for use...
*/
return (EPROTO);
}
/*
* Increment the action's packet count to note that
* it's being used.
*
* NOTE: We only have a read lock, so we need to use
* atomic_add_32(). The read lock is still
* important though as it is crucial to block
* out a destroy operation between the action
* state being checked and the packet count
* being incremented.
*/
/*
* If there's a log, grab the next entry and fill it
* in.
*/
} else {
}
/*
* Invoke the action.
*/
/*
* Also log the time that the action finished
* processing.
*/
/*
* Decrement the packet count.
*/
/*
* If the class' action id is the same now as it was
* before then clearly no 'next action' has been set.
* This is a protocol error.
*/
"action '%s' did not set next action\n",
return (EPROTO);
}
/*
* The action did not complete successfully. Terminate
* packet processing.
*/
if (rc != 0) {
"action error '%d' from action '%s'\n",
return (rc);
}
/*
* Look at the next action.
*/
}
/*
* No more real actions to invoke, check for 'virtual' ones.
*/
/*
* Packet deferred: module has held onto packet for processing
* later.
*/
return (0);
}
/*
* Packet dropped: free the packet and discontinue processing.
*/
return (0);
}
/*
* Must be 'continue processing': move onto the next class.
*/
pp->ippp_class_rindex++;
}
return (0);
}
int
{
/*
* Check for a special case 'virtual action' id.
*/
switch (aid) {
case IPP_ACTION_INVAL:
return (EINVAL);
case IPP_ACTION_DEFER:
/*FALLTHRU*/
case IPP_ACTION_CONT:
/*FALLTHRU*/
case IPP_ACTION_DROP:
break;
default:
/*
* Not a virtual action so try to translate the action id
* into the action pointer to confirm the actions existence.
*/
return (ENOENT);
}
break;
}
/*
* Set the class' new action id.
*/
return (0);
}
void
{
}
mblk_t *
{
}
void
void *buf,
void (*free_func)(void *))
{
}
void *
{
return (pp->ippp_private);
}
/*
* Statistics interface.
*/
int
const char *name,
int nstat,
int (*update)(ipp_stat_t *, void *, int),
void *arg,
ipp_stat_t **spp)
{
char *class;
char *modname;
int instance;
/*
* Sanity check the arguments.
*/
return (EINVAL);
/*
* Translate the action id into the action pointer.
*/
return (ENOENT);
/*
* Grab relevant action and module information.
*/
/*
* Allocate a stats info structure.
*/
return (ENOMEM);
/*
* Create a set of kstats.
*/
return (EINVAL); /* Assume EINVAL was the cause */
}
/*
* Set up the kstats structure with a private data pointer and an
* 'update' function.
*/
/*
* Keep a reference to the kstats structure in our own stats info
* structure.
*/
/*
* Fill in the rest of the stats info structure.
*/
sip->ippsi_count = 0;
(void *)ipltospl(LOCK_LEVEL));
/*
* Case the stats info structure to a semi-opaque structure that
* we pass back to the caller.
*/
return (0);
}
void
ipp_stat_t *sp)
{
/*
* Install the set of kstats referenced by the stats info structure.
*/
}
void
ipp_stat_t *sp)
{
/*
* Destroy the set of kstats referenced by the stats info structure.
*/
/*
* Destroy the stats info structure itself.
*/
}
int
ipp_stat_t *sp,
const char *name,
{
return (EINVAL);
if ((type & IPP_STAT_TAG) == 0)
return (EINVAL);
/*
* Check we will not exceed the maximum number of a stats that was
* indicated during set creation.
*/
return (ENOSPC);
}
/*
* Bump the count.
*/
sip->ippsi_count++;
/*
* Create a new named kstat.
*/
return (0);
}
int
void *valp,
int rw)
{
int rc = 0;
/*
* Copy data to or from the named kstat, depending on the specified
* opcode.
*/
switch (rw) {
case IPP_STAT_WRITE:
switch (type) {
case IPP_STAT_INT32:
break;
case IPP_STAT_UINT32:
break;
case IPP_STAT_INT64:
break;
case IPP_STAT_UINT64:
break;
case IPP_STAT_STRING:
break;
default:
ASSERT(0); /* should not reach here */
break;
}
break;
case IPP_STAT_READ:
switch (type) {
case IPP_STAT_INT32:
break;
case IPP_STAT_UINT32:
break;
case IPP_STAT_INT64:
break;
case IPP_STAT_UINT64:
break;
case IPP_STAT_STRING:
break;
default:
ASSERT(0); /* should not reach here */
break;
}
break;
default:
}
return (rc);
}
/*
* Local functions (for local people. There's nothing for you here!)
*/
static int
{
/*
* Add the new reference at the end of the module's list.
*/
}
/*
* Allocate a reference structure.
*/
return (ENOMEM);
/*
* Set the reference to the action and link it onto the module's list.
*/
/*
* Keep a 'back pointer' from the action structure to the module
* structure.
*/
return (0);
}
static void
{
/*
* Scan the module's list for the reference to the action.
*/
break;
}
/*
* Unlink the reference structure and free it.
*/
/*
* NULL the 'back pointer'.
*/
}
static int
{
/*
* Return a value which is true (non-zero) iff the module refers
* to no actions.
*/
}
static int
int *neltp)
{
int nelt;
int length;
/*
* Count the number of actions referred to from the module structure.
*/
nelt = 0;
nelt++;
}
/*
* If there are no actions referred to then there's nothing to do.
*/
if (nelt == 0) {
*neltp = 0;
return (0);
}
/*
* Allocate a buffer to pass back to the caller.
*/
return (ENOMEM);
/*
* Fill the buffer with an array of action ids.
*/
}
return (0);
}
static int
ipp_mod_id_t **bufp,
int *neltp)
{
int length;
/*
* If there are no modules registered then there's nothing to do.
*/
if (ipp_mod_count == 0) {
*neltp = 0;
return (0);
}
/*
* Allocate a buffer to pass back to the caller.
*/
return (ENOMEM);
}
/*
* Search the array of all modules.
*/
*neltp = ipp_mod_count;
continue;
/*
* If the module has 'destruct pending' set then it means it
* is either still in the cache (i.e not allocated) or in the
* process of being set up by alloc_mod().
*/
if (imp->ippm_destruct_pending) {
continue;
}
}
return (0);
}
static ipp_mod_id_t
const char *modname)
{
int hb;
/*
* Quick return if no modules are registered.
*/
if (ipp_mod_count == 0) {
return (IPP_MOD_INVAL);
}
/*
* Find the hash bucket where the module structure should be.
*/
/*
* Scan the bucket for a match.
*/
break;
}
return (IPP_MOD_INVAL);
}
return (IPP_MOD_INVAL);
}
return (mid);
}
static int
const char *modname,
{
int hb;
/*
* Find the right hash bucket for a module of the given name.
*/
/*
* Scan the bucket making sure the module isn't already
* registered.
*/
return (EEXIST);
}
}
/*
* Allocate a new reference structure and a new module structure.
*/
return (ENOMEM);
}
return (ENOMEM);
}
/*
* Set up the name of the new structure.
*/
/*
* Make sure the 'destruct pending' flag is clear. This indicates
* that the structure is no longer part of the cache.
*/
/*
* Set the reference and link it into the hash bucket.
*/
/*
* Increment the module count.
*/
return (0);
}
static void
{
int hb;
/*
* Find the hash bucket where the module structure should be.
*/
/*
* Scan the bucket for a match.
*/
break;
}
/*
* Unlink the reference structure and free it.
*/
/*
* Decrement the module count.
*/
/*
* Empty the name.
*/
/*
* If the hold count is zero then we can free the structure
* immediately, otherwise we defer to rele_mod().
*/
if (imp->ippm_hold_count == 0) {
return;
}
}
static ipp_mod_t *
{
if (mid < 0)
return (NULL);
/*
* Use the module id as an index into the array of all module
* structures.
*/
return (NULL);
}
/*
* If the modul has 'destruct pending' set then it means it is either
* still in the cache (i.e not allocated) or in the process of
* being set up by alloc_mod().
*/
if (imp->ippm_destruct_pending) {
return (NULL);
}
/*
* Increment the hold count to prevent the structure from being
* freed.
*/
return (imp);
}
static void
{
/*
* This call means we're done with the pointer so we can drop the
* hold count.
*/
/*
* If the structure has 'destruct pending' set then we tried to free
* it but couldn't, so do it now.
*/
return;
}
}
static ipp_mod_id_t
void)
{
int index;
int start;
int limit;
/*
* Start searching after the last module id we allocated.
*/
start = (int)ipp_next_mid;
limit = (int)ipp_mid_limit;
/*
* Look for a spare slot in the array.
*/
index++;
return (IPP_MOD_INVAL);
}
/*
* Note that we've just allocated a new module id so that we can
* start our search there next time.
*/
index++;
} else
return ((ipp_mod_id_t)(--index));
}
static int
{
/*
* Check to see if the action is already condemned.
*/
break;
}
/*
* Create a new entry for the action.
*/
return (ENOMEM);
}
return (0);
}
static int
{
int rc;
/*
* Check that the action is available.
*/
return (EPROTO);
}
/*
* Note that the action is in the process of creation/destruction.
*/
/*
* Wait for the in-transit packet count for this action to fall to
* zero (checking at millisecond intervals).
*
* NOTE: no new packets will enter the action now that the
* state has been changed.
*/
wait += 1000) {
/*
* NOTE: We can hang onto the lock because the packet count is
* decremented without needing to take the lock.
*/
drv_usecwait(1000);
}
/*
* The packet count did not fall to zero.
*/
if (ap->ippa_packets > 0) {
return (EAGAIN);
}
/*
* Check to see if any other action has a dependency on this one.
*/
if (is_action_refd(ap)) {
return (EBUSY);
}
/*
* Call into the module to destroy the action context.
*/
return (rc);
}
/*
* Free the action structure.
*/
return (0);
}
static int
{
/*
* We want to add the new reference at the end of the refering
* action's list.
*/
break;
}
/*
* There is an existing reference so increment its counter.
*/
rp->ippr_count++;
/*
* Find the 'back pointer' and increment its counter too.
*/
break;
}
rp->ippr_count++;
} else {
/*
* Allocate, fill in and link a new reference structure.
*/
return (ENOMEM);
/*
* We keep a 'back pointer' which we want to add at the end of
* a list in the referred action's structure.
*/
}
/*
* Allocate another reference structure and, if this fails,
* remember to clean up the first reference structure we
* allocated.
*/
KM_NOSLEEP)) == NULL) {
return (ENOMEM);
}
/*
* Fill in the reference structure with the 'back pointer' and
* link it into the list.
*/
}
return (0);
}
static int
{
/*
* Scan for the reference in the referring action's list.
*/
break;
}
return (ENOENT);
/*
* There are currently multiple references so decrement the
* count.
*/
rp->ippr_count--;
/*
* Find the 'back pointer' and decrement its counter too.
*/
break;
}
rp->ippr_count--;
} else {
/*
* There is currently only a single reference, so unlink and
* free the reference structure.
*/
/*
* Scan for the 'back pointer' in the referred action's list.
*/
break;
}
/*
* Unlink and free this reference structure too.
*/
}
return (0);
}
static int
{
/*
* Return a value which is true (non-zero) iff the action is not
* referred to by any other actions.
*/
}
static ipp_action_id_t
const char *aname)
{
int hb;
/*
* Quick return if there are no actions defined at all.
*/
if (ipp_action_count == 0) {
return (IPP_ACTION_INVAL);
}
/*
* Find the hash bucket where the action structure should be.
*/
/*
* Scan the bucket looking for a match.
*/
break;
}
return (IPP_ACTION_INVAL);
}
return (IPP_ACTION_INVAL);
}
return (aid);
}
static int
const char *aname,
{
int hb;
/*
* Find the right hash bucket for an action of the given name.
* (Nameless actions always go in a special bucket).
*/
} else
rpp = &ipp_action_noname;
/*
* Scan the bucket to make sure that an action with the given name
* does not already exist.
*/
aname);
return (EEXIST);
}
}
/*
* Allocate a new reference structure and a new action structure.
*/
return (ENOMEM);
}
return (ENOMEM);
}
/*
* Dream up a name if there isn't a real one and note that the action is
* really nameless.
*/
} else
/*
* Make sure the 'destruct pending' flag is clear. This indicates that
* the structure is no longer part of the cache.
*/
/*
* Fill in the reference structure and lint it onto the list.
*/
/*
* Increment the action count.
*/
return (0);
}
static void
{
int hb;
/*
* Find the hash bucket where the action structure should be.
*/
if (!ap->ippa_nameless) {
} else
rpp = &ipp_action_noname;
/*
* Scan the bucket for a match.
*/
break;
}
/*
* Unlink and free the reference structure.
*/
/*
* Decrement the action count.
*/
/*
* Empty the name.
*/
/*
* If the hold count is zero then we can free the structure
* immediately, otherwise we defer to rele_action().
*/
if (ap->ippa_hold_count == 0) {
return;
}
}
static ipp_action_t *
{
if (aid < 0)
return (NULL);
/*
* Use the action id as an index into the array of all action
* structures.
*/
return (NULL);
}
/*
* If the action has 'destruct pending' set then it means it is either
* still in the cache (i.e not allocated) or in the process of
* being set up by alloc_action().
*/
if (ap->ippa_destruct_pending) {
return (NULL);
}
/*
* Increment the hold count to prevent the structure from being
* freed.
*/
return (ap);
}
static void
{
/*
* This call means we're done with the pointer so we can drop the
* hold count.
*/
/*
* If the structure has 'destruct pending' set then we tried to free
* it but couldn't, so do it now.
*/
return;
}
}
static ipp_action_id_t
void)
{
int index;
int start;
int limit;
/*
* Start searching after the last action id that we allocated.
*/
start = (int)ipp_next_aid;
limit = (int)ipp_aid_limit;
/*
* Look for a spare slot in the array.
*/
index++;
return (IPP_ACTION_INVAL);
}
/*
* Note that we've just allocated a new action id so that we can
* start our search there next time.
*/
index++;
else
return ((ipp_action_id_t)(--index));
}
static int
const char *name,
ipp_packet_t **ppp)
{
return (ENOMEM);
/*
* Set the packet up with a single class.
*/
return (0);
}
static int
{
KM_NOSLEEP)) == NULL)
return (ENOMEM);
return (0);
}
static void
{
pp->ippp_class_windex = 0;
pp->ippp_class_rindex = 0;
}
static int
hash(
const char *name)
{
int val = 0;
char *ptr;
/*
* Make a hash value by XORing all the ascii codes in the text string.
*/
}
/*
* Return the value modulo the number of hash buckets we allow.
*/
return (val % IPP_NBUCKET);
}
static int
int rw)
{
/*
* Call the update function passed to ipp_stat_create() for the given
* set of kstats.
*/
}
static void
void)
{
/*
* Initialise the array of all module structures and the module
* structure kmem cache.
*/
(void *)ipltospl(LOCK_LEVEL));
KM_SLEEP);
/*
* Initialize the 'module by name' hash bucket array.
*/
(void *)ipltospl(LOCK_LEVEL));
}
static void
void)
{
/*
* Initialise the array of all action structures and the action
* structure cache.
*/
(void *)ipltospl(LOCK_LEVEL));
/*
* Initialize the 'action by name' hash bucket array (and the special
* 'hash' bucket for nameless actions).
*/
(void *)ipltospl(LOCK_LEVEL));
}
static void
void)
{
/*
* Initialise the packet structure cache.
*/
}
/*
* Kmem cache constructor/destructor functions.
*/
/*ARGSUSED*/
static int
void *buf,
void *cdrarg,
int kmflags)
{
/*
* Get a new module id.
*/
return (-1);
}
/*
* Initialize the buffer as a module structure in PROTO form.
*/
(void *)ipltospl(LOCK_LEVEL));
/*
* Insert it into the array of all module structures.
*/
return (0);
}
/*ARGSUSED*/
static void
void *buf,
void *cdrarg)
{
/*
* NULL the entry in the array of all module structures.
*/
/*
* Clean up any remnants of the module structure as the buffer is
* about to disappear.
*/
}
/*ARGSUSED*/
static int
void *buf,
void *cdrarg,
int kmflags)
{
/*
* Get a new action id.
*/
return (-1);
}
/*
* Initialize the buffer as an action structure in PROTO form.
*/
(void *)ipltospl(LOCK_LEVEL));
/*
* Insert it into the array of all action structures.
*/
return (0);
}
/*ARGSUSED*/
static void
void *buf,
void *cdrarg)
{
/*
* NULL the entry in the array of all action structures.
*/
/*
* Clean up any remnants of the action structure as the buffer is
* about to disappear.
*/
}
/*ARGSUSED*/
static int
void *buf,
void *cdrarg,
int kmflags)
{
KM_NOSLEEP)) == NULL)
return (ENOMEM);
pp->ippp_class_windex = 0;
pp->ippp_class_rindex = 0;
return (0);
}
/*ARGSUSED*/
static void
void *buf,
void *cdrarg)
{
}
}
/*
* Debug message printout code.
*/
#ifdef IPP_DBG
static void
const char *fn,
char *fmt,
...)
{
if ((type & ipp_debug_flags) == 0)
return;
buf);
}
#endif /* IPP_DBG */