1 /*
2  * CDDL HEADER START
3  *
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
7  * with the License.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * This file consists of routines to manage objects in the
31  * "Platform Environment Services Framework". The classes
32  * and subclasses are defined by attributes and methods.
33  * The objects, and their initial, static, attribute values are
34  * specified in a configuration file, "psvcobj.conf".
35  * psvc_init() reads the configuration file and creates a repository
36  * of environmental objects in memory. A client application may manipulate
37  * these objects by invoking the psvc_get_attr(), and psvc_set_attr()
38  * routines with the object's string ID specified as an argument.
39  */
40 #include <stdio.h>
41 #include <math.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <stropts.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <pthread.h>
49 #include <syslog.h>
50 #include <stdarg.h>
51 #include <pthread.h>
52 #include <sys/systeminfo.h>
53 
54 #define	LIBRARY_BUILD 1
55 #include <psvc_objects.h>
56 #include <psvc_objects_class.h>
57 #include <sys/i2c/clients/i2c_client.h>
58 
59 /* Mutex used for Daktari Fan speed reading */
60 pthread_mutex_t fan_mutex = PTHREAD_MUTEX_INITIALIZER;
61 
62 /*LINTLIBRARY*/
63 
64 #define	ENV_DEBUG(str, id) printf("%s id %s\n", (str), (id))
65 
66 #define	BUFSZ  512
67 
68 #define	CLASS_MAX	12
69 #define	SUBCLASS_MAX	10
70 
71 static int32_t i_psvc_constructor_0_0(EHdl_t *, char *, EObj_t **);
72 static int32_t i_psvc_constructor_0_1(EHdl_t *, char *, EObj_t **);
73 static int32_t i_psvc_constructor_1_0(EHdl_t *, char *, EObj_t **);
74 static int32_t i_psvc_constructor_2_0(EHdl_t *, char *, EObj_t **);
75 static int32_t i_psvc_constructor_2_1(EHdl_t *, char *, EObj_t **);
76 static int32_t i_psvc_constructor_2_2(EHdl_t *, char *, EObj_t **);
77 static int32_t i_psvc_constructor_3_0(EHdl_t *, char *, EObj_t **);
78 static int32_t i_psvc_constructor_4_0(EHdl_t *, char *, EObj_t **);
79 static int32_t i_psvc_constructor_5_0(EHdl_t *, char *, EObj_t **);
80 static int32_t i_psvc_constructor_6_0(EHdl_t *, char *, EObj_t **);
81 static int32_t i_psvc_constructor_7_0(EHdl_t *, char *, EObj_t **);
82 static int32_t i_psvc_constructor_8_0(EHdl_t *, char *, EObj_t **);
83 static int32_t i_psvc_constructor_9_0(EHdl_t *, char *, EObj_t **);
84 static int32_t i_psvc_constructor_10_0(EHdl_t *, char *, EObj_t **);
85 static int32_t i_psvc_constructor_10_1(EHdl_t *, char *, EObj_t **);
86 static int32_t i_psvc_constructor_11_0(EHdl_t *, char *, EObj_t **);
87 static int32_t i_psvc_constructor_11_1(EHdl_t *, char *, EObj_t **);
88 static int32_t i_psvc_constructor_11_2(EHdl_t *, char *, EObj_t **);
89 static int32_t i_psvc_constructor_11_3(EHdl_t *, char *, EObj_t **);
90 static int32_t i_psvc_constructor_11_4(EHdl_t *, char *, EObj_t **);
91 static int32_t i_psvc_constructor_11_5(EHdl_t *, char *, EObj_t **);
92 static int32_t i_psvc_constructor_11_6(EHdl_t *, char *, EObj_t **);
93 static int32_t i_psvc_constructor_11_7(EHdl_t *, char *, EObj_t **);
94 static int32_t i_psvc_constructor_11_8(EHdl_t *, char *, EObj_t **);
95 static int32_t i_psvc_constructor_11_9(EHdl_t *, char *, EObj_t **);
96 
97 static int32_t i_psvc_get_obj(EHdl_t *, char *, EObj_t **);
98 static int32_t i_psvc_destructor(EHdl_t *, char *, void *);
99 static int32_t i_psvc_get_devpath(EHdl_t *, uint64_t, char *);
100 static int32_t i_psvc_get_attr_generic(EHdl_t *, EObj_t *, int32_t, void *);
101 static int32_t i_psvc_get_attr_6_0(EHdl_t *, EObj_t *, int32_t, void *);
102 static int32_t i_psvc_get_reg_11_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id,
103     void *attrp);
104 static int32_t i_psvc_get_attr_10_1(EHdl_t *, EObj_t *, int32_t, void *);
105 static int32_t psvc_get_str_key(char *object);
106 
107 int32_t ioctl_retry(int fp, int request, void * arg_pointer);
108 
109 /*
110  * Method lookup tables
111  * Update when adding classes or subclasses.
112  */
113 
114 
115 /* Lookup method by class, subclass, used when calling method */
116 static int32_t (*i_psvc_constructor[CLASS_MAX][SUBCLASS_MAX])(EHdl_t *,
117 	char *, EObj_t **) = {
118 {i_psvc_constructor_0_0, i_psvc_constructor_0_1, 0, 0, 0, 0, 0, 0, 0, 0},
119 	{i_psvc_constructor_1_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
120 {i_psvc_constructor_2_0, i_psvc_constructor_2_1, i_psvc_constructor_2_2,
121 		0, 0, 0, 0, 0, 0, 0},
122 	{i_psvc_constructor_3_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
123 	{i_psvc_constructor_4_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
124 	{i_psvc_constructor_5_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
125 	{i_psvc_constructor_6_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
126 	{i_psvc_constructor_7_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
127 	{i_psvc_constructor_8_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
128 	{i_psvc_constructor_9_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
129 {i_psvc_constructor_10_0, i_psvc_constructor_10_1, 0, 0, 0, 0, 0, 0, 0, 0},
130 {i_psvc_constructor_11_0, i_psvc_constructor_11_1, i_psvc_constructor_11_2,
131 	i_psvc_constructor_11_3, i_psvc_constructor_11_4,
132 	i_psvc_constructor_11_5, i_psvc_constructor_11_6,
133 	i_psvc_constructor_11_7, i_psvc_constructor_11_8,
134 	i_psvc_constructor_11_9},
135 };
136 
137 static int32_t i_psvc_cell_size[8] = {1, 1, 2, 2, 4, 4, 8, 8};
138 
139 static struct bits {
140 	uint64_t	bit;
141 	char		*label;
142 } feature_bits[] = {
143 {PSVC_DEV_PERM, "PERM="},
144 {PSVC_DEV_HOTPLUG, "HOTPLUG="},
145 {PSVC_DEV_OPTION, "OPTION="},
146 {PSVC_DEV_PRIMARY, "PRIMARY="},
147 {PSVC_DEV_SECONDARY, "SECONDARY="},
148 {PSVC_DEV_RDONLY, "RDONLY="},
149 {PSVC_DEV_RDWR, "RDWR="},
150 {PSVC_DEV_FRU, "FRU="},
151 {PSVC_LOW_WARN, "LO_WARN_MASK="},
152 {PSVC_LOW_SHUT, "LO_SHUT_MASK="},
153 {PSVC_HIGH_WARN, "HI_WARN_MASK="},
154 {PSVC_HIGH_SHUT, "HI_SHUT_MASK="},
155 {PSVC_CONVERSION_TABLE, "CONV_TABLE="},
156 {PSVC_OPT_TEMP, "OPT_TEMP_MASK="},
157 {PSVC_HW_LOW_SHUT, "HW_LO_MASK="},
158 {PSVC_HW_HIGH_SHUT, "HW_HI_MASK="},
159 {PSVC_FAN_DRIVE_PR, "FAN_DRIVE_PR="},
160 {PSVC_TEMP_DRIVEN, "TEMP_DRIVEN="},
161 {PSVC_SPEED_CTRL_PR, "SPEED_CTRL_PR="},
162 {PSVC_FAN_ON_OFF, "FAN_ON_OFF="},
163 {PSVC_CLOSED_LOOP_CTRL, "CLOSED_LOOP_CTRL="},
164 {PSVC_FAN_DRIVE_TABLE_PR, "FAN_DRIVE_TABLE_PR="},
165 {PSVC_DIE_TEMP, "DIE_TEMP="},
166 {PSVC_AMB_TEMP, "AMB_TEMP="},
167 {PSVC_DIGI_SENSOR, "DIGI_SENSOR="},
168 {PSVC_BI_STATE, "BI_STATE="},
169 {PSVC_TRI_STATE, "TRI_STATE="},
170 {PSVC_GREEN, "GREEN="},
171 {PSVC_AMBER, "AMBER="},
172 {PSVC_OUTPUT, "OUTPUT="},
173 {PSVC_INPUT, "INPUT="},
174 {PSVC_BIDIR, "BIDIR="},
175 {PSVC_BIT_POS, "BIT_POS="},
176 {PSVC_VAL_POS, "VAL_POS="},
177 {PSVC_NORMAL_POS_AV, "NORMAL_POS_AV="},
178 {PSVC_DIAG_POS_AV, "DIAG_POS_AV="},
179 {PSVC_LOCK_POS_AV, "LOCK_POS_AV="},
180 {PSVC_OFF_POS_AV, "OFF_POS_AV="},
181 {PSVC_GPIO_PORT, "GPIO_PORT="},
182 {PSVC_GPIO_REG, "GPIO_REG="}
183 };
184 
185 #define	ASSOC_STR_TAB_SIZE 33
186 static char *assoc_str_tab[] = {
187 	"PSVC_PRESENCE_SENSOR",			/* 0 */
188 	"PSVC_FAN_ONOFF_SENSOR",		/* 1 */
189 	"PSVC_FAN_SPEED_TACHOMETER",		/* 2 */
190 	"PSVC_FAN_PRIM_SEC_SELECTOR",		/* 3 */
191 	"PSVC_DEV_TEMP_SENSOR",			/* 4 */
192 	"PSVC_FAN_DRIVE_CONTROL",		/* 5 */
193 	"PSVC_KS_NORMAL_POS_SENSOR",		/* 6 */
194 	"PSVC_KS_DIAG_POS_SENSOR",		/* 7 */
195 	"PSVC_KS_LOCK_POS_SENSOR",		/* 8 */
196 	"PSVC_KS_OFF_POS_SENSOR",		/* 9 */
197 	"PSVC_SLOT_FAULT_LED",			/* 10 */
198 	"PSVC_SLOT_REMOVE_LED",			/* 11 */
199 	"PSVC_TS_OVERTEMP_LED",			/* 12 */
200 	"PSVC_PS_I_SENSOR",			/* 13 */
201 	"PSVC_DEV_FAULT_SENSOR",		/* 14 */
202 	"PSVC_DEV_FAULT_LED",			/* 15 */
203 	"PSVC_TABLE",				/* 16 */
204 	"PSVC_PARENT",				/* 17 */
205 	"PSVC_CPU",				/* 18 */
206 	"PSVC_ALTERNATE",			/* 19 */
207 	"PSVC_HOTPLUG_ENABLE_SWITCH",		/* 20 */
208 	"PSVC_PS",				/* 21 */
209 	"PSVC_FAN",				/* 22 */
210 	"PSVC_TS",				/* 23 */
211 	"PSVC_DISK",				/* 24 */
212 	"PSVC_LED",				/* 25 */
213 	"PSVC_FSP_LED",				/* 26 */
214 	"PSVC_KEYSWITCH",			/* 27 */
215 	"PSVC_PCI_CARD",			/* 28 */
216 	"PSVC_PHYSICAL_DEVICE",			/* 29 */
217 	"PSVC_DEV_TYPE_SENSOR",			/* 30 */
218 	"PSVC_FAN_TRAY_FANS",			/* 31 */
219 	"PSVC_FRU"				/* 32 */
220 };
221 
222 #define	FEATURE_BITS (sizeof (feature_bits) / sizeof (struct bits))
223 
224 static struct bitfield {
225 	int8_t shift;
226 	char   *label;
227 	char   *format;
228 } addr_fields[] =
229 {
230 {PSVC_VERSION_SHIFT, "VERSION=", "%d"},
231 {PSVC_ACTIVE_LOW_SHIFT, "ACTIVE_LOW=", "%d"},
232 {PSVC_BIT_NUM_SHIFT, "BIT_NUM=", "%d"},
233 {PSVC_INVERT_SHIFT, "INVERT=", "%d"},
234 {PSVC_PORT_SHIFT, "PORT=", "%d"},
235 {PSVC_BITSHIFT_SHIFT, "BITSHIFT=", "%d"},
236 {PSVC_BYTEMASK_SHIFT, "BYTEMASK=", "%x"},
237 {PSVC_REG_SHIFT, "REG=", "%d"},
238 {PSVC_TYPE_SHIFT, "TYPE=", "%d"},
239 {PSVC_BUSADDR_SHIFT, "BUSADDR=", "%x"},
240 {PSVC_BUSNUM_SHIFT, "BUSNUM=", "%d"},
241 {PSVC_CNTLR_SHIFT, "CNTLR=", "%d"},
242 };
243 #define	ADDR_BITFIELDS (sizeof (addr_fields) / sizeof (struct bitfield))
244 
245 /*
246  * record format is:
247  * pathname label1=val1,label2=val2,label3=val3
248  * Must be a space after the pathname and a comma between variables.
249  */
250 
251 static char *
find_label(char * str,char * label)252 find_label(char *str, char *label)
253 {
254 	char *start;
255 
256 	start = strchr(str, ' ');
257 	if (start == NULL)
258 		return (start);
259 
260 	do {
261 		++start;
262 		if (strncmp(start, label, strlen(label)) == 0)
263 			return (start);
264 
265 		start = strchr(start, ',');
266 	} while (start != NULL);
267 
268 	return (NULL);
269 }
270 
271 static int32_t
i_psvc_value(char * buf,int32_t attr_id,void * attrp)272 i_psvc_value(char *buf, int32_t attr_id, void *attrp)
273 {
274 	char *val;
275 	uint32_t temp32;
276 	uint64_t temp64;
277 	uint64_t result;
278 	int32_t i;
279 	int32_t found;
280 	char label[64];
281 	int val_size;
282 	int label_size;
283 
284 
285 	switch (attr_id) {
286 	case PSVC_CLASS_ATTR:
287 	case PSVC_SUBCLASS_ATTR:
288 	case PSVC_INSTANCE_ATTR:
289 	case PSVC_LO_WARN_ATTR:
290 	case PSVC_LO_SHUT_ATTR:
291 	case PSVC_HI_WARN_ATTR:
292 	case PSVC_HI_SHUT_ATTR:
293 	case PSVC_HW_HI_SHUT_ATTR:
294 	case PSVC_HW_LO_SHUT_ATTR:
295 	case PSVC_OPTIMAL_TEMP_ATTR:
296 		snprintf(label, sizeof (label), "%s=", attr_str_tab[attr_id]);
297 		val = find_label(buf, label);
298 		if (val == NULL) {
299 			errno = EINVAL;
300 			return (PSVC_FAILURE);
301 		}
302 		found = sscanf(val + strlen(label),
303 			"%d", (int32_t *)attrp);
304 		if (found == 0)
305 			*(int32_t *)attrp = 0;
306 		break;
307 	case PSVC_SETPOINT_ATTR:
308 	case PSVC_HYSTERESIS_ATTR:
309 	case PSVC_LOOPGAIN_ATTR:
310 	case PSVC_LOOPBIAS_ATTR:
311 		snprintf(label, sizeof (label), "%s=", attr_str_tab[attr_id]);
312 		val = find_label(buf, label);
313 		if (val == NULL) {
314 			errno = EINVAL;
315 			return (PSVC_FAILURE);
316 		}
317 
318 		found = sscanf(val + strlen(label), "%hd", (int16_t *)attrp);
319 		if (found == 0)
320 			*(int16_t *)attrp = 0;
321 		break;
322 	case PSVC_LED_COLOR_ATTR:
323 	case PSVC_LED_IS_LOCATOR_ATTR:
324 	case PSVC_LED_LOCATOR_NAME_ATTR:
325 		snprintf(label, sizeof (label), "%s=", attr_str_tab[attr_id]);
326 		val = find_label(buf, label);
327 		if (val == NULL) {
328 			errno = EINVAL;
329 			return (PSVC_FAILURE);
330 		}
331 		val_size = strlen(val);
332 		label_size = strlen(label);
333 
334 		for (i = 0; i < val_size && val[i] != ','; i++);
335 		if (i < strlen(val) - 1) {
336 			strncpy((char *)attrp, val+label_size,
337 				i - label_size);
338 		} else
339 		found = sscanf(val + label_size, "%s", (char *)attrp);
340 		if (found == 0)
341 			strcpy((char *)attrp, "");
342 		break;
343 	case PSVC_FEATURES_ATTR:
344 		result = 0;
345 		for (i = 0; i < FEATURE_BITS; ++i) {
346 			val = find_label(buf, feature_bits[i].label);
347 			if (val == NULL)
348 				continue;
349 			found = sscanf(val + strlen(feature_bits[i].label),
350 				"%d", &temp32);
351 			if (found != 0) {
352 				if (temp32 == 1)
353 					result |= feature_bits[i].bit;
354 			}
355 		}
356 		*(uint64_t *)attrp = result;
357 		break;
358 	case PSVC_ADDR_SPEC_ATTR:
359 		result = 0;
360 		for (i = 0; i < ADDR_BITFIELDS; ++i) {
361 			val = find_label(buf, addr_fields[i].label);
362 			if (val == NULL)
363 				continue;
364 			found = sscanf(val + strlen(addr_fields[i].label),
365 				addr_fields[i].format, &temp32);
366 			if (found != 0) {
367 				temp64 = temp32;
368 				temp64 <<= addr_fields[i].shift;
369 				result |= temp64;
370 			}
371 		}
372 		*(uint64_t *)attrp = result;
373 		break;
374 	default:
375 		errno = EINVAL;
376 		return (PSVC_FAILURE);
377 	}
378 	return (PSVC_SUCCESS);
379 }
380 
381 /* determine number of records in file section */
382 static int32_t
i_psvc_count_records(FILE * fp,char * end,uint32_t * countp)383 i_psvc_count_records(FILE *fp, char *end, uint32_t *countp)
384 {
385 	long first_record;
386 	char *ret;
387 	char buf[BUFSZ];
388 	uint32_t count = 0;
389 
390 	first_record = ftell(fp);
391 
392 	while ((ret = fgets(buf, BUFSZ, fp)) != NULL) {
393 		if (strncmp(end, buf, strlen(end)) == 0)
394 			break;
395 		++count;
396 	}
397 
398 	if (ret == NULL) {
399 		errno = EINVAL;
400 		return (PSVC_FAILURE);
401 	}
402 
403 	fseek(fp, first_record, SEEK_SET);
404 	*countp = count;
405 	return (PSVC_SUCCESS);
406 }
407 
408 /* determine number of records in file section */
409 static int32_t
i_psvc_count_tables_associations(FILE * fp,uint32_t * countp,char * end)410 i_psvc_count_tables_associations(FILE *fp, uint32_t *countp, char *end)
411 {
412 	long first_record;
413 	char *ret;
414 	char buf[BUFSZ];
415 	uint32_t count = 0;
416 
417 	first_record = ftell(fp);
418 
419 	while ((ret = fgets(buf, BUFSZ, fp)) != NULL) {
420 		if (strncmp(end, buf, strlen(end)) == 0)
421 			++count;
422 	}
423 #ifdef	lint
424 	ret = ret;
425 #endif
426 
427 	fseek(fp, first_record, SEEK_SET);
428 	*countp = count;
429 	return (PSVC_SUCCESS);
430 }
431 
432 /* determine number of records in a table */
433 static int32_t
i_psvc_count_table_records(FILE * fp,char * end,uint32_t * countp)434 i_psvc_count_table_records(FILE *fp, char *end, uint32_t *countp)
435 {
436 	long first_record;
437 	int ret;
438 	char string[BUFSZ];
439 	uint32_t count = 0;
440 
441 	first_record = ftell(fp);
442 
443 	while ((ret = fscanf(fp, "%s", string)) == 1) {
444 		if (strncmp(end, string, strlen(end)) == 0)
445 			break;
446 		++count;
447 	}
448 
449 	if (ret != 1) {
450 		errno = EINVAL;
451 		return (PSVC_FAILURE);
452 	}
453 
454 	fseek(fp, first_record, SEEK_SET);
455 	*countp = count;
456 	return (PSVC_SUCCESS);
457 }
458 
459 /*
460  * Find number of matches to an antecedent_id of a certain
461  * association type.
462  */
463 static int32_t
i_psvc_get_assoc_matches(EHdl_t * hdlp,char * antecedent,int32_t assoc_id,int32_t * matches)464 i_psvc_get_assoc_matches(EHdl_t *hdlp, char *antecedent, int32_t assoc_id,
465 	int32_t *matches)
466 {
467 	int i;
468 	int32_t key;
469 	EAssocList_t *ap = hdlp->assoc_tbl + assoc_id;
470 
471 	*matches = 0;
472 
473 	if (ap->table == 0) {
474 		errno = EINVAL;
475 		return (PSVC_FAILURE);
476 	}
477 
478 	key = psvc_get_str_key(antecedent);
479 
480 	for (i = 0; i < ap->count; ++i) {
481 		if (ap->table[i].ant_key == key) {
482 			if (strcmp(ap->table[i].antecedent_id, antecedent)
483 			    == 0)
484 				++*matches;
485 		}
486 	}
487 	return (PSVC_SUCCESS);
488 }
489 
490 /*
491  * Find 1st m matches to an antecedent_id of a certain
492  * association type.
493  * Returns zero for success, -1 for failure.
494  */
495 static int32_t
i_psvc_get_assoc_id(EHdl_t * hdlp,char * antecedent,int32_t assoc_id,int32_t match,char ** id_list)496 i_psvc_get_assoc_id(EHdl_t *hdlp, char *antecedent, int32_t assoc_id,
497 	int32_t match, char **id_list)
498 {
499 	int i;
500 	int found = 0;
501 	int32_t key;
502 	EAssocList_t *ap = &hdlp->assoc_tbl[assoc_id];
503 
504 	if (ap->table == 0) {
505 		errno = EINVAL;
506 		return (-1);
507 	}
508 
509 	key = psvc_get_str_key(antecedent);
510 
511 	for (i = 0; i < ap->count; ++i) {
512 		if (ap->table[i].ant_key == key) {
513 			if (strcmp(ap->table[i].antecedent_id, antecedent)
514 			    == 0) {
515 				if (found == match) {
516 					*id_list = ap->table[i].dependent_id;
517 					return (0);
518 				}
519 				++found;
520 			}
521 		}
522 	}
523 
524 	errno = EINVAL;
525 	return (-1);
526 }
527 
528 static int32_t
i_psvc_get_table_value(EHdl_t * hdlp,char * table_id,uint32_t index,void * value)529 i_psvc_get_table_value(EHdl_t *hdlp, char *table_id, uint32_t index,
530 	void *value)
531 {
532 	int32_t i;
533 	ETable_t *tblp;
534 	ETable_Array *tbl_arr;
535 	int32_t key, array;
536 
537 	key = psvc_get_str_key(table_id);
538 	array = key % PSVC_MAX_TABLE_ARRAYS;
539 	tbl_arr = &(hdlp->tbl_arry[array]);
540 
541 	for (i = 0; i < tbl_arr->obj_count; ++i) {
542 		if (key == tbl_arr->obj_tbl[i].key) {
543 			if (strcmp(tbl_arr->obj_tbl[i].name,
544 				table_id) == 0)
545 				break;
546 		}
547 	}
548 
549 	if (tbl_arr->obj_tbl[i].type != PSVC_TBL)
550 		return (PSVC_FAILURE);
551 
552 	tblp = (ETable_t *)tbl_arr->obj_tbl[i].objp;
553 
554 	if (tblp->table == NULL)
555 		return (PSVC_FAILURE);
556 
557 	if (index >= tblp->size)
558 		return (PSVC_FAILURE);
559 
560 	switch (tblp->cell_type) {
561 		case 0:
562 			*(int8_t *)value = *((int8_t *)tblp->table + index);
563 			break;
564 		case 1:
565 			*(uint8_t *)value = *((uint8_t *)tblp->table + index);
566 			break;
567 		case 2:
568 			*(int16_t *)value = *((int16_t *)tblp->table + index);
569 			break;
570 		case 3:
571 			*(uint16_t *)value = *((uint16_t *)tblp->table + index);
572 			break;
573 		case 4:
574 			*(int32_t *)value = *((int32_t *)tblp->table + index);
575 			break;
576 		case 5:
577 			*(uint32_t *)value = *((uint32_t *)tblp->table + index);
578 			break;
579 		case 6:
580 			*(int64_t *)value = *((int64_t *)tblp->table + index);
581 			break;
582 		case 7:
583 			*(uint64_t *)value = *((uint64_t *)tblp->table + index);
584 			break;
585 		default:
586 			return (PSVC_FAILURE);
587 	}
588 
589 	return (PSVC_SUCCESS);
590 }
591 
592 int32_t
psvc_get_attr(EHdl_t * hdlp,char * name,int32_t attr_id,void * attr_valuep,...)593 psvc_get_attr(EHdl_t *hdlp, char *name, int32_t attr_id, void *attr_valuep, ...)
594 {
595 	EObj_t *objp;
596 	int32_t status = PSVC_SUCCESS;
597 	int32_t arg1, arg2;
598 	va_list ap;
599 
600 	pthread_mutex_lock(&hdlp->mutex);
601 
602 	if (attr_valuep == NULL) {
603 		errno = EFAULT;
604 		pthread_mutex_unlock(&hdlp->mutex);
605 		return (PSVC_FAILURE);
606 	}
607 
608 	switch (attr_id) {
609 	case PSVC_TABLE_VALUE_ATTR:
610 		va_start(ap, attr_valuep);
611 		status = i_psvc_get_table_value(hdlp, name,
612 			va_arg(ap, uint32_t), attr_valuep);
613 		va_end(ap);
614 		break;
615 	case PSVC_ASSOC_MATCHES_ATTR:
616 		va_start(ap, attr_valuep);
617 		status = i_psvc_get_assoc_matches(hdlp, name,
618 			va_arg(ap, int32_t), attr_valuep);
619 		va_end(ap);
620 		break;
621 	case PSVC_ASSOC_ID_ATTR:
622 		va_start(ap, attr_valuep);
623 		arg1 = va_arg(ap, int32_t);
624 		arg2 = va_arg(ap, int32_t);
625 		status = i_psvc_get_assoc_id(hdlp, name,
626 		    arg1, arg2, attr_valuep);
627 		va_end(ap);
628 		break;
629 	default:
630 		status = i_psvc_get_obj(hdlp, name, &objp);
631 		if (status != PSVC_SUCCESS) {
632 			pthread_mutex_unlock(&hdlp->mutex);
633 			return (status);
634 		}
635 		status = (*objp->get_attr)(hdlp, objp, attr_id,
636 			attr_valuep);
637 	}
638 
639 	if (status != PSVC_SUCCESS) {
640 		pthread_mutex_unlock(&hdlp->mutex);
641 		return (status);
642 	}
643 
644 	pthread_mutex_unlock(&hdlp->mutex);
645 	return (status);
646 }
647 
648 int32_t
psvc_set_attr(EHdl_t * hdlp,char * name,int32_t attr_id,void * attr_valuep)649 psvc_set_attr(EHdl_t *hdlp, char *name, int32_t attr_id, void *attr_valuep)
650 {
651 	EObj_t *objp;
652 	int32_t status = PSVC_SUCCESS;
653 
654 	pthread_mutex_lock(&hdlp->mutex);
655 	status = i_psvc_get_obj(hdlp, name, &objp);
656 	if (status != PSVC_SUCCESS) {
657 		pthread_mutex_unlock(&hdlp->mutex);
658 		return (status);
659 	}
660 
661 	if (attr_valuep == NULL) {
662 		errno = EFAULT;
663 		pthread_mutex_unlock(&hdlp->mutex);
664 		return (PSVC_FAILURE);
665 	}
666 
667 	status = (*objp->set_attr)(hdlp, objp, attr_id, attr_valuep);
668 	if (status != PSVC_SUCCESS) {
669 		pthread_mutex_unlock(&hdlp->mutex);
670 		return (status);
671 	}
672 
673 	pthread_mutex_unlock(&hdlp->mutex);
674 	return (status);
675 }
676 
677 
678 static int32_t
i_psvc_get_presence(EHdl_t * hdlp,EObj_t * objp,boolean_t * pr)679 i_psvc_get_presence(EHdl_t *hdlp, EObj_t *objp, boolean_t *pr)
680 {
681 	EObj_t *pobjp, *mobjp;
682 	int32_t matches;
683 	char *mid;
684 	char *parent_id;
685 	int32_t status = PSVC_SUCCESS;
686 	uint8_t value_8bit, value_8bit_inv;
687 	boolean_t active_low, value;
688 
689 	if (strcmp(objp->label, PSVC_CHASSIS) == 0) {
690 		*pr = PSVC_PRESENT;
691 		objp->present = PSVC_PRESENT;
692 		return (PSVC_SUCCESS);
693 	}
694 
695 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PARENT, 0,
696 		&parent_id);
697 	if (status != PSVC_SUCCESS)
698 		return (status);
699 
700 	if (strcmp(parent_id, PSVC_CHASSIS)) {
701 		status = i_psvc_get_obj(hdlp, parent_id, &pobjp);
702 		if (status != PSVC_SUCCESS)
703 			return (status);
704 		if (!pobjp->present) {
705 			pobjp->get_attr(hdlp, pobjp, PSVC_PRESENCE_ATTR, pr);
706 			*pr = pobjp->present;
707 			objp->present = pobjp->present;
708 			return (status);
709 		}
710 	}
711 
712 	(void) i_psvc_get_assoc_matches(hdlp, objp->label,
713 		PSVC_PRESENCE_SENSOR, &matches);
714 
715 	if (matches != 0) {
716 		status = i_psvc_get_assoc_id(hdlp, objp->label,
717 		    PSVC_PRESENCE_SENSOR, 0, &mid);
718 		if (status != PSVC_SUCCESS)
719 			return (status);
720 		status = i_psvc_get_obj(hdlp, mid, &mobjp);
721 		if (status != PSVC_SUCCESS)
722 			return (status);
723 
724 		active_low = PSVC_IS_ACTIVE_LOW(mobjp->addr_spec);
725 
726 		if (mobjp->class == PSVC_BOOLEAN_GPIO_CLASS) {
727 			status = mobjp->get_attr(hdlp, mobjp,
728 				PSVC_GPIO_VALUE_ATTR, &value);
729 			if (status != PSVC_SUCCESS)
730 				return (status);
731 			if (active_low)
732 				if (value == 0)
733 					*pr = PSVC_PRESENT;
734 				else
735 					*pr = PSVC_ABSENT;
736 			else
737 				if (value == 0)
738 					*pr = PSVC_ABSENT;
739 				else
740 					*pr = PSVC_PRESENT;
741 		} else if (mobjp->class == PSVC_8BIT_GPIO_CLASS) {
742 			uint8_t bitshift, bytemask;
743 
744 			status = mobjp->get_attr(hdlp, mobjp,
745 				PSVC_GPIO_VALUE_ATTR, &value_8bit);
746 			if (status != PSVC_SUCCESS)
747 				return (status);
748 			if (PSVC_HP_INVERT(mobjp->addr_spec))
749 				value_8bit_inv = ~value_8bit;
750 			else
751 				value_8bit_inv = value_8bit;
752 			bitshift = PSVC_GET_ASPEC_BITSHIFT(mobjp->addr_spec);
753 			bytemask = PSVC_GET_ASPEC_BYTEMASK(mobjp->addr_spec);
754 			value_8bit_inv =
755 				value_8bit_inv & (bytemask >> bitshift);
756 			if (active_low)
757 				if (value_8bit_inv == 0)
758 					*pr = PSVC_PRESENT;
759 				else
760 					*pr = PSVC_ABSENT;
761 			else
762 				if (value_8bit_inv == 0)
763 					*pr = PSVC_ABSENT;
764 				else
765 					*pr = PSVC_PRESENT;
766 		} else {
767 			errno = EINVAL;
768 			return (PSVC_FAILURE);
769 		}
770 	} else {
771 		*pr = PSVC_PRESENT;
772 	}
773 
774 	objp->present = *pr;
775 
776 	return (status);
777 }
778 
779 static int32_t
i_psvc_get_device_value_0_0(EHdl_t * hdlp,EObj_t * objp,int32_t * temp)780 i_psvc_get_device_value_0_0(EHdl_t *hdlp, EObj_t *objp, int32_t *temp)
781 {
782 	int32_t status = PSVC_SUCCESS, m;
783 	char *tid;
784 	int16_t temp16;
785 	char *physid;
786 	EObj_t *physobjp;
787 
788 	if (objp->present != PSVC_PRESENT) {
789 		errno = ENODEV;
790 		return (PSVC_FAILURE);
791 	}
792 
793 	status = i_psvc_get_assoc_id(
794 		hdlp, objp->label, PSVC_PHYSICAL_DEVICE, 0, &physid);
795 	if (status != PSVC_SUCCESS) {
796 		return (status);
797 	}
798 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
799 	if (status != PSVC_SUCCESS) {
800 		return (status);
801 	}
802 
803 	status = ((EPhysDev_t *)physobjp)->get_temperature(hdlp,
804 		objp->addr_spec, temp);
805 	if (status != PSVC_SUCCESS) {
806 		return (status);
807 	}
808 
809 	if (objp->features & PSVC_CONVERSION_TABLE) {
810 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
811 		    PSVC_TABLE, &m);
812 		if ((status != PSVC_SUCCESS) || (m != 1)) {
813 			return (status);
814 		}
815 
816 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
817 			&tid);
818 
819 		status = i_psvc_get_table_value(hdlp, tid, *temp, &temp16);
820 		*temp = temp16;
821 	}
822 	return (status);
823 }
824 
825 static int32_t
i_psvc_get_device_value_0_1(EHdl_t * hdlp,EObj_t * objp,int32_t * temp)826 i_psvc_get_device_value_0_1(EHdl_t *hdlp, EObj_t *objp, int32_t *temp)
827 {
828 	int32_t status = PSVC_SUCCESS, m;
829 	char *tid;
830 	int16_t temp16;
831 	char *physid;
832 	EObj_t *physobjp;
833 
834 	if (objp->present != PSVC_PRESENT) {
835 		errno = ENODEV;
836 		return (PSVC_FAILURE);
837 	}
838 
839 	status = i_psvc_get_assoc_id(
840 		hdlp, objp->label, PSVC_PHYSICAL_DEVICE, 0, &physid);
841 	if (status != PSVC_SUCCESS) {
842 		return (status);
843 	}
844 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
845 	if (status != PSVC_SUCCESS) {
846 		return (status);
847 	}
848 
849 	status = ((EPhysDev_t *)physobjp)->get_temperature(hdlp,
850 		objp->addr_spec, temp);
851 	if (status != PSVC_SUCCESS) {
852 		return (status);
853 	}
854 
855 	if (objp->features & PSVC_CONVERSION_TABLE) {
856 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
857 		    PSVC_TABLE, &m);
858 		if ((status != PSVC_SUCCESS) || (m != 1)) {
859 			return (status);
860 		}
861 
862 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
863 			&tid);
864 
865 		status = i_psvc_get_table_value(hdlp, tid, *temp, &temp16);
866 		*temp = temp16;
867 	}
868 	return (status);
869 }
870 
871 static int32_t
i_psvc_get_device_value_4_0(EHdl_t * hdlp,EObj_t * objp,int32_t * value)872 i_psvc_get_device_value_4_0(EHdl_t *hdlp, EObj_t *objp, int32_t *value)
873 {
874 	int32_t status = PSVC_SUCCESS;
875 	char *physid;
876 	EObj_t *physobjp;
877 
878 	if (objp->present != PSVC_PRESENT) {
879 		errno = ENODEV;
880 		return (PSVC_FAILURE);
881 	}
882 
883 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
884 		0, &physid);
885 	if (status != PSVC_SUCCESS)
886 		return (status);
887 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
888 	if (status != PSVC_SUCCESS)
889 		return (status);
890 
891 	status = ((EPhysDev_t *)physobjp)->get_input(hdlp, objp->addr_spec,
892 		value);
893 	if (status != PSVC_SUCCESS)
894 		return (status);
895 
896 	if (objp->features & PSVC_CONVERSION_TABLE) {
897 		int32_t m;
898 		char *tid;
899 		int16_t temp16;
900 
901 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
902 		    PSVC_TABLE, &m);
903 		if ((status != PSVC_SUCCESS) || (m != 1)) {
904 			return (status);
905 		}
906 
907 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
908 			&tid);
909 
910 		status = i_psvc_get_table_value(hdlp, tid, *value, &temp16);
911 		*value = temp16;
912 	}
913 
914 	return (status);
915 }
916 
917 static int32_t
i_psvc_set_device_value_5_0(EHdl_t * hdlp,EObj_t * objp,int32_t * value)918 i_psvc_set_device_value_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t *value)
919 {
920 	int32_t status = PSVC_SUCCESS;
921 	char *physid;
922 	EObj_t *physobjp;
923 
924 	if (objp->present != PSVC_PRESENT) {
925 		errno = ENODEV;
926 		return (PSVC_FAILURE);
927 	}
928 
929 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
930 		0, &physid);
931 	if (status != PSVC_SUCCESS)
932 		return (status);
933 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
934 	if (status != PSVC_SUCCESS)
935 		return (status);
936 	status = ((EPhysDev_t *)physobjp)->set_output(hdlp, objp->addr_spec,
937 		*value);
938 	if (status != PSVC_SUCCESS)
939 		return (status);
940 
941 	return (status);
942 }
943 
944 static int32_t
i_psvc_get_device_value_5_0(EHdl_t * hdlp,EObj_t * objp,int32_t * value)945 i_psvc_get_device_value_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t *value)
946 {
947 	int32_t status = PSVC_SUCCESS;
948 	char *physid;
949 	EObj_t *physobjp;
950 
951 	if (objp->present != PSVC_PRESENT) {
952 		errno = ENODEV;
953 		return (PSVC_FAILURE);
954 	}
955 
956 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
957 		0, &physid);
958 	if (status != PSVC_SUCCESS)
959 		return (status);
960 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
961 	if (status != PSVC_SUCCESS)
962 		return (status);
963 
964 	status = ((EPhysDev_t *)physobjp)->get_output(hdlp, objp->addr_spec,
965 		value);
966 	if (status != PSVC_SUCCESS)
967 		return (status);
968 
969 	if (objp->features & PSVC_CONVERSION_TABLE) {
970 		int32_t m;
971 		char *tid;
972 		int16_t temp16;
973 
974 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
975 		    PSVC_TABLE, &m);
976 		if ((status != PSVC_SUCCESS) || (m != 1)) {
977 			return (status);
978 		}
979 
980 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
981 			&tid);
982 
983 		status = i_psvc_get_table_value(hdlp, tid, *value, &temp16);
984 		*value = temp16;
985 	}
986 	return (status);
987 }
988 
989 static int32_t
i_psvc_get_device_value_6_0(EHdl_t * hdlp,EObj_t * objp,boolean_t * value)990 i_psvc_get_device_value_6_0(EHdl_t *hdlp, EObj_t *objp, boolean_t *value)
991 {
992 	int32_t status = PSVC_SUCCESS;
993 	int32_t bit_value;
994 	char *physid;
995 	EObj_t *physobjp;
996 
997 	if (objp->present != PSVC_PRESENT) {
998 		errno = ENODEV;
999 		return (PSVC_FAILURE);
1000 	}
1001 
1002 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1003 		0, &physid);
1004 	if (status != PSVC_SUCCESS)
1005 		return (status);
1006 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1007 	if (status != PSVC_SUCCESS)
1008 		return (status);
1009 
1010 	status = ((EPhysDev_t *)physobjp)->get_bit(hdlp, objp->addr_spec,
1011 		&bit_value);
1012 	if (status != PSVC_SUCCESS)
1013 		return (status);
1014 
1015 	*value = bit_value;
1016 
1017 	return (status);
1018 }
1019 
1020 static int32_t
i_psvc_set_device_value_6_0(EHdl_t * hdlp,EObj_t * objp,boolean_t * value)1021 i_psvc_set_device_value_6_0(EHdl_t *hdlp, EObj_t *objp, boolean_t *value)
1022 {
1023 	int32_t status = PSVC_SUCCESS;
1024 	int32_t bit_value;
1025 	char *physid;
1026 	EObj_t *physobjp;
1027 
1028 	if (objp->present != PSVC_PRESENT) {
1029 		errno = ENODEV;
1030 		return (PSVC_FAILURE);
1031 	}
1032 
1033 	bit_value = *value;
1034 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1035 		0, &physid);
1036 	if (status != PSVC_SUCCESS)
1037 		return (status);
1038 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1039 	if (status != PSVC_SUCCESS)
1040 		return (status);
1041 
1042 	status = ((EPhysDev_t *)physobjp)->set_bit(hdlp, objp->addr_spec,
1043 		bit_value);
1044 	if (status != PSVC_SUCCESS)
1045 		return (status);
1046 
1047 	return (status);
1048 }
1049 
1050 static int32_t
i_psvc_get_device_value_1_0(EHdl_t * hdlp,EObj_t * objp,int32_t * fan_speed)1051 i_psvc_get_device_value_1_0(EHdl_t *hdlp, EObj_t *objp, int32_t *fan_speed)
1052 {
1053 	int32_t status = PSVC_SUCCESS;
1054 	EObj_t *ftobjp;
1055 	char *fan_tach;
1056 
1057 	if (objp->present != PSVC_PRESENT) {
1058 		errno = ENODEV;
1059 		return (PSVC_FAILURE);
1060 	}
1061 
1062 	status = i_psvc_get_assoc_id(hdlp, objp->label,
1063 		PSVC_FAN_SPEED_TACHOMETER, 0, &fan_tach);
1064 	if (status != PSVC_SUCCESS)
1065 		return (status);
1066 
1067 	status = i_psvc_get_obj(hdlp, fan_tach, &ftobjp);
1068 	if (status != PSVC_SUCCESS)
1069 		return (status);
1070 
1071 	status = ftobjp->get_attr(hdlp, ftobjp, PSVC_SENSOR_VALUE_ATTR,
1072 		fan_speed);
1073 	if (status != PSVC_SUCCESS)
1074 		return (status);
1075 
1076 	return (status);
1077 }
1078 
1079 static int32_t
i_psvc_get_device_value_7_0(EHdl_t * hdlp,EObj_t * objp,int32_t * fan_speed)1080 i_psvc_get_device_value_7_0(EHdl_t *hdlp, EObj_t *objp, int32_t *fan_speed)
1081 {
1082 	char *physid;
1083 	EObj_t *physobjp;
1084 	int32_t status = PSVC_SUCCESS;
1085 
1086 	if (objp->present != PSVC_PRESENT) {
1087 		errno = ENODEV;
1088 		return (PSVC_FAILURE);
1089 	}
1090 
1091 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1092 		0, &physid);
1093 	if (status != PSVC_SUCCESS)
1094 		return (status);
1095 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1096 	if (status != PSVC_SUCCESS)
1097 		return (status);
1098 
1099 	status = ((EPhysDev_t *)physobjp)->get_fanspeed(hdlp, objp->addr_spec,
1100 		fan_speed);
1101 	if (status != PSVC_SUCCESS)
1102 		return (status);
1103 
1104 	if (objp->features & PSVC_CONVERSION_TABLE) {
1105 		int32_t m;
1106 		char *tid;
1107 		int16_t temp16;
1108 
1109 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
1110 		    PSVC_TABLE, &m);
1111 		if ((status != PSVC_SUCCESS) || (m != 1)) {
1112 			return (status);
1113 		}
1114 
1115 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
1116 			&tid);
1117 
1118 		status = i_psvc_get_table_value(hdlp, tid, *fan_speed, &temp16);
1119 		*fan_speed = temp16;
1120 	}
1121 	return (status);
1122 }
1123 
1124 static int32_t
i_psvc_get_device_state_2_0(EHdl_t * hdlp,EObj_t * objp,char * led_state)1125 i_psvc_get_device_state_2_0(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1126 {
1127 	int32_t status = PSVC_SUCCESS;
1128 	int32_t bit_value;
1129 	boolean_t active_low;
1130 	char *physid;
1131 	EObj_t *physobjp;
1132 
1133 	if (objp->present != PSVC_PRESENT) {
1134 		errno = ENODEV;
1135 		return (PSVC_FAILURE);
1136 	}
1137 
1138 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1139 		0, &physid);
1140 	if (status != PSVC_SUCCESS)
1141 		return (status);
1142 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1143 	if (status != PSVC_SUCCESS)
1144 		return (status);
1145 
1146 	status = ((EPhysDev_t *)physobjp)->get_bit(hdlp, objp->addr_spec,
1147 		&bit_value);
1148 	if (status != PSVC_SUCCESS)
1149 		return (status);
1150 
1151 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1152 	if (active_low)
1153 		if (bit_value == 0)
1154 			strcpy(led_state, PSVC_LED_ON);
1155 		else
1156 			strcpy(led_state, PSVC_LED_OFF);
1157 	else
1158 		if (bit_value == 0)
1159 			strcpy(led_state, PSVC_LED_OFF);
1160 		else
1161 			strcpy(led_state, PSVC_LED_ON);
1162 
1163 	return (status);
1164 }
1165 
1166 static int32_t
i_psvc_set_device_state_2_0(EHdl_t * hdlp,EObj_t * objp,char * led_state)1167 i_psvc_set_device_state_2_0(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1168 {
1169 	int32_t status = PSVC_SUCCESS;
1170 	boolean_t active_low;
1171 	int32_t bit_value;
1172 	char *physid;
1173 	EObj_t *physobjp;
1174 
1175 	if (objp->present != PSVC_PRESENT) {
1176 		errno = ENODEV;
1177 		return (PSVC_FAILURE);
1178 	}
1179 
1180 	if (strcmp(((ELed_t *)objp)->is_locator, PSVC_LOCATOR_TRUE) != 0) {
1181 		/*
1182 		 * For Locator LEDs we ignore lit_count.  RSC may have
1183 		 * altered the LED state underneath us, So we should
1184 		 * always just do what the user asked instead of trying
1185 		 * to be smart.
1186 		 */
1187 
1188 		if (strcmp(led_state, PSVC_LED_ON) == 0)
1189 			((ELed_t *)objp)->lit_count++;
1190 		else if (strcmp(led_state, PSVC_LED_OFF) == 0) {
1191 			if (--((ELed_t *)objp)->lit_count > 0) {
1192 				return (PSVC_SUCCESS);
1193 			} else if (((ELed_t *)objp)->lit_count < 0)
1194 				((ELed_t *)objp)->lit_count = 0;
1195 			/* Fall through case is when lit_count is 0 */
1196 		}
1197 	}
1198 
1199 	strcpy(objp->previous_state, objp->state);
1200 	strcpy(objp->state, led_state);
1201 
1202 	bit_value = (strcmp(led_state, PSVC_LED_ON) == 0);
1203 
1204 	/*
1205 	 * Flip the bit if necessary (for active_low devices,
1206 	 * O ==> ON; 1 ==> OFF.
1207 	 */
1208 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1209 	bit_value ^= active_low;
1210 
1211 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1212 		0, &physid);
1213 	if (status != PSVC_SUCCESS)
1214 		return (status);
1215 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1216 	if (status != PSVC_SUCCESS)
1217 		return (status);
1218 
1219 	status = ((EPhysDev_t *)physobjp)->set_bit(hdlp, objp->addr_spec,
1220 		bit_value);
1221 	return (status);
1222 }
1223 
1224 static int32_t
i_psvc_get_device_state_2_1(EHdl_t * hdlp,EObj_t * objp,char * led_state)1225 i_psvc_get_device_state_2_1(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1226 {
1227 	int32_t status = PSVC_SUCCESS;
1228 	uint8_t value;
1229 	char *physid;
1230 	EObj_t *physobjp;
1231 
1232 	if (objp->present != PSVC_PRESENT) {
1233 		errno = ENODEV;
1234 		return (PSVC_FAILURE);
1235 	}
1236 
1237 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1238 		0, &physid);
1239 	if (status != PSVC_SUCCESS)
1240 		return (status);
1241 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1242 	if (status != PSVC_SUCCESS)
1243 		return (status);
1244 
1245 	status = ((EPhysDev_t *)physobjp)->get_reg(hdlp, objp->addr_spec,
1246 		&value);
1247 	if (status != PSVC_SUCCESS)
1248 		return (status);
1249 
1250 	switch (value) {
1251 	case 0:
1252 		strcpy(led_state, PSVC_LED_OFF);
1253 		break;
1254 	case 1:
1255 		strcpy(led_state, PSVC_LED_SLOW_BLINK);
1256 		break;
1257 	case 2:
1258 		strcpy(led_state, PSVC_LED_FAST_BLINK);
1259 		break;
1260 	case 3:
1261 		strcpy(led_state, PSVC_LED_ON);
1262 		break;
1263 	}
1264 
1265 	return (status);
1266 }
1267 
1268 static int32_t
i_psvc_set_device_state_2_1(EHdl_t * hdlp,EObj_t * objp,char * led_state)1269 i_psvc_set_device_state_2_1(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1270 {
1271 	int32_t status = PSVC_SUCCESS;
1272 	uint8_t value;
1273 	char *physid;
1274 	EObj_t *physobjp;
1275 
1276 	if (objp->present != PSVC_PRESENT) {
1277 		errno = ENODEV;
1278 		return (PSVC_FAILURE);
1279 	}
1280 
1281 	if (strcmp(led_state, PSVC_LED_ON) == 0)
1282 		((ELed_t *)objp)->lit_count++;
1283 	else if (strcmp(led_state, PSVC_LED_OFF) == 0) {
1284 		if (--((ELed_t *)objp)->lit_count > 0) {
1285 			return (PSVC_SUCCESS);
1286 		} else if (((ELed_t *)objp)->lit_count < 0)
1287 			((ELed_t *)objp)->lit_count = 0;
1288 
1289 		/* Fall through case is when lit_count is 0 */
1290 	}
1291 
1292 	strcpy(objp->previous_state, objp->state);
1293 	strcpy(objp->state, led_state);
1294 
1295 	if (strcmp(led_state, PSVC_LED_OFF) == 0)
1296 		value = 0;
1297 	else if (strcmp(led_state, PSVC_LED_SLOW_BLINK) == 0)
1298 		value = 1;
1299 	else if (strcmp(led_state, PSVC_LED_FAST_BLINK) == 0)
1300 		value = 2;
1301 	else if (strcmp(led_state, PSVC_LED_ON) == 0)
1302 		value = 3;
1303 
1304 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1305 		0, &physid);
1306 	if (status != PSVC_SUCCESS)
1307 		return (status);
1308 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1309 	if (status != PSVC_SUCCESS)
1310 		return (status);
1311 
1312 	status = ((EPhysDev_t *)physobjp)->set_reg(hdlp, objp->addr_spec,
1313 		value);
1314 
1315 	return (status);
1316 }
1317 
1318 static int32_t
i_psvc_get_device_state_9_0(EHdl_t * hdlp,EObj_t * objp,char * pos)1319 i_psvc_get_device_state_9_0(EHdl_t *hdlp, EObj_t *objp, char *pos)
1320 {
1321 	int32_t status = PSVC_SUCCESS, matches;
1322 	char *sensorid;
1323 	EObj_t *sensorp;
1324 	char state[32];
1325 
1326 	if (objp->present != PSVC_PRESENT) {
1327 		errno = ENODEV;
1328 		return (PSVC_FAILURE);
1329 	}
1330 
1331 	if (objp->features & PSVC_NORMAL_POS_AV) {
1332 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1333 		    PSVC_KS_NORMAL_POS_SENSOR, &matches);
1334 		if (matches == 1) {
1335 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1336 				PSVC_KS_NORMAL_POS_SENSOR, 0, &sensorid);
1337 			if (status != PSVC_SUCCESS)
1338 				return (status);
1339 
1340 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1341 			if (status != PSVC_SUCCESS)
1342 				return (status);
1343 
1344 			status = sensorp->get_attr(hdlp, sensorp,
1345 				PSVC_SWITCH_STATE_ATTR, state);
1346 			if (status != PSVC_SUCCESS)
1347 				return (status);
1348 
1349 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1350 				strcpy(pos, PSVC_NORMAL_POS);
1351 				return (PSVC_SUCCESS);
1352 			}
1353 		}
1354 	}
1355 
1356 	if (objp->features & PSVC_DIAG_POS_AV) {
1357 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1358 		    PSVC_KS_DIAG_POS_SENSOR, &matches);
1359 		if (matches == 1) {
1360 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1361 			    PSVC_KS_DIAG_POS_SENSOR, 0, &sensorid);
1362 			if (status != PSVC_SUCCESS)
1363 				return (status);
1364 
1365 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1366 			if (status != PSVC_SUCCESS)
1367 				return (status);
1368 
1369 			status = sensorp->get_attr(hdlp, sensorp,
1370 				PSVC_SWITCH_STATE_ATTR, state);
1371 			if (status != PSVC_SUCCESS)
1372 				return (status);
1373 
1374 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1375 				strcpy(pos, PSVC_DIAG_POS);
1376 				return (PSVC_SUCCESS);
1377 			}
1378 		}
1379 	}
1380 
1381 	if (objp->features & PSVC_LOCK_POS_AV) {
1382 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1383 		    PSVC_KS_LOCK_POS_SENSOR, &matches);
1384 		if (matches == 1) {
1385 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1386 			    PSVC_KS_LOCK_POS_SENSOR, 0, &sensorid);
1387 			if (status != PSVC_SUCCESS)
1388 				return (status);
1389 
1390 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1391 			if (status != PSVC_SUCCESS)
1392 				return (status);
1393 
1394 			status = sensorp->get_attr(hdlp, sensorp,
1395 				PSVC_SWITCH_STATE_ATTR, state);
1396 			if (status != PSVC_SUCCESS)
1397 				return (status);
1398 
1399 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1400 				strcpy(pos, PSVC_LOCKED_POS);
1401 				return (PSVC_SUCCESS);
1402 			}
1403 		}
1404 	}
1405 
1406 	if (objp->features & PSVC_OFF_POS_AV) {
1407 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1408 		    PSVC_KS_OFF_POS_SENSOR, &matches);
1409 		if (matches == 1) {
1410 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1411 			    PSVC_KS_OFF_POS_SENSOR, 0, &sensorid);
1412 			if (status != PSVC_SUCCESS)
1413 				return (status);
1414 
1415 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1416 			if (status != PSVC_SUCCESS)
1417 				return (status);
1418 
1419 			status = sensorp->get_attr(hdlp, sensorp,
1420 				PSVC_SWITCH_STATE_ATTR, state);
1421 			if (status != PSVC_SUCCESS)
1422 				return (status);
1423 
1424 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1425 				strcpy(pos, PSVC_OFF_POS);
1426 				return (PSVC_SUCCESS);
1427 			}
1428 		}
1429 	}
1430 	/* If we have fallen through till here, something's wrong */
1431 	errno = EINVAL;
1432 	return (PSVC_FAILURE);
1433 }
1434 
1435 
1436 static int32_t
i_psvc_get_device_value_10_0(EHdl_t * hdlp,EObj_t * objp,uint8_t * value)1437 i_psvc_get_device_value_10_0(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1438 {
1439 	int32_t status = PSVC_SUCCESS;
1440 	char *physid;
1441 	EObj_t *physobjp;
1442 
1443 	if (objp->present != PSVC_PRESENT) {
1444 		errno = ENODEV;
1445 		return (PSVC_FAILURE);
1446 	}
1447 
1448 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1449 		0, &physid);
1450 	if (status != PSVC_SUCCESS)
1451 		return (status);
1452 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1453 	if (status != PSVC_SUCCESS)
1454 		return (status);
1455 
1456 	status = ((EPhysDev_t *)physobjp)->get_reg(hdlp, objp->addr_spec,
1457 		value);
1458 	if (status != PSVC_SUCCESS)
1459 		return (status);
1460 
1461 	if (objp->features & PSVC_CONVERSION_TABLE) {
1462 		int32_t m;
1463 		char *tid;
1464 		uint8_t temp8;
1465 
1466 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
1467 		    PSVC_TABLE, &m);
1468 		if ((status != PSVC_SUCCESS) || (m != 1)) {
1469 			return (status);
1470 		}
1471 
1472 		(void) i_psvc_get_assoc_id(hdlp, objp->label,
1473 			PSVC_TABLE, 0, &tid);
1474 
1475 		status = i_psvc_get_table_value(hdlp, tid, *value, &temp8);
1476 		*value = temp8;
1477 	}
1478 	return (status);
1479 }
1480 
1481 static int32_t
i_psvc_get_device_value_10_1(EHdl_t * hdlp,EObj_t * objp,uint8_t * value)1482 i_psvc_get_device_value_10_1(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1483 {
1484 	int32_t status = PSVC_SUCCESS;
1485 	char *physid;
1486 	EObj_t *physobjp;
1487 
1488 	if (objp->present != PSVC_PRESENT) {
1489 		errno = ENODEV;
1490 		return (PSVC_FAILURE);
1491 	}
1492 
1493 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1494 		0, &physid);
1495 	if (status != PSVC_SUCCESS)
1496 		return (status);
1497 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1498 	if (status != PSVC_SUCCESS)
1499 		return (status);
1500 
1501 	status = ((EPhysDev_t *)physobjp)->get_port(hdlp, objp->addr_spec,
1502 		value);
1503 	if (status != PSVC_SUCCESS)
1504 		return (status);
1505 
1506 	return (status);
1507 }
1508 
1509 static int32_t
i_psvc_set_device_value_10_0(EHdl_t * hdlp,EObj_t * objp,uint8_t * value)1510 i_psvc_set_device_value_10_0(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1511 {
1512 	int32_t status = PSVC_SUCCESS;
1513 	char *physid;
1514 	EObj_t *physobjp;
1515 
1516 	if (objp->present != PSVC_PRESENT) {
1517 		errno = ENODEV;
1518 		return (PSVC_FAILURE);
1519 	}
1520 
1521 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1522 		0, &physid);
1523 	if (status != PSVC_SUCCESS)
1524 		return (status);
1525 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1526 	if (status != PSVC_SUCCESS)
1527 		return (status);
1528 
1529 	status = ((EPhysDev_t *)physobjp)->set_reg(hdlp, objp->addr_spec,
1530 		*value);
1531 	return (status);
1532 }
1533 
1534 static int32_t
i_psvc_set_device_value_10_1(EHdl_t * hdlp,EObj_t * objp,uint8_t * value)1535 i_psvc_set_device_value_10_1(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1536 {
1537 	int32_t status = PSVC_SUCCESS;
1538 	char *physid;
1539 	EObj_t *physobjp;
1540 
1541 	if (objp->present != PSVC_PRESENT) {
1542 		errno = ENODEV;
1543 		return (PSVC_FAILURE);
1544 	}
1545 
1546 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1547 		0, &physid);
1548 	if (status != PSVC_SUCCESS)
1549 		return (status);
1550 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1551 	if (status != PSVC_SUCCESS)
1552 		return (status);
1553 
1554 	status = ((EPhysDev_t *)physobjp)->set_port(hdlp, objp->addr_spec,
1555 		*value);
1556 	return (status);
1557 }
1558 
1559 static int32_t
i_psvc_get_device_state_8_0(EHdl_t * hdlp,EObj_t * objp,char * sw_state)1560 i_psvc_get_device_state_8_0(EHdl_t *hdlp, EObj_t *objp, char *sw_state)
1561 {
1562 	int32_t status = PSVC_SUCCESS;
1563 	boolean_t active_low;
1564 	int32_t bit_value;
1565 	char *physid;
1566 	EObj_t *physobjp;
1567 
1568 	if (objp->present != PSVC_PRESENT) {
1569 		errno = ENODEV;
1570 		return (PSVC_FAILURE);
1571 	}
1572 
1573 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1574 		0, &physid);
1575 	if (status != PSVC_SUCCESS)
1576 		return (status);
1577 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1578 	if (status != PSVC_SUCCESS)
1579 		return (status);
1580 
1581 	status = ((EPhysDev_t *)physobjp)->get_bit(hdlp, objp->addr_spec,
1582 		&bit_value);
1583 	if (status != PSVC_SUCCESS)
1584 		return (status);
1585 
1586 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1587 	if (active_low)
1588 		if (bit_value == 0)
1589 			strcpy(sw_state, PSVC_SWITCH_ON);
1590 		else
1591 			strcpy(sw_state, PSVC_SWITCH_OFF);
1592 	else
1593 		if (bit_value == 0)
1594 			strcpy(sw_state, PSVC_SWITCH_OFF);
1595 		else
1596 			strcpy(sw_state, PSVC_SWITCH_ON);
1597 
1598 	return (status);
1599 }
1600 
1601 static int32_t
i_psvc_set_device_state_8_0(EHdl_t * hdlp,EObj_t * objp,char * sw_state)1602 i_psvc_set_device_state_8_0(EHdl_t *hdlp, EObj_t *objp, char *sw_state)
1603 {
1604 	int32_t status = PSVC_SUCCESS;
1605 	boolean_t active_low;
1606 	int32_t bit_value;
1607 	char *physid;
1608 	EObj_t *physobjp;
1609 
1610 	if (objp->present != PSVC_PRESENT) {
1611 		errno = ENODEV;
1612 		return (PSVC_FAILURE);
1613 	}
1614 
1615 	strcpy(objp->previous_state, objp->state);
1616 	strcpy(objp->state, sw_state);
1617 
1618 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1619 
1620 	if (active_low)
1621 		if (strcmp(sw_state, PSVC_SWITCH_ON) == 0)
1622 			bit_value = 0;
1623 		else
1624 			bit_value = 1;
1625 	else
1626 		if (strcmp(sw_state, PSVC_SWITCH_ON) == 0)
1627 			bit_value = 1;
1628 		else
1629 			bit_value = 0;
1630 
1631 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1632 		0, &physid);
1633 	if (status != PSVC_SUCCESS)
1634 		return (status);
1635 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1636 	if (status != PSVC_SUCCESS)
1637 		return (status);
1638 
1639 	status = ((EPhysDev_t *)physobjp)->set_bit(hdlp, objp->addr_spec,
1640 		bit_value);
1641 	return (status);
1642 }
1643 
1644 /* LM75 */
1645 static int32_t
i_psvc_get_temperature_11_2(EHdl_t * hdlp,uint64_t aspec,int32_t * temp)1646 i_psvc_get_temperature_11_2(EHdl_t *hdlp, uint64_t aspec, int32_t *temp)
1647 {
1648 	int32_t status = PSVC_SUCCESS;
1649 	char path[1024];
1650 	int32_t fp;
1651 	int16_t temp16;
1652 
1653 	status = i_psvc_get_devpath(hdlp, aspec, path);
1654 	if (status != PSVC_SUCCESS)
1655 		return (status);
1656 
1657 	fp = open(path, O_RDWR);
1658 	if (fp == -1)
1659 		return (PSVC_FAILURE);
1660 
1661 	status = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
1662 	if (status == -1) {
1663 		close(fp);
1664 		errno = EIO;
1665 		return (PSVC_FAILURE);
1666 	}
1667 	*temp = temp16;
1668 
1669 	close(fp);
1670 
1671 	return (status);
1672 }
1673 
1674 /* MAX1617 */
1675 static int32_t
i_psvc_get_temperature_11_4(EHdl_t * hdlp,uint64_t aspec,int32_t * temp)1676 i_psvc_get_temperature_11_4(EHdl_t *hdlp, uint64_t aspec, int32_t *temp)
1677 {
1678 	int32_t status = PSVC_SUCCESS;
1679 	char path[1024];
1680 	int32_t fp;
1681 	int16_t temp16;
1682 
1683 	status = i_psvc_get_devpath(hdlp, aspec, path);
1684 	if (status != PSVC_SUCCESS)
1685 		return (status);
1686 
1687 	fp = open(path, O_RDWR);
1688 	if (fp == -1)
1689 		return (PSVC_FAILURE);
1690 
1691 	status = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
1692 	if (status == -1) {
1693 		close(fp);
1694 		errno = EIO;
1695 		return (PSVC_FAILURE);
1696 	}
1697 	*temp = temp16;
1698 
1699 	close(fp);
1700 
1701 	return (status);
1702 }
1703 
1704 /* PCF8591 */
1705 static int32_t
i_psvc_get_temperature_11_6(EHdl_t * hdlp,uint64_t aspec,int32_t * temp)1706 i_psvc_get_temperature_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t *temp)
1707 {
1708 	int32_t status = PSVC_SUCCESS;
1709 	char path[1024];
1710 	int32_t fp;
1711 
1712 	status = i_psvc_get_devpath(hdlp, aspec, path);
1713 	if (status != PSVC_SUCCESS)
1714 		return (status);
1715 
1716 	fp = open(path, O_RDWR);
1717 	if (fp == -1)
1718 		return (PSVC_FAILURE);
1719 
1720 	status = ioctl_retry(fp, I2C_GET_INPUT, (void *)temp);
1721 	if (status == -1) {
1722 		close(fp);
1723 		errno = EIO;
1724 		return (-1);
1725 	}
1726 
1727 	close(fp);
1728 
1729 	return (status);
1730 }
1731 
1732 /* SSC050 */
1733 static int32_t
i_psvc_get_fanspeed_11_7(EHdl_t * hdlp,uint64_t aspec,int32_t * fan_speed)1734 i_psvc_get_fanspeed_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t *fan_speed)
1735 {
1736 	int32_t ret, status = PSVC_SUCCESS;
1737 	char path[1024];
1738 	int32_t fp;
1739 
1740 	status = i_psvc_get_devpath(hdlp, aspec, path);
1741 	if (status != PSVC_SUCCESS)
1742 		return (status);
1743 
1744 	fp = open(path, O_RDWR);
1745 	if (fp == -1)
1746 		return (PSVC_FAILURE);
1747 
1748 	ret = ioctl_retry(fp, I2C_GET_FAN_SPEED, (void *)fan_speed);
1749 	if (ret == -1) {
1750 		close(fp);
1751 		errno = EIO;
1752 		return (-1);
1753 	}
1754 
1755 	close(fp);
1756 
1757 	return (status);
1758 }
1759 
1760 /* PCF8591 */
1761 static int32_t
i_psvc_get_input_11_6(EHdl_t * hdlp,uint64_t aspec,int32_t * value)1762 i_psvc_get_input_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1763 {
1764 	int32_t ret, status = PSVC_SUCCESS;
1765 	char path[1024];
1766 	int32_t fp;
1767 
1768 	status = i_psvc_get_devpath(hdlp, aspec, path);
1769 	if (status != PSVC_SUCCESS)
1770 		return (status);
1771 
1772 	fp = open(path, O_RDWR);
1773 	if (fp == -1)
1774 		return (PSVC_FAILURE);
1775 
1776 	ret = ioctl_retry(fp, I2C_GET_INPUT, (void *)value);
1777 	if (ret == -1) {
1778 		close(fp);
1779 		errno = EIO;
1780 		return (-1);
1781 	}
1782 
1783 	close(fp);
1784 
1785 	return (status);
1786 }
1787 
1788 /* LTC1427 */
1789 static int32_t
i_psvc_get_output_11_3(EHdl_t * hdlp,uint64_t aspec,int32_t * value)1790 i_psvc_get_output_11_3(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1791 {
1792 	int32_t ret, status = PSVC_SUCCESS;
1793 	char path[1024];
1794 	int32_t fp;
1795 
1796 	status = i_psvc_get_devpath(hdlp, aspec, path);
1797 	if (status != PSVC_SUCCESS)
1798 		return (status);
1799 
1800 	fp = open(path, O_RDWR);
1801 	if (fp == -1)
1802 		return (PSVC_FAILURE);
1803 
1804 	ret = ioctl_retry(fp, I2C_GET_OUTPUT, (void *)value);
1805 	if (ret == -1) {
1806 		close(fp);
1807 		errno = EIO;
1808 		return (PSVC_FAILURE);
1809 	}
1810 
1811 	close(fp);
1812 
1813 	return (status);
1814 }
1815 
1816 /* PCF8591 */
1817 static int32_t
i_psvc_get_output_11_6(EHdl_t * hdlp,uint64_t aspec,int32_t * value)1818 i_psvc_get_output_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1819 {
1820 	int32_t ret, status = PSVC_SUCCESS;
1821 	char path[1024];
1822 	int32_t fp;
1823 
1824 	status = i_psvc_get_devpath(hdlp, aspec, path);
1825 	if (status != PSVC_SUCCESS)
1826 		return (status);
1827 
1828 	fp = open(path, O_RDWR);
1829 	if (fp == -1)
1830 		return (PSVC_FAILURE);
1831 
1832 	ret = ioctl_retry(fp, I2C_GET_OUTPUT, (void *)value);
1833 	if (ret == -1) {
1834 		close(fp);
1835 		errno = EIO;
1836 		return (PSVC_FAILURE);
1837 	}
1838 
1839 	close(fp);
1840 
1841 	return (status);
1842 }
1843 
1844 /* TDA8444 */
1845 static int32_t
i_psvc_get_output_11_8(EHdl_t * hdlp,uint64_t aspec,int32_t * value)1846 i_psvc_get_output_11_8(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1847 {
1848 	int32_t ret, status = PSVC_SUCCESS;
1849 	char path[1024];
1850 	int32_t fp;
1851 	int8_t buf;
1852 
1853 	status = i_psvc_get_devpath(hdlp, aspec, path);
1854 	if (status != PSVC_SUCCESS)
1855 		return (status);
1856 
1857 	fp = open(path, O_RDWR);
1858 	if (fp == -1)
1859 		return (PSVC_FAILURE);
1860 
1861 	ret = read(fp, &buf, 1);
1862 	if (ret == -1) {
1863 		close(fp);
1864 		errno = EIO;
1865 		return (PSVC_FAILURE);
1866 	}
1867 	*value = buf;
1868 
1869 	close(fp);
1870 
1871 	return (status);
1872 }
1873 
1874 /* LTC1427 */
1875 static int32_t
i_psvc_set_output_11_3(EHdl_t * hdlp,uint64_t aspec,int32_t value)1876 i_psvc_set_output_11_3(EHdl_t *hdlp, uint64_t aspec, int32_t value)
1877 {
1878 	int32_t ret, status = PSVC_SUCCESS;
1879 	char path[1024];
1880 	int32_t fp;
1881 
1882 	status = i_psvc_get_devpath(hdlp, aspec, path);
1883 	if (status != PSVC_SUCCESS)
1884 		return (status);
1885 
1886 	fp = open(path, O_RDWR);
1887 	if (fp == -1)
1888 		return (PSVC_FAILURE);
1889 
1890 	ret = ioctl_retry(fp, I2C_SET_OUTPUT, (void *)&value);
1891 	if (ret == -1) {
1892 		close(fp);
1893 		errno = EIO;
1894 		return (PSVC_FAILURE);
1895 	}
1896 
1897 	close(fp);
1898 
1899 	return (status);
1900 }
1901 
1902 /* PCF8591 */
1903 static int32_t
i_psvc_set_output_11_6(EHdl_t * hdlp,uint64_t aspec,int32_t value)1904 i_psvc_set_output_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t value)
1905 {
1906 	int32_t ret, status = PSVC_SUCCESS;
1907 	char path[1024];
1908 	int32_t fp;
1909 
1910 	status = i_psvc_get_devpath(hdlp, aspec, path);
1911 	if (status != PSVC_SUCCESS)
1912 		return (status);
1913 
1914 	fp = open(path, O_RDWR);
1915 	if (fp == -1)
1916 		return (PSVC_FAILURE);
1917 
1918 	ret = ioctl_retry(fp, I2C_SET_OUTPUT, (void *)&value);
1919 	if (ret == -1) {
1920 		close(fp);
1921 		errno = EIO;
1922 		return (PSVC_FAILURE);
1923 	}
1924 
1925 	close(fp);
1926 
1927 	return (status);
1928 }
1929 
1930 /* TDA8444 */
1931 static int32_t
i_psvc_set_output_11_8(EHdl_t * hdlp,uint64_t aspec,int32_t value)1932 i_psvc_set_output_11_8(EHdl_t *hdlp, uint64_t aspec, int32_t value)
1933 {
1934 	int32_t ret, status = PSVC_SUCCESS;
1935 	char path[1024];
1936 	int32_t fp;
1937 	int8_t buf;
1938 
1939 	status = i_psvc_get_devpath(hdlp, aspec, path);
1940 	if (status != PSVC_SUCCESS)
1941 		return (status);
1942 
1943 	fp = open(path, O_RDWR);
1944 	if (fp == -1)
1945 		return (PSVC_FAILURE);
1946 
1947 	buf = value;
1948 	ret = write(fp, &buf, 1);
1949 	if (ret == -1) {
1950 		close(fp);
1951 		errno = EIO;
1952 		return (PSVC_FAILURE);
1953 	}
1954 
1955 	close(fp);
1956 
1957 	return (status);
1958 }
1959 
1960 /* HPC3130 */
1961 static int32_t
i_psvc_get_reg_11_1(EHdl_t * hdlp,uint64_t aspec,uint8_t * value)1962 i_psvc_get_reg_11_1(EHdl_t *hdlp, uint64_t aspec, uint8_t *value)
1963 {
1964 	int32_t ret, status = PSVC_SUCCESS;
1965 	uint8_t bitshift, bytemask;
1966 	char path[1024];
1967 	i2c_reg_t i2cregarg;
1968 	int32_t fp;
1969 
1970 	status = i_psvc_get_devpath(hdlp, aspec, path);
1971 	if (status != PSVC_SUCCESS)
1972 		return (status);
1973 	fp = open(path, O_RDWR);
1974 	if (fp == -1)
1975 		return (PSVC_FAILURE);
1976 
1977 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
1978 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
1979 	if (ret == -1) {
1980 		close(fp);
1981 		errno = EIO;
1982 		return (-1);
1983 	}
1984 
1985 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
1986 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
1987 	if (value != NULL)
1988 		*value = (i2cregarg.reg_value & bytemask) >> bitshift;
1989 	close(fp);
1990 
1991 	return (status);
1992 }
1993 
1994 /* SSC050 */
1995 static int32_t
i_psvc_get_reg_11_7(EHdl_t * hdlp,uint64_t aspec,uint8_t * value)1996 i_psvc_get_reg_11_7(EHdl_t *hdlp, uint64_t aspec, uint8_t *value)
1997 {
1998 	int32_t ret, status = PSVC_SUCCESS;
1999 	uint8_t bitshift, bytemask;
2000 	char path[1024];
2001 	i2c_reg_t i2cregarg;
2002 	int32_t fp;
2003 
2004 	status = i_psvc_get_devpath(hdlp, aspec, path);
2005 	if (status != PSVC_SUCCESS)
2006 		return (status);
2007 
2008 	fp = open(path, O_RDWR);
2009 	if (fp == -1)
2010 		return (PSVC_FAILURE);
2011 
2012 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
2013 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
2014 	if (ret == -1) {
2015 		close(fp);
2016 		errno = EIO;
2017 		return (-1);
2018 	}
2019 
2020 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
2021 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
2022 	if (value != NULL)
2023 		*value = (i2cregarg.reg_value & bytemask) >> bitshift;
2024 
2025 	close(fp);
2026 
2027 	return (status);
2028 }
2029 
2030 /* HPC3130 */
2031 static int32_t
i_psvc_set_reg_11_1(EHdl_t * hdlp,uint64_t aspec,int32_t value)2032 i_psvc_set_reg_11_1(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2033 {
2034 	int32_t ret, status = PSVC_SUCCESS;
2035 	char path[1024];
2036 	i2c_reg_t i2cregarg;
2037 	int8_t tval;
2038 	uint8_t bitshift, bytemask;
2039 	int32_t fp;
2040 
2041 	status = i_psvc_get_devpath(hdlp, aspec, path);
2042 	if (status != PSVC_SUCCESS)
2043 		return (status);
2044 
2045 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
2046 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
2047 	value = value << bitshift;
2048 
2049 	fp = open(path, O_RDWR);
2050 	if (fp == -1)
2051 		return (PSVC_FAILURE);
2052 
2053 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
2054 	if (bytemask != 0xFF) {
2055 		ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
2056 		if (ret == -1) {
2057 			close(fp);
2058 			errno = EIO;
2059 			return (-1);
2060 		}
2061 		tval = i2cregarg.reg_value;
2062 		tval = tval & ~bytemask;
2063 	} else
2064 		tval = 0;
2065 
2066 	value = tval | value;
2067 	i2cregarg.reg_value = value;
2068 	ret = ioctl_retry(fp, I2C_SET_REG, (void *)&i2cregarg);
2069 	if (ret == -1) {
2070 		close(fp);
2071 		errno = EIO;
2072 		return (-1);
2073 	}
2074 
2075 	close(fp);
2076 
2077 	return (status);
2078 }
2079 
2080 /* SSC050 */
2081 static int32_t
i_psvc_set_reg_11_7(EHdl_t * hdlp,uint64_t aspec,int32_t value)2082 i_psvc_set_reg_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2083 {
2084 	int32_t ret, status = PSVC_SUCCESS;
2085 	char path[1024];
2086 	i2c_reg_t i2cregarg;
2087 	int8_t tval;
2088 	uint8_t bitshift, bytemask;
2089 	int32_t fp;
2090 
2091 	status = i_psvc_get_devpath(hdlp, aspec, path);
2092 	if (status != PSVC_SUCCESS)
2093 		return (status);
2094 
2095 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
2096 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
2097 	value = value << bitshift;
2098 
2099 	fp = open(path, O_RDWR);
2100 	if (fp == -1)
2101 		return (PSVC_FAILURE);
2102 
2103 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
2104 	if (bytemask != 0xFF) {
2105 		ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
2106 		if (ret == -1) {
2107 			close(fp);
2108 			errno = EIO;
2109 			return (-1);
2110 		}
2111 		tval = i2cregarg.reg_value;
2112 		tval = tval & ~bytemask;
2113 	} else
2114 		tval = 0;
2115 
2116 	value = tval | value;
2117 	i2cregarg.reg_value = value;
2118 	ret = ioctl_retry(fp, I2C_SET_REG, (void *)&i2cregarg);
2119 	if (ret == -1) {
2120 		close(fp);
2121 		errno = EIO;
2122 		return (-1);
2123 	}
2124 
2125 	close(fp);
2126 
2127 	return (status);
2128 }
2129 
2130 /* PCF8574 */
2131 static int32_t
i_psvc_get_bit_11_5(EHdl_t * hdlp,uint64_t aspec,int32_t * value)2132 i_psvc_get_bit_11_5(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
2133 {
2134 	int32_t ret, status = PSVC_SUCCESS;
2135 	char path[1024];
2136 	i2c_bit_t bitarg;
2137 	int32_t fp;
2138 
2139 	status = i_psvc_get_devpath(hdlp, aspec, path);
2140 	if (status != PSVC_SUCCESS)
2141 		return (status);
2142 
2143 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2144 	bitarg.direction = DIR_NO_CHANGE;
2145 
2146 	fp = open(path, O_RDWR);
2147 	if (fp == -1)
2148 		return (PSVC_FAILURE);
2149 
2150 	ret = ioctl_retry(fp, I2C_GET_BIT, (void *)&bitarg);
2151 	if (ret == -1) {
2152 		close(fp);
2153 		errno = EIO;
2154 		return (-1);
2155 	}
2156 
2157 	*value = bitarg.bit_value;
2158 
2159 	close(fp);
2160 
2161 	return (status);
2162 }
2163 
2164 /* PCF8574 */
2165 static int32_t
i_psvc_get_port_11_5(EHdl_t * hdlp,uint64_t aspec,uint8_t * value)2166 i_psvc_get_port_11_5(EHdl_t *hdlp, uint64_t aspec, uint8_t *value)
2167 {
2168 	int32_t ret, status = PSVC_SUCCESS;
2169 	char path[1024];
2170 	i2c_port_t port;
2171 	int32_t fp;
2172 
2173 	status = i_psvc_get_devpath(hdlp, aspec, path);
2174 	if (status != PSVC_SUCCESS)
2175 		return (status);
2176 
2177 	port.direction = DIR_NO_CHANGE;
2178 
2179 	fp = open(path, O_RDWR);
2180 	if (fp == -1)
2181 		return (PSVC_FAILURE);
2182 
2183 	ret = ioctl_retry(fp, I2C_GET_PORT, (void *)&port);
2184 	if (ret == -1) {
2185 		close(fp);
2186 		errno = EIO;
2187 		return (-1);
2188 	}
2189 
2190 	*value = port.value;
2191 
2192 	close(fp);
2193 
2194 	return (status);
2195 }
2196 
2197 /* SSC050 */
2198 static int32_t
i_psvc_get_bit_11_7(EHdl_t * hdlp,uint64_t aspec,int32_t * value)2199 i_psvc_get_bit_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
2200 {
2201 	int32_t ret, status = PSVC_SUCCESS;
2202 	char path[1024];
2203 	i2c_bit_t bitarg;
2204 	int32_t fp;
2205 
2206 	status = i_psvc_get_devpath(hdlp, aspec, path);
2207 	if (status != PSVC_SUCCESS)
2208 		return (status);
2209 
2210 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2211 	bitarg.direction = DIR_NO_CHANGE;
2212 
2213 	fp = open(path, O_RDWR);
2214 	if (fp == -1)
2215 		return (PSVC_FAILURE);
2216 
2217 	ret = ioctl_retry(fp, I2C_GET_BIT, (void *)&bitarg);
2218 	if (ret == -1) {
2219 		close(fp);
2220 		errno = EIO;
2221 		return (-1);
2222 	}
2223 
2224 	*value = bitarg.bit_value;
2225 
2226 	close(fp);
2227 
2228 	return (status);
2229 }
2230 
2231 /* PCF8574 */
2232 static int32_t
i_psvc_set_bit_11_5(EHdl_t * hdlp,uint64_t aspec,int32_t value)2233 i_psvc_set_bit_11_5(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2234 {
2235 	int32_t ret, status = PSVC_SUCCESS;
2236 	char path[1024];
2237 	i2c_bit_t bitarg;
2238 	int32_t fp;
2239 
2240 	status = i_psvc_get_devpath(hdlp, aspec, path);
2241 	if (status != PSVC_SUCCESS)
2242 		return (status);
2243 
2244 	bitarg.bit_value = value;
2245 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2246 	bitarg.direction = DIR_OUTPUT;
2247 	fp = open(path, O_RDWR);
2248 	if (fp == -1)
2249 		return (PSVC_FAILURE);
2250 
2251 	ret = ioctl_retry(fp, I2C_SET_BIT, (void *)&bitarg);
2252 	if (ret == -1) {
2253 		close(fp);
2254 		errno = EIO;
2255 		return (-1);
2256 	}
2257 
2258 	close(fp);
2259 
2260 	return (status);
2261 }
2262 
2263 /* PCF8574 */
2264 static int32_t
i_psvc_set_port_11_5(EHdl_t * hdlp,uint64_t aspec,int32_t value)2265 i_psvc_set_port_11_5(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2266 {
2267 	int32_t ret, status = PSVC_SUCCESS;
2268 	char path[1024];
2269 	i2c_port_t port;
2270 	int32_t fp;
2271 
2272 	status = i_psvc_get_devpath(hdlp, aspec, path);
2273 	if (status != PSVC_SUCCESS)
2274 		return (status);
2275 
2276 	port.value = (uint8_t)value;
2277 	port.direction = DIR_NO_CHANGE;
2278 	fp = open(path, O_RDWR);
2279 	if (fp == -1)
2280 		return (PSVC_FAILURE);
2281 
2282 	ret = ioctl_retry(fp, I2C_SET_PORT, (void *)&port);
2283 	if (ret == -1) {
2284 		close(fp);
2285 		errno = EIO;
2286 		return (-1);
2287 	}
2288 
2289 	close(fp);
2290 
2291 	return (status);
2292 }
2293 
2294 /* SSC050 */
2295 static int32_t
i_psvc_set_bit_11_7(EHdl_t * hdlp,uint64_t aspec,int32_t value)2296 i_psvc_set_bit_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2297 {
2298 	int32_t ret, status = PSVC_SUCCESS;
2299 	char path[1024];
2300 	i2c_bit_t bitarg;
2301 	int32_t fp;
2302 
2303 	status = i_psvc_get_devpath(hdlp, aspec, path);
2304 	if (status != PSVC_SUCCESS)
2305 		return (status);
2306 
2307 	bitarg.bit_value = value;
2308 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2309 	bitarg.direction = DIR_OUTPUT;
2310 
2311 	fp = open(path, O_RDWR);
2312 	if (fp == -1)
2313 		return (PSVC_FAILURE);
2314 
2315 	ret = ioctl_retry(fp, I2C_SET_BIT, (void *)&bitarg);
2316 	if (ret == -1) {
2317 		close(fp);
2318 		errno = EIO;
2319 		return (-1);
2320 	}
2321 
2322 	close(fp);
2323 
2324 	return (status);
2325 }
2326 
2327 /* AT24 */
2328 static int32_t
i_psvc_probe_11_0(EHdl_t * hdlp,EObj_t * objp)2329 i_psvc_probe_11_0(EHdl_t *hdlp, EObj_t *objp)
2330 {
2331 	int32_t ret, status = PSVC_SUCCESS;
2332 	uint8_t value;
2333 	char path[1024];
2334 	int32_t fp;
2335 
2336 	if (objp->present != PSVC_PRESENT) {
2337 		errno = ENODEV;
2338 		return (PSVC_FAILURE);
2339 	}
2340 
2341 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2342 	if (status != PSVC_SUCCESS) {
2343 		return (status);
2344 	}
2345 
2346 	fp = open(path, O_RDWR);
2347 	if (fp == -1) {
2348 		return (PSVC_FAILURE);
2349 	}
2350 
2351 	ret = read(fp, &value, 1);
2352 	if (ret == -1) {
2353 		close(fp);
2354 		errno = EIO;
2355 		return (-1);
2356 	}
2357 
2358 	close(fp);
2359 
2360 	return (status);
2361 }
2362 
2363 /* HPC3130 */
2364 static int32_t
i_psvc_probe_11_1(EHdl_t * hdlp,EObj_t * objp)2365 i_psvc_probe_11_1(EHdl_t *hdlp, EObj_t *objp)
2366 {
2367 	int32_t ret, status = PSVC_SUCCESS;
2368 	char path[1024];
2369 	i2c_reg_t reg;
2370 	int32_t fp;
2371 
2372 	if (objp->present != PSVC_PRESENT) {
2373 		errno = ENODEV;
2374 		return (PSVC_FAILURE);
2375 	}
2376 
2377 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2378 	if (status != PSVC_SUCCESS)
2379 		return (status);
2380 
2381 	fp = open(path, O_RDWR);
2382 	if (fp == -1)
2383 		return (PSVC_FAILURE);
2384 
2385 	reg.reg_num = 0;
2386 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&reg);
2387 	if (ret == -1) {
2388 		close(fp);
2389 		errno = EIO;
2390 		return (-1);
2391 	}
2392 
2393 	close(fp);
2394 
2395 	return (status);
2396 }
2397 
2398 /* LM75 */
2399 static int32_t
i_psvc_probe_11_2(EHdl_t * hdlp,EObj_t * objp)2400 i_psvc_probe_11_2(EHdl_t *hdlp, EObj_t *objp)
2401 {
2402 	int32_t ret, status = PSVC_SUCCESS;
2403 	char path[1024];
2404 	int32_t fp;
2405 	int16_t temp16;
2406 
2407 	if (objp->present != PSVC_PRESENT) {
2408 		errno = ENODEV;
2409 		return (PSVC_FAILURE);
2410 	}
2411 
2412 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2413 	if (status != PSVC_SUCCESS) {
2414 		return (status);
2415 	}
2416 
2417 	fp = open(path, O_RDWR);
2418 	if (fp == -1) {
2419 		return (PSVC_FAILURE);
2420 	}
2421 
2422 	ret = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
2423 	if (ret == -1) {
2424 		close(fp);
2425 		errno = EIO;
2426 		return (-1);
2427 	}
2428 
2429 	close(fp);
2430 
2431 	return (status);
2432 }
2433 
2434 /* LTC1427 */
2435 static int32_t
i_psvc_probe_11_3(EHdl_t * hdlp,EObj_t * objp)2436 i_psvc_probe_11_3(EHdl_t *hdlp, EObj_t *objp)
2437 {
2438 	int32_t ret, status = PSVC_SUCCESS;
2439 	int32_t value;
2440 	char path[1024];
2441 	int32_t fp;
2442 
2443 	if (objp->present != PSVC_PRESENT) {
2444 		errno = ENODEV;
2445 		return (PSVC_FAILURE);
2446 	}
2447 
2448 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2449 	if (status != PSVC_SUCCESS) {
2450 		return (status);
2451 	}
2452 
2453 	fp = open(path, O_RDWR);
2454 	if (fp == -1) {
2455 		return (PSVC_FAILURE);
2456 	}
2457 
2458 	ret = ioctl_retry(fp, I2C_GET_OUTPUT, (void *)&value);
2459 	if (ret == -1) {
2460 		close(fp);
2461 		errno = EINVAL;
2462 		return (-1);
2463 	}
2464 
2465 	ret = ioctl_retry(fp, I2C_SET_OUTPUT, (void *)&value);
2466 	if (ret == -1) {
2467 		close(fp);
2468 		errno = EIO;
2469 		return (-1);
2470 	}
2471 
2472 	close(fp);
2473 	return (status);
2474 }
2475 
2476 /* MAX1617 */
2477 static int32_t
i_psvc_probe_11_4(EHdl_t * hdlp,EObj_t * objp)2478 i_psvc_probe_11_4(EHdl_t *hdlp, EObj_t *objp)
2479 {
2480 	int32_t ret, status = PSVC_SUCCESS;
2481 	char path[1024];
2482 	int32_t fp;
2483 	int16_t temp16;
2484 
2485 	if (objp->present != PSVC_PRESENT) {
2486 		errno = ENODEV;
2487 		return (PSVC_FAILURE);
2488 	}
2489 
2490 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2491 	if (status != PSVC_SUCCESS) {
2492 		return (status);
2493 	}
2494 
2495 	fp = open(path, O_RDWR);
2496 	if (fp == -1) {
2497 		return (PSVC_FAILURE);
2498 	}
2499 
2500 	ret = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
2501 	if (ret == -1) {
2502 		close(fp);
2503 		errno = EIO;
2504 		return (-1);
2505 	}
2506 
2507 	close(fp);
2508 
2509 	return (status);
2510 }
2511 
2512 /* PCF8574 */
2513 static int32_t
i_psvc_probe_11_5(EHdl_t * hdlp,EObj_t * objp)2514 i_psvc_probe_11_5(EHdl_t *hdlp, EObj_t *objp)
2515 {
2516 	int32_t ret, status = PSVC_SUCCESS;
2517 	char path[1024];
2518 	i2c_port_t port;
2519 	int32_t fp;
2520 
2521 	if (objp->present != PSVC_PRESENT) {
2522 		errno = ENODEV;
2523 		return (PSVC_FAILURE);
2524 	}
2525 
2526 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2527 	if (status != PSVC_SUCCESS) {
2528 		return (status);
2529 	}
2530 
2531 	port.direction = DIR_NO_CHANGE;
2532 
2533 	fp = open(path, O_RDWR);
2534 	if (fp == -1) {
2535 		return (PSVC_FAILURE);
2536 	}
2537 
2538 	ret = ioctl_retry(fp, I2C_GET_PORT, (void *)&port);
2539 	if (ret == -1) {
2540 		close(fp);
2541 		errno = EIO;
2542 		return (-1);
2543 	}
2544 
2545 	close(fp);
2546 
2547 	return (status);
2548 }
2549 
2550 /* PCF8591 */
2551 static int32_t
i_psvc_probe_11_6(EHdl_t * hdlp,EObj_t * objp)2552 i_psvc_probe_11_6(EHdl_t *hdlp, EObj_t *objp)
2553 {
2554 	int32_t ret, status = PSVC_SUCCESS;
2555 	char path[1024];
2556 	int32_t arg;
2557 	int32_t fp;
2558 
2559 	if (objp->present != PSVC_PRESENT) {
2560 		errno = ENODEV;
2561 		return (PSVC_FAILURE);
2562 	}
2563 
2564 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2565 	if (status != PSVC_SUCCESS)
2566 		return (status);
2567 
2568 	fp = open(path, O_RDWR);
2569 	if (fp == -1)
2570 		return (PSVC_FAILURE);
2571 
2572 	ret = ioctl_retry(fp, I2C_GET_INPUT, (void *)&arg);
2573 	if (ret == -1) {
2574 		close(fp);
2575 		errno = EIO;
2576 		return (-1);
2577 	}
2578 
2579 	close(fp);
2580 
2581 	return (status);
2582 }
2583 
2584 /* SSC050 */
2585 static int32_t
i_psvc_probe_11_7(EHdl_t * hdlp,EObj_t * objp)2586 i_psvc_probe_11_7(EHdl_t *hdlp, EObj_t *objp)
2587 {
2588 	int32_t ret, status = PSVC_SUCCESS;
2589 	char path[1024];
2590 	i2c_port_t port;
2591 	int32_t fp;
2592 
2593 	if (objp->present != PSVC_PRESENT) {
2594 		errno = ENODEV;
2595 		return (PSVC_FAILURE);
2596 	}
2597 
2598 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2599 	if (status != PSVC_SUCCESS)
2600 		return (status);
2601 
2602 	port.direction = DIR_NO_CHANGE;
2603 
2604 	fp = open(path, O_RDWR);
2605 	if (fp == -1)
2606 		return (PSVC_FAILURE);
2607 
2608 	ret = ioctl_retry(fp, I2C_GET_PORT, (void *)&port);
2609 	if (ret == -1) {
2610 		close(fp);
2611 		errno = EIO;
2612 		return (-1);
2613 	}
2614 
2615 	close(fp);
2616 
2617 	return (status);
2618 }
2619 
2620 /* TDA8444 */
2621 static int32_t
i_psvc_probe_11_8(EHdl_t * hdlp,EObj_t * objp)2622 i_psvc_probe_11_8(EHdl_t *hdlp, EObj_t *objp)
2623 {
2624 	int32_t ret, status = PSVC_SUCCESS;
2625 	uint8_t value;
2626 	char path[1024];
2627 	int32_t fp;
2628 
2629 	if (objp->present != PSVC_PRESENT) {
2630 		errno = ENODEV;
2631 		return (PSVC_FAILURE);
2632 	}
2633 
2634 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2635 	if (status != PSVC_SUCCESS)
2636 		return (status);
2637 
2638 	fp = open(path, O_RDWR);
2639 	if (fp == -1)
2640 		return (PSVC_FAILURE);
2641 
2642 	ret = read(fp, &value, 1);
2643 	if (ret == -1) {
2644 		close(fp);
2645 		errno = EIO;
2646 		return (-1);
2647 	}
2648 
2649 	close(fp);
2650 
2651 	return (status);
2652 }
2653 
2654 
2655 /* SSC100 */
2656 static int32_t
i_psvc_probe_11_9(EHdl_t * hdlp,EObj_t * objp)2657 i_psvc_probe_11_9(EHdl_t *hdlp, EObj_t *objp)
2658 {
2659 	int32_t ret, status = PSVC_SUCCESS;
2660 	char path[1024];
2661 	i2c_reg_t reg;
2662 	int32_t fp;
2663 
2664 	if (objp->present != PSVC_PRESENT) {
2665 		errno = ENODEV;
2666 		return (PSVC_FAILURE);
2667 	}
2668 
2669 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2670 	if (status != PSVC_SUCCESS) {
2671 		return (status);
2672 	}
2673 
2674 	fp = open(path, O_RDWR);
2675 	if (fp == -1) {
2676 		return (PSVC_FAILURE);
2677 	}
2678 
2679 	/*
2680 	 * There are only a few register numbers that are valid numbers to
2681 	 * read from. 0x10 is one of these registers. Any non-valid registers
2682 	 * cause unknown behavior to the ssc100 device.
2683 	 */
2684 	reg.reg_num = 0x10;
2685 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&reg);
2686 	if (ret == -1) {
2687 		close(fp);
2688 		errno = EIO;
2689 		return (-1);
2690 	}
2691 
2692 	close(fp);
2693 
2694 	return (status);
2695 }
2696 
2697 
2698 /*
2699  * Find start of a section within the config file,
2700  * Returns number of records in the section.
2701  * FILE *fd is set to first data record within section.
2702  */
2703 static int32_t
i_psvc_find_file_section(FILE * fd,char * start)2704 i_psvc_find_file_section(FILE *fd, char *start)
2705 {
2706 	char *ret;
2707 	char buf[BUFSZ];
2708 	char name[32];
2709 	int found;
2710 
2711 	fseek(fd, 0, SEEK_SET);
2712 	while ((ret = fgets(buf, BUFSZ, fd)) != NULL) {
2713 		if (strncmp(start, buf, strlen(start)) == 0)
2714 			break;
2715 	}
2716 
2717 	if (ret == NULL) {
2718 		errno = EINVAL;
2719 		return (-1);
2720 	}
2721 
2722 	found = sscanf(buf, "%s", name);
2723 	if (found != 1) {
2724 		errno = EINVAL;
2725 		return (-1);
2726 	} else {
2727 		return (0);
2728 	}
2729 
2730 }
2731 
2732 /* compare routine for qsort of str_tbl */
2733 static int32_t
i_psvc_name_compare_qsort(EStringId_t * s1,EStringId_t * s2)2734 i_psvc_name_compare_qsort(EStringId_t *s1, EStringId_t *s2)
2735 {
2736 	return (strcmp(s1->name, s2->name));
2737 }
2738 
2739 /* compare routine for bsearch of str_tbl */
2740 static int32_t
i_psvc_name_compare_bsearch(char * s1,EStringId_t * s2)2741 i_psvc_name_compare_bsearch(char *s1, EStringId_t *s2)
2742 {
2743 	return (strcmp(s1, s2->name));
2744 }
2745 
2746 /*
2747  * Determine the initial state of a device.
2748  */
2749 static int32_t
i_psvc_init_state(EHdl_t * hp,EObj_t * objp)2750 i_psvc_init_state(EHdl_t *hp, EObj_t *objp)
2751 {
2752 	int32_t status = PSVC_SUCCESS;
2753 
2754 	if (objp->class == PSVC_ON_OFF_SWITCH_CLASS) {
2755 		char state[32];
2756 
2757 		status = objp->get_attr(hp, objp, PSVC_SWITCH_STATE_ATTR,
2758 			state);
2759 		if (status != PSVC_SUCCESS)
2760 			return (status);
2761 
2762 		if (strcmp(state, PSVC_SWITCH_ON) == 0)
2763 			strcpy(objp->state, PSVC_ON);
2764 		else
2765 			strcpy(objp->state, PSVC_OFF);
2766 	}
2767 
2768 	if (objp->class == PSVC_KEYSWITCH_CLASS) {
2769 		char state[32];
2770 
2771 		status = objp->get_attr(hp, objp, PSVC_SWITCH_STATE_ATTR,
2772 			state);
2773 		if (status != PSVC_SUCCESS)
2774 			return (status);
2775 		strcpy(objp->state, state);
2776 	}
2777 
2778 	return (status);
2779 }
2780 
2781 /*
2782  * Return the object pointer for the object name passed in.
2783  * Creates the object if this is the first access,
2784  * Returns 0 if successful, -1 if not.
2785  */
2786 static int32_t
i_psvc_get_obj(EHdl_t * hp,char * dev_name,EObj_t ** objp)2787 i_psvc_get_obj(EHdl_t *hp, char *dev_name, EObj_t **objp)
2788 {
2789 	int32_t i, ret;
2790 	int32_t found, key, array;
2791 	int32_t class, subclass;
2792 	boolean_t presence;
2793 	char name[NAMELEN];
2794 	char buf[BUFSZ];
2795 	char *start;
2796 	ETable_Array *tbl_arr;
2797 
2798 	key = psvc_get_str_key(dev_name);
2799 	array = key % PSVC_MAX_TABLE_ARRAYS;
2800 	tbl_arr = &(hp->tbl_arry[array]);
2801 
2802 	for (i = 0; i < tbl_arr->obj_count; ++i) {
2803 		if (key ==  tbl_arr->obj_tbl[i].key) {
2804 			if (strcmp(dev_name, tbl_arr->obj_tbl[i].name) == 0) {
2805 				if (tbl_arr->obj_tbl[i].type != PSVC_OBJ)
2806 					return (-1);
2807 				*objp = tbl_arr->obj_tbl[i].objp;
2808 				return (0);
2809 			}
2810 		}
2811 	}
2812 
2813 	if (i_psvc_find_file_section(hp->fp, "OBJECT_INFO") == -1) {
2814 		ENV_DEBUG("Couldn't find OBJECT_INFO section", dev_name);
2815 		return (-1);
2816 	}
2817 
2818 	fgets(buf, BUFSZ, hp->fp);
2819 	while (strcmp(buf, "OBJECT_INFO_END")) {
2820 		start = strrchr(buf, '/');
2821 		if (start == NULL) {
2822 			errno = EINVAL;
2823 			return (PSVC_FAILURE);
2824 		}
2825 		found = sscanf(start + 1, "%s",  name);
2826 		if (found != 1) {
2827 			errno = EINVAL;
2828 			return (PSVC_FAILURE);
2829 		}
2830 
2831 		if (strcmp(name, dev_name) == 0) {
2832 
2833 			if (i_psvc_value(buf, PSVC_CLASS_ATTR, &class)
2834 			    != PSVC_SUCCESS)
2835 				return (PSVC_FAILURE);
2836 			if (i_psvc_value(buf, PSVC_SUBCLASS_ATTR, &subclass)
2837 			    != PSVC_SUCCESS)
2838 				return (PSVC_FAILURE);
2839 			ret = (*i_psvc_constructor[class][subclass])(hp,
2840 				dev_name, objp);
2841 			if (ret != PSVC_SUCCESS) {
2842 				return (-1);
2843 			}
2844 			ret = (*objp)->get_attr(hp, *objp, PSVC_PRESENCE_ATTR,
2845 				&presence);
2846 			(*objp)->previous_presence = presence;
2847 			if (ret != PSVC_SUCCESS || presence != PSVC_PRESENT)
2848 				return (ret);
2849 
2850 			return (i_psvc_init_state(hp, *objp));
2851 		}
2852 		fgets(buf, BUFSZ, hp->fp);
2853 	}
2854 
2855 	errno = EINVAL;
2856 	return (-1);
2857 }
2858 
2859 /*
2860  * Gets the device path associated with an object id.
2861  * Returns 0 if successful, -1 if not.
2862  */
2863 static int32_t
i_psvc_get_devpath(EHdl_t * hp,uint64_t addr_spec,char * path)2864 i_psvc_get_devpath(EHdl_t *hp, uint64_t addr_spec, char *path)
2865 {
2866 	int i;
2867 	EDevice_t *dp;
2868 	uint32_t controller, bus, addr, port;
2869 
2870 	controller = PSVC_GET_ASPEC_CNTLR(addr_spec);
2871 	bus = PSVC_GET_ASPEC_BUSNUM(addr_spec);
2872 	addr = PSVC_GET_ASPEC_BUSADDR(addr_spec);
2873 	port = PSVC_GET_ASPEC_PORT(addr_spec);
2874 
2875 	for (i = 0; i < hp->dev_count; ++i) {
2876 		dp = &hp->dev_tbl[i];
2877 		if (dp->controller == controller &&
2878 		    dp->bus == bus &&
2879 		    dp->addr == addr &&
2880 		    dp->port == port) {
2881 			strcpy(path, dp->path);
2882 			return (PSVC_SUCCESS);
2883 		}
2884 	}
2885 
2886 	errno = EINVAL;
2887 	return (PSVC_FAILURE);
2888 }
2889 
2890 
2891 /* Load the association table */
2892 static int32_t
i_psvc_load_associations(EHdl_t * hp,FILE * fp)2893 i_psvc_load_associations(EHdl_t *hp, FILE *fp)
2894 {
2895 	uint32_t count;
2896 	int found;
2897 	int i, j;
2898 	char name1[32], name2[32];
2899 	char buf[BUFSZ];
2900 	EStringId_t *namep;
2901 	EAssoc_t *ap;
2902 	int32_t id;
2903 	int32_t status;
2904 
2905 	/*
2906 	 * ignore count in the file, correct count is highest
2907 	 * association id + 1, now figured when loading ASSOC_STR
2908 	 * section.
2909 	 */
2910 	if (i_psvc_find_file_section(fp, "ASSOCIATIONS") != PSVC_SUCCESS)
2911 		return (-1);
2912 	if ((hp->assoc_tbl = malloc(sizeof (EAssocList_t) * hp->assoc_count))
2913 			== NULL) {
2914 		return (-1);
2915 	}
2916 	memset(hp->assoc_tbl, 0, sizeof (EAssocList_t) * hp->assoc_count);
2917 
2918 	for (i = 0; i < hp->assoc_count; ++i) {
2919 		fgets(buf, BUFSZ, fp);
2920 		found = sscanf(buf, "%s %s", name1, name2);
2921 		if (strcmp("ASSOCIATIONS_END", name1) == 0)
2922 			break;
2923 		if (found != 2) {
2924 			errno = EINVAL;
2925 			return (-1);
2926 		}
2927 		namep = (EStringId_t *)bsearch(name2, hp->othr_tbl,
2928 			hp->othr_count, sizeof (EStringId_t),
2929 			(int (*)(const void *, const void *))
2930 			i_psvc_name_compare_bsearch);
2931 		if (namep == NULL) {
2932 			errno = EINVAL;
2933 			return (-1);
2934 		}
2935 		id = namep->id;
2936 
2937 		status = i_psvc_count_records(fp, "ASSOCIATION_END", &count);
2938 		if (status != PSVC_SUCCESS)
2939 			return (status);
2940 		hp->assoc_tbl[id].count = count;
2941 		hp->assoc_tbl[id].table =
2942 			(EAssoc_t *)malloc(sizeof (EAssoc_t) * count);
2943 		if (hp->assoc_tbl[id].table == NULL)
2944 			return (-1);
2945 
2946 		for (j = 0; j < count; ++j) {
2947 			ap = &hp->assoc_tbl[id].table[j];
2948 			fgets(buf, BUFSZ, fp);
2949 			found = sscanf(buf, "%s %s", ap->antecedent_id,
2950 				ap->dependent_id);
2951 			ap->ant_key = psvc_get_str_key(ap->antecedent_id);
2952 			if (found != 2) {
2953 				errno = EINVAL;
2954 				return (-1);
2955 			}
2956 		}
2957 
2958 
2959 		fgets(buf, BUFSZ, fp);
2960 		if (strncmp(buf, "ASSOCIATION_END", 15) != 0) {
2961 			errno = EINVAL;
2962 			return (-1);
2963 		}
2964 	}
2965 
2966 	return (0);
2967 }
2968 
2969 /* Load the table of tables */
2970 static int32_t
i_psvc_load_tables(EHdl_t * hp,FILE * fp)2971 i_psvc_load_tables(EHdl_t *hp, FILE *fp)
2972 {
2973 	int i, j;
2974 	int found;
2975 	int ret;
2976 	int32_t cell_type;
2977 	int64_t *table;
2978 	char buf[BUFSZ];
2979 	int32_t status;
2980 	uint32_t table_count;
2981 	int32_t num, key, array;
2982 	char name[NAMELEN];
2983 	ETable_Array *tbl_arr;
2984 
2985 	if (i_psvc_find_file_section(fp, "TABLES") != PSVC_SUCCESS)
2986 		return (PSVC_SUCCESS);	/* no tables */
2987 	status = i_psvc_count_tables_associations(fp, &table_count,
2988 			"TABLE_END");
2989 	if (status != PSVC_SUCCESS || table_count == 0)
2990 		return (status);
2991 
2992 	for (i = 0; i < table_count; ++i) {
2993 		int slot;
2994 		ETable_t *tblp;
2995 
2996 		fgets(buf, BUFSZ, fp);
2997 		if (strncmp(buf, "TABLE", 5) != 0) {
2998 			errno = EINVAL;
2999 			return (-1);
3000 		}
3001 
3002 		fgets(buf, BUFSZ, fp);
3003 		found = sscanf(buf, "%s %d", name, &cell_type);
3004 		key = psvc_get_str_key(name);
3005 		array = key % PSVC_MAX_TABLE_ARRAYS;
3006 		tbl_arr = &(hp->tbl_arry[array]);
3007 
3008 		if (tbl_arr->nextid == hp->total_obj_count) {
3009 			errno = EINVAL;
3010 			return (PSVC_FAILURE);
3011 		} else {
3012 			slot = tbl_arr->nextid++;
3013 			tbl_arr->obj_count++;
3014 		}
3015 
3016 		strcpy(tbl_arr->obj_tbl[slot].name, name);
3017 
3018 		tblp = (ETable_t *)malloc(sizeof (ETable_t));
3019 		if (tblp == NULL)
3020 			return (PSVC_FAILURE);
3021 		tbl_arr->obj_tbl[slot].key = key;
3022 		tbl_arr->obj_tbl[slot].objp = (EObj_t *)(void *)tblp;
3023 		tbl_arr->obj_tbl[slot].type = PSVC_TBL;
3024 
3025 		status = i_psvc_count_table_records(fp, "TABLE_END",
3026 			&tblp->size);
3027 		if (status != PSVC_SUCCESS)
3028 			return (status);
3029 		tblp->cell_type = (uint8_t)cell_type;
3030 		if (found != 2) {
3031 			errno = EINVAL;
3032 			return (-1);
3033 		}
3034 
3035 		/* allocate and load table */
3036 		tblp->table = (int64_t *)malloc(tblp->size *
3037 			i_psvc_cell_size[tblp->cell_type]);
3038 		if (tblp->table == NULL) {
3039 			return (-1);
3040 		}
3041 
3042 		table = tblp->table;
3043 		for (j = 0; j < tblp->size; ++j) {
3044 			switch (cell_type) {
3045 				case 0:
3046 					ret = fscanf(fp, "%d", &num);
3047 					*((int8_t *)table + j) = num;
3048 					break;
3049 				case 1:
3050 					ret = fscanf(fp, "%d", &num);
3051 					*((uint8_t *)table + j) = (uint8_t)num;
3052 					break;
3053 				case 2:
3054 					ret = fscanf(fp, "%hd",
3055 						((int16_t *)table + j));
3056 					break;
3057 				case 3:
3058 					ret = fscanf(fp, "%hd",
3059 						((uint16_t *)table + j));
3060 					break;
3061 				case 4:
3062 					ret = fscanf(fp, "%d",
3063 						((int32_t *)table + j));
3064 					break;
3065 				case 5:
3066 					ret = fscanf(fp, "%d",
3067 						((uint32_t *)table + j));
3068 					break;
3069 				case 6:
3070 					ret = fscanf(fp, "%lld",
3071 						((int64_t *)table + j));
3072 					break;
3073 				case 7:
3074 					ret = fscanf(fp, "%lld",
3075 						((uint64_t *)table + j));
3076 					break;
3077 				default:
3078 					errno = EINVAL;
3079 					return (-1);
3080 			}
3081 			if (ret != 1) {
3082 				errno = EINVAL;
3083 				return (-1);
3084 			}
3085 		}
3086 		fgets(buf, BUFSZ, fp);  /* reads newline on data line */
3087 		fgets(buf, BUFSZ, fp);
3088 		if (strncmp(buf, "TABLE_END", 9) != 0) {
3089 			errno = EINVAL;
3090 			return (-1);
3091 		}
3092 
3093 	}
3094 
3095 	return (0);
3096 }
3097 
3098 static int32_t
i_psvc_destructor(EHdl_t * hdlp,char * name,void * objp)3099 i_psvc_destructor(EHdl_t *hdlp, char *name, void *objp)
3100 {
3101 	int32_t i, key, array;
3102 
3103 	key = psvc_get_str_key(name);
3104 	array = key % PSVC_MAX_TABLE_ARRAYS;
3105 
3106 	for (i = 0; i < hdlp->tbl_arry[array].obj_count; ++i) {
3107 		if (key == hdlp->tbl_arry[array].obj_tbl[i].key) {
3108 			if (strcmp(hdlp->tbl_arry[array].obj_tbl[i].name,
3109 				name) == 0) {
3110 				hdlp->tbl_arry[array].obj_tbl[i].name[0] = '\0';
3111 				if (objp != NULL)
3112 					free(objp);
3113 				return (PSVC_SUCCESS);
3114 			}
3115 		}
3116 	}
3117 
3118