4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2000, 2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * PICL Daktari platform plug-in to create environment tree nodes.
47 #include <sys/types.h>
48 #include <sys/systeminfo.h>
49 #include <psvc_objects.h>
56 static psvc_opaque_t hdlp
;
58 #define PSVC_PLUGIN_VERSION PICLD_PLUGIN_VERSION_1
60 #pragma init(psvc_psr_plugin_register) /* place in .init section */
63 struct proj_prop
{ /* projected property */
64 picl_prophdl_t handle
;
65 picl_nodehdl_t dst_node
;
74 extern struct handle
{
80 extern struct proj_prop
*prop_list
;
81 extern uint32_t proj_prop_count
;
83 void psvc_psr_plugin_init(void);
84 void psvc_psr_plugin_fini(void);
86 picld_plugin_reg_t psvc_psr_reg
= {
88 PICLD_PLUGIN_CRITICAL
,
95 #define PSVC_INIT_MSG gettext("%s: Error in psvc_init(): %s\n")
96 #define PTREE_DELETE_NODE_MSG gettext("%s: ptree_delete_node() failed: %s\n")
97 #define PTREE_GET_NODE_MSG \
98 gettext("%s: ptree_get_node_by_path() failed for %s: %s\n")
99 #define INVALID_FILE_FORMAT_MSG gettext("%s: Invalid file format\n")
100 #define ID_NOT_FOUND_MSG gettext("%s: Can't determine id of %s\n")
101 #define NODE_NOT_FOUND_MSG gettext("%s: Can't determine node of %s\n")
102 #define SIZE_NOT_FOUND_MSG gettext("%s: Couldn't determine size of %s\n")
103 #define PTREE_CREATE_PROP_FAILED_MSG \
104 gettext("%s: ptree_create_prop failed, %s\n")
105 #define PTREE_ADD_PROP_FAILED_MSG gettext("%s: ptree_add_prop: %s\n")
106 #define FANSPEED_PROP_NOT_FOUND_MSG \
107 gettext("%s: Can't find property fan-speed\n")
108 #define FANSPEED_PROP_DELETE_FAILED_MSG \
109 gettext("%s: Can't delete property fan-speed\n")
111 static int32_t count_records(FILE *fp
, char *end
, uint32_t *countp
)
118 first_record
= ftell(fp
);
120 while ((ret
= fgets(buf
, BUFSZ
, fp
)) != NULL
) {
121 if (strncmp(end
, buf
, strlen(end
)) == 0)
131 fseek(fp
, first_record
, SEEK_SET
);
137 * Find start of a section within the config file,
138 * Returns number of records in the section.
139 * FILE *fd is set to first data record within section.
142 find_file_section(FILE *fd
, char *start
)
149 fseek(fd
, 0, SEEK_SET
);
150 while ((ret
= fgets(buf
, BUFSZ
, fd
)) != NULL
) {
151 if (strncmp(start
, buf
, strlen(start
)) == 0)
160 found
= sscanf(buf
, "%s", name
);
170 static int32_t name_compare_bsearch(char *s1
, picl_psvc_t
*s2
)
172 return (strcmp(s1
, s2
->name
));
175 static void init_err(char *fmt
, char *arg1
, char *arg2
)
179 sprintf(msg
, fmt
, arg1
, arg2
);
180 syslog(LOG_ERR
, msg
);
184 projected_lookup(picl_prophdl_t proph
, struct proj_prop
**dstp
)
188 for (i
= 0; i
< proj_prop_count
; ++i
) {
189 if (prop_list
[i
].handle
== proph
) {
190 *dstp
= &prop_list
[i
];
191 return (PICL_SUCCESS
);
195 return (PICL_INVALIDHANDLE
);
199 fan_speed_read(ptree_rarg_t
*rarg
, void *buf
)
201 struct proj_prop
*dstinfo
;
203 ptree_propinfo_t propinfo
;
204 picl_prophdl_t assoctbl
;
206 err
= projected_lookup(rarg
->proph
, &dstinfo
);
207 if (err
!= PSVC_SUCCESS
) {
208 return (PICL_FAILURE
);
212 /* see if there's a tach switch */
213 err
= ptree_get_propval_by_name(rarg
->nodeh
,
214 "PSVC_FAN_PRIM_SEC_SELECTOR", &assoctbl
, sizeof (assoctbl
));
216 if (err
!= PICL_SUCCESS
) {
219 char switch_state
[32], temp_state
[32];
221 picl_prophdl_t entry
;
222 picl_nodehdl_t tach_switch
;
223 char id
[PICL_PROPNAMELEN_MAX
];
224 char name
[PICL_PROPNAMELEN_MAX
];
226 err
= ptree_get_next_by_row(assoctbl
, &entry
);
227 if (err
!= PICL_SUCCESS
) {
230 err
= ptree_get_propval(entry
, &tach_switch
,
231 sizeof (tach_switch
));
232 if (err
!= PICL_SUCCESS
) {
236 err
= ptree_get_propval_by_name(rarg
->nodeh
, PICL_PROP_NAME
,
237 &id
, PICL_PROPNAMELEN_MAX
);
239 err
= psvc_get_attr(hdlp
, id
, PSVC_FEATURES_ATTR
, &features
);
241 if (err
!= PSVC_SUCCESS
) {
244 if (features
& PSVC_DEV_PRIMARY
) {
245 strlcpy(switch_state
, PSVC_SWITCH_ON
,
246 sizeof (switch_state
));
248 strlcpy(switch_state
, PSVC_SWITCH_OFF
,
249 sizeof (switch_state
));
252 pthread_mutex_lock(&fan_mutex
);
254 err
= ptree_get_propval_by_name(tach_switch
, PICL_PROP_NAME
,
255 &name
, PICL_PROPNAMELEN_MAX
);
257 err
= ptree_get_propval_by_name(tach_switch
, "State",
258 &temp_state
, sizeof (temp_state
));
260 err
= psvc_set_attr(hdlp
, name
, PSVC_SWITCH_STATE_ATTR
,
263 if (err
!= PSVC_SUCCESS
) {
264 pthread_mutex_unlock(&fan_mutex
);
267 (void) poll(NULL
, 0, 250);
271 err
= ptree_get_propinfo(rarg
->proph
, &propinfo
);
273 if (err
!= PICL_SUCCESS
) {
274 pthread_mutex_unlock(&fan_mutex
);
278 err
= ptree_get_propval_by_name(dstinfo
->dst_node
,
279 dstinfo
->name
, buf
, propinfo
.piclinfo
.size
);
280 if (err
!= PICL_SUCCESS
) {
281 pthread_mutex_unlock(&fan_mutex
);
285 pthread_mutex_unlock(&fan_mutex
);
287 return (PICL_SUCCESS
);
291 /* Load projected properties */
293 * This Routine Searches through the projected properties section of the conf
294 * file and replaces the currently set up values in the CPU and IO Fan Objects
295 * Fan-Speed property to Daktari specific values
298 load_projected_properties(FILE *fp
)
301 ptree_propinfo_t propinfo
;
302 ptree_propinfo_t dstinfo
;
303 picl_prophdl_t src_prophdl
, dst_prophdl
;
304 picl_nodehdl_t src_node
, dst_node
;
306 picl_psvc_t
*srcobjp
, *dstobjp
;
307 char src
[32], dst
[256];
308 char src_prop
[32], dst_prop
[32];
310 char *funcname
= "load_projected_properties";
312 if (find_file_section(fp
, "PROJECTED_PROPERTIES") != 0)
315 if (count_records(fp
, "PROJECTED_PROPERTIES_END",
316 &proj_prop_count
) != 0) {
317 init_err(INVALID_FILE_FORMAT_MSG
, funcname
, 0);
322 for (i
= 0; i
< proj_prop_count
; ++i
) {
323 fgets(buf
, BUFSZ
, fp
);
324 found
= sscanf(buf
, "%s %s %s %s", src
, src_prop
, dst
,
327 init_err(INVALID_FILE_FORMAT_MSG
, funcname
, 0);
330 if (strcmp(src_prop
, "Fan-speed") != 0)
333 if ((strcmp(src
, "IO_BRIDGE_PRIM_FAN") == 0) ||
334 (strcmp(src
, "IO_BRIDGE_SEC_FAN") == 0))
339 /* picl node name, outside psvc subtree */
340 err
= ptree_get_node_by_path(src
, &src_node
);
342 init_err(NODE_NOT_FOUND_MSG
, funcname
, src
);
346 srcobjp
= (picl_psvc_t
*)bsearch(src
, psvc_hdl
.objects
,
347 psvc_hdl
.obj_count
, sizeof (picl_psvc_t
),
348 (int (*)(const void *, const void *))
349 name_compare_bsearch
);
350 if (srcobjp
== NULL
) {
351 init_err(ID_NOT_FOUND_MSG
, funcname
, src
);
354 src_node
= srcobjp
->node
;
358 * Get the property Handle for the property names "Fan-Speed"
359 * from the source node
361 err
= ptree_get_prop_by_name(src_node
, "Fan-speed",
364 init_err(FANSPEED_PROP_NOT_FOUND_MSG
, funcname
, 0);
369 * Delete the current property Handle as we are going to replace
372 err
= ptree_delete_prop(src_prophdl
);
374 init_err(FANSPEED_PROP_DELETE_FAILED_MSG
, funcname
, 0);
378 /* destroy property created by generic plugin */
379 ptree_delete_prop(prop_list
[i
].handle
);
380 ptree_destroy_prop(prop_list
[i
].handle
);
384 /* picl node name, outside psvc subtree */
385 err
= ptree_get_node_by_path(dst
, &dst_node
);
387 init_err(NODE_NOT_FOUND_MSG
, funcname
, dst
);
390 prop_list
[i
].dst_node
= dst_node
;
392 dstobjp
= (picl_psvc_t
*)bsearch(dst
, psvc_hdl
.objects
,
393 psvc_hdl
.obj_count
, sizeof (picl_psvc_t
),
394 (int (*)(const void *, const void *))
395 name_compare_bsearch
);
396 if (dstobjp
== NULL
) {
397 init_err(ID_NOT_FOUND_MSG
, funcname
, dst
);
400 prop_list
[i
].dst_node
= dstobjp
->node
;
401 dst_node
= dstobjp
->node
;
404 /* determine destination property size */
405 err
= ptree_get_first_prop(dst_node
, &dst_prophdl
);
407 err
= ptree_get_propinfo(dst_prophdl
, &dstinfo
);
410 if (strcmp(dst_prop
, dstinfo
.piclinfo
.name
) == 0)
412 err
= ptree_get_next_prop(dst_prophdl
, &dst_prophdl
);
415 init_err(SIZE_NOT_FOUND_MSG
, funcname
, dst_prop
);
419 propinfo
.version
= PSVC_PLUGIN_VERSION
;
420 propinfo
.read
= fan_speed_read
;
422 propinfo
.piclinfo
.type
= dstinfo
.piclinfo
.type
;
423 propinfo
.piclinfo
.accessmode
= PICL_READ
| PICL_VOLATILE
;
424 propinfo
.piclinfo
.size
= dstinfo
.piclinfo
.size
;
425 strcpy(propinfo
.piclinfo
.name
, src_prop
);
427 err
= ptree_create_prop(&propinfo
, 0, &src_prophdl
);
429 init_err(PTREE_CREATE_PROP_FAILED_MSG
, funcname
,
434 err
= ptree_add_prop(src_node
, src_prophdl
);
436 init_err(PTREE_ADD_PROP_FAILED_MSG
, funcname
,
441 prop_list
[i
].handle
= src_prophdl
;
442 strcpy(prop_list
[i
].name
, dst_prop
);
448 psvc_psr_plugin_init(void)
450 char *funcname
= "psvc_psr_plugin_init";
456 * So the volatile read/write routines can retrieve data from
459 err
= psvc_init(&hdlp
);
461 init_err(PSVC_INIT_MSG
, funcname
, strerror(errno
));
464 load_projected_properties(psvc_hdl
.fp
);
467 * Remove nodes whose devices aren't present from the picl tree.
469 for (i
= 0; i
< psvc_hdl
.obj_count
; ++i
) {
473 objp
= &psvc_hdl
.objects
[i
];
475 err
= psvc_get_attr(hdlp
, objp
->name
, PSVC_PRESENCE_ATTR
,
477 if (err
!= PSVC_SUCCESS
)
479 err
= psvc_get_attr(hdlp
, objp
->name
, PSVC_FEATURES_ATTR
,
481 if (err
!= PSVC_SUCCESS
)
483 if ((features
& (PSVC_DEV_HOTPLUG
| PSVC_DEV_OPTION
)) &&
484 (present
== PSVC_ABSENT
)) {
485 err
= ptree_delete_node(objp
->node
);
487 init_err(PTREE_DELETE_NODE_MSG
, funcname
,
494 free(psvc_hdl
.objects
);
499 psvc_psr_plugin_fini(void)
505 psvc_psr_plugin_register(void)
507 picld_plugin_register(&psvc_psr_reg
);