/*
* 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
*/
/*
*/
#include <sys/isa_defs.h>
#include <sys/systeminfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <strings.h>
#include <dlfcn.h>
#include <limits.h>
#include <pthread.h>
#include <synch.h>
#include "smp_impl.h"
static int _libsmp_refcnt;
static void
{
return;
}
static void
{
break;
}
void
smp_engine_init(void)
{
(void) pthread_mutex_lock(&_libsmp_lock);
(void) pthread_mutex_unlock(&_libsmp_lock);
}
void
smp_engine_fini(void)
{
(void) pthread_mutex_lock(&_libsmp_lock);
ASSERT(_libsmp_refcnt > 0);
if (--_libsmp_refcnt == 0) {
while (_libsmp_engines != NULL) {
}
}
(void) pthread_mutex_unlock(&_libsmp_lock);
}
static int
{
void *obj;
return (smp_set_errno(ESMP_NOENGINE));
return (-1);
}
return (smp_set_errno(ESMP_BADENGINE));
}
return (-1);
}
return (0);
}
int
const smp_engine_config_t *ecp)
{
if (version != LIBSMP_ENGINE_VERSION)
return (smp_set_errno(ESMP_VERSION));
return (-1);
return (0);
}
static smp_engine_t *
{
return (ep);
}
}
(void) smp_set_errno(ESMP_NOENGINE);
return (NULL);
}
static smp_engine_t *
{
const char *pluginpath, *p, *q;
(void) pthread_mutex_lock(&_libsmp_lock);
(void) pthread_mutex_unlock(&_libsmp_lock);
return (ep);
}
#if defined(_LP64)
isa[0] = '\0';
#else
isa[0] = '\0';
#endif
for (p = pluginpath; p != NULL; p = q) {
while (*q == ':')
++q;
if (*q == '\0')
q = NULL;
if (len == 0)
continue;
} else {
(void) strcpy(pluginroot, p);
}
if (pluginroot[0] != '/')
continue;
if (smp_engine_loadone(path) == 0) {
(void) pthread_mutex_unlock(&_libsmp_lock);
return (ep);
}
}
return (NULL);
}
static void
{
(void) pthread_mutex_lock(&_libsmp_lock);
(void) pthread_mutex_unlock(&_libsmp_lock);
}
static void
{
const char *strval;
int intval;
}
}
{
void *private;
const char *engine;
}
return (NULL);
return (NULL);
}
return (NULL);
}
if (smp_plugin_load(tp) != 0) {
return (NULL);
}
return (tp);
}
void
{
}
{
}
const char *
{
}
const char *
{
return (tp->st_product);
}
const char *
{
return (tp->st_revision);
}
const char *
{
return (tp->st_component_vendor);
}
{
return (tp->st_component_id);
}
{
return (tp->st_component_revision);
}
{
return (cap);
}
void
{
}
{
return (tp->st_change_count);
}
{
}
{
}
void
{
}
/*
* Set the timeout in seconds for this action. If no timeout is specified
* or if the timeout is set to 0, an implementation-specific timeout will be
* used (which may vary based on the target, command or other variables).
* Not all engines support all timeout values. Setting the timeout to a value
* not supported by the engine will cause engine-defined behavior when the
* action is executed.
*/
void
{
}
/*
* Obtain the timeout setting for this action.
*/
{
return (ap->sa_timeout);
}
const smp_function_def_t *
{
}
/*
* Obtain the user-requested request allocation size. Note that the
* interpretation of this is function-dependent.
*/
{
return (ap->sa_request_rqsd);
}
/*
* Obtains the address and amount of space allocated for the portion of the
* request data that lies between the header (if any) and the CRC.
*/
void
{
if (ap->sa_request_data_off >= 0) {
} else {
}
}
}
/*
* Obtains the address and amount of valid response data (that part of the
* response frame, if any, that lies between the header and the CRC). The
* result, if any, is also returned in the location pointed to by result.
*/
void
{
}
/*
* Obtains the entire request frame and the amount of space allocated for it.
* This is intended only for use by plugins; front-end consumers should use
* smp_action_get_request() instead.
*/
void
{
}
/*
* Obtains the entire response frame and the amount of space allocated for it.
* This is intended only for use by plugins; front-end consumers should use
* smp_action_get_response() instead.
*/
void
{
else
}
}
/*
* Set the total response frame length as determined by the engine. This
* should never be called by consumers or plugins other than engines.
*/
void
{
}
void
{
}
/*
* Allocate an action object. The object will contain a request buffer
* to hold the frame to be transmitted to the target, a response buffer
* for the frame to be received from it, and auxiliary private information.
*
* For the request, callers may specify:
*
* - An externally-allocated buffer and its size in bytes, or
* - NULL and a function-specific size descriptor, or
*
* Note that for some functions, the size descriptor may be 0, indicating that
* a default buffer length will be used. It is the caller's responsibility
* to correctly interpret function-specific buffer lengths. See appropriate
* plugin documentation for information on buffer sizes and buffer content
* interpretation.
*
* For the response, callers may specify:
*
* - An externally-allocated buffer and its size in bytes, or
* - NULL and 0, to use a guaranteed-sufficient buffer.
*
* If an invalid request size descriptor is provided, or a preallocated
* buffer is provided and it is insufficiently large, this function will
* fail with ESMP_RANGE.
*
* Callers are discouraged from allocating their own buffers and must be
* aware of the consequences of specifying non-default lengths.
*/
{
int i;
continue;
break;
}
}
(void) smp_set_errno(ESMP_BADFUNC);
return (NULL);
}
return (NULL);
} else if (rqlen < SMP_REQ_MINLEN) {
(void) smp_set_errno(ESMP_RANGE);
return (NULL);
}
} else if (rslen < SMP_RESP_MINLEN) {
(void) smp_set_errno(ESMP_RANGE);
return (NULL);
}
return (NULL);
}
}
return (ap);
}
/*
* Simplified action allocator. All buffers are allocated for the
* caller. The request buffer size will be based on the function-specific
* interpretation of the rqsize parameter. The response buffer size will be
* a function-specific value sufficiently large to capture any response.
*/
{
}
void
{
return;
}
/*
* For testing purposes, we allow data to be corrupted via an environment
* variable setting. This helps ensure that higher level software can cope with
* arbitrarily broken targets. The mtbf value represents the number of bytes we
* will see, on average, in between each failure. Therefore, for each N bytes,
* we would expect to see (N / mtbf) bytes of corruption.
*/
static void
{
double prob;
if (len == 0)
return;
while (prob > 1) {
prob -= 1;
}
}
}
int
{
int ret;
if (tp->st_mtbf_request != 0) {
}
}
if (ret != 0)
return (ret);
/*
* Obtain the data length and offset from the underlying plugins.
* Then offer the plugins the opportunity to set any parameters in the
* target to reflect state observed in the response.
*/
return (0);
}