xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4u/psvc/psvcobj/psvcobj.c (revision 694c35faa87b858ecdadfe4fc592615f4eefbb07)
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 	return (PSVC_SUCCESS);
3119 }
3120 
3121 static int32_t
3122 i_psvc_get_attr_generic(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id,
3123     void * attrp)
3124 {
3125 	int32_t status = PSVC_SUCCESS;
3126 	char *parent_id;
3127 
3128 	switch (attr_id) {
3129 	case PSVC_ADDR_SPEC_ATTR:
3130 		*(uint64_t *)attrp = objp->addr_spec;
3131 		break;
3132 	case PSVC_CLASS_ATTR:
3133 		*(int32_t *)attrp = objp->class;
3134 		break;
3135 	case PSVC_SUBCLASS_ATTR:
3136 		*(int32_t *)attrp = objp->subclass;
3137 		break;
3138 	case PSVC_PRESENCE_ATTR:
3139 		status = i_psvc_get_presence(hdlp, objp, (boolean_t *)attrp);
3140 		break;
3141 	case PSVC_PREV_PRESENCE_ATTR:
3142 		*(boolean_t *)attrp = objp->previous_presence;
3143 		break;
3144 	case PSVC_STATE_ATTR:
3145 		strcpy((char *)attrp, objp->state);
3146 		break;
3147 	case PSVC_PREV_STATE_ATTR:
3148 		strcpy((char *)attrp, objp->previous_state);
3149 		break;
3150 	case PSVC_ENABLE_ATTR:
3151 		*(boolean_t *)attrp = objp->enabled;
3152 		break;
3153 	case PSVC_FAULTID_ATTR:
3154 		strcpy((char *)attrp, objp->fault_id);
3155 		break;
3156 	case PSVC_FEATURES_ATTR:
3157 		*(uint64_t *)attrp = objp->features;
3158 		break;
3159 	case PSVC_LABEL_ATTR:
3160 		strcpy((char *)attrp, objp->label);
3161 		break;
3162 	case PSVC_FRUID_ATTR:
3163 		while ((objp->features & PSVC_DEV_FRU) == 0) {
3164 			status = i_psvc_get_assoc_id(hdlp, objp->label,
3165 				PSVC_PARENT, 0, &parent_id);
3166 			if (status != PSVC_SUCCESS)
3167 				return (status);
3168 
3169 			status = i_psvc_get_obj(hdlp, parent_id, &objp);
3170 			if (status != PSVC_SUCCESS)
3171 				return (status);
3172 		}
3173 
3174 		strcpy((char *)attrp, objp->label);
3175 		break;
3176 	case PSVC_INSTANCE_ATTR:
3177 		*(int32_t *)attrp = objp->instance;
3178 		break;
3179 	default:
3180 		errno = EINVAL;
3181 		return (PSVC_FAILURE);
3182 	}
3183 
3184 	return (status);
3185 }
3186 
3187 static int32_t
3188 i_psvc_set_attr_generic(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id,
3189     void * attrp)
3190 {
3191 	int32_t status = PSVC_SUCCESS;
3192 
3193 	switch (attr_id) {
3194 	case PSVC_PREV_PRESENCE_ATTR:
3195 		objp->previous_presence = *(boolean_t *)attrp;
3196 		break;
3197 	case PSVC_STATE_ATTR:
3198 		strcpy(objp->previous_state, objp->state);
3199 		strcpy(objp->state, (char *)attrp);
3200 		break;
3201 	case PSVC_ENABLE_ATTR:
3202 		objp->enabled = *(boolean_t *)attrp;
3203 		break;
3204 	case PSVC_FAULTID_ATTR:
3205 		strcpy(objp->fault_id, (char *)attrp);
3206 		break;
3207 	default:
3208 		errno = EINVAL;
3209 		return (PSVC_FAILURE);
3210 	}
3211 	return (status);
3212 }
3213 
3214 static int32_t
3215 i_psvc_get_attr_0_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3216 {
3217 	int32_t status = PSVC_SUCCESS;
3218 
3219 	switch (attr_id) {
3220 	case PSVC_SENSOR_VALUE_ATTR:
3221 		return (i_psvc_get_device_value_0_0(hdlp, objp, attrp));
3222 	case PSVC_LO_WARN_ATTR:
3223 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_warn;
3224 		return (status);
3225 	case PSVC_LO_SHUT_ATTR:
3226 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_shut;
3227 		return (status);
3228 	case PSVC_HI_WARN_ATTR:
3229 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_warn;
3230 		return (status);
3231 	case PSVC_HI_SHUT_ATTR:
3232 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_shut;
3233 		return (status);
3234 	}
3235 
3236 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3237 
3238 	return (status);
3239 }
3240 
3241 static int32_t
3242 i_psvc_get_attr_0_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3243 {
3244 	int32_t status = PSVC_SUCCESS;
3245 
3246 	switch (attr_id) {
3247 	case PSVC_SENSOR_VALUE_ATTR:
3248 		return (i_psvc_get_device_value_0_1(hdlp, objp, attrp));
3249 	case PSVC_LO_WARN_ATTR:
3250 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_warn;
3251 		return (status);
3252 	case PSVC_LO_SHUT_ATTR:
3253 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_shut;
3254 		return (status);
3255 	case PSVC_HI_WARN_ATTR:
3256 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_warn;
3257 		return (status);
3258 	case PSVC_HI_SHUT_ATTR:
3259 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_shut;
3260 		return (status);
3261 	case PSVC_OPTIMAL_TEMP_ATTR:
3262 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->opt_temp;
3263 		return (status);
3264 	case PSVC_HW_HI_SHUT_ATTR:
3265 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hw_hi_shut;
3266 		return (status);
3267 	case PSVC_HW_LO_SHUT_ATTR:
3268 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hw_lo_shut;
3269 		return (status);
3270 	}
3271 
3272 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3273 
3274 	return (status);
3275 }
3276 
3277 static int32_t
3278 i_psvc_set_attr_0_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3279 {
3280 	int32_t status = PSVC_SUCCESS;
3281 
3282 	switch (attr_id) {
3283 	case PSVC_LO_WARN_ATTR:
3284 		((ETempSensor_t *)objp)->lo_warn = *(int32_t *)attrp;
3285 		return (status);
3286 	case PSVC_LO_SHUT_ATTR:
3287 		((ETempSensor_t *)objp)->lo_shut = *(int32_t *)attrp;
3288 		return (status);
3289 	case PSVC_HI_WARN_ATTR:
3290 		((ETempSensor_t *)objp)->hi_warn = *(int32_t *)attrp;
3291 		return (status);
3292 	case PSVC_HI_SHUT_ATTR:
3293 		((ETempSensor_t *)objp)->hi_shut = *(int32_t *)attrp;
3294 		return (status);
3295 	case PSVC_OPTIMAL_TEMP_ATTR:
3296 		((ETempSensor_t *)objp)->opt_temp = *(int32_t *)attrp;
3297 		return (status);
3298 	case PSVC_HW_HI_SHUT_ATTR:
3299 		((ETempSensor_t *)objp)->hw_hi_shut = *(int32_t *)attrp;
3300 		return (status);
3301 	case PSVC_HW_LO_SHUT_ATTR:
3302 		((ETempSensor_t *)objp)->hw_lo_shut = *(int32_t *)attrp;
3303 		return (status);
3304 	}
3305 
3306 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3307 
3308 	return (status);
3309 }
3310 
3311 static int32_t
3312 i_psvc_get_attr_1_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3313 {
3314 	int32_t status = PSVC_SUCCESS;
3315 
3316 	switch (attr_id) {
3317 	case PSVC_SENSOR_VALUE_ATTR:
3318 		return (i_psvc_get_device_value_1_0(hdlp, objp, attrp));
3319 	case PSVC_SETPOINT_ATTR:
3320 		*(int16_t *)attrp = ((EFan_t *)objp)->setpoint;
3321 		return (status);
3322 	case PSVC_HYSTERESIS_ATTR:
3323 		*(int16_t *)attrp = ((EFan_t *)objp)->hysteresis;
3324 		return (status);
3325 	case PSVC_LOOPGAIN_ATTR:
3326 		*(int16_t *)attrp = ((EFan_t *)objp)->loopgain;
3327 		return (status);
3328 	case PSVC_LOOPBIAS_ATTR:
3329 		*(int16_t *)attrp = ((EFan_t *)objp)->loopbias;
3330 		return (status);
3331 	case PSVC_TEMP_DIFFERENTIAL_ATTR:
3332 		memcpy(attrp, ((EFan_t *)objp)->temp_differential,
3333 			sizeof (((EFan_t *)objp)->temp_differential));
3334 		return (status);
3335 	case PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR:
3336 		*(int16_t *)attrp = ((EFan_t *)objp)->temp_differential_index;
3337 		return (status);
3338 	}
3339 
3340 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3341 
3342 	return (status);
3343 }
3344 
3345 static int32_t
3346 i_psvc_set_attr_1_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3347 {
3348 	int32_t status = PSVC_SUCCESS;
3349 
3350 	switch (attr_id) {
3351 	case PSVC_TEMP_DIFFERENTIAL_ATTR:
3352 		memcpy(((EFan_t *)objp)->temp_differential, attrp,
3353 			sizeof (((EFan_t *)objp)->temp_differential));
3354 		return (status);
3355 	case PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR:
3356 		((EFan_t *)objp)->temp_differential_index = *(int16_t *)attrp;
3357 		return (status);
3358 	case PSVC_SETPOINT_ATTR:
3359 		((EFan_t *)objp)->setpoint = *(int16_t *)attrp;
3360 		return (status);
3361 	}
3362 
3363 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3364 
3365 	return (PSVC_SUCCESS);
3366 }
3367 
3368 static int32_t
3369 i_psvc_get_attr_2_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3370 {
3371 	int32_t status = PSVC_SUCCESS;
3372 
3373 	switch (attr_id) {
3374 	case PSVC_LED_STATE_ATTR:
3375 	case PSVC_STATE_ATTR:
3376 		return (i_psvc_get_device_state_2_0(hdlp, objp, attrp));
3377 	case PSVC_LED_COLOR_ATTR:
3378 		strcpy((char *)attrp, ((ELed_t *)objp)->color);
3379 		return (status);
3380 	case PSVC_LIT_COUNT_ATTR:
3381 		*(int16_t *)attrp = ((ELed_t *)objp)->lit_count;
3382 		return (status);
3383 	}
3384 
3385 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3386 
3387 	return (status);
3388 }
3389 
3390 static int32_t
3391 i_psvc_set_attr_2_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3392 {
3393 	int32_t status = PSVC_SUCCESS;
3394 
3395 	switch (attr_id) {
3396 	case PSVC_LED_STATE_ATTR:
3397 	case PSVC_STATE_ATTR:
3398 		return (i_psvc_set_device_state_2_0(hdlp, objp, attrp));
3399 	}
3400 
3401 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3402 
3403 	return (status);
3404 }
3405 
3406 static int32_t
3407 i_psvc_get_attr_2_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3408 {
3409 	int32_t status = PSVC_SUCCESS;
3410 
3411 	switch (attr_id) {
3412 	case PSVC_LED_STATE_ATTR:
3413 	case PSVC_STATE_ATTR:
3414 		return (i_psvc_get_device_state_2_1(hdlp, objp, attrp));
3415 	case PSVC_LED_COLOR_ATTR:
3416 		strcpy((char *)attrp, ((ELed_t *)objp)->color);
3417 		return (status);
3418 	case PSVC_LIT_COUNT_ATTR:
3419 		*(int16_t *)attrp = ((ELed_t *)objp)->lit_count;
3420 		return (status);
3421 	}
3422 
3423 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3424 
3425 	return (status);
3426 }
3427 
3428 static int32_t
3429 i_psvc_set_attr_2_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3430 {
3431 	int32_t status = PSVC_SUCCESS;
3432 
3433 	switch (attr_id) {
3434 	case PSVC_LED_STATE_ATTR:
3435 	case PSVC_STATE_ATTR:
3436 		return (i_psvc_set_device_state_2_1(hdlp, objp, attrp));
3437 	}
3438 
3439 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3440 
3441 	return (status);
3442 }
3443 
3444 static int32_t
3445 i_psvc_get_attr_2_2(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3446 {
3447 	int32_t status = PSVC_SUCCESS;
3448 
3449 	switch (attr_id) {
3450 	case PSVC_LED_STATE_ATTR:
3451 	case PSVC_STATE_ATTR:
3452 		return (i_psvc_get_device_state_2_0(hdlp, objp, attrp));
3453 	case PSVC_LED_COLOR_ATTR:
3454 		strcpy((char *)attrp, ((ELed_t *)objp)->color);
3455 		return (status);
3456 	case PSVC_LIT_COUNT_ATTR:
3457 		*(int16_t *)attrp = ((ELed_t *)objp)->lit_count;
3458 		return (status);
3459 	case PSVC_LED_IS_LOCATOR_ATTR:
3460 		strcpy((char *)attrp, ((ELed_t *)objp)->is_locator);
3461 		return (status);
3462 	case PSVC_LED_LOCATOR_NAME_ATTR:
3463 		strcpy((char *)attrp, ((ELed_t *)objp)->locator_name);
3464 		return (status);
3465 	}
3466 
3467 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3468 
3469 	return (status);
3470 }
3471 
3472 static int32_t
3473 i_psvc_get_attr_4_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3474 {
3475 	int32_t status = PSVC_SUCCESS;
3476 
3477 	switch (attr_id) {
3478 	case PSVC_SENSOR_VALUE_ATTR:
3479 		return (i_psvc_get_device_value_4_0(hdlp, objp, attrp));
3480 	case PSVC_LO_WARN_ATTR:
3481 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->lo_warn;
3482 		return (status);
3483 	case PSVC_LO_SHUT_ATTR:
3484 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->lo_shut;
3485 		return (status);
3486 	case PSVC_HI_WARN_ATTR:
3487 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->hi_warn;
3488 		return (status);
3489 	case PSVC_HI_SHUT_ATTR:
3490 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->hi_shut;
3491 		return (status);
3492 	}
3493 
3494 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3495 
3496 	return (PSVC_SUCCESS);
3497 }
3498 
3499 static int32_t
3500 i_psvc_get_attr_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3501 {
3502 	int32_t status = PSVC_SUCCESS;
3503 
3504 	if (attr_id == PSVC_CONTROL_VALUE_ATTR) {
3505 		return (i_psvc_get_device_value_5_0(hdlp, objp, attrp));
3506 	}
3507 
3508 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3509 
3510 	return (status);
3511 }
3512 
3513 static int32_t
3514 i_psvc_set_attr_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3515 {
3516 	int32_t status = PSVC_SUCCESS;
3517 
3518 	if (attr_id == PSVC_CONTROL_VALUE_ATTR) {
3519 		return (i_psvc_set_device_value_5_0(hdlp, objp, attrp));
3520 	}
3521 
3522 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3523 
3524 	return (status);
3525 }
3526 
3527 static int32_t
3528 i_psvc_get_attr_6_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3529 {
3530 	int32_t status = PSVC_SUCCESS;
3531 
3532 	switch (attr_id) {
3533 	case PSVC_GPIO_VALUE_ATTR:
3534 		return (i_psvc_get_device_value_6_0(hdlp, objp, attrp));
3535 	case PSVC_GPIO_BITS:
3536 		*(int32_t *)attrp = 1;
3537 		return (status);
3538 	}
3539 
3540 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3541 
3542 	return (status);
3543 }
3544 
3545 static int32_t
3546 i_psvc_set_attr_6_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3547 {
3548 	int32_t status = PSVC_SUCCESS;
3549 
3550 	if (attr_id == PSVC_GPIO_VALUE_ATTR) {
3551 		return (i_psvc_set_device_value_6_0(hdlp, objp, attrp));
3552 	}
3553 
3554 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3555 
3556 	return (status);
3557 }
3558 
3559 static int32_t
3560 i_psvc_get_attr_7_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3561 {
3562 	int32_t status = PSVC_SUCCESS;
3563 
3564 	switch (attr_id) {
3565 	case PSVC_SENSOR_VALUE_ATTR:
3566 		return (i_psvc_get_device_value_7_0(hdlp, objp, attrp));
3567 	case PSVC_LO_WARN_ATTR:
3568 		*(int32_t *)attrp = ((EFanTach_t *)objp)->lo_warn;
3569 		return (status);
3570 	case PSVC_LO_SHUT_ATTR:
3571 		*(int32_t *)attrp = ((EFanTach_t *)objp)->lo_shut;
3572 		return (status);
3573 	case PSVC_HI_WARN_ATTR:
3574 		*(int32_t *)attrp = ((EFanTach_t *)objp)->hi_warn;
3575 		return (status);
3576 	case PSVC_HI_SHUT_ATTR:
3577 		*(int32_t *)attrp = ((EFanTach_t *)objp)->hi_shut;
3578 		return (status);
3579 	}
3580 
3581 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3582 
3583 	return (PSVC_SUCCESS);
3584 }
3585 
3586 static int32_t
3587 i_psvc_get_attr_8_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3588 {
3589 	int32_t status = PSVC_SUCCESS;
3590 
3591 	switch (attr_id) {
3592 	case PSVC_SWITCH_STATE_ATTR:
3593 	case PSVC_STATE_ATTR:
3594 		return (i_psvc_get_device_state_8_0(hdlp, objp, attrp));
3595 	}
3596 
3597 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3598 
3599 	return (status);
3600 }
3601 
3602 static int32_t
3603 i_psvc_set_attr_8_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3604 {
3605 	int32_t status = PSVC_SUCCESS;
3606 
3607 	switch (attr_id) {
3608 	case PSVC_SWITCH_STATE_ATTR:
3609 	case PSVC_STATE_ATTR:
3610 		return (i_psvc_set_device_state_8_0(hdlp, objp, attrp));
3611 	}
3612 
3613 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3614 
3615 	return (status);
3616 }
3617 
3618 static int32_t
3619 i_psvc_get_attr_9_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3620 {
3621 	int32_t status = PSVC_SUCCESS;
3622 
3623 	switch (attr_id) {
3624 	case PSVC_SWITCH_STATE_ATTR:
3625 	case PSVC_STATE_ATTR:
3626 		status = i_psvc_get_device_state_9_0(hdlp, objp, attrp);
3627 		if ((status == PSVC_FAILURE) && (errno == EINVAL)) {
3628 			strcpy((char *)attrp, PSVC_ERROR);
3629 			return (PSVC_SUCCESS);
3630 		} else {
3631 			return (status);
3632 		}
3633 	}
3634 
3635 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3636 
3637 	return (status);
3638 }
3639 
3640 static int32_t
3641 i_psvc_get_attr_10_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3642 {
3643 	int32_t status = PSVC_SUCCESS;
3644 
3645 	switch (attr_id) {
3646 	case PSVC_GPIO_VALUE_ATTR:
3647 		return (i_psvc_get_device_value_10_0(hdlp, objp, attrp));
3648 	case PSVC_GPIO_BITS:
3649 		*(int32_t *)attrp = 8;
3650 		return (status);
3651 	}
3652 
3653 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3654 
3655 	return (status);
3656 }
3657 
3658 static int32_t
3659 i_psvc_set_attr_10_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3660 {
3661 	int32_t status = PSVC_SUCCESS;
3662 
3663 	if (attr_id == PSVC_GPIO_VALUE_ATTR) {
3664 		return (i_psvc_set_device_value_10_0(hdlp, objp, attrp));
3665 	}
3666 
3667 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3668 
3669 	return (status);
3670 }
3671 
3672 static int32_t
3673 i_psvc_get_attr_10_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3674 {
3675 	int32_t status = PSVC_SUCCESS;
3676 
3677 	switch (attr_id) {
3678 	case PSVC_GPIO_VALUE_ATTR:
3679 		return (i_psvc_get_device_value_10_1(hdlp, objp, attrp));
3680 	case PSVC_GPIO_BITS:
3681 		*(int32_t *)attrp = 8;
3682 		return (status);
3683 	}
3684 
3685 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3686 
3687 	return (status);
3688 }
3689 
3690 static int32_t
3691 i_psvc_set_attr_10_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3692 {
3693 	int32_t status = PSVC_SUCCESS;
3694 
3695 	if (attr_id == PSVC_GPIO_VALUE_ATTR) {
3696 		return (i_psvc_set_device_value_10_1(hdlp, objp, attrp));
3697 	}
3698 
3699 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3700 
3701 	return (status);
3702 }
3703 
3704 /* AT24 */
3705 static int32_t
3706 i_psvc_get_attr_11_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3707 {
3708 	int32_t status = PSVC_SUCCESS;
3709 	int32_t probe_status;
3710 
3711 	switch (attr_id) {
3712 	case PSVC_PROBE_RESULT_ATTR:
3713 		probe_status = i_psvc_probe_11_0(hdlp, objp);
3714 		if (probe_status == PSVC_SUCCESS)
3715 			strcpy((char *)attrp, PSVC_OK);
3716 		else
3717 			strcpy((char *)attrp, PSVC_ERROR);
3718 		return (status);
3719 	case PSVC_FRU_INFO_ATTR:
3720 		status = i_psvc_get_reg_11_0(hdlp, objp, attr_id, attrp);
3721 		return (status);
3722 	}
3723 
3724 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3725 
3726 	return (status);
3727 }
3728 
3729 static int32_t
3730 i_psvc_get_reg_11_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3731 {
3732 	int32_t status = PSVC_SUCCESS, ret;
3733 	char path[1024], *data;
3734 	int32_t fp, temp_errno;
3735 	fru_info_t *fru_data;
3736 
3737 	fru_data = (fru_info_t *)attrp;
3738 
3739 	if (objp->present != PSVC_PRESENT) {
3740 		errno = ENODEV;
3741 		return (PSVC_FAILURE);
3742 	}
3743 
3744 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
3745 	if (status != PSVC_SUCCESS)
3746 		return (status);
3747 
3748 	fp = open(path, O_RDWR);
3749 	if (fp == -1) {
3750 		return (PSVC_FAILURE);
3751 	}
3752 
3753 	ret = lseek(fp, fru_data->buf_start, SEEK_SET);
3754 	if (ret != fru_data->buf_start) {
3755 		temp_errno = errno;
3756 		close(fp);
3757 		errno = temp_errno;
3758 		return (PSVC_FAILURE);
3759 	}
3760 
3761 	data = (char *)malloc(fru_data->read_size);
3762 	ret = read(fp, data, fru_data->read_size);
3763 	if (ret == -1) {
3764 		free(data);
3765 		close(fp);
3766 		errno = EIO;
3767 		return (-1);
3768 	}
3769 
3770 	memcpy(fru_data->buf, data, fru_data->read_size);
3771 	free(data);
3772 	close(fp);
3773 
3774 	return (status);
3775 }
3776 
3777 static int32_t
3778 i_psvc_get_attr_11_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3779 {
3780 	int32_t status = PSVC_SUCCESS;
3781 	int32_t probe_status;
3782 
3783 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3784 		probe_status = i_psvc_probe_11_1(hdlp, objp);
3785 		if (probe_status == PSVC_SUCCESS)
3786 			strcpy((char *)attrp, PSVC_OK);
3787 		else
3788 			strcpy((char *)attrp, PSVC_ERROR);
3789 		return (status);
3790 	}
3791 
3792 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3793 
3794 	return (status);
3795 }
3796 
3797 static int32_t
3798 i_psvc_get_attr_11_2(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3799 {
3800 	int32_t status = PSVC_SUCCESS;
3801 	int32_t probe_status;
3802 
3803 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3804 		probe_status = i_psvc_probe_11_2(hdlp, objp);
3805 		if (probe_status == PSVC_SUCCESS)
3806 			strcpy((char *)attrp, PSVC_OK);
3807 		else
3808 			strcpy((char *)attrp, PSVC_ERROR);
3809 		return (status);
3810 	}
3811 
3812 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3813 
3814 	return (status);
3815 }
3816 
3817 static int32_t
3818 i_psvc_get_attr_11_3(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3819 {
3820 	int32_t status = PSVC_SUCCESS;
3821 	int32_t probe_status;
3822 
3823 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3824 		probe_status = i_psvc_probe_11_3(hdlp, objp);
3825 		if (probe_status == PSVC_SUCCESS)
3826 			strcpy((char *)attrp, PSVC_OK);
3827 		else
3828 			strcpy((char *)attrp, PSVC_ERROR);
3829 		return (status);
3830 	}
3831 
3832 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3833 
3834 	return (status);
3835 }
3836 
3837 static int32_t
3838 i_psvc_get_attr_11_4(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3839 {
3840 	int32_t status = PSVC_SUCCESS;
3841 	int32_t probe_status;
3842 
3843 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3844 		probe_status = i_psvc_probe_11_4(hdlp, objp);
3845 		if (probe_status == PSVC_SUCCESS)
3846 			strcpy((char *)attrp, PSVC_OK);
3847 		else
3848 			strcpy((char *)attrp, PSVC_ERROR);
3849 		return (status);
3850 	}
3851 
3852 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3853 
3854 	return (status);
3855 }
3856 
3857 static int32_t
3858 i_psvc_get_attr_11_5(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3859 {
3860 	int32_t status = PSVC_SUCCESS;
3861 	int32_t probe_status;
3862 
3863 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3864 		probe_status = i_psvc_probe_11_5(hdlp, objp);
3865 		if (probe_status == PSVC_SUCCESS)
3866 			strcpy((char *)attrp, PSVC_OK);
3867 		else
3868 			strcpy((char *)attrp, PSVC_ERROR);
3869 		return (status);
3870 	}
3871 
3872 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3873 
3874 	return (status);
3875 }
3876 
3877 static int32_t
3878 i_psvc_get_attr_11_6(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3879 {
3880 	int32_t status = PSVC_SUCCESS;
3881 	int32_t probe_status;
3882 
3883 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3884 		probe_status = i_psvc_probe_11_6(hdlp, objp);
3885 		if (probe_status == PSVC_SUCCESS)
3886 			strcpy((char *)attrp, PSVC_OK);
3887 		else
3888 			strcpy((char *)attrp, PSVC_ERROR);
3889 		return (status);
3890 	}
3891 
3892 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3893 
3894 	return (status);
3895 }
3896 
3897 static int32_t
3898 i_psvc_get_attr_11_7(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3899 {
3900 	int32_t status = PSVC_SUCCESS;
3901 	int32_t probe_status;
3902 
3903 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3904 		probe_status = i_psvc_probe_11_7(hdlp, objp);
3905 		if (probe_status == PSVC_SUCCESS)
3906 			strcpy((char *)attrp, PSVC_OK);
3907 		else
3908 			strcpy((char *)attrp, PSVC_ERROR);
3909 		return (status);
3910 	}
3911 
3912 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3913 
3914 	return (status);
3915 }
3916 
3917 static int32_t
3918 i_psvc_get_attr_11_8(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3919 {
3920 	int32_t status = PSVC_SUCCESS;
3921 	int32_t probe_status;
3922 
3923 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3924 		probe_status = i_psvc_probe_11_8(hdlp, objp);
3925 		if (probe_status == PSVC_SUCCESS)
3926 			strcpy((char *)attrp, PSVC_OK);
3927 		else
3928 			strcpy((char *)attrp, PSVC_ERROR);
3929 		return (status);
3930 	}
3931 
3932 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3933 
3934 	return (status);
3935 }
3936 
3937 static int32_t
3938 i_psvc_get_attr_11_9(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3939 {
3940 	int32_t status = PSVC_SUCCESS;
3941 	int32_t probe_status;
3942 
3943 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3944 		probe_status = i_psvc_probe_11_9(hdlp, objp);
3945 		if (probe_status == PSVC_SUCCESS)
3946 			strcpy((char *)attrp, PSVC_OK);
3947 		else
3948 			strcpy((char *)attrp, PSVC_ERROR);
3949 		return (status);
3950 	}
3951 
3952 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3953 
3954 	return (status);
3955 }
3956 
3957 static int32_t
3958 i_psvc_load_generic(
3959 	EHdl_t	*hdlp,
3960 	char	*name,
3961 	EObj_t    **objpp,
3962 	char	  *buf,
3963 	int32_t   obj_size)
3964 {
3965 	int32_t found, key, array;
3966 	EObj_t *objp;
3967 	char *start;
3968 	char  cur_device[NAMELEN];
3969 	int slot;
3970 	ETable_Array *tbl_arr;
3971 
3972 	key = psvc_get_str_key(name);
3973 	array = key % PSVC_MAX_TABLE_ARRAYS;
3974 	tbl_arr = &(hdlp->tbl_arry[array]);
3975 
3976 	if (tbl_arr->nextid == hdlp->total_obj_count) {
3977 		errno = EINVAL;
3978 		return (PSVC_FAILURE);
3979 	} else {
3980 		slot = tbl_arr->nextid++;
3981 		tbl_arr->obj_count++;
3982 	}
3983 
3984 	if (i_psvc_find_file_section(hdlp->fp, "OBJECT_INFO") != PSVC_SUCCESS)
3985 		return (PSVC_FAILURE);
3986 
3987 	fgets(buf, BUFSZ, hdlp->fp);
3988 	while (strcmp(buf, "OBJECT_INFO_END")) {
3989 		start = strrchr(buf, '/');
3990 		if (start == NULL) {
3991 			errno = EINVAL;
3992 			return (PSVC_FAILURE);
3993 		}
3994 		found = sscanf(start + 1, "%s",  cur_device);
3995 		if (found != 1) {
3996 			errno = EINVAL;
3997 			return (PSVC_FAILURE);
3998 		}
3999 		if (strcmp(name, cur_device) == 0)  /* found it */
4000 			break;
4001 		fgets(buf, BUFSZ, hdlp->fp);
4002 	}
4003 
4004 	tbl_arr->obj_tbl[slot].objp = (EObj_t *)malloc(obj_size);
4005 	if (tbl_arr->obj_tbl[slot].objp == 0)
4006 		return (PSVC_FAILURE);
4007 	objp = (EObj_t *)tbl_arr->obj_tbl[slot].objp;
4008 	tbl_arr->obj_tbl[slot].type = PSVC_OBJ;
4009 
4010 	memset(objp, 0, obj_size);
4011 	strcpy(objp->label, name);
4012 	strcpy(tbl_arr->obj_tbl[slot].name, name);
4013 
4014 	tbl_arr->obj_tbl[slot].key = key;
4015 
4016 	if (i_psvc_value(buf, PSVC_CLASS_ATTR, &objp->class) != PSVC_SUCCESS) {
4017 		i_psvc_destructor(hdlp, name, objp);
4018 		return (PSVC_FAILURE);
4019 	}
4020 	if (i_psvc_value(buf, PSVC_SUBCLASS_ATTR, &objp->subclass) !=
4021 		PSVC_SUCCESS) {
4022 		i_psvc_destructor(hdlp, name, objp);
4023 		return (PSVC_FAILURE);
4024 	}
4025 	if (i_psvc_value(buf, PSVC_INSTANCE_ATTR, &objp->instance) !=
4026 		PSVC_SUCCESS) {
4027 		i_psvc_destructor(hdlp, name, objp);
4028 		return (PSVC_FAILURE);
4029 	}
4030 	if (i_psvc_value(buf, PSVC_FEATURES_ATTR, &objp->features) !=
4031 		PSVC_SUCCESS) {
4032 		i_psvc_destructor(hdlp, name, objp);
4033 		return (PSVC_FAILURE);
4034 	}
4035 	if (i_psvc_value(buf, PSVC_ADDR_SPEC_ATTR, &objp->addr_spec) !=
4036 		PSVC_SUCCESS) {
4037 		i_psvc_destructor(hdlp, name, objp);
4038 		return (PSVC_FAILURE);
4039 	}
4040 
4041 	if (objp->features & PSVC_DEV_SECONDARY)
4042 		objp->enabled = PSVC_DISABLED;
4043 	else
4044 		objp->enabled = PSVC_ENABLED;
4045 
4046 	if (PSVC_GET_VERSION(objp->addr_spec) > PSVC_VERSION) {
4047 		errno = EINVAL;
4048 		i_psvc_destructor(hdlp, name, objp);
4049 		return (PSVC_FAILURE);
4050 	}
4051 
4052 	*objpp = objp;
4053 	return (PSVC_SUCCESS);
4054 
4055 }
4056 
4057 
4058 static int32_t
4059 i_psvc_not_supported()
4060 {
4061 	errno = ENOTSUP;
4062 	return (PSVC_FAILURE);
4063 }
4064 
4065 /* Temperature sensor */
4066 /* Class 0 Subclass 0 are temperature sensors that cannot be updated */
4067 static int32_t
4068 i_psvc_constructor_0_0(
4069 	EHdl_t	*hdlp,
4070 	char	*id,
4071 	EObj_t    **objpp)
4072 {
4073 	int32_t status;
4074 	char buf[BUFSZ];
4075 	ETempSensor_t *dp;
4076 
4077 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4078 		sizeof (ETempSensor_t));
4079 	if (status != PSVC_SUCCESS)
4080 		return (status);
4081 
4082 	/* Load class specific info */
4083 	dp = (ETempSensor_t *)*objpp;
4084 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4085 	    != PSVC_SUCCESS) {
4086 		i_psvc_destructor(hdlp, id, dp);
4087 		return (PSVC_FAILURE);
4088 	}
4089 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4090 	    != PSVC_SUCCESS) {
4091 		i_psvc_destructor(hdlp, id, dp);
4092 		return (PSVC_FAILURE);
4093 	}
4094 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4095 	    != PSVC_SUCCESS) {
4096 		i_psvc_destructor(hdlp, id, dp);
4097 		return (PSVC_FAILURE);
4098 	}
4099 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4100 	    != PSVC_SUCCESS) {
4101 		i_psvc_destructor(hdlp, id, dp);
4102 		return (PSVC_FAILURE);
4103 	}
4104 
4105 	dp->ld.constructor = i_psvc_constructor_0_0;
4106 	dp->ld.destructor = i_psvc_destructor;
4107 	dp->ld.get_attr = i_psvc_get_attr_0_0;
4108 	dp->ld.set_attr = i_psvc_set_attr_generic;
4109 
4110 	return (0);
4111 }
4112 
4113 /* Class 0 Subclass 1 are temperature sensors that can be updated */
4114 static int32_t
4115 i_psvc_constructor_0_1(
4116 	EHdl_t	*hdlp,
4117 	char	*id,
4118 	EObj_t    **objpp)
4119 {
4120 	int32_t status;
4121 	char buf[BUFSZ];
4122 	ETempSensor_t *dp;
4123 
4124 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4125 		sizeof (ETempSensor_t));
4126 	if (status != PSVC_SUCCESS)
4127 		return (status);
4128 
4129 	/* Load class specific info */
4130 	dp = (ETempSensor_t *)*objpp;
4131 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4132 	    != PSVC_SUCCESS) {
4133 		i_psvc_destructor(hdlp, id, dp);
4134 		return (PSVC_FAILURE);
4135 	}
4136 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4137 	    != PSVC_SUCCESS) {
4138 		i_psvc_destructor(hdlp, id, dp);
4139 		return (PSVC_FAILURE);
4140 	}
4141 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4142 	    != PSVC_SUCCESS) {
4143 		i_psvc_destructor(hdlp, id, dp);
4144 		return (PSVC_FAILURE);
4145 	}
4146 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4147 	    != PSVC_SUCCESS) {
4148 		i_psvc_destructor(hdlp, id, dp);
4149 		return (PSVC_FAILURE);
4150 	}
4151 
4152 	if ((*objpp)->features & PSVC_OPT_TEMP) {
4153 		if (i_psvc_value(buf, PSVC_OPTIMAL_TEMP_ATTR, &dp->opt_temp)
4154 		    != PSVC_SUCCESS) {
4155 			i_psvc_destructor(hdlp, id, dp);
4156 			return (PSVC_FAILURE);
4157 		}
4158 	}
4159 	if ((*objpp)->features & PSVC_HW_LOW_SHUT) {
4160 		if (i_psvc_value(buf, PSVC_HW_LO_SHUT_ATTR, &dp->hw_lo_shut)
4161 		    != PSVC_SUCCESS) {
4162 			i_psvc_destructor(hdlp, id, dp);
4163 			return (PSVC_FAILURE);
4164 		}
4165 	}
4166 	if ((*objpp)->features & PSVC_HW_HIGH_SHUT) {
4167 		if (i_psvc_value(buf, PSVC_HW_HI_SHUT_ATTR, &dp->hw_hi_shut)
4168 		    != PSVC_SUCCESS) {
4169 			i_psvc_destructor(hdlp, id, dp);
4170 			return (PSVC_FAILURE);
4171 		}
4172 	}
4173 
4174 	dp->ld.constructor = i_psvc_constructor_0_1;
4175 	dp->ld.destructor = i_psvc_destructor;
4176 	dp->ld.get_attr = i_psvc_get_attr_0_1;
4177 	dp->ld.set_attr = i_psvc_set_attr_0_1;
4178 
4179 	return (0);
4180 }
4181 
4182 /* Fan */
4183 static int32_t
4184 i_psvc_constructor_1_0(
4185 	EHdl_t	*hdlp,
4186 	char	*id,
4187 	EObj_t  **objpp)
4188 {
4189 	int32_t status;
4190 	char buf[BUFSZ];
4191 	EFan_t *dp;
4192 
4193 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4194 		sizeof (EFan_t));
4195 	if (status != PSVC_SUCCESS)
4196 		return (status);
4197 
4198 	/* Load class specific info */
4199 	dp = (EFan_t *)*objpp;
4200 	if (i_psvc_value(buf, PSVC_SETPOINT_ATTR, &dp->setpoint)
4201 	    != PSVC_SUCCESS) {
4202 		i_psvc_destructor(hdlp, id, dp);
4203 		return (PSVC_FAILURE);
4204 	}
4205 	if (i_psvc_value(buf, PSVC_HYSTERESIS_ATTR, &dp->hysteresis)
4206 	    != PSVC_SUCCESS) {
4207 		i_psvc_destructor(hdlp, id, dp);
4208 		return (PSVC_FAILURE);
4209 	}
4210 	if (i_psvc_value(buf, PSVC_LOOPGAIN_ATTR, &dp->loopgain)
4211 	    != PSVC_SUCCESS) {
4212 		i_psvc_destructor(hdlp, id, dp);
4213 		return (PSVC_FAILURE);
4214 	}
4215 	if (i_psvc_value(buf, PSVC_LOOPBIAS_ATTR, &dp->loopbias)
4216 	    != PSVC_SUCCESS) {
4217 		i_psvc_destructor(hdlp, id, dp);
4218 		return (PSVC_FAILURE);
4219 	}
4220 
4221 	dp->ld.constructor = i_psvc_constructor_1_0;
4222 	dp->ld.destructor = i_psvc_destructor;
4223 	dp->ld.get_attr = i_psvc_get_attr_1_0;
4224 	dp->ld.set_attr = i_psvc_set_attr_1_0;
4225 
4226 	return (PSVC_SUCCESS);
4227 }
4228 
4229 
4230 /* LED */
4231 static int32_t
4232 i_psvc_constructor_2_0(
4233 	EHdl_t	*hdlp,
4234 	char	*id,
4235 	EObj_t  **objpp)
4236 {
4237 	int32_t status;
4238 	char buf[BUFSZ];
4239 	ELed_t *dp;
4240 
4241 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4242 		sizeof (ELed_t));
4243 	if (status != PSVC_SUCCESS)
4244 		return (status);
4245 
4246 	/* Load class specific info */
4247 	dp = (ELed_t *)*objpp;
4248 
4249 	if (i_psvc_value(buf, PSVC_LED_COLOR_ATTR, dp->color)
4250 	    != PSVC_SUCCESS) {
4251 		i_psvc_destructor(hdlp, id, dp);
4252 		return (PSVC_FAILURE);
4253 	}
4254 
4255 	dp->ld.constructor = i_psvc_constructor_2_0;
4256 	dp->ld.destructor = i_psvc_destructor;
4257 	dp->ld.get_attr = i_psvc_get_attr_2_0;
4258 	dp->ld.set_attr = i_psvc_set_attr_2_0;
4259 
4260 	return (PSVC_SUCCESS);
4261 }
4262 
4263 static int32_t
4264 i_psvc_constructor_2_1(
4265 	EHdl_t	*hdlp,
4266 	char	*id,
4267 	EObj_t  **objpp)
4268 {
4269 	int32_t status;
4270 	char buf[BUFSZ];
4271 	ELed_t *dp;
4272 
4273 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4274 		sizeof (ELed_t));
4275 	if (status != PSVC_SUCCESS)
4276 		return (status);
4277 
4278 	/* Load class specific info */
4279 	dp = (ELed_t *)*objpp;
4280 
4281 	if (i_psvc_value(buf, PSVC_LED_COLOR_ATTR, dp->color)
4282 	    != PSVC_SUCCESS) {
4283 		i_psvc_destructor(hdlp, id, dp);
4284 		return (PSVC_FAILURE);
4285 	}
4286 
4287 	dp->ld.constructor = i_psvc_constructor_2_1;
4288 	dp->ld.destructor = i_psvc_destructor;
4289 	dp->ld.get_attr = i_psvc_get_attr_2_1;
4290 	dp->ld.set_attr = i_psvc_set_attr_2_1;
4291 
4292 	return (PSVC_SUCCESS);
4293 }
4294 
4295 static int32_t
4296 i_psvc_constructor_2_2(
4297 	EHdl_t	*hdlp,
4298 	char	*id,
4299 	EObj_t  **objpp)
4300 {
4301 	int32_t status;
4302 	char buf[BUFSZ];
4303 	ELed_t *dp;
4304 
4305 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4306 		sizeof (ELed_t));
4307 	if (status != PSVC_SUCCESS)
4308 		return (status);
4309 
4310 	/* Load class specific info */
4311 	dp = (ELed_t *)*objpp;
4312 
4313 	if (i_psvc_value(buf, PSVC_LED_COLOR_ATTR, dp->color)
4314 	    != PSVC_SUCCESS) {
4315 		i_psvc_destructor(hdlp, id, dp);
4316 		return (PSVC_FAILURE);
4317 	}
4318 	if (i_psvc_value(buf, PSVC_LED_IS_LOCATOR_ATTR, dp->is_locator)
4319 	    != PSVC_SUCCESS) {
4320 		i_psvc_destructor(hdlp, id, dp);
4321 		return (PSVC_FAILURE);
4322 	}
4323 	if (strcmp(dp->is_locator, PSVC_LOCATOR_TRUE) == 0) {
4324 		if (i_psvc_value(buf, PSVC_LED_LOCATOR_NAME_ATTR,
4325 		    dp->locator_name) != PSVC_SUCCESS) {
4326 			i_psvc_destructor(hdlp, id, dp);
4327 			return (PSVC_FAILURE);
4328 		}
4329 	} else {
4330 		strcpy(dp->locator_name, "N/A");
4331 	}
4332 
4333 	dp->ld.constructor = i_psvc_constructor_2_2;
4334 	dp->ld.destructor = i_psvc_destructor;
4335 	dp->ld.get_attr = i_psvc_get_attr_2_2;
4336 	dp->ld.set_attr = i_psvc_set_attr_2_0;
4337 
4338 	return (PSVC_SUCCESS);
4339 }
4340 
4341 /* System Device */
4342 static int32_t
4343 i_psvc_constructor_3_0(
4344 	EHdl_t	*hdlp,
4345 	char	*id,
4346 	EObj_t  **objpp)
4347 {
4348 	int32_t status;
4349 	char buf[BUFSZ];
4350 	ESystem_t *dp;
4351 
4352 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (ESystem_t));
4353 	if (status != PSVC_SUCCESS)
4354 		return (status);
4355 
4356 	/* Load class specific info */
4357 	dp = (ESystem_t *)*objpp;
4358 
4359 	dp->ld.constructor = i_psvc_constructor_3_0;
4360 	dp->ld.destructor = i_psvc_destructor;
4361 	dp->ld.get_attr = i_psvc_get_attr_generic;
4362 	dp->ld.set_attr = i_psvc_set_attr_generic;
4363 
4364 	return (PSVC_SUCCESS);
4365 }
4366 
4367 /* Digital Sensor */
4368 static int32_t
4369 i_psvc_constructor_4_0(
4370 	EHdl_t	*hdlp,
4371 	char	*id,
4372 	EObj_t  **objpp)
4373 {
4374 	int32_t status;
4375 	char buf[BUFSZ];
4376 	EDigiSensor_t *dp;
4377 
4378 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4379 		sizeof (EDigiSensor_t));
4380 	if (status != PSVC_SUCCESS) {
4381 		return (status);
4382 	}
4383 
4384 	/* Load class specific info */
4385 	dp = (EDigiSensor_t *)*objpp;
4386 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4387 	    != PSVC_SUCCESS) {
4388 		i_psvc_destructor(hdlp, id, dp);
4389 		return (PSVC_FAILURE);
4390 	}
4391 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4392 	    != PSVC_SUCCESS) {
4393 		i_psvc_destructor(hdlp, id, dp);
4394 		return (PSVC_FAILURE);
4395 	}
4396 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4397 	    != PSVC_SUCCESS) {
4398 		i_psvc_destructor(hdlp, id, dp);
4399 		return (PSVC_FAILURE);
4400 	}
4401 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4402 	    != PSVC_SUCCESS) {
4403 		i_psvc_destructor(hdlp, id, dp);
4404 		return (PSVC_FAILURE);
4405 	}
4406 
4407 	dp->ld.constructor = i_psvc_constructor_4_0;
4408 	dp->ld.destructor = i_psvc_destructor;
4409 	dp->ld.get_attr = i_psvc_get_attr_4_0;
4410 	dp->ld.set_attr = i_psvc_set_attr_generic;
4411 
4412 	return (PSVC_SUCCESS);
4413 }
4414 
4415 /* Digital Control */
4416 static int32_t
4417 i_psvc_constructor_5_0(
4418 	EHdl_t	*hdlp,
4419 	char	*id,
4420 	EObj_t  **objpp)
4421 {
4422 	int32_t status;
4423 	char buf[BUFSZ];
4424 	EDigiControl_t *dp;
4425 
4426 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4427 		sizeof (EDigiControl_t));
4428 	if (status != PSVC_SUCCESS)
4429 		return (status);
4430 
4431 	/* Load class specific info */
4432 	dp = (EDigiControl_t *)*objpp;
4433 
4434 	dp->ld.constructor = i_psvc_constructor_5_0;
4435 	dp->ld.destructor = i_psvc_destructor;
4436 	dp->ld.get_attr = i_psvc_get_attr_5_0;
4437 	dp->ld.set_attr = i_psvc_set_attr_5_0;
4438 	return (PSVC_SUCCESS);
4439 }
4440 
4441 /* Boolean GPIO */
4442 static int32_t
4443 i_psvc_constructor_6_0(
4444 	EHdl_t	*hdlp,
4445 	char	*id,
4446 	EObj_t  **objpp)
4447 {
4448 	int32_t status;
4449 	char buf[BUFSZ];
4450 	EBoolSensor_t *dp;
4451 
4452 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4453 		sizeof (EBoolSensor_t));
4454 	if (status != PSVC_SUCCESS)
4455 		return (status);
4456 
4457 	/* Load class specific info */
4458 	dp = (EBoolSensor_t *)*objpp;
4459 
4460 	dp->ld.constructor = i_psvc_constructor_6_0;
4461 	dp->ld.destructor = i_psvc_destructor;
4462 	dp->ld.get_attr = i_psvc_get_attr_6_0;
4463 	dp->ld.set_attr = i_psvc_set_attr_6_0;
4464 
4465 	return (PSVC_SUCCESS);
4466 }
4467 
4468 /* Fan Tachometer */
4469 static int32_t
4470 i_psvc_constructor_7_0(
4471 	EHdl_t	*hdlp,
4472 	char	*id,
4473 	EObj_t  **objpp)
4474 {
4475 	int32_t status;
4476 	char buf[BUFSZ];
4477 	EFanTach_t *dp;
4478 
4479 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4480 		sizeof (EFanTach_t));
4481 	if (status != PSVC_SUCCESS)
4482 		return (status);
4483 
4484 	/* Load class specific info */
4485 	dp = (EFanTach_t *)*objpp;
4486 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4487 	    != PSVC_SUCCESS) {
4488 		i_psvc_destructor(hdlp, id, dp);
4489 		return (PSVC_FAILURE);
4490 	}
4491 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4492 	    != PSVC_SUCCESS) {
4493 		i_psvc_destructor(hdlp, id, dp);
4494 		return (PSVC_FAILURE);
4495 	}
4496 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4497 	    != PSVC_SUCCESS) {
4498 		i_psvc_destructor(hdlp, id, dp);
4499 		return (PSVC_FAILURE);
4500 	}
4501 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4502 	    != PSVC_SUCCESS) {
4503 		i_psvc_destructor(hdlp, id, dp);
4504 		return (PSVC_FAILURE);
4505 	}
4506 
4507 	dp->ld.constructor = i_psvc_constructor_7_0;
4508 	dp->ld.destructor = i_psvc_destructor;
4509 	dp->ld.get_attr = i_psvc_get_attr_7_0;
4510 	dp->ld.set_attr = i_psvc_set_attr_generic;
4511 
4512 	return (PSVC_SUCCESS);
4513 }
4514 
4515 /* On Off Switch */
4516 static int32_t
4517 i_psvc_constructor_8_0(
4518 	EHdl_t	*hdlp,
4519 	char	*id,
4520 	EObj_t  **objpp)
4521 {
4522 	int32_t status;
4523 	char buf[BUFSZ];
4524 	ESwitch_t *dp;
4525 
4526 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4527 		sizeof (ESwitch_t));
4528 	if (status != PSVC_SUCCESS)
4529 		return (status);
4530 
4531 	/* Load class specific info */
4532 	dp = (ESwitch_t *)*objpp;
4533 
4534 	dp->ld.constructor = i_psvc_constructor_8_0;
4535 	dp->ld.destructor = i_psvc_destructor;
4536 	dp->ld.get_attr = i_psvc_get_attr_8_0;
4537 	dp->ld.set_attr = i_psvc_set_attr_8_0;
4538 
4539 	return (PSVC_SUCCESS);
4540 }
4541 
4542 /* Key Switch */
4543 static int32_t
4544 i_psvc_constructor_9_0(
4545 	EHdl_t	*hdlp,
4546 	char	*id,
4547 	EObj_t  **objpp)
4548 {
4549 	int32_t status;
4550 	char buf[BUFSZ];
4551 	EKeySwitch_t *dp;
4552 
4553 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4554 		sizeof (EKeySwitch_t));
4555 	if (status != PSVC_SUCCESS)
4556 		return (status);
4557 
4558 	/* Load class specific info */
4559 	dp = (EKeySwitch_t *)*objpp;
4560 
4561 	dp->ld.constructor = i_psvc_constructor_9_0;
4562 	dp->ld.destructor = i_psvc_destructor;
4563 	dp->ld.get_attr = i_psvc_get_attr_9_0;
4564 	dp->ld.set_attr = i_psvc_set_attr_generic;
4565 
4566 	return (PSVC_SUCCESS);
4567 }
4568 
4569 /* 8 Bit GPIO , devices with registers, calls get_reg()/set_reg() */
4570 static int32_t
4571 i_psvc_constructor_10_0(
4572 	EHdl_t	*hdlp,
4573 	char	*id,
4574 	EObj_t  **objpp)
4575 {
4576 	int32_t status;
4577 	char buf[BUFSZ];
4578 	EGPIO8_t *dp;
4579 
4580 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EGPIO8_t));
4581 	if (status != PSVC_SUCCESS)
4582 		return (status);
4583 
4584 	/* Load class specific info */
4585 	dp = (EGPIO8_t *)*objpp;
4586 
4587 	dp->ld.constructor = i_psvc_constructor_10_0;
4588 	dp->ld.destructor = i_psvc_destructor;
4589 	dp->ld.get_attr = i_psvc_get_attr_10_0;
4590 	dp->ld.set_attr = i_psvc_set_attr_10_0;
4591 
4592 	return (PSVC_SUCCESS);
4593 }
4594 
4595 /* 8 Bit GPIO , devices with ports, calls get_port()/set_port() */
4596 static int32_t
4597 i_psvc_constructor_10_1(
4598 	EHdl_t	*hdlp,
4599 	char	*id,
4600 	EObj_t  **objpp)
4601 {
4602 	int32_t status;
4603 	char buf[BUFSZ];
4604 	EGPIO8_t *dp;
4605 
4606 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EGPIO8_t));
4607 	if (status != PSVC_SUCCESS)
4608 		return (status);
4609 
4610 	/* Load class specific info */
4611 	dp = (EGPIO8_t *)*objpp;
4612 
4613 	dp->ld.constructor = i_psvc_constructor_10_1;
4614 	dp->ld.destructor = i_psvc_destructor;
4615 	dp->ld.get_attr = i_psvc_get_attr_10_1;
4616 	dp->ld.set_attr = i_psvc_set_attr_10_1;
4617 
4618 	return (PSVC_SUCCESS);
4619 }
4620 
4621 /* AT24 */
4622 static int32_t
4623 i_psvc_constructor_11_0(
4624 	EHdl_t	*hdlp,
4625 	char	*id,
4626 	EObj_t  **objpp)
4627 {
4628 	int32_t status;
4629 	char buf[BUFSZ];
4630 	EPhysDev_t *dp;
4631 
4632 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4633 		sizeof (EPhysDev_t));
4634 	if (status != PSVC_SUCCESS)
4635 		return (status);
4636 
4637 	/* Load class specific info */
4638 	dp = (EPhysDev_t *)*objpp;
4639 
4640 	dp->ld.constructor = i_psvc_constructor_11_0;
4641 	dp->ld.destructor = i_psvc_destructor;
4642 	dp->ld.get_attr = i_psvc_get_attr_11_0;
4643 	dp->ld.set_attr = i_psvc_set_attr_generic;
4644 	dp->get_temperature = i_psvc_not_supported;
4645 	dp->get_fanspeed = i_psvc_not_supported;
4646 	dp->get_input = i_psvc_not_supported;
4647 	dp->get_bit = i_psvc_not_supported;
4648 	dp->set_bit = i_psvc_not_supported;
4649 	dp->get_port = i_psvc_not_supported;
4650 	dp->set_port = i_psvc_not_supported;
4651 	dp->get_output = i_psvc_not_supported;
4652 	dp->set_output = i_psvc_not_supported;
4653 	dp->get_reg = i_psvc_get_reg_11_0;
4654 	dp->set_reg = i_psvc_not_supported;
4655 
4656 	return (PSVC_SUCCESS);
4657 }
4658 
4659 /* HPC3130 */
4660 static int32_t
4661 i_psvc_constructor_11_1(
4662 	EHdl_t	*hdlp,
4663 	char	*id,
4664 	EObj_t  **objpp)
4665 {
4666 	int32_t status;
4667 	char buf[BUFSZ];
4668 	EPhysDev_t *dp;
4669 
4670 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4671 	if (status != PSVC_SUCCESS)
4672 		return (status);
4673 
4674 	/* Load class specific info */
4675 	dp = (EPhysDev_t *)*objpp;
4676 
4677 	dp->ld.constructor = i_psvc_constructor_11_1;
4678 	dp->ld.destructor = i_psvc_destructor;
4679 	dp->ld.get_attr = i_psvc_get_attr_11_1;
4680 	dp->ld.set_attr = i_psvc_set_attr_generic;
4681 	dp->get_temperature = i_psvc_not_supported;
4682 	dp->get_fanspeed = i_psvc_not_supported;
4683 	dp->get_input = i_psvc_not_supported;
4684 	dp->get_bit = i_psvc_not_supported;
4685 	dp->set_bit = i_psvc_not_supported;
4686 	dp->get_port = i_psvc_not_supported;
4687 	dp->set_port = i_psvc_not_supported;
4688 	dp->get_output = i_psvc_not_supported;
4689 	dp->set_output = i_psvc_not_supported;
4690 	dp->get_reg = i_psvc_get_reg_11_1;
4691 	dp->set_reg = i_psvc_set_reg_11_1;
4692 
4693 	return (PSVC_SUCCESS);
4694 }
4695 
4696 /* LM75 */
4697 static int32_t
4698 i_psvc_constructor_11_2(
4699 	EHdl_t	*hdlp,
4700 	char	*id,
4701 	EObj_t  **objpp)
4702 {
4703 	int32_t status;
4704 	char buf[BUFSZ];
4705 	EPhysDev_t *dp;
4706 
4707 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4708 	if (status != PSVC_SUCCESS)
4709 		return (status);
4710 
4711 	/* Load class specific info */
4712 	dp = (EPhysDev_t *)*objpp;
4713 
4714 	dp->ld.constructor = i_psvc_constructor_11_2;
4715 	dp->ld.destructor = i_psvc_destructor;
4716 	dp->ld.get_attr = i_psvc_get_attr_11_2;
4717 	dp->ld.set_attr = i_psvc_set_attr_generic;
4718 	dp->get_temperature = i_psvc_get_temperature_11_2;
4719 	dp->get_fanspeed = i_psvc_not_supported;
4720 	dp->get_input = i_psvc_not_supported;
4721 	dp->get_bit = i_psvc_not_supported;
4722 	dp->set_bit = i_psvc_not_supported;
4723 	dp->get_port = i_psvc_not_supported;
4724 	dp->set_port = i_psvc_not_supported;
4725 	dp->get_output = i_psvc_not_supported;
4726 	dp->set_output = i_psvc_not_supported;
4727 	dp->get_reg = i_psvc_not_supported;
4728 	dp->set_reg = i_psvc_not_supported;
4729 
4730 	return (PSVC_SUCCESS);
4731 }
4732 
4733 /* LTC1427 */
4734 static int32_t
4735 i_psvc_constructor_11_3(
4736 	EHdl_t	*hdlp,
4737 	char	*id,
4738 	EObj_t  **objpp)
4739 {
4740 	int32_t status;
4741 	char buf[BUFSZ];
4742 	EPhysDev_t *dp;
4743 	char path[1024];
4744 
4745 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4746 	if (status != PSVC_SUCCESS)
4747 		return (status);
4748 
4749 	/*
4750 	 * The following code upto and including the open() call is so the
4751 	 * device driver for the ltc1427 does not get unloaded by the OS at
4752 	 * any time. This is important as the device driver is a write only
4753 	 * physical device but DOES keep readable states in the device unitp
4754 	 * structure (I2C_GET_OUTPUT) as a result this device should not
4755 	 * be unload while PSVC is up and running
4756 	 */
4757 	status = i_psvc_get_devpath(hdlp, (*objpp)->addr_spec, path);
4758 	if (status != PSVC_SUCCESS) {
4759 		return (status);
4760 	}
4761 
4762 	/*
4763 	 * We deliberately do not close our file handle, to prevent
4764 	 * any device instances from being detached.  If an instance
4765 	 * is detached, the "readable states in the device unitp"
4766 	 * will be unloaded, causing loss of control of the device
4767 	 * and incorrect error(s) to be displayed.
4768 	 */
4769 	if (open(path, O_RDWR) == -1) {
4770 		return (PSVC_FAILURE);
4771 	}
4772 	/* Load class specific info */
4773 	dp = (EPhysDev_t *)*objpp;
4774 
4775 	dp->ld.constructor = i_psvc_constructor_11_3;
4776 	dp->ld.destructor = i_psvc_destructor;
4777 	dp->ld.get_attr = i_psvc_get_attr_11_3;
4778 	dp->ld.set_attr = i_psvc_set_attr_generic;
4779 	dp->get_temperature = i_psvc_not_supported;
4780 	dp->get_fanspeed = i_psvc_not_supported;
4781 	dp->get_input = i_psvc_not_supported;
4782 	dp->get_bit = i_psvc_not_supported;
4783 	dp->set_bit = i_psvc_not_supported;
4784 	dp->get_port = i_psvc_not_supported;
4785 	dp->set_port = i_psvc_not_supported;
4786 	dp->get_output = i_psvc_get_output_11_3;
4787 	dp->set_output = i_psvc_set_output_11_3;
4788 	dp->get_reg = i_psvc_not_supported;
4789 	dp->set_reg = i_psvc_not_supported;
4790 
4791 	return (PSVC_SUCCESS);
4792 }
4793 
4794 /* MAX1617 */
4795 static int32_t
4796 i_psvc_constructor_11_4(
4797 	EHdl_t	*hdlp,
4798 	char	*id,
4799 	EObj_t  **objpp)
4800 {
4801 	int32_t status;
4802 	char buf[BUFSZ];
4803 	EPhysDev_t *dp;
4804 
4805 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4806 	if (status != PSVC_SUCCESS)
4807 		return (status);
4808 
4809 	/* Load class specific info */
4810 	dp = (EPhysDev_t *)*objpp;
4811 
4812 	dp->ld.constructor = i_psvc_constructor_11_4;
4813 	dp->ld.destructor = i_psvc_destructor;
4814 	dp->ld.get_attr = i_psvc_get_attr_11_4;
4815 	dp->ld.set_attr = i_psvc_set_attr_generic;
4816 	dp->get_temperature = i_psvc_get_temperature_11_4;
4817 	dp->get_fanspeed = i_psvc_not_supported;
4818 	dp->get_input = i_psvc_not_supported;
4819 	dp->get_bit = i_psvc_not_supported;
4820 	dp->set_bit = i_psvc_not_supported;
4821 	dp->get_port = i_psvc_not_supported;
4822 	dp->set_port = i_psvc_not_supported;
4823 	dp->get_output = i_psvc_not_supported;
4824 	dp->set_output = i_psvc_not_supported;
4825 	dp->get_reg = i_psvc_not_supported;
4826 	dp->set_reg = i_psvc_not_supported;
4827 
4828 	return (PSVC_SUCCESS);
4829 }
4830 
4831 /* PCF8574 */
4832 static int32_t
4833 i_psvc_constructor_11_5(
4834 	EHdl_t	*hdlp,
4835 	char	*id,
4836 	EObj_t  **objpp)
4837 {
4838 	int32_t status;
4839 	char buf[BUFSZ];
4840 	EPhysDev_t *dp;
4841 
4842 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4843 	if (status != PSVC_SUCCESS)
4844 		return (status);
4845 
4846 	/* Load class specific info */
4847 	dp = (EPhysDev_t *)*objpp;
4848 
4849 	dp->ld.constructor = i_psvc_constructor_11_5;
4850 	dp->ld.destructor = i_psvc_destructor;
4851 	dp->ld.get_attr = i_psvc_get_attr_11_5;
4852 	dp->ld.set_attr = i_psvc_set_attr_generic;
4853 	dp->get_temperature = i_psvc_not_supported;
4854 	dp->get_fanspeed = i_psvc_not_supported;
4855 	dp->get_input = i_psvc_not_supported;
4856 	dp->get_bit = i_psvc_get_bit_11_5;
4857 	dp->set_bit = i_psvc_set_bit_11_5;
4858 	dp->get_port = i_psvc_get_port_11_5;
4859 	dp->set_port = i_psvc_set_port_11_5;
4860 	dp->get_output = i_psvc_not_supported;
4861 	dp->set_output = i_psvc_not_supported;
4862 	dp->get_reg = i_psvc_not_supported;
4863 	dp->set_reg = i_psvc_not_supported;
4864 
4865 	return (PSVC_SUCCESS);
4866 }
4867 
4868 /* PCF8591 */
4869 static int32_t
4870 i_psvc_constructor_11_6(
4871 	EHdl_t	*hdlp,
4872 	char	*id,
4873 	EObj_t  **objpp)
4874 {
4875 	int32_t status;
4876 	char buf[BUFSZ];
4877 	EPhysDev_t *dp;
4878 
4879 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4880 	if (status != PSVC_SUCCESS)
4881 		return (status);
4882 
4883 	/* Load class specific info */
4884 	dp = (EPhysDev_t *)*objpp;
4885 
4886 	dp->ld.constructor = i_psvc_constructor_11_6;
4887 	dp->ld.destructor = i_psvc_destructor;
4888 	dp->ld.get_attr = i_psvc_get_attr_11_6;
4889 	dp->ld.set_attr = i_psvc_set_attr_generic;
4890 	dp->get_temperature = i_psvc_get_temperature_11_6;
4891 	dp->get_fanspeed = i_psvc_not_supported;
4892 	dp->get_input = i_psvc_get_input_11_6;
4893 	dp->get_bit = i_psvc_not_supported;
4894 	dp->set_bit = i_psvc_not_supported;
4895 	dp->get_port = i_psvc_not_supported;
4896 	dp->set_port = i_psvc_not_supported;
4897 	dp->get_output = i_psvc_get_output_11_6;
4898 	dp->set_output = i_psvc_set_output_11_6;
4899 	dp->get_reg = i_psvc_not_supported;
4900 	dp->set_reg = i_psvc_not_supported;
4901 
4902 	return (PSVC_SUCCESS);
4903 }
4904 
4905 /* SSC050 */
4906 static int32_t
4907 i_psvc_constructor_11_7(
4908 	EHdl_t	*hdlp,
4909 	char	*id,
4910 	EObj_t  **objpp)
4911 {
4912 	int32_t status;
4913 	char buf[BUFSZ];
4914 	EPhysDev_t *dp;
4915 
4916 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4917 	if (status != PSVC_SUCCESS)
4918 		return (status);
4919 
4920 	/* Load class specific info */
4921 	dp = (EPhysDev_t *)*objpp;
4922 
4923 	dp->ld.constructor = i_psvc_constructor_11_7;
4924 	dp->ld.destructor = i_psvc_destructor;
4925 	dp->ld.get_attr = i_psvc_get_attr_11_7;
4926 	dp->ld.set_attr = i_psvc_set_attr_generic;
4927 	dp->get_temperature = i_psvc_not_supported;
4928 	dp->get_fanspeed = i_psvc_get_fanspeed_11_7;
4929 	dp->get_input = i_psvc_not_supported;
4930 	dp->get_bit = i_psvc_get_bit_11_7;
4931 	dp->set_bit = i_psvc_set_bit_11_7;
4932 	dp->get_port = i_psvc_get_port_11_5;	/* same as for class = 11, 5 */
4933 	dp->set_port = i_psvc_set_port_11_5;
4934 	dp->get_output = i_psvc_not_supported;
4935 	dp->set_output = i_psvc_not_supported;
4936 	dp->get_reg = i_psvc_get_reg_11_7;
4937 	dp->set_reg = i_psvc_set_reg_11_7;
4938 
4939 	return (PSVC_SUCCESS);
4940 }
4941 
4942 /* TDA8444 */
4943 static int32_t
4944 i_psvc_constructor_11_8(
4945 	EHdl_t	*hdlp,
4946 	char	*id,
4947 	EObj_t  **objpp)
4948 {
4949 	int32_t status;
4950 	char buf[BUFSZ];
4951 	EPhysDev_t *dp;
4952 
4953 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4954 	if (status != PSVC_SUCCESS)
4955 		return (status);
4956 
4957 	/* Load class specific info */
4958 	dp = (EPhysDev_t *)*objpp;
4959 
4960 	dp->ld.constructor = i_psvc_constructor_11_8;
4961 	dp->ld.destructor = i_psvc_destructor;
4962 	dp->ld.get_attr = i_psvc_get_attr_11_8;
4963 	dp->ld.set_attr = i_psvc_set_attr_generic;
4964 	dp->get_temperature = i_psvc_not_supported;
4965 	dp->get_fanspeed = i_psvc_not_supported;
4966 	dp->get_input = i_psvc_not_supported;
4967 	dp->get_bit = i_psvc_not_supported;
4968 	dp->set_bit = i_psvc_not_supported;
4969 	dp->get_port = i_psvc_not_supported;
4970 	dp->set_port = i_psvc_not_supported;
4971 	dp->get_output = i_psvc_get_output_11_8;
4972 	dp->set_output = i_psvc_set_output_11_8;
4973 	dp->get_reg = i_psvc_not_supported;
4974 	dp->set_reg = i_psvc_not_supported;
4975 
4976 	return (PSVC_SUCCESS);
4977 }
4978 
4979 /* SSC100 */
4980 static int32_t
4981 i_psvc_constructor_11_9(
4982 	EHdl_t	*hdlp,
4983 	char	*id,
4984 	EObj_t  **objpp)
4985 {
4986 	int32_t status;
4987 	char buf[BUFSZ];
4988 	EPhysDev_t *dp;
4989 
4990 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4991 	if (status != PSVC_SUCCESS)
4992 		return (status);
4993 
4994 	/* Load class specific info */
4995 	dp = (EPhysDev_t *)*objpp;
4996 
4997 	dp->ld.constructor = i_psvc_constructor_11_9;
4998 	dp->ld.destructor = i_psvc_destructor;
4999 	dp->ld.get_attr = i_psvc_get_attr_11_9;
5000 	dp->ld.set_attr = i_psvc_set_attr_generic;
5001 	dp->get_temperature = i_psvc_not_supported;
5002 	dp->get_fanspeed = i_psvc_not_supported;
5003 	dp->get_input = i_psvc_not_supported;
5004 	dp->get_bit = i_psvc_not_supported;
5005 	dp->set_bit = i_psvc_not_supported;
5006 	dp->get_port = i_psvc_get_port_11_5;	/* Same as for class = 11, 5 */
5007 	dp->set_port = i_psvc_set_port_11_5;
5008 	dp->get_output = i_psvc_not_supported;
5009 	dp->set_output = i_psvc_not_supported;
5010 	dp->get_reg = i_psvc_not_supported;
5011 	dp->set_reg = i_psvc_not_supported;
5012 
5013 	return (PSVC_SUCCESS);
5014 }
5015 
5016 int32_t
5017 psvc_init(EHdl_t **hdlpp)
5018 {
5019 	EHdl_t *hdlp;
5020 	int    i;
5021 	char   buf[BUFSZ];
5022 	char   platform[32];
5023 	char   filename[256];
5024 	int    found;
5025 	int32_t status;
5026 	pthread_mutexattr_t mutex_attr;
5027 	uint32_t table_count;
5028 	int	forward_slash = 47;
5029 	int	new_line = 10;
5030 	char	*nl_char;
5031 
5032 	hdlp = (EHdl_t *)malloc(sizeof (EHdl_t));
5033 	if (hdlp == NULL)
5034 		return (-1);
5035 	memset(hdlp, 0, sizeof (EHdl_t));
5036 
5037 	/* Initialize the lock */
5038 	status = pthread_mutexattr_init(&mutex_attr);
5039 	if (status != 0) {
5040 		errno = status;
5041 		return (-1);
5042 	}
5043 	status = pthread_mutex_init(&hdlp->mutex, &mutex_attr);
5044 	if (status != 0) {
5045 		errno = status;
5046 		return (-1);
5047 	}
5048 	pthread_mutexattr_destroy(&mutex_attr);
5049 
5050 	if (sysinfo(SI_PLATFORM, platform, sizeof (platform)) == -1) {
5051 		return (-1);
5052 	}
5053 
5054 	snprintf(filename, sizeof (filename),
5055 	    "/usr/platform/%s/lib/psvcobj.conf", platform);
5056 	if ((hdlp->fp = fopen(filename, "r")) == NULL) {
5057 		return (-1);
5058 	}
5059 
5060 
5061 	/* Build the association ID lookup table */
5062 
5063 	hdlp->othr_count = hdlp->assoc_count = ASSOC_STR_TAB_SIZE;
5064 	if ((hdlp->othr_tbl = (EStringId_t *)malloc(sizeof (EStringId_t) *
5065 		hdlp->othr_count)) == NULL) {
5066 		return (-1);
5067 	}
5068 
5069 	for (i = 0; i < hdlp->othr_count; ++i) {
5070 		hdlp->othr_tbl[i].id = i;
5071 		strcpy(hdlp->othr_tbl[i].name, assoc_str_tab[i]);
5072 	}
5073 	qsort(hdlp->othr_tbl, hdlp->othr_count, sizeof (EStringId_t),
5074 		(int (*)(const void *, const void *))i_psvc_name_compare_qsort);
5075 
5076 	/* determine total number of objects + tables */
5077 	if (i_psvc_find_file_section(hdlp->fp, "OBJECT_INFO") == -1) {
5078 		return (-1);
5079 	}
5080 	if (i_psvc_count_records(hdlp->fp, "OBJECT_INFO_END",
5081 		&hdlp->total_obj_count) == -1) {
5082 		return (-1);
5083 	}
5084 	if (i_psvc_find_file_section(hdlp->fp, "TABLES") == PSVC_SUCCESS) {
5085 		status = i_psvc_count_tables_associations(hdlp->fp,
5086 			&table_count, "TABLE_END");
5087 		if (status == PSVC_FAILURE) {
5088 			return (status);
5089 		}
5090 		hdlp->total_obj_count += table_count;
5091 	}
5092 
5093 	/* Allocate object name to object pointer translation table */
5094 	for (i = 0; i < PSVC_MAX_TABLE_ARRAYS; i++) {
5095 		if ((hdlp->tbl_arry[i].obj_tbl =
5096 			(ENamePtr_t *)malloc(
5097 		sizeof (ENamePtr_t) *hdlp->total_obj_count)) == NULL) {
5098 			return (-1);
5099 		}
5100 		memset(hdlp->tbl_arry[i].obj_tbl, 0,
5101 		    sizeof (ENamePtr_t) * hdlp->total_obj_count);
5102 		hdlp->tbl_arry[i].obj_count = 0;
5103 	}
5104 
5105 	/* Build the association table */
5106 	if (i_psvc_load_associations(hdlp, hdlp->fp) == -1)
5107 		return (-1);
5108 
5109 	/* Build the table of device paths */
5110 	if (i_psvc_find_file_section(hdlp->fp, "DEVPATHS") == -1)
5111 		return (-1);
5112 	if (i_psvc_count_records(hdlp->fp, "DEVPATHS_END",
5113 		&hdlp->dev_count) == -1)
5114 		return (-1);
5115 	if ((hdlp->dev_tbl = (EDevice_t *)malloc(sizeof (EDevice_t) *
5116 		hdlp->dev_count)) == NULL) {
5117 		return (-1);
5118 	}
5119 	for (i = 0; i < hdlp->dev_count; ++i) {
5120 		fgets(buf, BUFSZ, hdlp->fp);
5121 		found = sscanf(buf, "%d %d %x %d",
5122 			&hdlp->dev_tbl[i].controller,
5123 			&hdlp->dev_tbl[i].bus, &hdlp->dev_tbl[i].addr,
5124 			&hdlp->dev_tbl[i].port);
5125 		if (found != 4) {
5126 			errno = EINVAL;
5127 			return (-1);
5128 		}
5129 		strcpy(hdlp->dev_tbl[i].path, strchr(buf, forward_slash));
5130 		/*
5131 		 * Replace new line character with NUL character
5132 		 */
5133 		nl_char = strchr(hdlp->dev_tbl[i].path, new_line);
5134 		*nl_char = 0;
5135 	}
5136 
5137 	/* Build the table of tables */
5138 	if (i_psvc_load_tables(hdlp, hdlp->fp) == -1)
5139 		return (-1);
5140 	*hdlpp = hdlp;
5141 	return (0);
5142 }
5143 
5144 int32_t
5145 psvc_fini(EHdl_t *hdlp)
5146 {
5147 	int32_t i, j;
5148 	ETable_Array *array;
5149 
5150 	if (hdlp == 0)
5151 		return (PSVC_SUCCESS);
5152 
5153 	for (j = 0; j < PSVC_MAX_TABLE_ARRAYS; j++) {
5154 		if (hdlp->tbl_arry[j].obj_tbl != 0) {
5155 			array = &(hdlp->tbl_arry[j]);
5156 			for (i = 0; i < array->obj_count; ++i) {
5157 				if (array->obj_tbl[i].type == PSVC_OBJ) {
5158 					if (!array->obj_tbl[i].objp) {
5159 						/* Skip non-existent object */
5160 						continue;
5161 					}
5162 					array->obj_tbl[i].objp->destructor(hdlp,
5163 					    array->obj_tbl[i].objp->label,
5164 					    array->obj_tbl[i].objp);
5165 				}
5166 
5167 				if (array->obj_tbl[i].type == PSVC_TBL) {
5168 					ETable_t *tblp =
5169 					    (ETable_t *)array->obj_tbl[i].objp;
5170 					if (tblp->table != 0)
5171 						free(tblp->table);
5172 				}
5173 			}
5174 
5175 			free(array->obj_tbl);
5176 		}
5177 	}
5178 
5179 	if (hdlp->othr_tbl != 0)
5180 		free(hdlp->othr_tbl);
5181 
5182 	if (hdlp->assoc_tbl != 0) {
5183 		for (i = 0; i < hdlp->assoc_count; ++i) {
5184 			if (hdlp->assoc_tbl[i].table != 0)
5185 				free(hdlp->assoc_tbl[i].table);
5186 		}
5187 		free(hdlp->assoc_tbl);
5188 	}
5189 
5190 	if (hdlp->dev_tbl != 0)
5191 		free(hdlp->dev_tbl);
5192 	if (hdlp->fp != 0)
5193 		fclose(hdlp->fp);
5194 	pthread_mutex_destroy(&hdlp->mutex);
5195 	free(hdlp);
5196 	return (PSVC_SUCCESS);
5197 }
5198 
5199 int32_t
5200 ioctl_retry(int fp, int request, void * arg_pointer)
5201 {
5202 	int32_t ret = PSVC_SUCCESS;
5203 	int32_t tries = 0;
5204 
5205 	/*
5206 	 * Becuase the i2c bus is a multimaster bus we need to protect
5207 	 * ourselves from bus masters that are not being good bus citizens.
5208 	 * A retry number of 10 should be sufficient to handle any bad bus
5209 	 * citizens.  After that we will simply say that there is something
5210 	 * wrong with the ioctl transaction and let it bubble back up.
5211 	 */
5212 	do {
5213 		ret = ioctl(fp, request, arg_pointer);
5214 		tries ++;
5215 	} while ((ret == -1) && (tries < 10));
5216 
5217 	return (ret);
5218 }
5219 
5220 static int32_t
5221 psvc_get_str_key(char *object)
5222 {
5223 	int32_t key = 0;
5224 	int i, length;
5225 
5226 	length = strlen(object);
5227 	for (i = 0; i < length; i++) {
5228 		if ((object[i] > 47) && (object[i] < 58)) {
5229 			key = key + ((object[i] - 50) + 2);
5230 		} else {
5231 			key = key + object[i];
5232 		}
5233 	}
5234 
5235 
5236 	return (key);
5237 }
5238