1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2000, 2002 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate * PICL Daktari platform plug-in to create environment tree nodes.
31*0Sstevel@tonic-gate */
32*0Sstevel@tonic-gate
33*0Sstevel@tonic-gate #include <poll.h>
34*0Sstevel@tonic-gate #include <picl.h>
35*0Sstevel@tonic-gate #include <picltree.h>
36*0Sstevel@tonic-gate #include <stdio.h>
37*0Sstevel@tonic-gate #include <time.h>
38*0Sstevel@tonic-gate #include <fcntl.h>
39*0Sstevel@tonic-gate #include <unistd.h>
40*0Sstevel@tonic-gate #include <stdlib.h>
41*0Sstevel@tonic-gate #include <libintl.h>
42*0Sstevel@tonic-gate #include <limits.h>
43*0Sstevel@tonic-gate #include <ctype.h>
44*0Sstevel@tonic-gate #include <pthread.h>
45*0Sstevel@tonic-gate #include <errno.h>
46*0Sstevel@tonic-gate #include <syslog.h>
47*0Sstevel@tonic-gate #include <sys/types.h>
48*0Sstevel@tonic-gate #include <sys/systeminfo.h>
49*0Sstevel@tonic-gate #include <psvc_objects.h>
50*0Sstevel@tonic-gate #include <strings.h>
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate /*LINTLIBRARY*/
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate #define BUFSZ 512
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate static psvc_opaque_t hdlp;
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gate #define PSVC_PLUGIN_VERSION PICLD_PLUGIN_VERSION_1
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gate #pragma init(psvc_psr_plugin_register) /* place in .init section */
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate struct proj_prop { /* projected property */
64*0Sstevel@tonic-gate picl_prophdl_t handle;
65*0Sstevel@tonic-gate picl_nodehdl_t dst_node;
66*0Sstevel@tonic-gate char name[32];
67*0Sstevel@tonic-gate };
68*0Sstevel@tonic-gate
69*0Sstevel@tonic-gate typedef struct {
70*0Sstevel@tonic-gate char name[32];
71*0Sstevel@tonic-gate picl_nodehdl_t node;
72*0Sstevel@tonic-gate } picl_psvc_t;
73*0Sstevel@tonic-gate
74*0Sstevel@tonic-gate extern struct handle {
75*0Sstevel@tonic-gate uint32_t obj_count;
76*0Sstevel@tonic-gate picl_psvc_t *objects;
77*0Sstevel@tonic-gate FILE *fp;
78*0Sstevel@tonic-gate } psvc_hdl;
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gate extern struct proj_prop *prop_list;
81*0Sstevel@tonic-gate extern uint32_t proj_prop_count;
82*0Sstevel@tonic-gate
83*0Sstevel@tonic-gate void psvc_psr_plugin_init(void);
84*0Sstevel@tonic-gate void psvc_psr_plugin_fini(void);
85*0Sstevel@tonic-gate
86*0Sstevel@tonic-gate picld_plugin_reg_t psvc_psr_reg = {
87*0Sstevel@tonic-gate PSVC_PLUGIN_VERSION,
88*0Sstevel@tonic-gate PICLD_PLUGIN_CRITICAL,
89*0Sstevel@tonic-gate "PSVC_PSR",
90*0Sstevel@tonic-gate psvc_psr_plugin_init,
91*0Sstevel@tonic-gate psvc_psr_plugin_fini
92*0Sstevel@tonic-gate };
93*0Sstevel@tonic-gate
94*0Sstevel@tonic-gate
95*0Sstevel@tonic-gate #define PSVC_INIT_MSG gettext("%s: Error in psvc_init(): %s\n")
96*0Sstevel@tonic-gate #define PTREE_DELETE_NODE_MSG gettext("%s: ptree_delete_node() failed: %s\n")
97*0Sstevel@tonic-gate #define PTREE_GET_NODE_MSG \
98*0Sstevel@tonic-gate gettext("%s: ptree_get_node_by_path() failed for %s: %s\n")
99*0Sstevel@tonic-gate #define INVALID_FILE_FORMAT_MSG gettext("%s: Invalid file format\n")
100*0Sstevel@tonic-gate #define ID_NOT_FOUND_MSG gettext("%s: Can't determine id of %s\n")
101*0Sstevel@tonic-gate #define NODE_NOT_FOUND_MSG gettext("%s: Can't determine node of %s\n")
102*0Sstevel@tonic-gate #define SIZE_NOT_FOUND_MSG gettext("%s: Couldn't determine size of %s\n")
103*0Sstevel@tonic-gate #define PTREE_CREATE_PROP_FAILED_MSG \
104*0Sstevel@tonic-gate gettext("%s: ptree_create_prop failed, %s\n")
105*0Sstevel@tonic-gate #define PTREE_ADD_PROP_FAILED_MSG gettext("%s: ptree_add_prop: %s\n")
106*0Sstevel@tonic-gate #define FANSPEED_PROP_NOT_FOUND_MSG \
107*0Sstevel@tonic-gate gettext("%s: Can't find property fan-speed\n")
108*0Sstevel@tonic-gate #define FANSPEED_PROP_DELETE_FAILED_MSG \
109*0Sstevel@tonic-gate gettext("%s: Can't delete property fan-speed\n")
110*0Sstevel@tonic-gate
count_records(FILE * fp,char * end,uint32_t * countp)111*0Sstevel@tonic-gate static int32_t count_records(FILE *fp, char *end, uint32_t *countp)
112*0Sstevel@tonic-gate {
113*0Sstevel@tonic-gate long first_record;
114*0Sstevel@tonic-gate char *ret;
115*0Sstevel@tonic-gate char buf[BUFSZ];
116*0Sstevel@tonic-gate uint32_t count = 0;
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gate first_record = ftell(fp);
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate while ((ret = fgets(buf, BUFSZ, fp)) != NULL) {
121*0Sstevel@tonic-gate if (strncmp(end, buf, strlen(end)) == 0)
122*0Sstevel@tonic-gate break;
123*0Sstevel@tonic-gate ++count;
124*0Sstevel@tonic-gate }
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate if (ret == NULL) {
127*0Sstevel@tonic-gate errno = EINVAL;
128*0Sstevel@tonic-gate return (-1);
129*0Sstevel@tonic-gate }
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate fseek(fp, first_record, SEEK_SET);
132*0Sstevel@tonic-gate *countp = count;
133*0Sstevel@tonic-gate return (0);
134*0Sstevel@tonic-gate }
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gate /*
137*0Sstevel@tonic-gate * Find start of a section within the config file,
138*0Sstevel@tonic-gate * Returns number of records in the section.
139*0Sstevel@tonic-gate * FILE *fd is set to first data record within section.
140*0Sstevel@tonic-gate */
141*0Sstevel@tonic-gate static int32_t
find_file_section(FILE * fd,char * start)142*0Sstevel@tonic-gate find_file_section(FILE *fd, char *start)
143*0Sstevel@tonic-gate {
144*0Sstevel@tonic-gate char *ret;
145*0Sstevel@tonic-gate char buf[BUFSZ];
146*0Sstevel@tonic-gate char name[32];
147*0Sstevel@tonic-gate int found;
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate fseek(fd, 0, SEEK_SET);
150*0Sstevel@tonic-gate while ((ret = fgets(buf, BUFSZ, fd)) != NULL) {
151*0Sstevel@tonic-gate if (strncmp(start, buf, strlen(start)) == 0)
152*0Sstevel@tonic-gate break;
153*0Sstevel@tonic-gate }
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gate if (ret == NULL) {
156*0Sstevel@tonic-gate errno = EINVAL;
157*0Sstevel@tonic-gate return (-1);
158*0Sstevel@tonic-gate }
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate found = sscanf(buf, "%s", name);
161*0Sstevel@tonic-gate if (found != 1) {
162*0Sstevel@tonic-gate errno = EINVAL;
163*0Sstevel@tonic-gate return (-1);
164*0Sstevel@tonic-gate } else {
165*0Sstevel@tonic-gate return (0);
166*0Sstevel@tonic-gate }
167*0Sstevel@tonic-gate
168*0Sstevel@tonic-gate }
169*0Sstevel@tonic-gate
name_compare_bsearch(char * s1,picl_psvc_t * s2)170*0Sstevel@tonic-gate static int32_t name_compare_bsearch(char *s1, picl_psvc_t *s2)
171*0Sstevel@tonic-gate {
172*0Sstevel@tonic-gate return (strcmp(s1, s2->name));
173*0Sstevel@tonic-gate }
174*0Sstevel@tonic-gate
init_err(char * fmt,char * arg1,char * arg2)175*0Sstevel@tonic-gate static void init_err(char *fmt, char *arg1, char *arg2)
176*0Sstevel@tonic-gate {
177*0Sstevel@tonic-gate char msg[256];
178*0Sstevel@tonic-gate
179*0Sstevel@tonic-gate sprintf(msg, fmt, arg1, arg2);
180*0Sstevel@tonic-gate syslog(LOG_ERR, msg);
181*0Sstevel@tonic-gate }
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate static int
projected_lookup(picl_prophdl_t proph,struct proj_prop ** dstp)184*0Sstevel@tonic-gate projected_lookup(picl_prophdl_t proph, struct proj_prop **dstp)
185*0Sstevel@tonic-gate {
186*0Sstevel@tonic-gate int i;
187*0Sstevel@tonic-gate
188*0Sstevel@tonic-gate for (i = 0; i < proj_prop_count; ++i) {
189*0Sstevel@tonic-gate if (prop_list[i].handle == proph) {
190*0Sstevel@tonic-gate *dstp = &prop_list[i];
191*0Sstevel@tonic-gate return (PICL_SUCCESS);
192*0Sstevel@tonic-gate }
193*0Sstevel@tonic-gate }
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate return (PICL_INVALIDHANDLE);
196*0Sstevel@tonic-gate }
197*0Sstevel@tonic-gate
198*0Sstevel@tonic-gate int
fan_speed_read(ptree_rarg_t * rarg,void * buf)199*0Sstevel@tonic-gate fan_speed_read(ptree_rarg_t *rarg, void *buf)
200*0Sstevel@tonic-gate {
201*0Sstevel@tonic-gate struct proj_prop *dstinfo;
202*0Sstevel@tonic-gate int err;
203*0Sstevel@tonic-gate ptree_propinfo_t propinfo;
204*0Sstevel@tonic-gate picl_prophdl_t assoctbl;
205*0Sstevel@tonic-gate
206*0Sstevel@tonic-gate err = projected_lookup(rarg->proph, &dstinfo);
207*0Sstevel@tonic-gate if (err != PSVC_SUCCESS) {
208*0Sstevel@tonic-gate return (PICL_FAILURE);
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate
211*0Sstevel@tonic-gate
212*0Sstevel@tonic-gate /* see if there's a tach switch */
213*0Sstevel@tonic-gate err = ptree_get_propval_by_name(rarg->nodeh,
214*0Sstevel@tonic-gate "PSVC_FAN_PRIM_SEC_SELECTOR", &assoctbl, sizeof (assoctbl));
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gate if (err != PICL_SUCCESS) {
217*0Sstevel@tonic-gate return (err);
218*0Sstevel@tonic-gate } else {
219*0Sstevel@tonic-gate char switch_state[32], temp_state[32];
220*0Sstevel@tonic-gate uint64_t features;
221*0Sstevel@tonic-gate picl_prophdl_t entry;
222*0Sstevel@tonic-gate picl_nodehdl_t tach_switch;
223*0Sstevel@tonic-gate char id[PICL_PROPNAMELEN_MAX];
224*0Sstevel@tonic-gate char name[PICL_PROPNAMELEN_MAX];
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate err = ptree_get_next_by_row(assoctbl, &entry);
227*0Sstevel@tonic-gate if (err != PICL_SUCCESS) {
228*0Sstevel@tonic-gate return (err);
229*0Sstevel@tonic-gate }
230*0Sstevel@tonic-gate err = ptree_get_propval(entry, &tach_switch,
231*0Sstevel@tonic-gate sizeof (tach_switch));
232*0Sstevel@tonic-gate if (err != PICL_SUCCESS) {
233*0Sstevel@tonic-gate return (err);
234*0Sstevel@tonic-gate }
235*0Sstevel@tonic-gate
236*0Sstevel@tonic-gate err = ptree_get_propval_by_name(rarg->nodeh, PICL_PROP_NAME,
237*0Sstevel@tonic-gate &id, PICL_PROPNAMELEN_MAX);
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gate err = psvc_get_attr(hdlp, id, PSVC_FEATURES_ATTR, &features);
240*0Sstevel@tonic-gate
241*0Sstevel@tonic-gate if (err != PSVC_SUCCESS) {
242*0Sstevel@tonic-gate return (err);
243*0Sstevel@tonic-gate }
244*0Sstevel@tonic-gate if (features & PSVC_DEV_PRIMARY) {
245*0Sstevel@tonic-gate strlcpy(switch_state, PSVC_SWITCH_ON,
246*0Sstevel@tonic-gate sizeof (switch_state));
247*0Sstevel@tonic-gate } else {
248*0Sstevel@tonic-gate strlcpy(switch_state, PSVC_SWITCH_OFF,
249*0Sstevel@tonic-gate sizeof (switch_state));
250*0Sstevel@tonic-gate }
251*0Sstevel@tonic-gate
252*0Sstevel@tonic-gate pthread_mutex_lock(&fan_mutex);
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate err = ptree_get_propval_by_name(tach_switch, PICL_PROP_NAME,
255*0Sstevel@tonic-gate &name, PICL_PROPNAMELEN_MAX);
256*0Sstevel@tonic-gate
257*0Sstevel@tonic-gate err = ptree_get_propval_by_name(tach_switch, "State",
258*0Sstevel@tonic-gate &temp_state, sizeof (temp_state));
259*0Sstevel@tonic-gate
260*0Sstevel@tonic-gate err = psvc_set_attr(hdlp, name, PSVC_SWITCH_STATE_ATTR,
261*0Sstevel@tonic-gate &switch_state);
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate if (err != PSVC_SUCCESS) {
264*0Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex);
265*0Sstevel@tonic-gate return (err);
266*0Sstevel@tonic-gate }
267*0Sstevel@tonic-gate (void) poll(NULL, 0, 250);
268*0Sstevel@tonic-gate }
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gate
271*0Sstevel@tonic-gate err = ptree_get_propinfo(rarg->proph, &propinfo);
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate if (err != PICL_SUCCESS) {
274*0Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex);
275*0Sstevel@tonic-gate return (err);
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate
278*0Sstevel@tonic-gate err = ptree_get_propval_by_name(dstinfo->dst_node,
279*0Sstevel@tonic-gate dstinfo->name, buf, propinfo.piclinfo.size);
280*0Sstevel@tonic-gate if (err != PICL_SUCCESS) {
281*0Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex);
282*0Sstevel@tonic-gate return (err);
283*0Sstevel@tonic-gate }
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex);
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate return (PICL_SUCCESS);
288*0Sstevel@tonic-gate }
289*0Sstevel@tonic-gate
290*0Sstevel@tonic-gate
291*0Sstevel@tonic-gate /* Load projected properties */
292*0Sstevel@tonic-gate /*
293*0Sstevel@tonic-gate * This Routine Searches through the projected properties section of the conf
294*0Sstevel@tonic-gate * file and replaces the currently set up values in the CPU and IO Fan Objects
295*0Sstevel@tonic-gate * Fan-Speed property to Daktari specific values
296*0Sstevel@tonic-gate */
297*0Sstevel@tonic-gate static void
load_projected_properties(FILE * fp)298*0Sstevel@tonic-gate load_projected_properties(FILE *fp)
299*0Sstevel@tonic-gate {
300*0Sstevel@tonic-gate int32_t found;
301*0Sstevel@tonic-gate ptree_propinfo_t propinfo;
302*0Sstevel@tonic-gate ptree_propinfo_t dstinfo;
303*0Sstevel@tonic-gate picl_prophdl_t src_prophdl, dst_prophdl;
304*0Sstevel@tonic-gate picl_nodehdl_t src_node, dst_node;
305*0Sstevel@tonic-gate int err, i;
306*0Sstevel@tonic-gate picl_psvc_t *srcobjp, *dstobjp;
307*0Sstevel@tonic-gate char src[32], dst[256];
308*0Sstevel@tonic-gate char src_prop[32], dst_prop[32];
309*0Sstevel@tonic-gate char buf[BUFSZ];
310*0Sstevel@tonic-gate char *funcname = "load_projected_properties";
311*0Sstevel@tonic-gate
312*0Sstevel@tonic-gate if (find_file_section(fp, "PROJECTED_PROPERTIES") != 0)
313*0Sstevel@tonic-gate return;
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate if (count_records(fp, "PROJECTED_PROPERTIES_END",
316*0Sstevel@tonic-gate &proj_prop_count) != 0) {
317*0Sstevel@tonic-gate init_err(INVALID_FILE_FORMAT_MSG, funcname, 0);
318*0Sstevel@tonic-gate return;
319*0Sstevel@tonic-gate }
320*0Sstevel@tonic-gate
321*0Sstevel@tonic-gate
322*0Sstevel@tonic-gate for (i = 0; i < proj_prop_count; ++i) {
323*0Sstevel@tonic-gate fgets(buf, BUFSZ, fp);
324*0Sstevel@tonic-gate found = sscanf(buf, "%s %s %s %s", src, src_prop, dst,
325*0Sstevel@tonic-gate dst_prop);
326*0Sstevel@tonic-gate if (found != 4) {
327*0Sstevel@tonic-gate init_err(INVALID_FILE_FORMAT_MSG, funcname, 0);
328*0Sstevel@tonic-gate return;
329*0Sstevel@tonic-gate }
330*0Sstevel@tonic-gate if (strcmp(src_prop, "Fan-speed") != 0)
331*0Sstevel@tonic-gate continue;
332*0Sstevel@tonic-gate
333*0Sstevel@tonic-gate if ((strcmp(src, "IO_BRIDGE_PRIM_FAN") == 0) ||
334*0Sstevel@tonic-gate (strcmp(src, "IO_BRIDGE_SEC_FAN") == 0))
335*0Sstevel@tonic-gate continue;
336*0Sstevel@tonic-gate
337*0Sstevel@tonic-gate /* find src node */
338*0Sstevel@tonic-gate if (src[0] == '/') {
339*0Sstevel@tonic-gate /* picl node name, outside psvc subtree */
340*0Sstevel@tonic-gate err = ptree_get_node_by_path(src, &src_node);
341*0Sstevel@tonic-gate if (err != 0) {
342*0Sstevel@tonic-gate init_err(NODE_NOT_FOUND_MSG, funcname, src);
343*0Sstevel@tonic-gate return;
344*0Sstevel@tonic-gate }
345*0Sstevel@tonic-gate } else {
346*0Sstevel@tonic-gate srcobjp = (picl_psvc_t *)bsearch(src, psvc_hdl.objects,
347*0Sstevel@tonic-gate psvc_hdl.obj_count, sizeof (picl_psvc_t),
348*0Sstevel@tonic-gate (int (*)(const void *, const void *))
349*0Sstevel@tonic-gate name_compare_bsearch);
350*0Sstevel@tonic-gate if (srcobjp == NULL) {
351*0Sstevel@tonic-gate init_err(ID_NOT_FOUND_MSG, funcname, src);
352*0Sstevel@tonic-gate return;
353*0Sstevel@tonic-gate }
354*0Sstevel@tonic-gate src_node = srcobjp->node;
355*0Sstevel@tonic-gate }
356*0Sstevel@tonic-gate
357*0Sstevel@tonic-gate /*
358*0Sstevel@tonic-gate * Get the property Handle for the property names "Fan-Speed"
359*0Sstevel@tonic-gate * from the source node
360*0Sstevel@tonic-gate */
361*0Sstevel@tonic-gate err = ptree_get_prop_by_name(src_node, "Fan-speed",
362*0Sstevel@tonic-gate &src_prophdl);
363*0Sstevel@tonic-gate if (err != 0) {
364*0Sstevel@tonic-gate init_err(FANSPEED_PROP_NOT_FOUND_MSG, funcname, 0);
365*0Sstevel@tonic-gate return;
366*0Sstevel@tonic-gate }
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gate /*
369*0Sstevel@tonic-gate * Delete the current property Handle as we are going to replace
370*0Sstevel@tonic-gate * it's values
371*0Sstevel@tonic-gate */
372*0Sstevel@tonic-gate err = ptree_delete_prop(src_prophdl);
373*0Sstevel@tonic-gate if (err != 0) {
374*0Sstevel@tonic-gate init_err(FANSPEED_PROP_DELETE_FAILED_MSG, funcname, 0);
375*0Sstevel@tonic-gate return;
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate
378*0Sstevel@tonic-gate /* destroy property created by generic plugin */
379*0Sstevel@tonic-gate ptree_delete_prop(prop_list[i].handle);
380*0Sstevel@tonic-gate ptree_destroy_prop(prop_list[i].handle);
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gate /* find dest node */
383*0Sstevel@tonic-gate if (dst[0] == '/') {
384*0Sstevel@tonic-gate /* picl node name, outside psvc subtree */
385*0Sstevel@tonic-gate err = ptree_get_node_by_path(dst, &dst_node);
386*0Sstevel@tonic-gate if (err != 0) {
387*0Sstevel@tonic-gate init_err(NODE_NOT_FOUND_MSG, funcname, dst);
388*0Sstevel@tonic-gate return;
389*0Sstevel@tonic-gate }
390*0Sstevel@tonic-gate prop_list[i].dst_node = dst_node;
391*0Sstevel@tonic-gate } else {
392*0Sstevel@tonic-gate dstobjp = (picl_psvc_t *)bsearch(dst, psvc_hdl.objects,
393*0Sstevel@tonic-gate psvc_hdl.obj_count, sizeof (picl_psvc_t),
394*0Sstevel@tonic-gate (int (*)(const void *, const void *))
395*0Sstevel@tonic-gate name_compare_bsearch);
396*0Sstevel@tonic-gate if (dstobjp == NULL) {
397*0Sstevel@tonic-gate init_err(ID_NOT_FOUND_MSG, funcname, dst);
398*0Sstevel@tonic-gate return;
399*0Sstevel@tonic-gate }
400*0Sstevel@tonic-gate prop_list[i].dst_node = dstobjp->node;
401*0Sstevel@tonic-gate dst_node = dstobjp->node;
402*0Sstevel@tonic-gate }
403*0Sstevel@tonic-gate
404*0Sstevel@tonic-gate /* determine destination property size */
405*0Sstevel@tonic-gate err = ptree_get_first_prop(dst_node, &dst_prophdl);
406*0Sstevel@tonic-gate while (err == 0) {
407*0Sstevel@tonic-gate err = ptree_get_propinfo(dst_prophdl, &dstinfo);
408*0Sstevel@tonic-gate if (err != 0)
409*0Sstevel@tonic-gate break;
410*0Sstevel@tonic-gate if (strcmp(dst_prop, dstinfo.piclinfo.name) == 0)
411*0Sstevel@tonic-gate break;
412*0Sstevel@tonic-gate err = ptree_get_next_prop(dst_prophdl, &dst_prophdl);
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate if (err != 0) {
415*0Sstevel@tonic-gate init_err(SIZE_NOT_FOUND_MSG, funcname, dst_prop);
416*0Sstevel@tonic-gate return;
417*0Sstevel@tonic-gate }
418*0Sstevel@tonic-gate
419*0Sstevel@tonic-gate propinfo.version = PSVC_PLUGIN_VERSION;
420*0Sstevel@tonic-gate propinfo.read = fan_speed_read;
421*0Sstevel@tonic-gate propinfo.write = 0;
422*0Sstevel@tonic-gate propinfo.piclinfo.type = dstinfo.piclinfo.type;
423*0Sstevel@tonic-gate propinfo.piclinfo.accessmode = PICL_READ | PICL_VOLATILE;
424*0Sstevel@tonic-gate propinfo.piclinfo.size = dstinfo.piclinfo.size;
425*0Sstevel@tonic-gate strcpy(propinfo.piclinfo.name, src_prop);
426*0Sstevel@tonic-gate
427*0Sstevel@tonic-gate err = ptree_create_prop(&propinfo, 0, &src_prophdl);
428*0Sstevel@tonic-gate if (err != 0) {
429*0Sstevel@tonic-gate init_err(PTREE_CREATE_PROP_FAILED_MSG, funcname,
430*0Sstevel@tonic-gate picl_strerror(err));
431*0Sstevel@tonic-gate return;
432*0Sstevel@tonic-gate }
433*0Sstevel@tonic-gate
434*0Sstevel@tonic-gate err = ptree_add_prop(src_node, src_prophdl);
435*0Sstevel@tonic-gate if (err != 0) {
436*0Sstevel@tonic-gate init_err(PTREE_ADD_PROP_FAILED_MSG, funcname,
437*0Sstevel@tonic-gate picl_strerror(err));
438*0Sstevel@tonic-gate return;
439*0Sstevel@tonic-gate }
440*0Sstevel@tonic-gate
441*0Sstevel@tonic-gate prop_list[i].handle = src_prophdl;
442*0Sstevel@tonic-gate strcpy(prop_list[i].name, dst_prop);
443*0Sstevel@tonic-gate }
444*0Sstevel@tonic-gate }
445*0Sstevel@tonic-gate
446*0Sstevel@tonic-gate
447*0Sstevel@tonic-gate void
psvc_psr_plugin_init(void)448*0Sstevel@tonic-gate psvc_psr_plugin_init(void)
449*0Sstevel@tonic-gate {
450*0Sstevel@tonic-gate char *funcname = "psvc_psr_plugin_init";
451*0Sstevel@tonic-gate int32_t i;
452*0Sstevel@tonic-gate int err;
453*0Sstevel@tonic-gate boolean_t present;
454*0Sstevel@tonic-gate
455*0Sstevel@tonic-gate /*
456*0Sstevel@tonic-gate * So the volatile read/write routines can retrieve data from
457*0Sstevel@tonic-gate * psvc or picl
458*0Sstevel@tonic-gate */
459*0Sstevel@tonic-gate err = psvc_init(&hdlp);
460*0Sstevel@tonic-gate if (err != 0) {
461*0Sstevel@tonic-gate init_err(PSVC_INIT_MSG, funcname, strerror(errno));
462*0Sstevel@tonic-gate }
463*0Sstevel@tonic-gate
464*0Sstevel@tonic-gate load_projected_properties(psvc_hdl.fp);
465*0Sstevel@tonic-gate
466*0Sstevel@tonic-gate /*
467*0Sstevel@tonic-gate * Remove nodes whose devices aren't present from the picl tree.
468*0Sstevel@tonic-gate */
469*0Sstevel@tonic-gate for (i = 0; i < psvc_hdl.obj_count; ++i) {
470*0Sstevel@tonic-gate picl_psvc_t *objp;
471*0Sstevel@tonic-gate uint64_t features;
472*0Sstevel@tonic-gate
473*0Sstevel@tonic-gate objp = &psvc_hdl.objects[i];
474*0Sstevel@tonic-gate
475*0Sstevel@tonic-gate err = psvc_get_attr(hdlp, objp->name, PSVC_PRESENCE_ATTR,
476*0Sstevel@tonic-gate &present);
477*0Sstevel@tonic-gate if (err != PSVC_SUCCESS)
478*0Sstevel@tonic-gate continue;
479*0Sstevel@tonic-gate err = psvc_get_attr(hdlp, objp->name, PSVC_FEATURES_ATTR,
480*0Sstevel@tonic-gate &features);
481*0Sstevel@tonic-gate if (err != PSVC_SUCCESS)
482*0Sstevel@tonic-gate continue;
483*0Sstevel@tonic-gate if ((features & (PSVC_DEV_HOTPLUG | PSVC_DEV_OPTION)) &&
484*0Sstevel@tonic-gate (present == PSVC_ABSENT)) {
485*0Sstevel@tonic-gate err = ptree_delete_node(objp->node);
486*0Sstevel@tonic-gate if (err != 0) {
487*0Sstevel@tonic-gate init_err(PTREE_DELETE_NODE_MSG, funcname,
488*0Sstevel@tonic-gate picl_strerror(err));
489*0Sstevel@tonic-gate return;
490*0Sstevel@tonic-gate }
491*0Sstevel@tonic-gate }
492*0Sstevel@tonic-gate }
493*0Sstevel@tonic-gate
494*0Sstevel@tonic-gate free(psvc_hdl.objects);
495*0Sstevel@tonic-gate
496*0Sstevel@tonic-gate }
497*0Sstevel@tonic-gate
498*0Sstevel@tonic-gate void
psvc_psr_plugin_fini(void)499*0Sstevel@tonic-gate psvc_psr_plugin_fini(void)
500*0Sstevel@tonic-gate {
501*0Sstevel@tonic-gate psvc_fini(hdlp);
502*0Sstevel@tonic-gate }
503*0Sstevel@tonic-gate
504*0Sstevel@tonic-gate void
psvc_psr_plugin_register(void)505*0Sstevel@tonic-gate psvc_psr_plugin_register(void)
506*0Sstevel@tonic-gate {
507*0Sstevel@tonic-gate picld_plugin_register(&psvc_psr_reg);
508*0Sstevel@tonic-gate }
509