psvcplugin.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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* PICL plug-in to create environment tree nodes.
* This plugin should only be installed in the platform directories
*/
#include <picl.h>
#include <picltree.h>
#include <stdio.h>
#include <time.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <pthread.h>
#include <libintl.h>
#include <errno.h>
#include <semaphore.h>
#include <sched.h>
#include <syslog.h>
#include <string.h>
#include <signal.h>
#include <sys/systeminfo.h>
#include <psvc_objects.h>
#include <psvc_objects_class.h>
int init_done;
#define BUFSZ 512
typedef struct {
char name[32];
} EName_t;
typedef struct {
char routine[64];
} ETask_t;
typedef struct interval_info {
struct interval_info *next;
} EInterval_t;
static EInterval_t *first_interval;
static psvc_opaque_t hdlp;
extern int ptree_get_node_by_path(const char *, picl_nodehdl_t *);
/* Timer states */
#define NOT_READY 0
#define READY 1
#define HAVE_REQUEST 2
#define ACTIVE 3
int timer_state = NOT_READY;
int app_timeout;
/* Lock State Loop State Definitions */
#define STATE_CHANGED 1
#define STATE_NOT_CHANGED 0
#ifdef DEBUG
#else
static int32_t debug_flag = 0;
#endif
typedef struct {
char parent_path[256];
char child_name[32];
} psvc_name_t;
#define PTREE_CREATE_TABLE_FAILED_MSG \
gettext("%s: ptree_create_table failed, %s\n")
#define PTREE_CREATE_PROP_FAILED_MSG \
gettext("%s: ptree_create_prop failed, %s\n")
#define PTREE_CREATE_NODE_FAILED_MSG \
gettext("%s: ptree_create_node failed, %s\n")
#define LOCK_STRING_MAX 32
static picl_nodehdl_t lock_node;
static char *class_name[] = {
"temperature-sensor",
"fan",
"led",
"picl",
"digital-sensor",
"digital-control",
"gpio",
"fan-tachometer",
"switch",
"keyswitch",
"gpio",
"i2c"
};
#define NUM_CLASSES (sizeof (class_name) / sizeof (char *))
struct proj_prop { /* projected property */
char name[32];
};
struct propinfo {
char *name;
};
};
struct propinfo led_properties[] = {
};
/*
* We define the amount of LED properties to 1 because not all LED's have
* the two remainding properties. This number is augmented in psvc_plugin_init
* when it sees an LED of subclass 2.
*/
#define LED_COUNT 1
struct propinfo temperature_sensor_properties[] = {
};
#define TEMP_SENSOR_COUNT \
(sizeof (temperature_sensor_properties) / sizeof (struct propinfo))
struct propinfo digi_sensor_properties[] = {
};
#define DIGI_SENSOR_COUNT \
(sizeof (digi_sensor_properties) / sizeof (struct propinfo))
struct propinfo boolgpio_properties[] = {
};
struct propinfo gpio8_properties[] = {
};
struct propinfo digictrl_properties[] = {
};
struct classinfo {
} class_properties[] =
{
{0, 0}, /* fan, only has projected properties */
{0, 0}, /* system class */
{0, 0},
{0, 0},
{0, 0},
};
struct prop_trans {
char *picl_class;
char *picl_prop;
} picl_prop_trans[] =
{
};
#define PICL_PROP_TRANS_COUNT \
(sizeof (picl_prop_trans) / sizeof (struct prop_trans))
typedef struct {
char name[32];
} picl_psvc_t;
struct assoc_pair {
char antecedent[32];
char dependent[32];
};
struct handle {
} psvc_hdl;
int psvc_picl_nodes;
void psvc_plugin_init(void);
void psvc_plugin_fini(void);
"PSVC",
};
/*
* psvcplugin_add_children was written so that devices which are hotplugable
* will be able to add in all thier children and children's children. The
* routine takes in the path of a parent and then searches the psvc_paths
* array to find all of it's children. It in turns adds the child and then
* recursively check to see if it had children and add them too.
*/
void
{
int i;
char next_path[256];
for (i = 0; i < psvc_picl_nodes; ++i) {
}
}
}
void
{
int i;
for (i = 0; i < psvc_picl_nodes; ++i) {
}
}
}
void
{
int status;
if (status != 0) {
}
for (;;) {
/* wait for thread to tell us to start timer */
timer_state = READY;
do {
if (status != 0) {
}
/*
* Will get signalled after semaphore acquired,
* or when timeout occurs.
*/
if (timer_state == HAVE_REQUEST) {
do {
&timer_mutex, &timeout);
}
if (status != 0) {
} else {
}
}
}
}
static int
lock_state_loop(char *set_lock_state)
{
return (STATE_NOT_CHANGED);
}
return (STATE_CHANGED);
}
static int timed_lock_wait(char *set_lock_state)
{
/* Only want one timer active at a time */
do {
if (status == -1)
return (status);
while (timer_state != READY)
sched_yield();
/*
* We now spin checking the state env_lock_state for it to change to
* enabled.
*/
while (lock_state_loop(set_lock_state))
sleep(1);
if (timer_state == ACTIVE) {
}
}
return (0);
}
{
/* Grab mutex to stop the env_lock from being changed. */
/*
* Check to see if the lock is anything but Enabled. If so, we then
* goto our timer routine to wait for it to become enabled.
* If not then set it to RUNNING and run policy.
*/
/* drop mutex and goto timer */
if (status == -1) {
}
} else {
}
char dev_name[32];
}
/* The policy is done so set the lock back to ENABLED. */
}
{
int32_t i, j;
do {
do {
} while (remaining > 0);
}
for (j = 0; j < tp->num_objects; ++j) {
lock_and_run(tp, j);
}
}
}
{
ip);
if (status != 0) {
if (debug_flag)
exit(-1);
}
}
{
void *hp;
if (debug_flag) {
}
exit(1);
}
if (debug_flag) {
}
exit(1);
}
return (0);
}
{
char name[32];
char *cp;
/* skip blank lines */
do {
return (1);
++cp;
return (-1);
}
return (0);
}
{
char name[32];
char *cp;
/* skip blank lines */
do {
return (1);
++cp;
if (found != 3) {
return (-1);
}
return (-1);
}
return (-1);
/* allocate and load table */
return (-1);
if (found != 3) {
return (-1);
}
if (status == -1)
return (-1);
if (found != 1) {
if (debug_flag)
return (-1);
}
return (-1);
for (j = 0; j < tp->num_objects; ++j) {
if (found != 1) {
if (debug_flag)
"Wrong number of objects for task");
return (-1);
}
}
if (debug_flag)
return (-1);
}
}
if (debug_flag)
return (-1);
}
return (0);
}
void
init_daemon(void)
{
char platform[64];
if (debug_flag)
return;
}
platform);
if (debug_flag)
return;
}
if (status != 0) {
if (debug_flag)
return;
}
if (status == -1) {
if (debug_flag)
return;
}
(void *(*)())timer_thread, 0);
if (status != 0) {
if (debug_flag)
return;
}
/* get timer thread running */
while (timer_state != READY)
sched_yield();
for (;;) {
if (status != 0)
break;
#ifdef lint
#endif
if (first_interval == 0)
first_interval = ip;
else
++intervals;
} else {
++threads;
}
}
if (intervals == 0) {
if (debug_flag)
return;
}
if (status == -1) {
if (debug_flag)
return;
}
return;
}
{
long first_record;
char *ret;
break;
++count;
}
return (-1);
}
return (0);
}
/*
* Find start of a section within the config file,
* Returns number of records in the section.
* FILE *fd is set to first data record within section.
*/
static int32_t
{
char *ret;
char name[32];
int found;
break;
}
return (-1);
}
if (found != 1) {
return (-1);
} else {
return (0);
}
}
{
}
{
}
/*
* Create a property and add it to the specified node.
* PICL will take a segmentation violation if a volatile property
* has a non-zero size.
*/
int (*read)(ptree_rarg_t *, void *),
{
int err;
if (accessmode & PICL_VOLATILE) {
} else {
}
if (err != 0) {
return (err);
}
if (err != 0)
return (err);
return (0);
}
{
char msg[256];
}
static int
{
int i;
for (i = 0; i < proj_prop_count; ++i) {
return (PICL_SUCCESS);
}
}
return (PICL_INVALIDHANDLE);
}
int
{
int err;
if (err != 0) {
return (PICL_FAILURE);
}
if (err != 0)
return (err);
if (err != 0)
return (err);
return (PICL_SUCCESS);
}
int
{
int err;
if (err != 0) {
return (PICL_FAILURE);
}
if (err != 0)
return (err);
if (err != 0)
return (err);
return (PICL_SUCCESS);
}
int
{
int err, i;
int32_t use_attr_num = 0;
sizeof (name));
if (err != 0) {
return (err);
}
sizeof (class));
if (err != 0) {
return (err);
}
if (err != 0) {
return (err);
}
for (i = 0; i < PICL_PROP_TRANS_COUNT; i++) {
picl_prop_trans[i].picl_prop) == 0)) {
attr_num = i;
break;
}
}
if (attr_num == -1)
for (i = 0; i < ATTR_STR_TAB_SIZE; i++) {
attr_str_tab[i]) == 0) {
attr_num = i;
use_attr_num = 1;
break;
}
}
if (use_attr_num)
else
buf);
if (err != 0) {
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
int
{
int err, i;
int32_t use_attr_num = 0;
return (PICL_PERMDENIED);
sizeof (name));
if (err != 0) {
return (err);
}
sizeof (class));
if (err != 0) {
return (err);
}
if (err != 0) {
return (err);
}
for (i = 0; i < PICL_PROP_TRANS_COUNT; i++) {
picl_prop_trans[i].picl_prop) == 0)) {
attr_num = i;
break;
}
}
if (attr_num == -1)
for (i = 0; i < ATTR_STR_TAB_SIZE; i++) {
attr_str_tab[i]) == 0) {
attr_num = i;
use_attr_num = 1;
break;
}
}
if (use_attr_num)
else
(void *)buf);
if (err != 0) {
return (PICL_FAILURE);
}
return (PICL_SUCCESS);
}
char *assoc_name)
{
char *funcname = "create_reference_properties";
char name[PICL_PROPNAMELEN_MAX];
char class[PICL_CLASSNAMELEN_MAX];
for (i = 0; i < count; ++i) {
/* antecedent */
sizeof (picl_psvc_t),
(int (*)(const void *, const void *))
return;
}
/* skip if table already created */
continue;
}
/* create a new table */
if (err != 0) {
return;
}
assoc_name, &tbl_hdl);
if (err != 0) {
picl_strerror(err));
return;
}
/* determine number of elements in the table */
dependents = 0;
for (j = i; j < count; ++j) {
++dependents;
}
return;
}
/* build row of reference properties */
offset = 0;
for (j = i; j < count; ++j) {
continue;
(int (*)(const void *, const void *))
return;
}
/*
* Reference property name must be
* _classname_propertyname
*/
if (err != 0) {
return;
}
if (err != 0) {
return;
}
++offset;
}
/* add row to table */
if (err != 0) {
picl_strerror(err));
return;
}
}
}
/* Load projected properties */
static void
{
int err, i;
char *funcname = "load_projected_properties";
return;
0) {
return;
}
* proj_prop_count);
return;
}
for (i = 0; i < proj_prop_count; ++i) {
dst_prop);
if (found != 4) {
return;
}
/* find src node */
if (src[0] == '/') {
/* picl node name, outside psvc subtree */
if (err != 0) {
return;
}
} else {
(int (*)(const void *, const void *))
return;
}
}
/* find dest node */
if (dst[0] == '/') {
/* picl node name, outside psvc subtree */
if (err != 0) {
return;
}
} else {
(int (*)(const void *, const void *))
return;
}
}
/* determine destination property size */
while (err == 0) {
if (err != 0)
break;
break;
}
if (err != 0) {
return;
}
if (err != 0) {
picl_strerror(err));
return;
}
if (err != 0) {
picl_strerror(err));
return;
}
}
}
/* Load the association table */
{
char *funcname = "load_associations";
int found;
int j;
char assoc_name[32];
struct assoc_pair *assoc_tbl;
char name1[32];
/*
* ignore count in the file, correct count is highest
* association id + 1, now figured when loading ASSOC_STR
* section.
*/
return;
if (found != 2) {
return;
}
return;
}
sizeof (struct assoc_pair) * count);
return;
}
for (j = 0; j < count; ++j) {
if (found != 2) {
0);
return;
}
}
return;
}
/* Create separate list of dependents for each antecedent */
}
}
}
/* Enviornmental Lock Object's Read and Write routine */
static int
{
return (PSVC_SUCCESS);
}
static int
{
/*
* Check to make sure that the value is either Disabled or Enabled
* as these are the only 2 states that this object can be set to.
*/
return (PSVC_FAILURE);
}
/*
* If the state is already Enabled we can set the state to Disabled
* to stop the policies.
*/
if (status == -1) {
}
return (status);
}
/*
* If the state is Running we must go into timed_lock_wait to aquire
* the env_lock.
*/
if (status == -1) {
}
return (status);
}
/*
* If the state is already Disabled we need to first check to see if
* we are resetting it to Disabled or changing it to Enabled. If we
* are resetting it to Disabled then we need to stop the timer and
* restart it. If we are changing it to Enabled we just set it to
* enabled.
*/
if (timer_state == ACTIVE) {
/* stop timer */
/* wait for timer to reset */
while (timer_state != READY)
sched_yield();
/* restart timer */
}
} else {
}
}
return (PSVC_SUCCESS);
}
static int
{
int err;
char *funcname = "init_env_lock_node";
/* Here we are creating a Enviornmental Lock Node */
if (err != PICL_SUCCESS) {
picl_strerror(err));
return (err);
}
if (err != PICL_SUCCESS) {
return (err);
}
if (err != PICL_SUCCESS) {
picl_strerror(err));
return (err);
}
if (err != PICL_SUCCESS) {
picl_strerror(err));
return (err);
}
return (PSVC_SUCCESS);
}
void
psvc_plugin_init(void)
{
char *funcname = "psvc_plugin_init";
char platform[32];
char filename[256];
int32_t i, j;
psvc_paths = NULL;
/*
* psvc or picl
*/
if (err != 0) {
}
return;
}
return;
}
/* Create all PICL nodes */
return;
}
== -1) {
return;
}
return;
}
if (err != 0) {
picl_strerror(err));
return;
}
/* Following array is accessed directly by the psvc policies. */
if (psvc_paths == NULL) {
return;
}
char *start;
break;
filename);
return;
}
if (found != 1) {
filename);
return;
}
/* get class */
if (err != PSVC_SUCCESS) {
return;
}
if (class > NUM_CLASSES) {
return;
}
&subclass);
if (err != PSVC_SUCCESS) {
return;
}
if (err != 0) {
picl_strerror(err));
return;
}
for (j = 0; j < COMMON_COUNT; ++j) {
psvc_read_volatile : 0,
psvc_write_volatile : 0,
if (err != PSVC_SUCCESS) {
picl_strerror(err));
return;
}
}
/* Locator LED Support */
cp_count = 3;
} else {
}
for (j = 0; j < cp_count; ++j) {
if (err != PSVC_SUCCESS) {
picl_strerror(err));
return;
}
}
/* Link the nodes into the PICL tree */
*start = 0;
} else {
if (err != PICL_SUCCESS) {
return;
}
}
if (err != PICL_SUCCESS) {
picl_strerror(err));
return;
}
}
(int (*)(const void *, const void *))name_compare_qsort);
return;
init_daemon();
init_done = 1;
}
void
psvc_plugin_fini(void)
{
int32_t i;
/* Fix memory leaks */
/*
* We don't check return types.
* If this call fails, it's because we did not
* run thread_setup() on this particular ip
*
* Please refer to init_daemon() for thread
* assignments
*/
}
}
void
psvc_plugin_register(void)
{
}