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