xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4u/psvc/psvcobj/psvcobj.c (revision 7a6d80f1660abd4755c68cbd094d4a914681d26e)
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 /*
28  * This file consists of routines to manage objects in the
29  * "Platform Environment Services Framework". The classes
30  * and subclasses are defined by attributes and methods.
31  * The objects, and their initial, static, attribute values are
32  * specified in a configuration file, "psvcobj.conf".
33  * psvc_init() reads the configuration file and creates a repository
34  * of environmental objects in memory. A client application may manipulate
35  * these objects by invoking the psvc_get_attr(), and psvc_set_attr()
36  * routines with the object's string ID specified as an argument.
37  */
38 #include <stdio.h>
39 #include <math.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <stropts.h>
43 #include <string.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <pthread.h>
47 #include <syslog.h>
48 #include <stdarg.h>
49 #include <pthread.h>
50 #include <sys/systeminfo.h>
51 
52 #define	LIBRARY_BUILD 1
53 #include <psvc_objects.h>
54 #include <psvc_objects_class.h>
55 #include <sys/i2c/clients/i2c_client.h>
56 
57 /* Mutex used for Daktari Fan speed reading */
58 pthread_mutex_t fan_mutex = PTHREAD_MUTEX_INITIALIZER;
59 
60 /*LINTLIBRARY*/
61 
62 #define	ENV_DEBUG(str, id) printf("%s id %s\n", (str), (id))
63 
64 #define	BUFSZ  512
65 
66 #define	CLASS_MAX	12
67 #define	SUBCLASS_MAX	10
68 
69 static int32_t i_psvc_constructor_0_0(EHdl_t *, char *, EObj_t **);
70 static int32_t i_psvc_constructor_0_1(EHdl_t *, char *, EObj_t **);
71 static int32_t i_psvc_constructor_1_0(EHdl_t *, char *, EObj_t **);
72 static int32_t i_psvc_constructor_2_0(EHdl_t *, char *, EObj_t **);
73 static int32_t i_psvc_constructor_2_1(EHdl_t *, char *, EObj_t **);
74 static int32_t i_psvc_constructor_2_2(EHdl_t *, char *, EObj_t **);
75 static int32_t i_psvc_constructor_3_0(EHdl_t *, char *, EObj_t **);
76 static int32_t i_psvc_constructor_4_0(EHdl_t *, char *, EObj_t **);
77 static int32_t i_psvc_constructor_5_0(EHdl_t *, char *, EObj_t **);
78 static int32_t i_psvc_constructor_6_0(EHdl_t *, char *, EObj_t **);
79 static int32_t i_psvc_constructor_7_0(EHdl_t *, char *, EObj_t **);
80 static int32_t i_psvc_constructor_8_0(EHdl_t *, char *, EObj_t **);
81 static int32_t i_psvc_constructor_9_0(EHdl_t *, char *, EObj_t **);
82 static int32_t i_psvc_constructor_10_0(EHdl_t *, char *, EObj_t **);
83 static int32_t i_psvc_constructor_10_1(EHdl_t *, char *, EObj_t **);
84 static int32_t i_psvc_constructor_11_0(EHdl_t *, char *, EObj_t **);
85 static int32_t i_psvc_constructor_11_1(EHdl_t *, char *, EObj_t **);
86 static int32_t i_psvc_constructor_11_2(EHdl_t *, char *, EObj_t **);
87 static int32_t i_psvc_constructor_11_3(EHdl_t *, char *, EObj_t **);
88 static int32_t i_psvc_constructor_11_4(EHdl_t *, char *, EObj_t **);
89 static int32_t i_psvc_constructor_11_5(EHdl_t *, char *, EObj_t **);
90 static int32_t i_psvc_constructor_11_6(EHdl_t *, char *, EObj_t **);
91 static int32_t i_psvc_constructor_11_7(EHdl_t *, char *, EObj_t **);
92 static int32_t i_psvc_constructor_11_8(EHdl_t *, char *, EObj_t **);
93 static int32_t i_psvc_constructor_11_9(EHdl_t *, char *, EObj_t **);
94 
95 static int32_t i_psvc_get_obj(EHdl_t *, char *, EObj_t **);
96 static int32_t i_psvc_destructor(EHdl_t *, char *, void *);
97 static int32_t i_psvc_get_devpath(EHdl_t *, uint64_t, char *);
98 static int32_t i_psvc_get_attr_generic(EHdl_t *, EObj_t *, int32_t, void *);
99 static int32_t i_psvc_get_attr_6_0(EHdl_t *, EObj_t *, int32_t, void *);
100 static int32_t i_psvc_get_reg_11_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id,
101     void *attrp);
102 static int32_t i_psvc_get_attr_10_1(EHdl_t *, EObj_t *, int32_t, void *);
103 static int32_t psvc_get_str_key(char *object);
104 
105 int32_t ioctl_retry(int fp, int request, void * arg_pointer);
106 
107 /*
108  * Method lookup tables
109  * Update when adding classes or subclasses.
110  */
111 
112 
113 /* Lookup method by class, subclass, used when calling method */
114 static int32_t (*i_psvc_constructor[CLASS_MAX][SUBCLASS_MAX])(EHdl_t *,
115 	char *, EObj_t **) = {
116 {i_psvc_constructor_0_0, i_psvc_constructor_0_1, 0, 0, 0, 0, 0, 0, 0, 0},
117 	{i_psvc_constructor_1_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
118 {i_psvc_constructor_2_0, i_psvc_constructor_2_1, i_psvc_constructor_2_2,
119 		0, 0, 0, 0, 0, 0, 0},
120 	{i_psvc_constructor_3_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
121 	{i_psvc_constructor_4_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
122 	{i_psvc_constructor_5_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
123 	{i_psvc_constructor_6_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
124 	{i_psvc_constructor_7_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
125 	{i_psvc_constructor_8_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
126 	{i_psvc_constructor_9_0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
127 {i_psvc_constructor_10_0, i_psvc_constructor_10_1, 0, 0, 0, 0, 0, 0, 0, 0},
128 {i_psvc_constructor_11_0, i_psvc_constructor_11_1, i_psvc_constructor_11_2,
129 	i_psvc_constructor_11_3, i_psvc_constructor_11_4,
130 	i_psvc_constructor_11_5, i_psvc_constructor_11_6,
131 	i_psvc_constructor_11_7, i_psvc_constructor_11_8,
132 	i_psvc_constructor_11_9},
133 };
134 
135 static int32_t i_psvc_cell_size[8] = {1, 1, 2, 2, 4, 4, 8, 8};
136 
137 static struct bits {
138 	uint64_t	bit;
139 	char		*label;
140 } feature_bits[] = {
141 {PSVC_DEV_PERM, "PERM="},
142 {PSVC_DEV_HOTPLUG, "HOTPLUG="},
143 {PSVC_DEV_OPTION, "OPTION="},
144 {PSVC_DEV_PRIMARY, "PRIMARY="},
145 {PSVC_DEV_SECONDARY, "SECONDARY="},
146 {PSVC_DEV_RDONLY, "RDONLY="},
147 {PSVC_DEV_RDWR, "RDWR="},
148 {PSVC_DEV_FRU, "FRU="},
149 {PSVC_LOW_WARN, "LO_WARN_MASK="},
150 {PSVC_LOW_SHUT, "LO_SHUT_MASK="},
151 {PSVC_HIGH_WARN, "HI_WARN_MASK="},
152 {PSVC_HIGH_SHUT, "HI_SHUT_MASK="},
153 {PSVC_CONVERSION_TABLE, "CONV_TABLE="},
154 {PSVC_OPT_TEMP, "OPT_TEMP_MASK="},
155 {PSVC_HW_LOW_SHUT, "HW_LO_MASK="},
156 {PSVC_HW_HIGH_SHUT, "HW_HI_MASK="},
157 {PSVC_FAN_DRIVE_PR, "FAN_DRIVE_PR="},
158 {PSVC_TEMP_DRIVEN, "TEMP_DRIVEN="},
159 {PSVC_SPEED_CTRL_PR, "SPEED_CTRL_PR="},
160 {PSVC_FAN_ON_OFF, "FAN_ON_OFF="},
161 {PSVC_CLOSED_LOOP_CTRL, "CLOSED_LOOP_CTRL="},
162 {PSVC_FAN_DRIVE_TABLE_PR, "FAN_DRIVE_TABLE_PR="},
163 {PSVC_DIE_TEMP, "DIE_TEMP="},
164 {PSVC_AMB_TEMP, "AMB_TEMP="},
165 {PSVC_DIGI_SENSOR, "DIGI_SENSOR="},
166 {PSVC_BI_STATE, "BI_STATE="},
167 {PSVC_TRI_STATE, "TRI_STATE="},
168 {PSVC_GREEN, "GREEN="},
169 {PSVC_AMBER, "AMBER="},
170 {PSVC_OUTPUT, "OUTPUT="},
171 {PSVC_INPUT, "INPUT="},
172 {PSVC_BIDIR, "BIDIR="},
173 {PSVC_BIT_POS, "BIT_POS="},
174 {PSVC_VAL_POS, "VAL_POS="},
175 {PSVC_NORMAL_POS_AV, "NORMAL_POS_AV="},
176 {PSVC_DIAG_POS_AV, "DIAG_POS_AV="},
177 {PSVC_LOCK_POS_AV, "LOCK_POS_AV="},
178 {PSVC_OFF_POS_AV, "OFF_POS_AV="},
179 {PSVC_GPIO_PORT, "GPIO_PORT="},
180 {PSVC_GPIO_REG, "GPIO_REG="}
181 };
182 
183 #define	ASSOC_STR_TAB_SIZE 33
184 static char *assoc_str_tab[] = {
185 	"PSVC_PRESENCE_SENSOR",			/* 0 */
186 	"PSVC_FAN_ONOFF_SENSOR",		/* 1 */
187 	"PSVC_FAN_SPEED_TACHOMETER",		/* 2 */
188 	"PSVC_FAN_PRIM_SEC_SELECTOR",		/* 3 */
189 	"PSVC_DEV_TEMP_SENSOR",			/* 4 */
190 	"PSVC_FAN_DRIVE_CONTROL",		/* 5 */
191 	"PSVC_KS_NORMAL_POS_SENSOR",		/* 6 */
192 	"PSVC_KS_DIAG_POS_SENSOR",		/* 7 */
193 	"PSVC_KS_LOCK_POS_SENSOR",		/* 8 */
194 	"PSVC_KS_OFF_POS_SENSOR",		/* 9 */
195 	"PSVC_SLOT_FAULT_LED",			/* 10 */
196 	"PSVC_SLOT_REMOVE_LED",			/* 11 */
197 	"PSVC_TS_OVERTEMP_LED",			/* 12 */
198 	"PSVC_PS_I_SENSOR",			/* 13 */
199 	"PSVC_DEV_FAULT_SENSOR",		/* 14 */
200 	"PSVC_DEV_FAULT_LED",			/* 15 */
201 	"PSVC_TABLE",				/* 16 */
202 	"PSVC_PARENT",				/* 17 */
203 	"PSVC_CPU",				/* 18 */
204 	"PSVC_ALTERNATE",			/* 19 */
205 	"PSVC_HOTPLUG_ENABLE_SWITCH",		/* 20 */
206 	"PSVC_PS",				/* 21 */
207 	"PSVC_FAN",				/* 22 */
208 	"PSVC_TS",				/* 23 */
209 	"PSVC_DISK",				/* 24 */
210 	"PSVC_LED",				/* 25 */
211 	"PSVC_FSP_LED",				/* 26 */
212 	"PSVC_KEYSWITCH",			/* 27 */
213 	"PSVC_PCI_CARD",			/* 28 */
214 	"PSVC_PHYSICAL_DEVICE",			/* 29 */
215 	"PSVC_DEV_TYPE_SENSOR",			/* 30 */
216 	"PSVC_FAN_TRAY_FANS",			/* 31 */
217 	"PSVC_FRU"				/* 32 */
218 };
219 
220 #define	FEATURE_BITS (sizeof (feature_bits) / sizeof (struct bits))
221 
222 static struct bitfield {
223 	int8_t shift;
224 	char   *label;
225 	char   *format;
226 } addr_fields[] =
227 {
228 {PSVC_VERSION_SHIFT, "VERSION=", "%d"},
229 {PSVC_ACTIVE_LOW_SHIFT, "ACTIVE_LOW=", "%d"},
230 {PSVC_BIT_NUM_SHIFT, "BIT_NUM=", "%d"},
231 {PSVC_INVERT_SHIFT, "INVERT=", "%d"},
232 {PSVC_PORT_SHIFT, "PORT=", "%d"},
233 {PSVC_BITSHIFT_SHIFT, "BITSHIFT=", "%d"},
234 {PSVC_BYTEMASK_SHIFT, "BYTEMASK=", "%x"},
235 {PSVC_REG_SHIFT, "REG=", "%d"},
236 {PSVC_TYPE_SHIFT, "TYPE=", "%d"},
237 {PSVC_BUSADDR_SHIFT, "BUSADDR=", "%x"},
238 {PSVC_BUSNUM_SHIFT, "BUSNUM=", "%d"},
239 {PSVC_CNTLR_SHIFT, "CNTLR=", "%d"},
240 };
241 #define	ADDR_BITFIELDS (sizeof (addr_fields) / sizeof (struct bitfield))
242 
243 /*
244  * record format is:
245  * pathname label1=val1,label2=val2,label3=val3
246  * Must be a space after the pathname and a comma between variables.
247  */
248 
249 static char *
250 find_label(char *str, char *label)
251 {
252 	char *start;
253 
254 	start = strchr(str, ' ');
255 	if (start == NULL)
256 		return (start);
257 
258 	do {
259 		++start;
260 		if (strncmp(start, label, strlen(label)) == 0)
261 			return (start);
262 
263 		start = strchr(start, ',');
264 	} while (start != NULL);
265 
266 	return (NULL);
267 }
268 
269 static int32_t
270 i_psvc_value(char *buf, int32_t attr_id, void *attrp)
271 {
272 	char *val;
273 	uint32_t temp32;
274 	uint64_t temp64;
275 	uint64_t result;
276 	int32_t i;
277 	int32_t found;
278 	char label[64];
279 	int val_size;
280 	int label_size;
281 
282 
283 	switch (attr_id) {
284 	case PSVC_CLASS_ATTR:
285 	case PSVC_SUBCLASS_ATTR:
286 	case PSVC_INSTANCE_ATTR:
287 	case PSVC_LO_WARN_ATTR:
288 	case PSVC_LO_SHUT_ATTR:
289 	case PSVC_HI_WARN_ATTR:
290 	case PSVC_HI_SHUT_ATTR:
291 	case PSVC_HW_HI_SHUT_ATTR:
292 	case PSVC_HW_LO_SHUT_ATTR:
293 	case PSVC_OPTIMAL_TEMP_ATTR:
294 		snprintf(label, sizeof (label), "%s=", attr_str_tab[attr_id]);
295 		val = find_label(buf, label);
296 		if (val == NULL) {
297 			errno = EINVAL;
298 			return (PSVC_FAILURE);
299 		}
300 		found = sscanf(val + strlen(label),
301 			"%d", (int32_t *)attrp);
302 		if (found == 0)
303 			*(int32_t *)attrp = 0;
304 		break;
305 	case PSVC_SETPOINT_ATTR:
306 	case PSVC_HYSTERESIS_ATTR:
307 	case PSVC_LOOPGAIN_ATTR:
308 	case PSVC_LOOPBIAS_ATTR:
309 		snprintf(label, sizeof (label), "%s=", attr_str_tab[attr_id]);
310 		val = find_label(buf, label);
311 		if (val == NULL) {
312 			errno = EINVAL;
313 			return (PSVC_FAILURE);
314 		}
315 
316 		found = sscanf(val + strlen(label), "%hd", (int16_t *)attrp);
317 		if (found == 0)
318 			*(int16_t *)attrp = 0;
319 		break;
320 	case PSVC_LED_COLOR_ATTR:
321 	case PSVC_LED_IS_LOCATOR_ATTR:
322 	case PSVC_LED_LOCATOR_NAME_ATTR:
323 		snprintf(label, sizeof (label), "%s=", attr_str_tab[attr_id]);
324 		val = find_label(buf, label);
325 		if (val == NULL) {
326 			errno = EINVAL;
327 			return (PSVC_FAILURE);
328 		}
329 		val_size = strlen(val);
330 		label_size = strlen(label);
331 
332 		for (i = 0; i < val_size && val[i] != ','; i++);
333 		if (i < strlen(val) - 1) {
334 			strncpy((char *)attrp, val+label_size,
335 				i - label_size);
336 		} else
337 		found = sscanf(val + label_size, "%s", (char *)attrp);
338 		if (found == 0)
339 			strcpy((char *)attrp, "");
340 		break;
341 	case PSVC_FEATURES_ATTR:
342 		result = 0;
343 		for (i = 0; i < FEATURE_BITS; ++i) {
344 			val = find_label(buf, feature_bits[i].label);
345 			if (val == NULL)
346 				continue;
347 			found = sscanf(val + strlen(feature_bits[i].label),
348 				"%d", &temp32);
349 			if (found != 0) {
350 				if (temp32 == 1)
351 					result |= feature_bits[i].bit;
352 			}
353 		}
354 		*(uint64_t *)attrp = result;
355 		break;
356 	case PSVC_ADDR_SPEC_ATTR:
357 		result = 0;
358 		for (i = 0; i < ADDR_BITFIELDS; ++i) {
359 			val = find_label(buf, addr_fields[i].label);
360 			if (val == NULL)
361 				continue;
362 			found = sscanf(val + strlen(addr_fields[i].label),
363 				addr_fields[i].format, &temp32);
364 			if (found != 0) {
365 				temp64 = temp32;
366 				temp64 <<= addr_fields[i].shift;
367 				result |= temp64;
368 			}
369 		}
370 		*(uint64_t *)attrp = result;
371 		break;
372 	default:
373 		errno = EINVAL;
374 		return (PSVC_FAILURE);
375 	}
376 	return (PSVC_SUCCESS);
377 }
378 
379 /* determine number of records in file section */
380 static int32_t
381 i_psvc_count_records(FILE *fp, char *end, uint32_t *countp)
382 {
383 	long first_record;
384 	char *ret;
385 	char buf[BUFSZ];
386 	uint32_t count = 0;
387 
388 	first_record = ftell(fp);
389 
390 	while ((ret = fgets(buf, BUFSZ, fp)) != NULL) {
391 		if (strncmp(end, buf, strlen(end)) == 0)
392 			break;
393 		++count;
394 	}
395 
396 	if (ret == NULL) {
397 		errno = EINVAL;
398 		return (PSVC_FAILURE);
399 	}
400 
401 	fseek(fp, first_record, SEEK_SET);
402 	*countp = count;
403 	return (PSVC_SUCCESS);
404 }
405 
406 /* determine number of records in file section */
407 static int32_t
408 i_psvc_count_tables_associations(FILE *fp, uint32_t *countp, char *end)
409 {
410 	long first_record;
411 	char *ret;
412 	char buf[BUFSZ];
413 	uint32_t count = 0;
414 
415 	first_record = ftell(fp);
416 
417 	while ((ret = fgets(buf, BUFSZ, fp)) != NULL) {
418 		if (strncmp(end, buf, strlen(end)) == 0)
419 			++count;
420 	}
421 #ifdef	lint
422 	ret = ret;
423 #endif
424 
425 	fseek(fp, first_record, SEEK_SET);
426 	*countp = count;
427 	return (PSVC_SUCCESS);
428 }
429 
430 /* determine number of records in a table */
431 static int32_t
432 i_psvc_count_table_records(FILE *fp, char *end, uint32_t *countp)
433 {
434 	long first_record;
435 	int ret;
436 	char string[BUFSZ];
437 	uint32_t count = 0;
438 
439 	first_record = ftell(fp);
440 
441 	while ((ret = fscanf(fp, "%s", string)) == 1) {
442 		if (strncmp(end, string, strlen(end)) == 0)
443 			break;
444 		++count;
445 	}
446 
447 	if (ret != 1) {
448 		errno = EINVAL;
449 		return (PSVC_FAILURE);
450 	}
451 
452 	fseek(fp, first_record, SEEK_SET);
453 	*countp = count;
454 	return (PSVC_SUCCESS);
455 }
456 
457 /*
458  * Find number of matches to an antecedent_id of a certain
459  * association type.
460  */
461 static int32_t
462 i_psvc_get_assoc_matches(EHdl_t *hdlp, char *antecedent, int32_t assoc_id,
463 	int32_t *matches)
464 {
465 	int i;
466 	int32_t key;
467 	EAssocList_t *ap = hdlp->assoc_tbl + assoc_id;
468 
469 	*matches = 0;
470 
471 	if (ap->table == 0) {
472 		errno = EINVAL;
473 		return (PSVC_FAILURE);
474 	}
475 
476 	key = psvc_get_str_key(antecedent);
477 
478 	for (i = 0; i < ap->count; ++i) {
479 		if (ap->table[i].ant_key == key) {
480 			if (strcmp(ap->table[i].antecedent_id, antecedent)
481 			    == 0)
482 				++*matches;
483 		}
484 	}
485 	return (PSVC_SUCCESS);
486 }
487 
488 /*
489  * Find 1st m matches to an antecedent_id of a certain
490  * association type.
491  * Returns zero for success, -1 for failure.
492  */
493 static int32_t
494 i_psvc_get_assoc_id(EHdl_t *hdlp, char *antecedent, int32_t assoc_id,
495 	int32_t match, char **id_list)
496 {
497 	int i;
498 	int found = 0;
499 	int32_t key;
500 	EAssocList_t *ap = &hdlp->assoc_tbl[assoc_id];
501 
502 	if (ap->table == 0) {
503 		errno = EINVAL;
504 		return (-1);
505 	}
506 
507 	key = psvc_get_str_key(antecedent);
508 
509 	for (i = 0; i < ap->count; ++i) {
510 		if (ap->table[i].ant_key == key) {
511 			if (strcmp(ap->table[i].antecedent_id, antecedent)
512 			    == 0) {
513 				if (found == match) {
514 					*id_list = ap->table[i].dependent_id;
515 					return (0);
516 				}
517 				++found;
518 			}
519 		}
520 	}
521 
522 	errno = EINVAL;
523 	return (-1);
524 }
525 
526 static int32_t
527 i_psvc_get_table_value(EHdl_t *hdlp, char *table_id, uint32_t index,
528 	void *value)
529 {
530 	int32_t i;
531 	ETable_t *tblp;
532 	ETable_Array *tbl_arr;
533 	int32_t key, array;
534 
535 	key = psvc_get_str_key(table_id);
536 	array = key % PSVC_MAX_TABLE_ARRAYS;
537 	tbl_arr = &(hdlp->tbl_arry[array]);
538 
539 	for (i = 0; i < tbl_arr->obj_count; ++i) {
540 		if (key == tbl_arr->obj_tbl[i].key) {
541 			if (strcmp(tbl_arr->obj_tbl[i].name,
542 				table_id) == 0)
543 				break;
544 		}
545 	}
546 
547 	if (tbl_arr->obj_tbl[i].type != PSVC_TBL)
548 		return (PSVC_FAILURE);
549 
550 	tblp = (ETable_t *)tbl_arr->obj_tbl[i].objp;
551 
552 	if (tblp->table == NULL)
553 		return (PSVC_FAILURE);
554 
555 	if (index >= tblp->size)
556 		return (PSVC_FAILURE);
557 
558 	switch (tblp->cell_type) {
559 		case 0:
560 			*(int8_t *)value = *((int8_t *)tblp->table + index);
561 			break;
562 		case 1:
563 			*(uint8_t *)value = *((uint8_t *)tblp->table + index);
564 			break;
565 		case 2:
566 			*(int16_t *)value = *((int16_t *)tblp->table + index);
567 			break;
568 		case 3:
569 			*(uint16_t *)value = *((uint16_t *)tblp->table + index);
570 			break;
571 		case 4:
572 			*(int32_t *)value = *((int32_t *)tblp->table + index);
573 			break;
574 		case 5:
575 			*(uint32_t *)value = *((uint32_t *)tblp->table + index);
576 			break;
577 		case 6:
578 			*(int64_t *)value = *((int64_t *)tblp->table + index);
579 			break;
580 		case 7:
581 			*(uint64_t *)value = *((uint64_t *)tblp->table + index);
582 			break;
583 		default:
584 			return (PSVC_FAILURE);
585 	}
586 
587 	return (PSVC_SUCCESS);
588 }
589 
590 int32_t
591 psvc_get_attr(EHdl_t *hdlp, char *name, int32_t attr_id, void *attr_valuep, ...)
592 {
593 	EObj_t *objp;
594 	int32_t status = PSVC_SUCCESS;
595 	int32_t arg1, arg2;
596 	va_list ap;
597 
598 	pthread_mutex_lock(&hdlp->mutex);
599 
600 	if (attr_valuep == NULL) {
601 		errno = EFAULT;
602 		pthread_mutex_unlock(&hdlp->mutex);
603 		return (PSVC_FAILURE);
604 	}
605 
606 	switch (attr_id) {
607 	case PSVC_TABLE_VALUE_ATTR:
608 		va_start(ap, attr_valuep);
609 		status = i_psvc_get_table_value(hdlp, name,
610 			va_arg(ap, uint32_t), attr_valuep);
611 		va_end(ap);
612 		break;
613 	case PSVC_ASSOC_MATCHES_ATTR:
614 		va_start(ap, attr_valuep);
615 		status = i_psvc_get_assoc_matches(hdlp, name,
616 			va_arg(ap, int32_t), attr_valuep);
617 		va_end(ap);
618 		break;
619 	case PSVC_ASSOC_ID_ATTR:
620 		va_start(ap, attr_valuep);
621 		arg1 = va_arg(ap, int32_t);
622 		arg2 = va_arg(ap, int32_t);
623 		status = i_psvc_get_assoc_id(hdlp, name,
624 		    arg1, arg2, attr_valuep);
625 		va_end(ap);
626 		break;
627 	default:
628 		status = i_psvc_get_obj(hdlp, name, &objp);
629 		if (status != PSVC_SUCCESS) {
630 			pthread_mutex_unlock(&hdlp->mutex);
631 			return (status);
632 		}
633 		status = (*objp->get_attr)(hdlp, objp, attr_id,
634 			attr_valuep);
635 	}
636 
637 	if (status != PSVC_SUCCESS) {
638 		pthread_mutex_unlock(&hdlp->mutex);
639 		return (status);
640 	}
641 
642 	pthread_mutex_unlock(&hdlp->mutex);
643 	return (status);
644 }
645 
646 int32_t
647 psvc_set_attr(EHdl_t *hdlp, char *name, int32_t attr_id, void *attr_valuep)
648 {
649 	EObj_t *objp;
650 	int32_t status = PSVC_SUCCESS;
651 
652 	pthread_mutex_lock(&hdlp->mutex);
653 	status = i_psvc_get_obj(hdlp, name, &objp);
654 	if (status != PSVC_SUCCESS) {
655 		pthread_mutex_unlock(&hdlp->mutex);
656 		return (status);
657 	}
658 
659 	if (attr_valuep == NULL) {
660 		errno = EFAULT;
661 		pthread_mutex_unlock(&hdlp->mutex);
662 		return (PSVC_FAILURE);
663 	}
664 
665 	status = (*objp->set_attr)(hdlp, objp, attr_id, attr_valuep);
666 	if (status != PSVC_SUCCESS) {
667 		pthread_mutex_unlock(&hdlp->mutex);
668 		return (status);
669 	}
670 
671 	pthread_mutex_unlock(&hdlp->mutex);
672 	return (status);
673 }
674 
675 
676 static int32_t
677 i_psvc_get_presence(EHdl_t *hdlp, EObj_t *objp, boolean_t *pr)
678 {
679 	EObj_t *pobjp, *mobjp;
680 	int32_t matches;
681 	char *mid;
682 	char *parent_id;
683 	int32_t status = PSVC_SUCCESS;
684 	uint8_t value_8bit, value_8bit_inv;
685 	boolean_t active_low, value;
686 
687 	if (strcmp(objp->label, PSVC_CHASSIS) == 0) {
688 		*pr = PSVC_PRESENT;
689 		objp->present = PSVC_PRESENT;
690 		return (PSVC_SUCCESS);
691 	}
692 
693 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PARENT, 0,
694 		&parent_id);
695 	if (status != PSVC_SUCCESS)
696 		return (status);
697 
698 	if (strcmp(parent_id, PSVC_CHASSIS)) {
699 		status = i_psvc_get_obj(hdlp, parent_id, &pobjp);
700 		if (status != PSVC_SUCCESS)
701 			return (status);
702 		if (!pobjp->present) {
703 			pobjp->get_attr(hdlp, pobjp, PSVC_PRESENCE_ATTR, pr);
704 			*pr = pobjp->present;
705 			objp->present = pobjp->present;
706 			return (status);
707 		}
708 	}
709 
710 	(void) i_psvc_get_assoc_matches(hdlp, objp->label,
711 		PSVC_PRESENCE_SENSOR, &matches);
712 
713 	if (matches != 0) {
714 		status = i_psvc_get_assoc_id(hdlp, objp->label,
715 		    PSVC_PRESENCE_SENSOR, 0, &mid);
716 		if (status != PSVC_SUCCESS)
717 			return (status);
718 		status = i_psvc_get_obj(hdlp, mid, &mobjp);
719 		if (status != PSVC_SUCCESS)
720 			return (status);
721 
722 		active_low = PSVC_IS_ACTIVE_LOW(mobjp->addr_spec);
723 
724 		if (mobjp->class == PSVC_BOOLEAN_GPIO_CLASS) {
725 			status = mobjp->get_attr(hdlp, mobjp,
726 				PSVC_GPIO_VALUE_ATTR, &value);
727 			if (status != PSVC_SUCCESS)
728 				return (status);
729 			if (active_low)
730 				if (value == 0)
731 					*pr = PSVC_PRESENT;
732 				else
733 					*pr = PSVC_ABSENT;
734 			else
735 				if (value == 0)
736 					*pr = PSVC_ABSENT;
737 				else
738 					*pr = PSVC_PRESENT;
739 		} else if (mobjp->class == PSVC_8BIT_GPIO_CLASS) {
740 			uint8_t bitshift, bytemask;
741 
742 			status = mobjp->get_attr(hdlp, mobjp,
743 				PSVC_GPIO_VALUE_ATTR, &value_8bit);
744 			if (status != PSVC_SUCCESS)
745 				return (status);
746 			if (PSVC_HP_INVERT(mobjp->addr_spec))
747 				value_8bit_inv = ~value_8bit;
748 			else
749 				value_8bit_inv = value_8bit;
750 			bitshift = PSVC_GET_ASPEC_BITSHIFT(mobjp->addr_spec);
751 			bytemask = PSVC_GET_ASPEC_BYTEMASK(mobjp->addr_spec);
752 			value_8bit_inv =
753 				value_8bit_inv & (bytemask >> bitshift);
754 			if (active_low)
755 				if (value_8bit_inv == 0)
756 					*pr = PSVC_PRESENT;
757 				else
758 					*pr = PSVC_ABSENT;
759 			else
760 				if (value_8bit_inv == 0)
761 					*pr = PSVC_ABSENT;
762 				else
763 					*pr = PSVC_PRESENT;
764 		} else {
765 			errno = EINVAL;
766 			return (PSVC_FAILURE);
767 		}
768 	} else {
769 		*pr = PSVC_PRESENT;
770 	}
771 
772 	objp->present = *pr;
773 
774 	return (status);
775 }
776 
777 static int32_t
778 i_psvc_get_device_value_0_0(EHdl_t *hdlp, EObj_t *objp, int32_t *temp)
779 {
780 	int32_t status = PSVC_SUCCESS, m;
781 	char *tid;
782 	int16_t temp16;
783 	char *physid;
784 	EObj_t *physobjp;
785 
786 	if (objp->present != PSVC_PRESENT) {
787 		errno = ENODEV;
788 		return (PSVC_FAILURE);
789 	}
790 
791 	status = i_psvc_get_assoc_id(
792 		hdlp, objp->label, PSVC_PHYSICAL_DEVICE, 0, &physid);
793 	if (status != PSVC_SUCCESS) {
794 		return (status);
795 	}
796 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
797 	if (status != PSVC_SUCCESS) {
798 		return (status);
799 	}
800 
801 	status = ((EPhysDev_t *)physobjp)->get_temperature(hdlp,
802 		objp->addr_spec, temp);
803 	if (status != PSVC_SUCCESS) {
804 		return (status);
805 	}
806 
807 	if (objp->features & PSVC_CONVERSION_TABLE) {
808 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
809 		    PSVC_TABLE, &m);
810 		if ((status != PSVC_SUCCESS) || (m != 1)) {
811 			return (status);
812 		}
813 
814 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
815 			&tid);
816 
817 		status = i_psvc_get_table_value(hdlp, tid, *temp, &temp16);
818 		*temp = temp16;
819 	}
820 	return (status);
821 }
822 
823 static int32_t
824 i_psvc_get_device_value_0_1(EHdl_t *hdlp, EObj_t *objp, int32_t *temp)
825 {
826 	int32_t status = PSVC_SUCCESS, m;
827 	char *tid;
828 	int16_t temp16;
829 	char *physid;
830 	EObj_t *physobjp;
831 
832 	if (objp->present != PSVC_PRESENT) {
833 		errno = ENODEV;
834 		return (PSVC_FAILURE);
835 	}
836 
837 	status = i_psvc_get_assoc_id(
838 		hdlp, objp->label, PSVC_PHYSICAL_DEVICE, 0, &physid);
839 	if (status != PSVC_SUCCESS) {
840 		return (status);
841 	}
842 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
843 	if (status != PSVC_SUCCESS) {
844 		return (status);
845 	}
846 
847 	status = ((EPhysDev_t *)physobjp)->get_temperature(hdlp,
848 		objp->addr_spec, temp);
849 	if (status != PSVC_SUCCESS) {
850 		return (status);
851 	}
852 
853 	if (objp->features & PSVC_CONVERSION_TABLE) {
854 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
855 		    PSVC_TABLE, &m);
856 		if ((status != PSVC_SUCCESS) || (m != 1)) {
857 			return (status);
858 		}
859 
860 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
861 			&tid);
862 
863 		status = i_psvc_get_table_value(hdlp, tid, *temp, &temp16);
864 		*temp = temp16;
865 	}
866 	return (status);
867 }
868 
869 static int32_t
870 i_psvc_get_device_value_4_0(EHdl_t *hdlp, EObj_t *objp, int32_t *value)
871 {
872 	int32_t status = PSVC_SUCCESS;
873 	char *physid;
874 	EObj_t *physobjp;
875 
876 	if (objp->present != PSVC_PRESENT) {
877 		errno = ENODEV;
878 		return (PSVC_FAILURE);
879 	}
880 
881 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
882 		0, &physid);
883 	if (status != PSVC_SUCCESS)
884 		return (status);
885 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
886 	if (status != PSVC_SUCCESS)
887 		return (status);
888 
889 	status = ((EPhysDev_t *)physobjp)->get_input(hdlp, objp->addr_spec,
890 		value);
891 	if (status != PSVC_SUCCESS)
892 		return (status);
893 
894 	if (objp->features & PSVC_CONVERSION_TABLE) {
895 		int32_t m;
896 		char *tid;
897 		int16_t temp16;
898 
899 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
900 		    PSVC_TABLE, &m);
901 		if ((status != PSVC_SUCCESS) || (m != 1)) {
902 			return (status);
903 		}
904 
905 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
906 			&tid);
907 
908 		status = i_psvc_get_table_value(hdlp, tid, *value, &temp16);
909 		*value = temp16;
910 	}
911 
912 	return (status);
913 }
914 
915 static int32_t
916 i_psvc_set_device_value_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t *value)
917 {
918 	int32_t status = PSVC_SUCCESS;
919 	char *physid;
920 	EObj_t *physobjp;
921 
922 	if (objp->present != PSVC_PRESENT) {
923 		errno = ENODEV;
924 		return (PSVC_FAILURE);
925 	}
926 
927 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
928 		0, &physid);
929 	if (status != PSVC_SUCCESS)
930 		return (status);
931 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
932 	if (status != PSVC_SUCCESS)
933 		return (status);
934 	status = ((EPhysDev_t *)physobjp)->set_output(hdlp, objp->addr_spec,
935 		*value);
936 	if (status != PSVC_SUCCESS)
937 		return (status);
938 
939 	return (status);
940 }
941 
942 static int32_t
943 i_psvc_get_device_value_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t *value)
944 {
945 	int32_t status = PSVC_SUCCESS;
946 	char *physid;
947 	EObj_t *physobjp;
948 
949 	if (objp->present != PSVC_PRESENT) {
950 		errno = ENODEV;
951 		return (PSVC_FAILURE);
952 	}
953 
954 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
955 		0, &physid);
956 	if (status != PSVC_SUCCESS)
957 		return (status);
958 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
959 	if (status != PSVC_SUCCESS)
960 		return (status);
961 
962 	status = ((EPhysDev_t *)physobjp)->get_output(hdlp, objp->addr_spec,
963 		value);
964 	if (status != PSVC_SUCCESS)
965 		return (status);
966 
967 	if (objp->features & PSVC_CONVERSION_TABLE) {
968 		int32_t m;
969 		char *tid;
970 		int16_t temp16;
971 
972 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
973 		    PSVC_TABLE, &m);
974 		if ((status != PSVC_SUCCESS) || (m != 1)) {
975 			return (status);
976 		}
977 
978 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
979 			&tid);
980 
981 		status = i_psvc_get_table_value(hdlp, tid, *value, &temp16);
982 		*value = temp16;
983 	}
984 	return (status);
985 }
986 
987 static int32_t
988 i_psvc_get_device_value_6_0(EHdl_t *hdlp, EObj_t *objp, boolean_t *value)
989 {
990 	int32_t status = PSVC_SUCCESS;
991 	int32_t bit_value;
992 	char *physid;
993 	EObj_t *physobjp;
994 
995 	if (objp->present != PSVC_PRESENT) {
996 		errno = ENODEV;
997 		return (PSVC_FAILURE);
998 	}
999 
1000 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1001 		0, &physid);
1002 	if (status != PSVC_SUCCESS)
1003 		return (status);
1004 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1005 	if (status != PSVC_SUCCESS)
1006 		return (status);
1007 
1008 	status = ((EPhysDev_t *)physobjp)->get_bit(hdlp, objp->addr_spec,
1009 		&bit_value);
1010 	if (status != PSVC_SUCCESS)
1011 		return (status);
1012 
1013 	*value = bit_value;
1014 
1015 	return (status);
1016 }
1017 
1018 static int32_t
1019 i_psvc_set_device_value_6_0(EHdl_t *hdlp, EObj_t *objp, boolean_t *value)
1020 {
1021 	int32_t status = PSVC_SUCCESS;
1022 	int32_t bit_value;
1023 	char *physid;
1024 	EObj_t *physobjp;
1025 
1026 	if (objp->present != PSVC_PRESENT) {
1027 		errno = ENODEV;
1028 		return (PSVC_FAILURE);
1029 	}
1030 
1031 	bit_value = *value;
1032 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1033 		0, &physid);
1034 	if (status != PSVC_SUCCESS)
1035 		return (status);
1036 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1037 	if (status != PSVC_SUCCESS)
1038 		return (status);
1039 
1040 	status = ((EPhysDev_t *)physobjp)->set_bit(hdlp, objp->addr_spec,
1041 		bit_value);
1042 	if (status != PSVC_SUCCESS)
1043 		return (status);
1044 
1045 	return (status);
1046 }
1047 
1048 static int32_t
1049 i_psvc_get_device_value_1_0(EHdl_t *hdlp, EObj_t *objp, int32_t *fan_speed)
1050 {
1051 	int32_t status = PSVC_SUCCESS;
1052 	EObj_t *ftobjp;
1053 	char *fan_tach;
1054 
1055 	if (objp->present != PSVC_PRESENT) {
1056 		errno = ENODEV;
1057 		return (PSVC_FAILURE);
1058 	}
1059 
1060 	status = i_psvc_get_assoc_id(hdlp, objp->label,
1061 		PSVC_FAN_SPEED_TACHOMETER, 0, &fan_tach);
1062 	if (status != PSVC_SUCCESS)
1063 		return (status);
1064 
1065 	status = i_psvc_get_obj(hdlp, fan_tach, &ftobjp);
1066 	if (status != PSVC_SUCCESS)
1067 		return (status);
1068 
1069 	status = ftobjp->get_attr(hdlp, ftobjp, PSVC_SENSOR_VALUE_ATTR,
1070 		fan_speed);
1071 	if (status != PSVC_SUCCESS)
1072 		return (status);
1073 
1074 	return (status);
1075 }
1076 
1077 static int32_t
1078 i_psvc_get_device_value_7_0(EHdl_t *hdlp, EObj_t *objp, int32_t *fan_speed)
1079 {
1080 	char *physid;
1081 	EObj_t *physobjp;
1082 	int32_t status = PSVC_SUCCESS;
1083 
1084 	if (objp->present != PSVC_PRESENT) {
1085 		errno = ENODEV;
1086 		return (PSVC_FAILURE);
1087 	}
1088 
1089 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1090 		0, &physid);
1091 	if (status != PSVC_SUCCESS)
1092 		return (status);
1093 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1094 	if (status != PSVC_SUCCESS)
1095 		return (status);
1096 
1097 	status = ((EPhysDev_t *)physobjp)->get_fanspeed(hdlp, objp->addr_spec,
1098 		fan_speed);
1099 	if (status != PSVC_SUCCESS)
1100 		return (status);
1101 
1102 	if (objp->features & PSVC_CONVERSION_TABLE) {
1103 		int32_t m;
1104 		char *tid;
1105 		int16_t temp16;
1106 
1107 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
1108 		    PSVC_TABLE, &m);
1109 		if ((status != PSVC_SUCCESS) || (m != 1)) {
1110 			return (status);
1111 		}
1112 
1113 		(void) i_psvc_get_assoc_id(hdlp, objp->label, PSVC_TABLE, 0,
1114 			&tid);
1115 
1116 		status = i_psvc_get_table_value(hdlp, tid, *fan_speed, &temp16);
1117 		*fan_speed = temp16;
1118 	}
1119 	return (status);
1120 }
1121 
1122 static int32_t
1123 i_psvc_get_device_state_2_0(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1124 {
1125 	int32_t status = PSVC_SUCCESS;
1126 	int32_t bit_value;
1127 	boolean_t active_low;
1128 	char *physid;
1129 	EObj_t *physobjp;
1130 
1131 	if (objp->present != PSVC_PRESENT) {
1132 		errno = ENODEV;
1133 		return (PSVC_FAILURE);
1134 	}
1135 
1136 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1137 		0, &physid);
1138 	if (status != PSVC_SUCCESS)
1139 		return (status);
1140 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1141 	if (status != PSVC_SUCCESS)
1142 		return (status);
1143 
1144 	status = ((EPhysDev_t *)physobjp)->get_bit(hdlp, objp->addr_spec,
1145 		&bit_value);
1146 	if (status != PSVC_SUCCESS)
1147 		return (status);
1148 
1149 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1150 	if (active_low)
1151 		if (bit_value == 0)
1152 			strcpy(led_state, PSVC_LED_ON);
1153 		else
1154 			strcpy(led_state, PSVC_LED_OFF);
1155 	else
1156 		if (bit_value == 0)
1157 			strcpy(led_state, PSVC_LED_OFF);
1158 		else
1159 			strcpy(led_state, PSVC_LED_ON);
1160 
1161 	return (status);
1162 }
1163 
1164 static int32_t
1165 i_psvc_set_device_state_2_0(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1166 {
1167 	int32_t status = PSVC_SUCCESS;
1168 	boolean_t active_low;
1169 	int32_t bit_value;
1170 	char *physid;
1171 	EObj_t *physobjp;
1172 
1173 	if (objp->present != PSVC_PRESENT) {
1174 		errno = ENODEV;
1175 		return (PSVC_FAILURE);
1176 	}
1177 
1178 	if (strcmp(((ELed_t *)objp)->is_locator, PSVC_LOCATOR_TRUE) != 0) {
1179 		/*
1180 		 * For Locator LEDs we ignore lit_count.  RSC may have
1181 		 * altered the LED state underneath us, So we should
1182 		 * always just do what the user asked instead of trying
1183 		 * to be smart.
1184 		 */
1185 
1186 		if (strcmp(led_state, PSVC_LED_ON) == 0)
1187 			((ELed_t *)objp)->lit_count++;
1188 		else if (strcmp(led_state, PSVC_LED_OFF) == 0) {
1189 			if (--((ELed_t *)objp)->lit_count > 0) {
1190 				return (PSVC_SUCCESS);
1191 			} else if (((ELed_t *)objp)->lit_count < 0)
1192 				((ELed_t *)objp)->lit_count = 0;
1193 			/* Fall through case is when lit_count is 0 */
1194 		}
1195 	}
1196 
1197 	strcpy(objp->previous_state, objp->state);
1198 	strcpy(objp->state, led_state);
1199 
1200 	bit_value = (strcmp(led_state, PSVC_LED_ON) == 0);
1201 
1202 	/*
1203 	 * Flip the bit if necessary (for active_low devices,
1204 	 * O ==> ON; 1 ==> OFF.
1205 	 */
1206 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1207 	bit_value ^= active_low;
1208 
1209 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1210 		0, &physid);
1211 	if (status != PSVC_SUCCESS)
1212 		return (status);
1213 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1214 	if (status != PSVC_SUCCESS)
1215 		return (status);
1216 
1217 	status = ((EPhysDev_t *)physobjp)->set_bit(hdlp, objp->addr_spec,
1218 		bit_value);
1219 	return (status);
1220 }
1221 
1222 static int32_t
1223 i_psvc_get_device_state_2_1(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1224 {
1225 	int32_t status = PSVC_SUCCESS;
1226 	uint8_t value;
1227 	char *physid;
1228 	EObj_t *physobjp;
1229 
1230 	if (objp->present != PSVC_PRESENT) {
1231 		errno = ENODEV;
1232 		return (PSVC_FAILURE);
1233 	}
1234 
1235 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1236 		0, &physid);
1237 	if (status != PSVC_SUCCESS)
1238 		return (status);
1239 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1240 	if (status != PSVC_SUCCESS)
1241 		return (status);
1242 
1243 	status = ((EPhysDev_t *)physobjp)->get_reg(hdlp, objp->addr_spec,
1244 		&value);
1245 	if (status != PSVC_SUCCESS)
1246 		return (status);
1247 
1248 	switch (value) {
1249 	case 0:
1250 		strcpy(led_state, PSVC_LED_OFF);
1251 		break;
1252 	case 1:
1253 		strcpy(led_state, PSVC_LED_SLOW_BLINK);
1254 		break;
1255 	case 2:
1256 		strcpy(led_state, PSVC_LED_FAST_BLINK);
1257 		break;
1258 	case 3:
1259 		strcpy(led_state, PSVC_LED_ON);
1260 		break;
1261 	}
1262 
1263 	return (status);
1264 }
1265 
1266 static int32_t
1267 i_psvc_set_device_state_2_1(EHdl_t *hdlp, EObj_t *objp, char *led_state)
1268 {
1269 	int32_t status = PSVC_SUCCESS;
1270 	uint8_t value;
1271 	char *physid;
1272 	EObj_t *physobjp;
1273 
1274 	if (objp->present != PSVC_PRESENT) {
1275 		errno = ENODEV;
1276 		return (PSVC_FAILURE);
1277 	}
1278 
1279 	if (strcmp(led_state, PSVC_LED_ON) == 0)
1280 		((ELed_t *)objp)->lit_count++;
1281 	else if (strcmp(led_state, PSVC_LED_OFF) == 0) {
1282 		if (--((ELed_t *)objp)->lit_count > 0) {
1283 			return (PSVC_SUCCESS);
1284 		} else if (((ELed_t *)objp)->lit_count < 0)
1285 			((ELed_t *)objp)->lit_count = 0;
1286 
1287 		/* Fall through case is when lit_count is 0 */
1288 	}
1289 
1290 	strcpy(objp->previous_state, objp->state);
1291 	strcpy(objp->state, led_state);
1292 
1293 	if (strcmp(led_state, PSVC_LED_OFF) == 0)
1294 		value = 0;
1295 	else if (strcmp(led_state, PSVC_LED_SLOW_BLINK) == 0)
1296 		value = 1;
1297 	else if (strcmp(led_state, PSVC_LED_FAST_BLINK) == 0)
1298 		value = 2;
1299 	else if (strcmp(led_state, PSVC_LED_ON) == 0)
1300 		value = 3;
1301 
1302 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1303 		0, &physid);
1304 	if (status != PSVC_SUCCESS)
1305 		return (status);
1306 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1307 	if (status != PSVC_SUCCESS)
1308 		return (status);
1309 
1310 	status = ((EPhysDev_t *)physobjp)->set_reg(hdlp, objp->addr_spec,
1311 		value);
1312 
1313 	return (status);
1314 }
1315 
1316 static int32_t
1317 i_psvc_get_device_state_9_0(EHdl_t *hdlp, EObj_t *objp, char *pos)
1318 {
1319 	int32_t status = PSVC_SUCCESS, matches;
1320 	char *sensorid;
1321 	EObj_t *sensorp;
1322 	char state[32];
1323 
1324 	if (objp->present != PSVC_PRESENT) {
1325 		errno = ENODEV;
1326 		return (PSVC_FAILURE);
1327 	}
1328 
1329 	if (objp->features & PSVC_NORMAL_POS_AV) {
1330 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1331 		    PSVC_KS_NORMAL_POS_SENSOR, &matches);
1332 		if (matches == 1) {
1333 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1334 				PSVC_KS_NORMAL_POS_SENSOR, 0, &sensorid);
1335 			if (status != PSVC_SUCCESS)
1336 				return (status);
1337 
1338 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1339 			if (status != PSVC_SUCCESS)
1340 				return (status);
1341 
1342 			status = sensorp->get_attr(hdlp, sensorp,
1343 				PSVC_SWITCH_STATE_ATTR, state);
1344 			if (status != PSVC_SUCCESS)
1345 				return (status);
1346 
1347 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1348 				strcpy(pos, PSVC_NORMAL_POS);
1349 				return (PSVC_SUCCESS);
1350 			}
1351 		}
1352 	}
1353 
1354 	if (objp->features & PSVC_DIAG_POS_AV) {
1355 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1356 		    PSVC_KS_DIAG_POS_SENSOR, &matches);
1357 		if (matches == 1) {
1358 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1359 			    PSVC_KS_DIAG_POS_SENSOR, 0, &sensorid);
1360 			if (status != PSVC_SUCCESS)
1361 				return (status);
1362 
1363 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1364 			if (status != PSVC_SUCCESS)
1365 				return (status);
1366 
1367 			status = sensorp->get_attr(hdlp, sensorp,
1368 				PSVC_SWITCH_STATE_ATTR, state);
1369 			if (status != PSVC_SUCCESS)
1370 				return (status);
1371 
1372 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1373 				strcpy(pos, PSVC_DIAG_POS);
1374 				return (PSVC_SUCCESS);
1375 			}
1376 		}
1377 	}
1378 
1379 	if (objp->features & PSVC_LOCK_POS_AV) {
1380 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1381 		    PSVC_KS_LOCK_POS_SENSOR, &matches);
1382 		if (matches == 1) {
1383 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1384 			    PSVC_KS_LOCK_POS_SENSOR, 0, &sensorid);
1385 			if (status != PSVC_SUCCESS)
1386 				return (status);
1387 
1388 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1389 			if (status != PSVC_SUCCESS)
1390 				return (status);
1391 
1392 			status = sensorp->get_attr(hdlp, sensorp,
1393 				PSVC_SWITCH_STATE_ATTR, state);
1394 			if (status != PSVC_SUCCESS)
1395 				return (status);
1396 
1397 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1398 				strcpy(pos, PSVC_LOCKED_POS);
1399 				return (PSVC_SUCCESS);
1400 			}
1401 		}
1402 	}
1403 
1404 	if (objp->features & PSVC_OFF_POS_AV) {
1405 		(void) i_psvc_get_assoc_matches(hdlp, objp->label,
1406 		    PSVC_KS_OFF_POS_SENSOR, &matches);
1407 		if (matches == 1) {
1408 			status = i_psvc_get_assoc_id(hdlp, objp->label,
1409 			    PSVC_KS_OFF_POS_SENSOR, 0, &sensorid);
1410 			if (status != PSVC_SUCCESS)
1411 				return (status);
1412 
1413 			status = i_psvc_get_obj(hdlp, sensorid, &sensorp);
1414 			if (status != PSVC_SUCCESS)
1415 				return (status);
1416 
1417 			status = sensorp->get_attr(hdlp, sensorp,
1418 				PSVC_SWITCH_STATE_ATTR, state);
1419 			if (status != PSVC_SUCCESS)
1420 				return (status);
1421 
1422 			if (strcmp(state, PSVC_SWITCH_ON) == 0) {
1423 				strcpy(pos, PSVC_OFF_POS);
1424 				return (PSVC_SUCCESS);
1425 			}
1426 		}
1427 	}
1428 	/* If we have fallen through till here, something's wrong */
1429 	errno = EINVAL;
1430 	return (PSVC_FAILURE);
1431 }
1432 
1433 
1434 static int32_t
1435 i_psvc_get_device_value_10_0(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1436 {
1437 	int32_t status = PSVC_SUCCESS;
1438 	char *physid;
1439 	EObj_t *physobjp;
1440 
1441 	if (objp->present != PSVC_PRESENT) {
1442 		errno = ENODEV;
1443 		return (PSVC_FAILURE);
1444 	}
1445 
1446 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1447 		0, &physid);
1448 	if (status != PSVC_SUCCESS)
1449 		return (status);
1450 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1451 	if (status != PSVC_SUCCESS)
1452 		return (status);
1453 
1454 	status = ((EPhysDev_t *)physobjp)->get_reg(hdlp, objp->addr_spec,
1455 		value);
1456 	if (status != PSVC_SUCCESS)
1457 		return (status);
1458 
1459 	if (objp->features & PSVC_CONVERSION_TABLE) {
1460 		int32_t m;
1461 		char *tid;
1462 		uint8_t temp8;
1463 
1464 		status = i_psvc_get_assoc_matches(hdlp, objp->label,
1465 		    PSVC_TABLE, &m);
1466 		if ((status != PSVC_SUCCESS) || (m != 1)) {
1467 			return (status);
1468 		}
1469 
1470 		(void) i_psvc_get_assoc_id(hdlp, objp->label,
1471 			PSVC_TABLE, 0, &tid);
1472 
1473 		status = i_psvc_get_table_value(hdlp, tid, *value, &temp8);
1474 		*value = temp8;
1475 	}
1476 	return (status);
1477 }
1478 
1479 static int32_t
1480 i_psvc_get_device_value_10_1(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1481 {
1482 	int32_t status = PSVC_SUCCESS;
1483 	char *physid;
1484 	EObj_t *physobjp;
1485 
1486 	if (objp->present != PSVC_PRESENT) {
1487 		errno = ENODEV;
1488 		return (PSVC_FAILURE);
1489 	}
1490 
1491 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1492 		0, &physid);
1493 	if (status != PSVC_SUCCESS)
1494 		return (status);
1495 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1496 	if (status != PSVC_SUCCESS)
1497 		return (status);
1498 
1499 	status = ((EPhysDev_t *)physobjp)->get_port(hdlp, objp->addr_spec,
1500 		value);
1501 	if (status != PSVC_SUCCESS)
1502 		return (status);
1503 
1504 	return (status);
1505 }
1506 
1507 static int32_t
1508 i_psvc_set_device_value_10_0(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1509 {
1510 	int32_t status = PSVC_SUCCESS;
1511 	char *physid;
1512 	EObj_t *physobjp;
1513 
1514 	if (objp->present != PSVC_PRESENT) {
1515 		errno = ENODEV;
1516 		return (PSVC_FAILURE);
1517 	}
1518 
1519 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1520 		0, &physid);
1521 	if (status != PSVC_SUCCESS)
1522 		return (status);
1523 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1524 	if (status != PSVC_SUCCESS)
1525 		return (status);
1526 
1527 	status = ((EPhysDev_t *)physobjp)->set_reg(hdlp, objp->addr_spec,
1528 		*value);
1529 	return (status);
1530 }
1531 
1532 static int32_t
1533 i_psvc_set_device_value_10_1(EHdl_t *hdlp, EObj_t *objp, uint8_t *value)
1534 {
1535 	int32_t status = PSVC_SUCCESS;
1536 	char *physid;
1537 	EObj_t *physobjp;
1538 
1539 	if (objp->present != PSVC_PRESENT) {
1540 		errno = ENODEV;
1541 		return (PSVC_FAILURE);
1542 	}
1543 
1544 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1545 		0, &physid);
1546 	if (status != PSVC_SUCCESS)
1547 		return (status);
1548 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1549 	if (status != PSVC_SUCCESS)
1550 		return (status);
1551 
1552 	status = ((EPhysDev_t *)physobjp)->set_port(hdlp, objp->addr_spec,
1553 		*value);
1554 	return (status);
1555 }
1556 
1557 static int32_t
1558 i_psvc_get_device_state_8_0(EHdl_t *hdlp, EObj_t *objp, char *sw_state)
1559 {
1560 	int32_t status = PSVC_SUCCESS;
1561 	boolean_t active_low;
1562 	int32_t bit_value;
1563 	char *physid;
1564 	EObj_t *physobjp;
1565 
1566 	if (objp->present != PSVC_PRESENT) {
1567 		errno = ENODEV;
1568 		return (PSVC_FAILURE);
1569 	}
1570 
1571 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1572 		0, &physid);
1573 	if (status != PSVC_SUCCESS)
1574 		return (status);
1575 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1576 	if (status != PSVC_SUCCESS)
1577 		return (status);
1578 
1579 	status = ((EPhysDev_t *)physobjp)->get_bit(hdlp, objp->addr_spec,
1580 		&bit_value);
1581 	if (status != PSVC_SUCCESS)
1582 		return (status);
1583 
1584 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1585 	if (active_low)
1586 		if (bit_value == 0)
1587 			strcpy(sw_state, PSVC_SWITCH_ON);
1588 		else
1589 			strcpy(sw_state, PSVC_SWITCH_OFF);
1590 	else
1591 		if (bit_value == 0)
1592 			strcpy(sw_state, PSVC_SWITCH_OFF);
1593 		else
1594 			strcpy(sw_state, PSVC_SWITCH_ON);
1595 
1596 	return (status);
1597 }
1598 
1599 static int32_t
1600 i_psvc_set_device_state_8_0(EHdl_t *hdlp, EObj_t *objp, char *sw_state)
1601 {
1602 	int32_t status = PSVC_SUCCESS;
1603 	boolean_t active_low;
1604 	int32_t bit_value;
1605 	char *physid;
1606 	EObj_t *physobjp;
1607 
1608 	if (objp->present != PSVC_PRESENT) {
1609 		errno = ENODEV;
1610 		return (PSVC_FAILURE);
1611 	}
1612 
1613 	strcpy(objp->previous_state, objp->state);
1614 	strcpy(objp->state, sw_state);
1615 
1616 	active_low = PSVC_IS_ACTIVE_LOW(objp->addr_spec);
1617 
1618 	if (active_low)
1619 		if (strcmp(sw_state, PSVC_SWITCH_ON) == 0)
1620 			bit_value = 0;
1621 		else
1622 			bit_value = 1;
1623 	else
1624 		if (strcmp(sw_state, PSVC_SWITCH_ON) == 0)
1625 			bit_value = 1;
1626 		else
1627 			bit_value = 0;
1628 
1629 	status = i_psvc_get_assoc_id(hdlp, objp->label, PSVC_PHYSICAL_DEVICE,
1630 		0, &physid);
1631 	if (status != PSVC_SUCCESS)
1632 		return (status);
1633 	status = i_psvc_get_obj(hdlp, physid, &physobjp);
1634 	if (status != PSVC_SUCCESS)
1635 		return (status);
1636 
1637 	status = ((EPhysDev_t *)physobjp)->set_bit(hdlp, objp->addr_spec,
1638 		bit_value);
1639 	return (status);
1640 }
1641 
1642 /* LM75 */
1643 static int32_t
1644 i_psvc_get_temperature_11_2(EHdl_t *hdlp, uint64_t aspec, int32_t *temp)
1645 {
1646 	int32_t status = PSVC_SUCCESS;
1647 	char path[1024];
1648 	int32_t fp;
1649 	int16_t temp16;
1650 
1651 	status = i_psvc_get_devpath(hdlp, aspec, path);
1652 	if (status != PSVC_SUCCESS)
1653 		return (status);
1654 
1655 	fp = open(path, O_RDWR);
1656 	if (fp == -1)
1657 		return (PSVC_FAILURE);
1658 
1659 	status = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
1660 	if (status == -1) {
1661 		close(fp);
1662 		errno = EIO;
1663 		return (PSVC_FAILURE);
1664 	}
1665 	*temp = temp16;
1666 
1667 	close(fp);
1668 
1669 	return (status);
1670 }
1671 
1672 /* MAX1617 */
1673 static int32_t
1674 i_psvc_get_temperature_11_4(EHdl_t *hdlp, uint64_t aspec, int32_t *temp)
1675 {
1676 	int32_t status = PSVC_SUCCESS;
1677 	char path[1024];
1678 	int32_t fp;
1679 	int16_t temp16;
1680 
1681 	status = i_psvc_get_devpath(hdlp, aspec, path);
1682 	if (status != PSVC_SUCCESS)
1683 		return (status);
1684 
1685 	fp = open(path, O_RDWR);
1686 	if (fp == -1)
1687 		return (PSVC_FAILURE);
1688 
1689 	status = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
1690 	if (status == -1) {
1691 		close(fp);
1692 		errno = EIO;
1693 		return (PSVC_FAILURE);
1694 	}
1695 	*temp = temp16;
1696 
1697 	close(fp);
1698 
1699 	return (status);
1700 }
1701 
1702 /* PCF8591 */
1703 static int32_t
1704 i_psvc_get_temperature_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t *temp)
1705 {
1706 	int32_t status = PSVC_SUCCESS;
1707 	char path[1024];
1708 	int32_t fp;
1709 
1710 	status = i_psvc_get_devpath(hdlp, aspec, path);
1711 	if (status != PSVC_SUCCESS)
1712 		return (status);
1713 
1714 	fp = open(path, O_RDWR);
1715 	if (fp == -1)
1716 		return (PSVC_FAILURE);
1717 
1718 	status = ioctl_retry(fp, I2C_GET_INPUT, (void *)temp);
1719 	if (status == -1) {
1720 		close(fp);
1721 		errno = EIO;
1722 		return (-1);
1723 	}
1724 
1725 	close(fp);
1726 
1727 	return (status);
1728 }
1729 
1730 /* SSC050 */
1731 static int32_t
1732 i_psvc_get_fanspeed_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t *fan_speed)
1733 {
1734 	int32_t ret, status = PSVC_SUCCESS;
1735 	char path[1024];
1736 	int32_t fp;
1737 
1738 	status = i_psvc_get_devpath(hdlp, aspec, path);
1739 	if (status != PSVC_SUCCESS)
1740 		return (status);
1741 
1742 	fp = open(path, O_RDWR);
1743 	if (fp == -1)
1744 		return (PSVC_FAILURE);
1745 
1746 	ret = ioctl_retry(fp, I2C_GET_FAN_SPEED, (void *)fan_speed);
1747 	if (ret == -1) {
1748 		close(fp);
1749 		errno = EIO;
1750 		return (-1);
1751 	}
1752 
1753 	close(fp);
1754 
1755 	return (status);
1756 }
1757 
1758 /* PCF8591 */
1759 static int32_t
1760 i_psvc_get_input_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1761 {
1762 	int32_t ret, status = PSVC_SUCCESS;
1763 	char path[1024];
1764 	int32_t fp;
1765 
1766 	status = i_psvc_get_devpath(hdlp, aspec, path);
1767 	if (status != PSVC_SUCCESS)
1768 		return (status);
1769 
1770 	fp = open(path, O_RDWR);
1771 	if (fp == -1)
1772 		return (PSVC_FAILURE);
1773 
1774 	ret = ioctl_retry(fp, I2C_GET_INPUT, (void *)value);
1775 	if (ret == -1) {
1776 		close(fp);
1777 		errno = EIO;
1778 		return (-1);
1779 	}
1780 
1781 	close(fp);
1782 
1783 	return (status);
1784 }
1785 
1786 /* LTC1427 */
1787 static int32_t
1788 i_psvc_get_output_11_3(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1789 {
1790 	int32_t ret, status = PSVC_SUCCESS;
1791 	char path[1024];
1792 	int32_t fp;
1793 
1794 	status = i_psvc_get_devpath(hdlp, aspec, path);
1795 	if (status != PSVC_SUCCESS)
1796 		return (status);
1797 
1798 	fp = open(path, O_RDWR);
1799 	if (fp == -1)
1800 		return (PSVC_FAILURE);
1801 
1802 	ret = ioctl_retry(fp, I2C_GET_OUTPUT, (void *)value);
1803 	if (ret == -1) {
1804 		close(fp);
1805 		errno = EIO;
1806 		return (PSVC_FAILURE);
1807 	}
1808 
1809 	close(fp);
1810 
1811 	return (status);
1812 }
1813 
1814 /* PCF8591 */
1815 static int32_t
1816 i_psvc_get_output_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1817 {
1818 	int32_t ret, status = PSVC_SUCCESS;
1819 	char path[1024];
1820 	int32_t fp;
1821 
1822 	status = i_psvc_get_devpath(hdlp, aspec, path);
1823 	if (status != PSVC_SUCCESS)
1824 		return (status);
1825 
1826 	fp = open(path, O_RDWR);
1827 	if (fp == -1)
1828 		return (PSVC_FAILURE);
1829 
1830 	ret = ioctl_retry(fp, I2C_GET_OUTPUT, (void *)value);
1831 	if (ret == -1) {
1832 		close(fp);
1833 		errno = EIO;
1834 		return (PSVC_FAILURE);
1835 	}
1836 
1837 	close(fp);
1838 
1839 	return (status);
1840 }
1841 
1842 /* TDA8444 */
1843 static int32_t
1844 i_psvc_get_output_11_8(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
1845 {
1846 	int32_t ret, status = PSVC_SUCCESS;
1847 	char path[1024];
1848 	int32_t fp;
1849 	int8_t buf;
1850 
1851 	status = i_psvc_get_devpath(hdlp, aspec, path);
1852 	if (status != PSVC_SUCCESS)
1853 		return (status);
1854 
1855 	fp = open(path, O_RDWR);
1856 	if (fp == -1)
1857 		return (PSVC_FAILURE);
1858 
1859 	ret = read(fp, &buf, 1);
1860 	if (ret == -1) {
1861 		close(fp);
1862 		errno = EIO;
1863 		return (PSVC_FAILURE);
1864 	}
1865 	*value = buf;
1866 
1867 	close(fp);
1868 
1869 	return (status);
1870 }
1871 
1872 /* LTC1427 */
1873 static int32_t
1874 i_psvc_set_output_11_3(EHdl_t *hdlp, uint64_t aspec, int32_t value)
1875 {
1876 	int32_t ret, status = PSVC_SUCCESS;
1877 	char path[1024];
1878 	int32_t fp;
1879 
1880 	status = i_psvc_get_devpath(hdlp, aspec, path);
1881 	if (status != PSVC_SUCCESS)
1882 		return (status);
1883 
1884 	fp = open(path, O_RDWR);
1885 	if (fp == -1)
1886 		return (PSVC_FAILURE);
1887 
1888 	ret = ioctl_retry(fp, I2C_SET_OUTPUT, (void *)&value);
1889 	if (ret == -1) {
1890 		close(fp);
1891 		errno = EIO;
1892 		return (PSVC_FAILURE);
1893 	}
1894 
1895 	close(fp);
1896 
1897 	return (status);
1898 }
1899 
1900 /* PCF8591 */
1901 static int32_t
1902 i_psvc_set_output_11_6(EHdl_t *hdlp, uint64_t aspec, int32_t value)
1903 {
1904 	int32_t ret, status = PSVC_SUCCESS;
1905 	char path[1024];
1906 	int32_t fp;
1907 
1908 	status = i_psvc_get_devpath(hdlp, aspec, path);
1909 	if (status != PSVC_SUCCESS)
1910 		return (status);
1911 
1912 	fp = open(path, O_RDWR);
1913 	if (fp == -1)
1914 		return (PSVC_FAILURE);
1915 
1916 	ret = ioctl_retry(fp, I2C_SET_OUTPUT, (void *)&value);
1917 	if (ret == -1) {
1918 		close(fp);
1919 		errno = EIO;
1920 		return (PSVC_FAILURE);
1921 	}
1922 
1923 	close(fp);
1924 
1925 	return (status);
1926 }
1927 
1928 /* TDA8444 */
1929 static int32_t
1930 i_psvc_set_output_11_8(EHdl_t *hdlp, uint64_t aspec, int32_t value)
1931 {
1932 	int32_t ret, status = PSVC_SUCCESS;
1933 	char path[1024];
1934 	int32_t fp;
1935 	int8_t buf;
1936 
1937 	status = i_psvc_get_devpath(hdlp, aspec, path);
1938 	if (status != PSVC_SUCCESS)
1939 		return (status);
1940 
1941 	fp = open(path, O_RDWR);
1942 	if (fp == -1)
1943 		return (PSVC_FAILURE);
1944 
1945 	buf = value;
1946 	ret = write(fp, &buf, 1);
1947 	if (ret == -1) {
1948 		close(fp);
1949 		errno = EIO;
1950 		return (PSVC_FAILURE);
1951 	}
1952 
1953 	close(fp);
1954 
1955 	return (status);
1956 }
1957 
1958 /* HPC3130 */
1959 static int32_t
1960 i_psvc_get_reg_11_1(EHdl_t *hdlp, uint64_t aspec, uint8_t *value)
1961 {
1962 	int32_t ret, status = PSVC_SUCCESS;
1963 	uint8_t bitshift, bytemask;
1964 	char path[1024];
1965 	i2c_reg_t i2cregarg;
1966 	int32_t fp;
1967 
1968 	status = i_psvc_get_devpath(hdlp, aspec, path);
1969 	if (status != PSVC_SUCCESS)
1970 		return (status);
1971 	fp = open(path, O_RDWR);
1972 	if (fp == -1)
1973 		return (PSVC_FAILURE);
1974 
1975 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
1976 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
1977 	if (ret == -1) {
1978 		close(fp);
1979 		errno = EIO;
1980 		return (-1);
1981 	}
1982 
1983 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
1984 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
1985 	if (value != NULL)
1986 		*value = (i2cregarg.reg_value & bytemask) >> bitshift;
1987 	close(fp);
1988 
1989 	return (status);
1990 }
1991 
1992 /* SSC050 */
1993 static int32_t
1994 i_psvc_get_reg_11_7(EHdl_t *hdlp, uint64_t aspec, uint8_t *value)
1995 {
1996 	int32_t ret, status = PSVC_SUCCESS;
1997 	uint8_t bitshift, bytemask;
1998 	char path[1024];
1999 	i2c_reg_t i2cregarg;
2000 	int32_t fp;
2001 
2002 	status = i_psvc_get_devpath(hdlp, aspec, path);
2003 	if (status != PSVC_SUCCESS)
2004 		return (status);
2005 
2006 	fp = open(path, O_RDWR);
2007 	if (fp == -1)
2008 		return (PSVC_FAILURE);
2009 
2010 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
2011 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
2012 	if (ret == -1) {
2013 		close(fp);
2014 		errno = EIO;
2015 		return (-1);
2016 	}
2017 
2018 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
2019 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
2020 	if (value != NULL)
2021 		*value = (i2cregarg.reg_value & bytemask) >> bitshift;
2022 
2023 	close(fp);
2024 
2025 	return (status);
2026 }
2027 
2028 /* HPC3130 */
2029 static int32_t
2030 i_psvc_set_reg_11_1(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2031 {
2032 	int32_t ret, status = PSVC_SUCCESS;
2033 	char path[1024];
2034 	i2c_reg_t i2cregarg;
2035 	int8_t tval;
2036 	uint8_t bitshift, bytemask;
2037 	int32_t fp;
2038 
2039 	status = i_psvc_get_devpath(hdlp, aspec, path);
2040 	if (status != PSVC_SUCCESS)
2041 		return (status);
2042 
2043 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
2044 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
2045 	value = value << bitshift;
2046 
2047 	fp = open(path, O_RDWR);
2048 	if (fp == -1)
2049 		return (PSVC_FAILURE);
2050 
2051 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
2052 	if (bytemask != 0xFF) {
2053 		ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
2054 		if (ret == -1) {
2055 			close(fp);
2056 			errno = EIO;
2057 			return (-1);
2058 		}
2059 		tval = i2cregarg.reg_value;
2060 		tval = tval & ~bytemask;
2061 	} else
2062 		tval = 0;
2063 
2064 	value = tval | value;
2065 	i2cregarg.reg_value = value;
2066 	ret = ioctl_retry(fp, I2C_SET_REG, (void *)&i2cregarg);
2067 	if (ret == -1) {
2068 		close(fp);
2069 		errno = EIO;
2070 		return (-1);
2071 	}
2072 
2073 	close(fp);
2074 
2075 	return (status);
2076 }
2077 
2078 /* SSC050 */
2079 static int32_t
2080 i_psvc_set_reg_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2081 {
2082 	int32_t ret, status = PSVC_SUCCESS;
2083 	char path[1024];
2084 	i2c_reg_t i2cregarg;
2085 	int8_t tval;
2086 	uint8_t bitshift, bytemask;
2087 	int32_t fp;
2088 
2089 	status = i_psvc_get_devpath(hdlp, aspec, path);
2090 	if (status != PSVC_SUCCESS)
2091 		return (status);
2092 
2093 	bitshift = PSVC_GET_ASPEC_BITSHIFT(aspec);
2094 	bytemask = PSVC_GET_ASPEC_BYTEMASK(aspec);
2095 	value = value << bitshift;
2096 
2097 	fp = open(path, O_RDWR);
2098 	if (fp == -1)
2099 		return (PSVC_FAILURE);
2100 
2101 	i2cregarg.reg_num = PSVC_GET_ASPEC_REG(aspec);
2102 	if (bytemask != 0xFF) {
2103 		ret = ioctl_retry(fp, I2C_GET_REG, (void *)&i2cregarg);
2104 		if (ret == -1) {
2105 			close(fp);
2106 			errno = EIO;
2107 			return (-1);
2108 		}
2109 		tval = i2cregarg.reg_value;
2110 		tval = tval & ~bytemask;
2111 	} else
2112 		tval = 0;
2113 
2114 	value = tval | value;
2115 	i2cregarg.reg_value = value;
2116 	ret = ioctl_retry(fp, I2C_SET_REG, (void *)&i2cregarg);
2117 	if (ret == -1) {
2118 		close(fp);
2119 		errno = EIO;
2120 		return (-1);
2121 	}
2122 
2123 	close(fp);
2124 
2125 	return (status);
2126 }
2127 
2128 /* PCF8574 */
2129 static int32_t
2130 i_psvc_get_bit_11_5(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
2131 {
2132 	int32_t ret, status = PSVC_SUCCESS;
2133 	char path[1024];
2134 	i2c_bit_t bitarg;
2135 	int32_t fp;
2136 
2137 	status = i_psvc_get_devpath(hdlp, aspec, path);
2138 	if (status != PSVC_SUCCESS)
2139 		return (status);
2140 
2141 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2142 	bitarg.direction = DIR_NO_CHANGE;
2143 
2144 	fp = open(path, O_RDWR);
2145 	if (fp == -1)
2146 		return (PSVC_FAILURE);
2147 
2148 	ret = ioctl_retry(fp, I2C_GET_BIT, (void *)&bitarg);
2149 	if (ret == -1) {
2150 		close(fp);
2151 		errno = EIO;
2152 		return (-1);
2153 	}
2154 
2155 	*value = bitarg.bit_value;
2156 
2157 	close(fp);
2158 
2159 	return (status);
2160 }
2161 
2162 /* PCF8574 */
2163 static int32_t
2164 i_psvc_get_port_11_5(EHdl_t *hdlp, uint64_t aspec, uint8_t *value)
2165 {
2166 	int32_t ret, status = PSVC_SUCCESS;
2167 	char path[1024];
2168 	i2c_port_t port;
2169 	int32_t fp;
2170 
2171 	status = i_psvc_get_devpath(hdlp, aspec, path);
2172 	if (status != PSVC_SUCCESS)
2173 		return (status);
2174 
2175 	port.direction = DIR_NO_CHANGE;
2176 
2177 	fp = open(path, O_RDWR);
2178 	if (fp == -1)
2179 		return (PSVC_FAILURE);
2180 
2181 	ret = ioctl_retry(fp, I2C_GET_PORT, (void *)&port);
2182 	if (ret == -1) {
2183 		close(fp);
2184 		errno = EIO;
2185 		return (-1);
2186 	}
2187 
2188 	*value = port.value;
2189 
2190 	close(fp);
2191 
2192 	return (status);
2193 }
2194 
2195 /* SSC050 */
2196 static int32_t
2197 i_psvc_get_bit_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t *value)
2198 {
2199 	int32_t ret, status = PSVC_SUCCESS;
2200 	char path[1024];
2201 	i2c_bit_t bitarg;
2202 	int32_t fp;
2203 
2204 	status = i_psvc_get_devpath(hdlp, aspec, path);
2205 	if (status != PSVC_SUCCESS)
2206 		return (status);
2207 
2208 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2209 	bitarg.direction = DIR_NO_CHANGE;
2210 
2211 	fp = open(path, O_RDWR);
2212 	if (fp == -1)
2213 		return (PSVC_FAILURE);
2214 
2215 	ret = ioctl_retry(fp, I2C_GET_BIT, (void *)&bitarg);
2216 	if (ret == -1) {
2217 		close(fp);
2218 		errno = EIO;
2219 		return (-1);
2220 	}
2221 
2222 	*value = bitarg.bit_value;
2223 
2224 	close(fp);
2225 
2226 	return (status);
2227 }
2228 
2229 /* PCF8574 */
2230 static int32_t
2231 i_psvc_set_bit_11_5(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2232 {
2233 	int32_t ret, status = PSVC_SUCCESS;
2234 	char path[1024];
2235 	i2c_bit_t bitarg;
2236 	int32_t fp;
2237 
2238 	status = i_psvc_get_devpath(hdlp, aspec, path);
2239 	if (status != PSVC_SUCCESS)
2240 		return (status);
2241 
2242 	bitarg.bit_value = value;
2243 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2244 	bitarg.direction = DIR_OUTPUT;
2245 	fp = open(path, O_RDWR);
2246 	if (fp == -1)
2247 		return (PSVC_FAILURE);
2248 
2249 	ret = ioctl_retry(fp, I2C_SET_BIT, (void *)&bitarg);
2250 	if (ret == -1) {
2251 		close(fp);
2252 		errno = EIO;
2253 		return (-1);
2254 	}
2255 
2256 	close(fp);
2257 
2258 	return (status);
2259 }
2260 
2261 /* PCF8574 */
2262 static int32_t
2263 i_psvc_set_port_11_5(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2264 {
2265 	int32_t ret, status = PSVC_SUCCESS;
2266 	char path[1024];
2267 	i2c_port_t port;
2268 	int32_t fp;
2269 
2270 	status = i_psvc_get_devpath(hdlp, aspec, path);
2271 	if (status != PSVC_SUCCESS)
2272 		return (status);
2273 
2274 	port.value = (uint8_t)value;
2275 	port.direction = DIR_NO_CHANGE;
2276 	fp = open(path, O_RDWR);
2277 	if (fp == -1)
2278 		return (PSVC_FAILURE);
2279 
2280 	ret = ioctl_retry(fp, I2C_SET_PORT, (void *)&port);
2281 	if (ret == -1) {
2282 		close(fp);
2283 		errno = EIO;
2284 		return (-1);
2285 	}
2286 
2287 	close(fp);
2288 
2289 	return (status);
2290 }
2291 
2292 /* SSC050 */
2293 static int32_t
2294 i_psvc_set_bit_11_7(EHdl_t *hdlp, uint64_t aspec, int32_t value)
2295 {
2296 	int32_t ret, status = PSVC_SUCCESS;
2297 	char path[1024];
2298 	i2c_bit_t bitarg;
2299 	int32_t fp;
2300 
2301 	status = i_psvc_get_devpath(hdlp, aspec, path);
2302 	if (status != PSVC_SUCCESS)
2303 		return (status);
2304 
2305 	bitarg.bit_value = value;
2306 	bitarg.bit_num = PSVC_GET_BIT_NUM(aspec);
2307 	bitarg.direction = DIR_OUTPUT;
2308 
2309 	fp = open(path, O_RDWR);
2310 	if (fp == -1)
2311 		return (PSVC_FAILURE);
2312 
2313 	ret = ioctl_retry(fp, I2C_SET_BIT, (void *)&bitarg);
2314 	if (ret == -1) {
2315 		close(fp);
2316 		errno = EIO;
2317 		return (-1);
2318 	}
2319 
2320 	close(fp);
2321 
2322 	return (status);
2323 }
2324 
2325 /* AT24 */
2326 static int32_t
2327 i_psvc_probe_11_0(EHdl_t *hdlp, EObj_t *objp)
2328 {
2329 	int32_t ret, status = PSVC_SUCCESS;
2330 	uint8_t value;
2331 	char path[1024];
2332 	int32_t fp;
2333 
2334 	if (objp->present != PSVC_PRESENT) {
2335 		errno = ENODEV;
2336 		return (PSVC_FAILURE);
2337 	}
2338 
2339 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2340 	if (status != PSVC_SUCCESS) {
2341 		return (status);
2342 	}
2343 
2344 	fp = open(path, O_RDWR);
2345 	if (fp == -1) {
2346 		return (PSVC_FAILURE);
2347 	}
2348 
2349 	ret = read(fp, &value, 1);
2350 	if (ret == -1) {
2351 		close(fp);
2352 		errno = EIO;
2353 		return (-1);
2354 	}
2355 
2356 	close(fp);
2357 
2358 	return (status);
2359 }
2360 
2361 /* HPC3130 */
2362 static int32_t
2363 i_psvc_probe_11_1(EHdl_t *hdlp, EObj_t *objp)
2364 {
2365 	int32_t ret, status = PSVC_SUCCESS;
2366 	char path[1024];
2367 	i2c_reg_t reg;
2368 	int32_t fp;
2369 
2370 	if (objp->present != PSVC_PRESENT) {
2371 		errno = ENODEV;
2372 		return (PSVC_FAILURE);
2373 	}
2374 
2375 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2376 	if (status != PSVC_SUCCESS)
2377 		return (status);
2378 
2379 	fp = open(path, O_RDWR);
2380 	if (fp == -1)
2381 		return (PSVC_FAILURE);
2382 
2383 	reg.reg_num = 0;
2384 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&reg);
2385 	if (ret == -1) {
2386 		close(fp);
2387 		errno = EIO;
2388 		return (-1);
2389 	}
2390 
2391 	close(fp);
2392 
2393 	return (status);
2394 }
2395 
2396 /* LM75 */
2397 static int32_t
2398 i_psvc_probe_11_2(EHdl_t *hdlp, EObj_t *objp)
2399 {
2400 	int32_t ret, status = PSVC_SUCCESS;
2401 	char path[1024];
2402 	int32_t fp;
2403 	int16_t temp16;
2404 
2405 	if (objp->present != PSVC_PRESENT) {
2406 		errno = ENODEV;
2407 		return (PSVC_FAILURE);
2408 	}
2409 
2410 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2411 	if (status != PSVC_SUCCESS) {
2412 		return (status);
2413 	}
2414 
2415 	fp = open(path, O_RDWR);
2416 	if (fp == -1) {
2417 		return (PSVC_FAILURE);
2418 	}
2419 
2420 	ret = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
2421 	if (ret == -1) {
2422 		close(fp);
2423 		errno = EIO;
2424 		return (-1);
2425 	}
2426 
2427 	close(fp);
2428 
2429 	return (status);
2430 }
2431 
2432 /* LTC1427 */
2433 static int32_t
2434 i_psvc_probe_11_3(EHdl_t *hdlp, EObj_t *objp)
2435 {
2436 	int32_t ret, status = PSVC_SUCCESS;
2437 	int32_t value;
2438 	char path[1024];
2439 	int32_t fp;
2440 
2441 	if (objp->present != PSVC_PRESENT) {
2442 		errno = ENODEV;
2443 		return (PSVC_FAILURE);
2444 	}
2445 
2446 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2447 	if (status != PSVC_SUCCESS) {
2448 		return (status);
2449 	}
2450 
2451 	fp = open(path, O_RDWR);
2452 	if (fp == -1) {
2453 		return (PSVC_FAILURE);
2454 	}
2455 
2456 	ret = ioctl_retry(fp, I2C_GET_OUTPUT, (void *)&value);
2457 	if (ret == -1) {
2458 		close(fp);
2459 		errno = EINVAL;
2460 		return (-1);
2461 	}
2462 
2463 	ret = ioctl_retry(fp, I2C_SET_OUTPUT, (void *)&value);
2464 	if (ret == -1) {
2465 		close(fp);
2466 		errno = EIO;
2467 		return (-1);
2468 	}
2469 
2470 	close(fp);
2471 	return (status);
2472 }
2473 
2474 /* MAX1617 */
2475 static int32_t
2476 i_psvc_probe_11_4(EHdl_t *hdlp, EObj_t *objp)
2477 {
2478 	int32_t ret, status = PSVC_SUCCESS;
2479 	char path[1024];
2480 	int32_t fp;
2481 	int16_t temp16;
2482 
2483 	if (objp->present != PSVC_PRESENT) {
2484 		errno = ENODEV;
2485 		return (PSVC_FAILURE);
2486 	}
2487 
2488 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2489 	if (status != PSVC_SUCCESS) {
2490 		return (status);
2491 	}
2492 
2493 	fp = open(path, O_RDWR);
2494 	if (fp == -1) {
2495 		return (PSVC_FAILURE);
2496 	}
2497 
2498 	ret = ioctl_retry(fp, I2C_GET_TEMPERATURE, (void *)&temp16);
2499 	if (ret == -1) {
2500 		close(fp);
2501 		errno = EIO;
2502 		return (-1);
2503 	}
2504 
2505 	close(fp);
2506 
2507 	return (status);
2508 }
2509 
2510 /* PCF8574 */
2511 static int32_t
2512 i_psvc_probe_11_5(EHdl_t *hdlp, EObj_t *objp)
2513 {
2514 	int32_t ret, status = PSVC_SUCCESS;
2515 	char path[1024];
2516 	i2c_port_t port;
2517 	int32_t fp;
2518 
2519 	if (objp->present != PSVC_PRESENT) {
2520 		errno = ENODEV;
2521 		return (PSVC_FAILURE);
2522 	}
2523 
2524 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2525 	if (status != PSVC_SUCCESS) {
2526 		return (status);
2527 	}
2528 
2529 	port.direction = DIR_NO_CHANGE;
2530 
2531 	fp = open(path, O_RDWR);
2532 	if (fp == -1) {
2533 		return (PSVC_FAILURE);
2534 	}
2535 
2536 	ret = ioctl_retry(fp, I2C_GET_PORT, (void *)&port);
2537 	if (ret == -1) {
2538 		close(fp);
2539 		errno = EIO;
2540 		return (-1);
2541 	}
2542 
2543 	close(fp);
2544 
2545 	return (status);
2546 }
2547 
2548 /* PCF8591 */
2549 static int32_t
2550 i_psvc_probe_11_6(EHdl_t *hdlp, EObj_t *objp)
2551 {
2552 	int32_t ret, status = PSVC_SUCCESS;
2553 	char path[1024];
2554 	int32_t arg;
2555 	int32_t fp;
2556 
2557 	if (objp->present != PSVC_PRESENT) {
2558 		errno = ENODEV;
2559 		return (PSVC_FAILURE);
2560 	}
2561 
2562 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2563 	if (status != PSVC_SUCCESS)
2564 		return (status);
2565 
2566 	fp = open(path, O_RDWR);
2567 	if (fp == -1)
2568 		return (PSVC_FAILURE);
2569 
2570 	ret = ioctl_retry(fp, I2C_GET_INPUT, (void *)&arg);
2571 	if (ret == -1) {
2572 		close(fp);
2573 		errno = EIO;
2574 		return (-1);
2575 	}
2576 
2577 	close(fp);
2578 
2579 	return (status);
2580 }
2581 
2582 /* SSC050 */
2583 static int32_t
2584 i_psvc_probe_11_7(EHdl_t *hdlp, EObj_t *objp)
2585 {
2586 	int32_t ret, status = PSVC_SUCCESS;
2587 	char path[1024];
2588 	i2c_port_t port;
2589 	int32_t fp;
2590 
2591 	if (objp->present != PSVC_PRESENT) {
2592 		errno = ENODEV;
2593 		return (PSVC_FAILURE);
2594 	}
2595 
2596 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2597 	if (status != PSVC_SUCCESS)
2598 		return (status);
2599 
2600 	port.direction = DIR_NO_CHANGE;
2601 
2602 	fp = open(path, O_RDWR);
2603 	if (fp == -1)
2604 		return (PSVC_FAILURE);
2605 
2606 	ret = ioctl_retry(fp, I2C_GET_PORT, (void *)&port);
2607 	if (ret == -1) {
2608 		close(fp);
2609 		errno = EIO;
2610 		return (-1);
2611 	}
2612 
2613 	close(fp);
2614 
2615 	return (status);
2616 }
2617 
2618 /* TDA8444 */
2619 static int32_t
2620 i_psvc_probe_11_8(EHdl_t *hdlp, EObj_t *objp)
2621 {
2622 	int32_t ret, status = PSVC_SUCCESS;
2623 	uint8_t value;
2624 	char path[1024];
2625 	int32_t fp;
2626 
2627 	if (objp->present != PSVC_PRESENT) {
2628 		errno = ENODEV;
2629 		return (PSVC_FAILURE);
2630 	}
2631 
2632 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2633 	if (status != PSVC_SUCCESS)
2634 		return (status);
2635 
2636 	fp = open(path, O_RDWR);
2637 	if (fp == -1)
2638 		return (PSVC_FAILURE);
2639 
2640 	ret = read(fp, &value, 1);
2641 	if (ret == -1) {
2642 		close(fp);
2643 		errno = EIO;
2644 		return (-1);
2645 	}
2646 
2647 	close(fp);
2648 
2649 	return (status);
2650 }
2651 
2652 
2653 /* SSC100 */
2654 static int32_t
2655 i_psvc_probe_11_9(EHdl_t *hdlp, EObj_t *objp)
2656 {
2657 	int32_t ret, status = PSVC_SUCCESS;
2658 	char path[1024];
2659 	i2c_reg_t reg;
2660 	int32_t fp;
2661 
2662 	if (objp->present != PSVC_PRESENT) {
2663 		errno = ENODEV;
2664 		return (PSVC_FAILURE);
2665 	}
2666 
2667 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
2668 	if (status != PSVC_SUCCESS) {
2669 		return (status);
2670 	}
2671 
2672 	fp = open(path, O_RDWR);
2673 	if (fp == -1) {
2674 		return (PSVC_FAILURE);
2675 	}
2676 
2677 	/*
2678 	 * There are only a few register numbers that are valid numbers to
2679 	 * read from. 0x10 is one of these registers. Any non-valid registers
2680 	 * cause unknown behavior to the ssc100 device.
2681 	 */
2682 	reg.reg_num = 0x10;
2683 	ret = ioctl_retry(fp, I2C_GET_REG, (void *)&reg);
2684 	if (ret == -1) {
2685 		close(fp);
2686 		errno = EIO;
2687 		return (-1);
2688 	}
2689 
2690 	close(fp);
2691 
2692 	return (status);
2693 }
2694 
2695 
2696 /*
2697  * Find start of a section within the config file,
2698  * Returns number of records in the section.
2699  * FILE *fd is set to first data record within section.
2700  */
2701 static int32_t
2702 i_psvc_find_file_section(FILE *fd, char *start)
2703 {
2704 	char *ret;
2705 	char buf[BUFSZ];
2706 	char name[32];
2707 	int found;
2708 
2709 	fseek(fd, 0, SEEK_SET);
2710 	while ((ret = fgets(buf, BUFSZ, fd)) != NULL) {
2711 		if (strncmp(start, buf, strlen(start)) == 0)
2712 			break;
2713 	}
2714 
2715 	if (ret == NULL) {
2716 		errno = EINVAL;
2717 		return (-1);
2718 	}
2719 
2720 	found = sscanf(buf, "%s", name);
2721 	if (found != 1) {
2722 		errno = EINVAL;
2723 		return (-1);
2724 	} else {
2725 		return (0);
2726 	}
2727 
2728 }
2729 
2730 /* compare routine for qsort of str_tbl */
2731 static int32_t
2732 i_psvc_name_compare_qsort(EStringId_t *s1, EStringId_t *s2)
2733 {
2734 	return (strcmp(s1->name, s2->name));
2735 }
2736 
2737 /* compare routine for bsearch of str_tbl */
2738 static int32_t
2739 i_psvc_name_compare_bsearch(char *s1, EStringId_t *s2)
2740 {
2741 	return (strcmp(s1, s2->name));
2742 }
2743 
2744 /*
2745  * Determine the initial state of a device.
2746  */
2747 static int32_t
2748 i_psvc_init_state(EHdl_t *hp, EObj_t *objp)
2749 {
2750 	int32_t status = PSVC_SUCCESS;
2751 
2752 	if (objp->class == PSVC_ON_OFF_SWITCH_CLASS) {
2753 		char state[32];
2754 
2755 		status = objp->get_attr(hp, objp, PSVC_SWITCH_STATE_ATTR,
2756 			state);
2757 		if (status != PSVC_SUCCESS)
2758 			return (status);
2759 
2760 		if (strcmp(state, PSVC_SWITCH_ON) == 0)
2761 			strcpy(objp->state, PSVC_ON);
2762 		else
2763 			strcpy(objp->state, PSVC_OFF);
2764 	}
2765 
2766 	if (objp->class == PSVC_KEYSWITCH_CLASS) {
2767 		char state[32];
2768 
2769 		status = objp->get_attr(hp, objp, PSVC_SWITCH_STATE_ATTR,
2770 			state);
2771 		if (status != PSVC_SUCCESS)
2772 			return (status);
2773 		strcpy(objp->state, state);
2774 	}
2775 
2776 	return (status);
2777 }
2778 
2779 /*
2780  * Return the object pointer for the object name passed in.
2781  * Creates the object if this is the first access,
2782  * Returns 0 if successful, -1 if not.
2783  */
2784 static int32_t
2785 i_psvc_get_obj(EHdl_t *hp, char *dev_name, EObj_t **objp)
2786 {
2787 	int32_t i, ret;
2788 	int32_t found, key, array;
2789 	int32_t class, subclass;
2790 	boolean_t presence;
2791 	char name[NAMELEN];
2792 	char buf[BUFSZ];
2793 	char *start;
2794 	ETable_Array *tbl_arr;
2795 
2796 	key = psvc_get_str_key(dev_name);
2797 	array = key % PSVC_MAX_TABLE_ARRAYS;
2798 	tbl_arr = &(hp->tbl_arry[array]);
2799 
2800 	for (i = 0; i < tbl_arr->obj_count; ++i) {
2801 		if (key ==  tbl_arr->obj_tbl[i].key) {
2802 			if (strcmp(dev_name, tbl_arr->obj_tbl[i].name) == 0) {
2803 				if (tbl_arr->obj_tbl[i].type != PSVC_OBJ)
2804 					return (-1);
2805 				*objp = tbl_arr->obj_tbl[i].objp;
2806 				return (0);
2807 			}
2808 		}
2809 	}
2810 
2811 	if (i_psvc_find_file_section(hp->fp, "OBJECT_INFO") == -1) {
2812 		ENV_DEBUG("Couldn't find OBJECT_INFO section", dev_name);
2813 		return (-1);
2814 	}
2815 
2816 	fgets(buf, BUFSZ, hp->fp);
2817 	while (strcmp(buf, "OBJECT_INFO_END")) {
2818 		start = strrchr(buf, '/');
2819 		if (start == NULL) {
2820 			errno = EINVAL;
2821 			return (PSVC_FAILURE);
2822 		}
2823 		found = sscanf(start + 1, "%s",  name);
2824 		if (found != 1) {
2825 			errno = EINVAL;
2826 			return (PSVC_FAILURE);
2827 		}
2828 
2829 		if (strcmp(name, dev_name) == 0) {
2830 
2831 			if (i_psvc_value(buf, PSVC_CLASS_ATTR, &class)
2832 			    != PSVC_SUCCESS)
2833 				return (PSVC_FAILURE);
2834 			if (i_psvc_value(buf, PSVC_SUBCLASS_ATTR, &subclass)
2835 			    != PSVC_SUCCESS)
2836 				return (PSVC_FAILURE);
2837 			ret = (*i_psvc_constructor[class][subclass])(hp,
2838 				dev_name, objp);
2839 			if (ret != PSVC_SUCCESS) {
2840 				return (-1);
2841 			}
2842 			ret = (*objp)->get_attr(hp, *objp, PSVC_PRESENCE_ATTR,
2843 				&presence);
2844 			(*objp)->previous_presence = presence;
2845 			if (ret != PSVC_SUCCESS || presence != PSVC_PRESENT)
2846 				return (ret);
2847 
2848 			return (i_psvc_init_state(hp, *objp));
2849 		}
2850 		fgets(buf, BUFSZ, hp->fp);
2851 	}
2852 
2853 	errno = EINVAL;
2854 	return (-1);
2855 }
2856 
2857 /*
2858  * Gets the device path associated with an object id.
2859  * Returns 0 if successful, -1 if not.
2860  */
2861 static int32_t
2862 i_psvc_get_devpath(EHdl_t *hp, uint64_t addr_spec, char *path)
2863 {
2864 	int i;
2865 	EDevice_t *dp;
2866 	uint32_t controller, bus, addr, port;
2867 
2868 	controller = PSVC_GET_ASPEC_CNTLR(addr_spec);
2869 	bus = PSVC_GET_ASPEC_BUSNUM(addr_spec);
2870 	addr = PSVC_GET_ASPEC_BUSADDR(addr_spec);
2871 	port = PSVC_GET_ASPEC_PORT(addr_spec);
2872 
2873 	for (i = 0; i < hp->dev_count; ++i) {
2874 		dp = &hp->dev_tbl[i];
2875 		if (dp->controller == controller &&
2876 		    dp->bus == bus &&
2877 		    dp->addr == addr &&
2878 		    dp->port == port) {
2879 			strcpy(path, dp->path);
2880 			return (PSVC_SUCCESS);
2881 		}
2882 	}
2883 
2884 	errno = EINVAL;
2885 	return (PSVC_FAILURE);
2886 }
2887 
2888 
2889 /* Load the association table */
2890 static int32_t
2891 i_psvc_load_associations(EHdl_t *hp, FILE *fp)
2892 {
2893 	uint32_t count;
2894 	int found;
2895 	int i, j;
2896 	char name1[32], name2[32];
2897 	char buf[BUFSZ];
2898 	EStringId_t *namep;
2899 	EAssoc_t *ap;
2900 	int32_t id;
2901 	int32_t status;
2902 
2903 	/*
2904 	 * ignore count in the file, correct count is highest
2905 	 * association id + 1, now figured when loading ASSOC_STR
2906 	 * section.
2907 	 */
2908 	if (i_psvc_find_file_section(fp, "ASSOCIATIONS") != PSVC_SUCCESS)
2909 		return (-1);
2910 	if ((hp->assoc_tbl = malloc(sizeof (EAssocList_t) * hp->assoc_count))
2911 			== NULL) {
2912 		return (-1);
2913 	}
2914 	memset(hp->assoc_tbl, 0, sizeof (EAssocList_t) * hp->assoc_count);
2915 
2916 	for (i = 0; i < hp->assoc_count; ++i) {
2917 		fgets(buf, BUFSZ, fp);
2918 		found = sscanf(buf, "%s %s", name1, name2);
2919 		if (strcmp("ASSOCIATIONS_END", name1) == 0)
2920 			break;
2921 		if (found != 2) {
2922 			errno = EINVAL;
2923 			return (-1);
2924 		}
2925 		namep = (EStringId_t *)bsearch(name2, hp->othr_tbl,
2926 			hp->othr_count, sizeof (EStringId_t),
2927 			(int (*)(const void *, const void *))
2928 			i_psvc_name_compare_bsearch);
2929 		if (namep == NULL) {
2930 			errno = EINVAL;
2931 			return (-1);
2932 		}
2933 		id = namep->id;
2934 
2935 		status = i_psvc_count_records(fp, "ASSOCIATION_END", &count);
2936 		if (status != PSVC_SUCCESS)
2937 			return (status);
2938 		hp->assoc_tbl[id].count = count;
2939 		hp->assoc_tbl[id].table =
2940 			(EAssoc_t *)malloc(sizeof (EAssoc_t) * count);
2941 		if (hp->assoc_tbl[id].table == NULL)
2942 			return (-1);
2943 
2944 		for (j = 0; j < count; ++j) {
2945 			ap = &hp->assoc_tbl[id].table[j];
2946 			fgets(buf, BUFSZ, fp);
2947 			found = sscanf(buf, "%s %s", ap->antecedent_id,
2948 				ap->dependent_id);
2949 			ap->ant_key = psvc_get_str_key(ap->antecedent_id);
2950 			if (found != 2) {
2951 				errno = EINVAL;
2952 				return (-1);
2953 			}
2954 		}
2955 
2956 
2957 		fgets(buf, BUFSZ, fp);
2958 		if (strncmp(buf, "ASSOCIATION_END", 15) != 0) {
2959 			errno = EINVAL;
2960 			return (-1);
2961 		}
2962 	}
2963 
2964 	return (0);
2965 }
2966 
2967 /* Load the table of tables */
2968 static int32_t
2969 i_psvc_load_tables(EHdl_t *hp, FILE *fp)
2970 {
2971 	int i, j;
2972 	int found;
2973 	int ret;
2974 	int32_t cell_type;
2975 	int64_t *table;
2976 	char buf[BUFSZ];
2977 	int32_t status;
2978 	uint32_t table_count;
2979 	int32_t num, key, array;
2980 	char name[NAMELEN];
2981 	ETable_Array *tbl_arr;
2982 
2983 	if (i_psvc_find_file_section(fp, "TABLES") != PSVC_SUCCESS)
2984 		return (PSVC_SUCCESS);	/* no tables */
2985 	status = i_psvc_count_tables_associations(fp, &table_count,
2986 			"TABLE_END");
2987 	if (status != PSVC_SUCCESS || table_count == 0)
2988 		return (status);
2989 
2990 	for (i = 0; i < table_count; ++i) {
2991 		int slot;
2992 		ETable_t *tblp;
2993 
2994 		fgets(buf, BUFSZ, fp);
2995 		if (strncmp(buf, "TABLE", 5) != 0) {
2996 			errno = EINVAL;
2997 			return (-1);
2998 		}
2999 
3000 		fgets(buf, BUFSZ, fp);
3001 		found = sscanf(buf, "%s %d", name, &cell_type);
3002 		key = psvc_get_str_key(name);
3003 		array = key % PSVC_MAX_TABLE_ARRAYS;
3004 		tbl_arr = &(hp->tbl_arry[array]);
3005 
3006 		if (tbl_arr->nextid == hp->total_obj_count) {
3007 			errno = EINVAL;
3008 			return (PSVC_FAILURE);
3009 		} else {
3010 			slot = tbl_arr->nextid++;
3011 			tbl_arr->obj_count++;
3012 		}
3013 
3014 		strcpy(tbl_arr->obj_tbl[slot].name, name);
3015 
3016 		tblp = (ETable_t *)malloc(sizeof (ETable_t));
3017 		if (tblp == NULL)
3018 			return (PSVC_FAILURE);
3019 		tbl_arr->obj_tbl[slot].key = key;
3020 		tbl_arr->obj_tbl[slot].objp = (EObj_t *)(void *)tblp;
3021 		tbl_arr->obj_tbl[slot].type = PSVC_TBL;
3022 
3023 		status = i_psvc_count_table_records(fp, "TABLE_END",
3024 			&tblp->size);
3025 		if (status != PSVC_SUCCESS)
3026 			return (status);
3027 		tblp->cell_type = (uint8_t)cell_type;
3028 		if (found != 2) {
3029 			errno = EINVAL;
3030 			return (-1);
3031 		}
3032 
3033 		/* allocate and load table */
3034 		tblp->table = (int64_t *)malloc(tblp->size *
3035 			i_psvc_cell_size[tblp->cell_type]);
3036 		if (tblp->table == NULL) {
3037 			return (-1);
3038 		}
3039 
3040 		table = tblp->table;
3041 		for (j = 0; j < tblp->size; ++j) {
3042 			switch (cell_type) {
3043 				case 0:
3044 					ret = fscanf(fp, "%d", &num);
3045 					*((int8_t *)table + j) = num;
3046 					break;
3047 				case 1:
3048 					ret = fscanf(fp, "%d", &num);
3049 					*((uint8_t *)table + j) = (uint8_t)num;
3050 					break;
3051 				case 2:
3052 					ret = fscanf(fp, "%hd",
3053 						((int16_t *)table + j));
3054 					break;
3055 				case 3:
3056 					ret = fscanf(fp, "%hd",
3057 						((uint16_t *)table + j));
3058 					break;
3059 				case 4:
3060 					ret = fscanf(fp, "%d",
3061 						((int32_t *)table + j));
3062 					break;
3063 				case 5:
3064 					ret = fscanf(fp, "%d",
3065 						((uint32_t *)table + j));
3066 					break;
3067 				case 6:
3068 					ret = fscanf(fp, "%lld",
3069 						((int64_t *)table + j));
3070 					break;
3071 				case 7:
3072 					ret = fscanf(fp, "%lld",
3073 						((uint64_t *)table + j));
3074 					break;
3075 				default:
3076 					errno = EINVAL;
3077 					return (-1);
3078 			}
3079 			if (ret != 1) {
3080 				errno = EINVAL;
3081 				return (-1);
3082 			}
3083 		}
3084 		fgets(buf, BUFSZ, fp);  /* reads newline on data line */
3085 		fgets(buf, BUFSZ, fp);
3086 		if (strncmp(buf, "TABLE_END", 9) != 0) {
3087 			errno = EINVAL;
3088 			return (-1);
3089 		}
3090 
3091 	}
3092 
3093 	return (0);
3094 }
3095 
3096 static int32_t
3097 i_psvc_destructor(EHdl_t *hdlp, char *name, void *objp)
3098 {
3099 	int32_t i, key, array;
3100 
3101 	key = psvc_get_str_key(name);
3102 	array = key % PSVC_MAX_TABLE_ARRAYS;
3103 
3104 	for (i = 0; i < hdlp->tbl_arry[array].obj_count; ++i) {
3105 		if (key == hdlp->tbl_arry[array].obj_tbl[i].key) {
3106 			if (strcmp(hdlp->tbl_arry[array].obj_tbl[i].name,
3107 				name) == 0) {
3108 				hdlp->tbl_arry[array].obj_tbl[i].name[0] = '\0';
3109 				if (objp != NULL)
3110 					free(objp);
3111 				return (PSVC_SUCCESS);
3112 			}
3113 		}
3114 	}
3115 
3116 	return (PSVC_SUCCESS);
3117 }
3118 
3119 static int32_t
3120 i_psvc_get_attr_generic(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id,
3121     void * attrp)
3122 {
3123 	int32_t status = PSVC_SUCCESS;
3124 	char *parent_id;
3125 
3126 	switch (attr_id) {
3127 	case PSVC_ADDR_SPEC_ATTR:
3128 		*(uint64_t *)attrp = objp->addr_spec;
3129 		break;
3130 	case PSVC_CLASS_ATTR:
3131 		*(int32_t *)attrp = objp->class;
3132 		break;
3133 	case PSVC_SUBCLASS_ATTR:
3134 		*(int32_t *)attrp = objp->subclass;
3135 		break;
3136 	case PSVC_PRESENCE_ATTR:
3137 		status = i_psvc_get_presence(hdlp, objp, (boolean_t *)attrp);
3138 		break;
3139 	case PSVC_PREV_PRESENCE_ATTR:
3140 		*(boolean_t *)attrp = objp->previous_presence;
3141 		break;
3142 	case PSVC_STATE_ATTR:
3143 		strcpy((char *)attrp, objp->state);
3144 		break;
3145 	case PSVC_PREV_STATE_ATTR:
3146 		strcpy((char *)attrp, objp->previous_state);
3147 		break;
3148 	case PSVC_ENABLE_ATTR:
3149 		*(boolean_t *)attrp = objp->enabled;
3150 		break;
3151 	case PSVC_FAULTID_ATTR:
3152 		strcpy((char *)attrp, objp->fault_id);
3153 		break;
3154 	case PSVC_FEATURES_ATTR:
3155 		*(uint64_t *)attrp = objp->features;
3156 		break;
3157 	case PSVC_LABEL_ATTR:
3158 		strcpy((char *)attrp, objp->label);
3159 		break;
3160 	case PSVC_FRUID_ATTR:
3161 		while ((objp->features & PSVC_DEV_FRU) == 0) {
3162 			status = i_psvc_get_assoc_id(hdlp, objp->label,
3163 				PSVC_PARENT, 0, &parent_id);
3164 			if (status != PSVC_SUCCESS)
3165 				return (status);
3166 
3167 			status = i_psvc_get_obj(hdlp, parent_id, &objp);
3168 			if (status != PSVC_SUCCESS)
3169 				return (status);
3170 		}
3171 
3172 		strcpy((char *)attrp, objp->label);
3173 		break;
3174 	case PSVC_INSTANCE_ATTR:
3175 		*(int32_t *)attrp = objp->instance;
3176 		break;
3177 	default:
3178 		errno = EINVAL;
3179 		return (PSVC_FAILURE);
3180 	}
3181 
3182 	return (status);
3183 }
3184 
3185 static int32_t
3186 i_psvc_set_attr_generic(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id,
3187     void * attrp)
3188 {
3189 	int32_t status = PSVC_SUCCESS;
3190 
3191 	switch (attr_id) {
3192 	case PSVC_PREV_PRESENCE_ATTR:
3193 		objp->previous_presence = *(boolean_t *)attrp;
3194 		break;
3195 	case PSVC_STATE_ATTR:
3196 		strcpy(objp->previous_state, objp->state);
3197 		strcpy(objp->state, (char *)attrp);
3198 		break;
3199 	case PSVC_ENABLE_ATTR:
3200 		objp->enabled = *(boolean_t *)attrp;
3201 		break;
3202 	case PSVC_FAULTID_ATTR:
3203 		strcpy(objp->fault_id, (char *)attrp);
3204 		break;
3205 	default:
3206 		errno = EINVAL;
3207 		return (PSVC_FAILURE);
3208 	}
3209 	return (status);
3210 }
3211 
3212 static int32_t
3213 i_psvc_get_attr_0_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3214 {
3215 	int32_t status = PSVC_SUCCESS;
3216 
3217 	switch (attr_id) {
3218 	case PSVC_SENSOR_VALUE_ATTR:
3219 		return (i_psvc_get_device_value_0_0(hdlp, objp, attrp));
3220 	case PSVC_LO_WARN_ATTR:
3221 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_warn;
3222 		return (status);
3223 	case PSVC_LO_SHUT_ATTR:
3224 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_shut;
3225 		return (status);
3226 	case PSVC_HI_WARN_ATTR:
3227 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_warn;
3228 		return (status);
3229 	case PSVC_HI_SHUT_ATTR:
3230 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_shut;
3231 		return (status);
3232 	}
3233 
3234 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3235 
3236 	return (status);
3237 }
3238 
3239 static int32_t
3240 i_psvc_get_attr_0_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3241 {
3242 	int32_t status = PSVC_SUCCESS;
3243 
3244 	switch (attr_id) {
3245 	case PSVC_SENSOR_VALUE_ATTR:
3246 		return (i_psvc_get_device_value_0_1(hdlp, objp, attrp));
3247 	case PSVC_LO_WARN_ATTR:
3248 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_warn;
3249 		return (status);
3250 	case PSVC_LO_SHUT_ATTR:
3251 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->lo_shut;
3252 		return (status);
3253 	case PSVC_HI_WARN_ATTR:
3254 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_warn;
3255 		return (status);
3256 	case PSVC_HI_SHUT_ATTR:
3257 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hi_shut;
3258 		return (status);
3259 	case PSVC_OPTIMAL_TEMP_ATTR:
3260 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->opt_temp;
3261 		return (status);
3262 	case PSVC_HW_HI_SHUT_ATTR:
3263 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hw_hi_shut;
3264 		return (status);
3265 	case PSVC_HW_LO_SHUT_ATTR:
3266 		*(int32_t *)attrp = ((ETempSensor_t *)objp)->hw_lo_shut;
3267 		return (status);
3268 	}
3269 
3270 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3271 
3272 	return (status);
3273 }
3274 
3275 static int32_t
3276 i_psvc_set_attr_0_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3277 {
3278 	int32_t status = PSVC_SUCCESS;
3279 
3280 	switch (attr_id) {
3281 	case PSVC_LO_WARN_ATTR:
3282 		((ETempSensor_t *)objp)->lo_warn = *(int32_t *)attrp;
3283 		return (status);
3284 	case PSVC_LO_SHUT_ATTR:
3285 		((ETempSensor_t *)objp)->lo_shut = *(int32_t *)attrp;
3286 		return (status);
3287 	case PSVC_HI_WARN_ATTR:
3288 		((ETempSensor_t *)objp)->hi_warn = *(int32_t *)attrp;
3289 		return (status);
3290 	case PSVC_HI_SHUT_ATTR:
3291 		((ETempSensor_t *)objp)->hi_shut = *(int32_t *)attrp;
3292 		return (status);
3293 	case PSVC_OPTIMAL_TEMP_ATTR:
3294 		((ETempSensor_t *)objp)->opt_temp = *(int32_t *)attrp;
3295 		return (status);
3296 	case PSVC_HW_HI_SHUT_ATTR:
3297 		((ETempSensor_t *)objp)->hw_hi_shut = *(int32_t *)attrp;
3298 		return (status);
3299 	case PSVC_HW_LO_SHUT_ATTR:
3300 		((ETempSensor_t *)objp)->hw_lo_shut = *(int32_t *)attrp;
3301 		return (status);
3302 	}
3303 
3304 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3305 
3306 	return (status);
3307 }
3308 
3309 static int32_t
3310 i_psvc_get_attr_1_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3311 {
3312 	int32_t status = PSVC_SUCCESS;
3313 
3314 	switch (attr_id) {
3315 	case PSVC_SENSOR_VALUE_ATTR:
3316 		return (i_psvc_get_device_value_1_0(hdlp, objp, attrp));
3317 	case PSVC_SETPOINT_ATTR:
3318 		*(int16_t *)attrp = ((EFan_t *)objp)->setpoint;
3319 		return (status);
3320 	case PSVC_HYSTERESIS_ATTR:
3321 		*(int16_t *)attrp = ((EFan_t *)objp)->hysteresis;
3322 		return (status);
3323 	case PSVC_LOOPGAIN_ATTR:
3324 		*(int16_t *)attrp = ((EFan_t *)objp)->loopgain;
3325 		return (status);
3326 	case PSVC_LOOPBIAS_ATTR:
3327 		*(int16_t *)attrp = ((EFan_t *)objp)->loopbias;
3328 		return (status);
3329 	case PSVC_TEMP_DIFFERENTIAL_ATTR:
3330 		memcpy(attrp, ((EFan_t *)objp)->temp_differential,
3331 			sizeof (((EFan_t *)objp)->temp_differential));
3332 		return (status);
3333 	case PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR:
3334 		*(int16_t *)attrp = ((EFan_t *)objp)->temp_differential_index;
3335 		return (status);
3336 	}
3337 
3338 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3339 
3340 	return (status);
3341 }
3342 
3343 static int32_t
3344 i_psvc_set_attr_1_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3345 {
3346 	int32_t status = PSVC_SUCCESS;
3347 
3348 	switch (attr_id) {
3349 	case PSVC_TEMP_DIFFERENTIAL_ATTR:
3350 		memcpy(((EFan_t *)objp)->temp_differential, attrp,
3351 			sizeof (((EFan_t *)objp)->temp_differential));
3352 		return (status);
3353 	case PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR:
3354 		((EFan_t *)objp)->temp_differential_index = *(int16_t *)attrp;
3355 		return (status);
3356 	case PSVC_SETPOINT_ATTR:
3357 		((EFan_t *)objp)->setpoint = *(int16_t *)attrp;
3358 		return (status);
3359 	}
3360 
3361 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3362 
3363 	return (PSVC_SUCCESS);
3364 }
3365 
3366 static int32_t
3367 i_psvc_get_attr_2_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3368 {
3369 	int32_t status = PSVC_SUCCESS;
3370 
3371 	switch (attr_id) {
3372 	case PSVC_LED_STATE_ATTR:
3373 	case PSVC_STATE_ATTR:
3374 		return (i_psvc_get_device_state_2_0(hdlp, objp, attrp));
3375 	case PSVC_LED_COLOR_ATTR:
3376 		strcpy((char *)attrp, ((ELed_t *)objp)->color);
3377 		return (status);
3378 	case PSVC_LIT_COUNT_ATTR:
3379 		*(int16_t *)attrp = ((ELed_t *)objp)->lit_count;
3380 		return (status);
3381 	}
3382 
3383 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3384 
3385 	return (status);
3386 }
3387 
3388 static int32_t
3389 i_psvc_set_attr_2_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3390 {
3391 	int32_t status = PSVC_SUCCESS;
3392 
3393 	switch (attr_id) {
3394 	case PSVC_LED_STATE_ATTR:
3395 	case PSVC_STATE_ATTR:
3396 		return (i_psvc_set_device_state_2_0(hdlp, objp, attrp));
3397 	}
3398 
3399 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3400 
3401 	return (status);
3402 }
3403 
3404 static int32_t
3405 i_psvc_get_attr_2_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3406 {
3407 	int32_t status = PSVC_SUCCESS;
3408 
3409 	switch (attr_id) {
3410 	case PSVC_LED_STATE_ATTR:
3411 	case PSVC_STATE_ATTR:
3412 		return (i_psvc_get_device_state_2_1(hdlp, objp, attrp));
3413 	case PSVC_LED_COLOR_ATTR:
3414 		strcpy((char *)attrp, ((ELed_t *)objp)->color);
3415 		return (status);
3416 	case PSVC_LIT_COUNT_ATTR:
3417 		*(int16_t *)attrp = ((ELed_t *)objp)->lit_count;
3418 		return (status);
3419 	}
3420 
3421 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3422 
3423 	return (status);
3424 }
3425 
3426 static int32_t
3427 i_psvc_set_attr_2_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3428 {
3429 	int32_t status = PSVC_SUCCESS;
3430 
3431 	switch (attr_id) {
3432 	case PSVC_LED_STATE_ATTR:
3433 	case PSVC_STATE_ATTR:
3434 		return (i_psvc_set_device_state_2_1(hdlp, objp, attrp));
3435 	}
3436 
3437 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3438 
3439 	return (status);
3440 }
3441 
3442 static int32_t
3443 i_psvc_get_attr_2_2(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3444 {
3445 	int32_t status = PSVC_SUCCESS;
3446 
3447 	switch (attr_id) {
3448 	case PSVC_LED_STATE_ATTR:
3449 	case PSVC_STATE_ATTR:
3450 		return (i_psvc_get_device_state_2_0(hdlp, objp, attrp));
3451 	case PSVC_LED_COLOR_ATTR:
3452 		strcpy((char *)attrp, ((ELed_t *)objp)->color);
3453 		return (status);
3454 	case PSVC_LIT_COUNT_ATTR:
3455 		*(int16_t *)attrp = ((ELed_t *)objp)->lit_count;
3456 		return (status);
3457 	case PSVC_LED_IS_LOCATOR_ATTR:
3458 		strcpy((char *)attrp, ((ELed_t *)objp)->is_locator);
3459 		return (status);
3460 	case PSVC_LED_LOCATOR_NAME_ATTR:
3461 		strcpy((char *)attrp, ((ELed_t *)objp)->locator_name);
3462 		return (status);
3463 	}
3464 
3465 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3466 
3467 	return (status);
3468 }
3469 
3470 static int32_t
3471 i_psvc_get_attr_4_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3472 {
3473 	int32_t status = PSVC_SUCCESS;
3474 
3475 	switch (attr_id) {
3476 	case PSVC_SENSOR_VALUE_ATTR:
3477 		return (i_psvc_get_device_value_4_0(hdlp, objp, attrp));
3478 	case PSVC_LO_WARN_ATTR:
3479 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->lo_warn;
3480 		return (status);
3481 	case PSVC_LO_SHUT_ATTR:
3482 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->lo_shut;
3483 		return (status);
3484 	case PSVC_HI_WARN_ATTR:
3485 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->hi_warn;
3486 		return (status);
3487 	case PSVC_HI_SHUT_ATTR:
3488 		*(int32_t *)attrp = ((EDigiSensor_t *)objp)->hi_shut;
3489 		return (status);
3490 	}
3491 
3492 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3493 
3494 	return (PSVC_SUCCESS);
3495 }
3496 
3497 static int32_t
3498 i_psvc_get_attr_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3499 {
3500 	int32_t status = PSVC_SUCCESS;
3501 
3502 	if (attr_id == PSVC_CONTROL_VALUE_ATTR) {
3503 		return (i_psvc_get_device_value_5_0(hdlp, objp, attrp));
3504 	}
3505 
3506 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3507 
3508 	return (status);
3509 }
3510 
3511 static int32_t
3512 i_psvc_set_attr_5_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3513 {
3514 	int32_t status = PSVC_SUCCESS;
3515 
3516 	if (attr_id == PSVC_CONTROL_VALUE_ATTR) {
3517 		return (i_psvc_set_device_value_5_0(hdlp, objp, attrp));
3518 	}
3519 
3520 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3521 
3522 	return (status);
3523 }
3524 
3525 static int32_t
3526 i_psvc_get_attr_6_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3527 {
3528 	int32_t status = PSVC_SUCCESS;
3529 
3530 	switch (attr_id) {
3531 	case PSVC_GPIO_VALUE_ATTR:
3532 		return (i_psvc_get_device_value_6_0(hdlp, objp, attrp));
3533 	case PSVC_GPIO_BITS:
3534 		*(int32_t *)attrp = 1;
3535 		return (status);
3536 	}
3537 
3538 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3539 
3540 	return (status);
3541 }
3542 
3543 static int32_t
3544 i_psvc_set_attr_6_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3545 {
3546 	int32_t status = PSVC_SUCCESS;
3547 
3548 	if (attr_id == PSVC_GPIO_VALUE_ATTR) {
3549 		return (i_psvc_set_device_value_6_0(hdlp, objp, attrp));
3550 	}
3551 
3552 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3553 
3554 	return (status);
3555 }
3556 
3557 static int32_t
3558 i_psvc_get_attr_7_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3559 {
3560 	int32_t status = PSVC_SUCCESS;
3561 
3562 	switch (attr_id) {
3563 	case PSVC_SENSOR_VALUE_ATTR:
3564 		return (i_psvc_get_device_value_7_0(hdlp, objp, attrp));
3565 	case PSVC_LO_WARN_ATTR:
3566 		*(int32_t *)attrp = ((EFanTach_t *)objp)->lo_warn;
3567 		return (status);
3568 	case PSVC_LO_SHUT_ATTR:
3569 		*(int32_t *)attrp = ((EFanTach_t *)objp)->lo_shut;
3570 		return (status);
3571 	case PSVC_HI_WARN_ATTR:
3572 		*(int32_t *)attrp = ((EFanTach_t *)objp)->hi_warn;
3573 		return (status);
3574 	case PSVC_HI_SHUT_ATTR:
3575 		*(int32_t *)attrp = ((EFanTach_t *)objp)->hi_shut;
3576 		return (status);
3577 	}
3578 
3579 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3580 
3581 	return (PSVC_SUCCESS);
3582 }
3583 
3584 static int32_t
3585 i_psvc_get_attr_8_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3586 {
3587 	int32_t status = PSVC_SUCCESS;
3588 
3589 	switch (attr_id) {
3590 	case PSVC_SWITCH_STATE_ATTR:
3591 	case PSVC_STATE_ATTR:
3592 		return (i_psvc_get_device_state_8_0(hdlp, objp, attrp));
3593 	}
3594 
3595 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3596 
3597 	return (status);
3598 }
3599 
3600 static int32_t
3601 i_psvc_set_attr_8_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3602 {
3603 	int32_t status = PSVC_SUCCESS;
3604 
3605 	switch (attr_id) {
3606 	case PSVC_SWITCH_STATE_ATTR:
3607 	case PSVC_STATE_ATTR:
3608 		return (i_psvc_set_device_state_8_0(hdlp, objp, attrp));
3609 	}
3610 
3611 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3612 
3613 	return (status);
3614 }
3615 
3616 static int32_t
3617 i_psvc_get_attr_9_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3618 {
3619 	int32_t status = PSVC_SUCCESS;
3620 
3621 	switch (attr_id) {
3622 	case PSVC_SWITCH_STATE_ATTR:
3623 	case PSVC_STATE_ATTR:
3624 		status = i_psvc_get_device_state_9_0(hdlp, objp, attrp);
3625 		if ((status == PSVC_FAILURE) && (errno == EINVAL)) {
3626 			strcpy((char *)attrp, PSVC_ERROR);
3627 			return (PSVC_SUCCESS);
3628 		} else {
3629 			return (status);
3630 		}
3631 	}
3632 
3633 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3634 
3635 	return (status);
3636 }
3637 
3638 static int32_t
3639 i_psvc_get_attr_10_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3640 {
3641 	int32_t status = PSVC_SUCCESS;
3642 
3643 	switch (attr_id) {
3644 	case PSVC_GPIO_VALUE_ATTR:
3645 		return (i_psvc_get_device_value_10_0(hdlp, objp, attrp));
3646 	case PSVC_GPIO_BITS:
3647 		*(int32_t *)attrp = 8;
3648 		return (status);
3649 	}
3650 
3651 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3652 
3653 	return (status);
3654 }
3655 
3656 static int32_t
3657 i_psvc_set_attr_10_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3658 {
3659 	int32_t status = PSVC_SUCCESS;
3660 
3661 	if (attr_id == PSVC_GPIO_VALUE_ATTR) {
3662 		return (i_psvc_set_device_value_10_0(hdlp, objp, attrp));
3663 	}
3664 
3665 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3666 
3667 	return (status);
3668 }
3669 
3670 static int32_t
3671 i_psvc_get_attr_10_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3672 {
3673 	int32_t status = PSVC_SUCCESS;
3674 
3675 	switch (attr_id) {
3676 	case PSVC_GPIO_VALUE_ATTR:
3677 		return (i_psvc_get_device_value_10_1(hdlp, objp, attrp));
3678 	case PSVC_GPIO_BITS:
3679 		*(int32_t *)attrp = 8;
3680 		return (status);
3681 	}
3682 
3683 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3684 
3685 	return (status);
3686 }
3687 
3688 static int32_t
3689 i_psvc_set_attr_10_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3690 {
3691 	int32_t status = PSVC_SUCCESS;
3692 
3693 	if (attr_id == PSVC_GPIO_VALUE_ATTR) {
3694 		return (i_psvc_set_device_value_10_1(hdlp, objp, attrp));
3695 	}
3696 
3697 	status = i_psvc_set_attr_generic(hdlp, objp, attr_id, attrp);
3698 
3699 	return (status);
3700 }
3701 
3702 /* AT24 */
3703 static int32_t
3704 i_psvc_get_attr_11_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3705 {
3706 	int32_t status = PSVC_SUCCESS;
3707 	int32_t probe_status;
3708 
3709 	switch (attr_id) {
3710 	case PSVC_PROBE_RESULT_ATTR:
3711 		probe_status = i_psvc_probe_11_0(hdlp, objp);
3712 		if (probe_status == PSVC_SUCCESS)
3713 			strcpy((char *)attrp, PSVC_OK);
3714 		else
3715 			strcpy((char *)attrp, PSVC_ERROR);
3716 		return (status);
3717 	case PSVC_FRU_INFO_ATTR:
3718 		status = i_psvc_get_reg_11_0(hdlp, objp, attr_id, attrp);
3719 		return (status);
3720 	}
3721 
3722 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3723 
3724 	return (status);
3725 }
3726 
3727 static int32_t
3728 i_psvc_get_reg_11_0(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3729 {
3730 	int32_t status = PSVC_SUCCESS, ret;
3731 	char path[1024], *data;
3732 	int32_t fp, temp_errno;
3733 	fru_info_t *fru_data;
3734 
3735 	fru_data = (fru_info_t *)attrp;
3736 
3737 	if (objp->present != PSVC_PRESENT) {
3738 		errno = ENODEV;
3739 		return (PSVC_FAILURE);
3740 	}
3741 
3742 	status = i_psvc_get_devpath(hdlp, objp->addr_spec, path);
3743 	if (status != PSVC_SUCCESS)
3744 		return (status);
3745 
3746 	fp = open(path, O_RDWR);
3747 	if (fp == -1) {
3748 		return (PSVC_FAILURE);
3749 	}
3750 
3751 	ret = lseek(fp, fru_data->buf_start, SEEK_SET);
3752 	if (ret != fru_data->buf_start) {
3753 		temp_errno = errno;
3754 		close(fp);
3755 		errno = temp_errno;
3756 		return (PSVC_FAILURE);
3757 	}
3758 
3759 	data = (char *)malloc(fru_data->read_size);
3760 	ret = read(fp, data, fru_data->read_size);
3761 	if (ret == -1) {
3762 		free(data);
3763 		close(fp);
3764 		errno = EIO;
3765 		return (-1);
3766 	}
3767 
3768 	memcpy(fru_data->buf, data, fru_data->read_size);
3769 	free(data);
3770 	close(fp);
3771 
3772 	return (status);
3773 }
3774 
3775 static int32_t
3776 i_psvc_get_attr_11_1(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3777 {
3778 	int32_t status = PSVC_SUCCESS;
3779 	int32_t probe_status;
3780 
3781 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3782 		probe_status = i_psvc_probe_11_1(hdlp, objp);
3783 		if (probe_status == PSVC_SUCCESS)
3784 			strcpy((char *)attrp, PSVC_OK);
3785 		else
3786 			strcpy((char *)attrp, PSVC_ERROR);
3787 		return (status);
3788 	}
3789 
3790 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3791 
3792 	return (status);
3793 }
3794 
3795 static int32_t
3796 i_psvc_get_attr_11_2(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3797 {
3798 	int32_t status = PSVC_SUCCESS;
3799 	int32_t probe_status;
3800 
3801 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3802 		probe_status = i_psvc_probe_11_2(hdlp, objp);
3803 		if (probe_status == PSVC_SUCCESS)
3804 			strcpy((char *)attrp, PSVC_OK);
3805 		else
3806 			strcpy((char *)attrp, PSVC_ERROR);
3807 		return (status);
3808 	}
3809 
3810 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3811 
3812 	return (status);
3813 }
3814 
3815 static int32_t
3816 i_psvc_get_attr_11_3(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3817 {
3818 	int32_t status = PSVC_SUCCESS;
3819 	int32_t probe_status;
3820 
3821 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3822 		probe_status = i_psvc_probe_11_3(hdlp, objp);
3823 		if (probe_status == PSVC_SUCCESS)
3824 			strcpy((char *)attrp, PSVC_OK);
3825 		else
3826 			strcpy((char *)attrp, PSVC_ERROR);
3827 		return (status);
3828 	}
3829 
3830 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3831 
3832 	return (status);
3833 }
3834 
3835 static int32_t
3836 i_psvc_get_attr_11_4(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3837 {
3838 	int32_t status = PSVC_SUCCESS;
3839 	int32_t probe_status;
3840 
3841 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3842 		probe_status = i_psvc_probe_11_4(hdlp, objp);
3843 		if (probe_status == PSVC_SUCCESS)
3844 			strcpy((char *)attrp, PSVC_OK);
3845 		else
3846 			strcpy((char *)attrp, PSVC_ERROR);
3847 		return (status);
3848 	}
3849 
3850 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3851 
3852 	return (status);
3853 }
3854 
3855 static int32_t
3856 i_psvc_get_attr_11_5(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3857 {
3858 	int32_t status = PSVC_SUCCESS;
3859 	int32_t probe_status;
3860 
3861 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3862 		probe_status = i_psvc_probe_11_5(hdlp, objp);
3863 		if (probe_status == PSVC_SUCCESS)
3864 			strcpy((char *)attrp, PSVC_OK);
3865 		else
3866 			strcpy((char *)attrp, PSVC_ERROR);
3867 		return (status);
3868 	}
3869 
3870 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3871 
3872 	return (status);
3873 }
3874 
3875 static int32_t
3876 i_psvc_get_attr_11_6(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3877 {
3878 	int32_t status = PSVC_SUCCESS;
3879 	int32_t probe_status;
3880 
3881 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3882 		probe_status = i_psvc_probe_11_6(hdlp, objp);
3883 		if (probe_status == PSVC_SUCCESS)
3884 			strcpy((char *)attrp, PSVC_OK);
3885 		else
3886 			strcpy((char *)attrp, PSVC_ERROR);
3887 		return (status);
3888 	}
3889 
3890 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3891 
3892 	return (status);
3893 }
3894 
3895 static int32_t
3896 i_psvc_get_attr_11_7(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3897 {
3898 	int32_t status = PSVC_SUCCESS;
3899 	int32_t probe_status;
3900 
3901 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3902 		probe_status = i_psvc_probe_11_7(hdlp, objp);
3903 		if (probe_status == PSVC_SUCCESS)
3904 			strcpy((char *)attrp, PSVC_OK);
3905 		else
3906 			strcpy((char *)attrp, PSVC_ERROR);
3907 		return (status);
3908 	}
3909 
3910 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3911 
3912 	return (status);
3913 }
3914 
3915 static int32_t
3916 i_psvc_get_attr_11_8(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3917 {
3918 	int32_t status = PSVC_SUCCESS;
3919 	int32_t probe_status;
3920 
3921 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3922 		probe_status = i_psvc_probe_11_8(hdlp, objp);
3923 		if (probe_status == PSVC_SUCCESS)
3924 			strcpy((char *)attrp, PSVC_OK);
3925 		else
3926 			strcpy((char *)attrp, PSVC_ERROR);
3927 		return (status);
3928 	}
3929 
3930 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3931 
3932 	return (status);
3933 }
3934 
3935 static int32_t
3936 i_psvc_get_attr_11_9(EHdl_t *hdlp, EObj_t *objp, int32_t attr_id, void *attrp)
3937 {
3938 	int32_t status = PSVC_SUCCESS;
3939 	int32_t probe_status;
3940 
3941 	if (attr_id == PSVC_PROBE_RESULT_ATTR) {
3942 		probe_status = i_psvc_probe_11_9(hdlp, objp);
3943 		if (probe_status == PSVC_SUCCESS)
3944 			strcpy((char *)attrp, PSVC_OK);
3945 		else
3946 			strcpy((char *)attrp, PSVC_ERROR);
3947 		return (status);
3948 	}
3949 
3950 	status = i_psvc_get_attr_generic(hdlp, objp, attr_id, attrp);
3951 
3952 	return (status);
3953 }
3954 
3955 static int32_t
3956 i_psvc_load_generic(
3957 	EHdl_t	*hdlp,
3958 	char	*name,
3959 	EObj_t    **objpp,
3960 	char	  *buf,
3961 	int32_t   obj_size)
3962 {
3963 	int32_t found, key, array;
3964 	EObj_t *objp;
3965 	char *start;
3966 	char  cur_device[NAMELEN];
3967 	int slot;
3968 	ETable_Array *tbl_arr;
3969 
3970 	key = psvc_get_str_key(name);
3971 	array = key % PSVC_MAX_TABLE_ARRAYS;
3972 	tbl_arr = &(hdlp->tbl_arry[array]);
3973 
3974 	if (tbl_arr->nextid == hdlp->total_obj_count) {
3975 		errno = EINVAL;
3976 		return (PSVC_FAILURE);
3977 	} else {
3978 		slot = tbl_arr->nextid++;
3979 		tbl_arr->obj_count++;
3980 	}
3981 
3982 	if (i_psvc_find_file_section(hdlp->fp, "OBJECT_INFO") != PSVC_SUCCESS)
3983 		return (PSVC_FAILURE);
3984 
3985 	fgets(buf, BUFSZ, hdlp->fp);
3986 	while (strcmp(buf, "OBJECT_INFO_END")) {
3987 		start = strrchr(buf, '/');
3988 		if (start == NULL) {
3989 			errno = EINVAL;
3990 			return (PSVC_FAILURE);
3991 		}
3992 		found = sscanf(start + 1, "%s",  cur_device);
3993 		if (found != 1) {
3994 			errno = EINVAL;
3995 			return (PSVC_FAILURE);
3996 		}
3997 		if (strcmp(name, cur_device) == 0)  /* found it */
3998 			break;
3999 		fgets(buf, BUFSZ, hdlp->fp);
4000 	}
4001 
4002 	tbl_arr->obj_tbl[slot].objp = (EObj_t *)malloc(obj_size);
4003 	if (tbl_arr->obj_tbl[slot].objp == 0)
4004 		return (PSVC_FAILURE);
4005 	objp = (EObj_t *)tbl_arr->obj_tbl[slot].objp;
4006 	tbl_arr->obj_tbl[slot].type = PSVC_OBJ;
4007 
4008 	memset(objp, 0, obj_size);
4009 	strcpy(objp->label, name);
4010 	strcpy(tbl_arr->obj_tbl[slot].name, name);
4011 
4012 	tbl_arr->obj_tbl[slot].key = key;
4013 
4014 	if (i_psvc_value(buf, PSVC_CLASS_ATTR, &objp->class) != PSVC_SUCCESS) {
4015 		i_psvc_destructor(hdlp, name, objp);
4016 		return (PSVC_FAILURE);
4017 	}
4018 	if (i_psvc_value(buf, PSVC_SUBCLASS_ATTR, &objp->subclass) !=
4019 		PSVC_SUCCESS) {
4020 		i_psvc_destructor(hdlp, name, objp);
4021 		return (PSVC_FAILURE);
4022 	}
4023 	if (i_psvc_value(buf, PSVC_INSTANCE_ATTR, &objp->instance) !=
4024 		PSVC_SUCCESS) {
4025 		i_psvc_destructor(hdlp, name, objp);
4026 		return (PSVC_FAILURE);
4027 	}
4028 	if (i_psvc_value(buf, PSVC_FEATURES_ATTR, &objp->features) !=
4029 		PSVC_SUCCESS) {
4030 		i_psvc_destructor(hdlp, name, objp);
4031 		return (PSVC_FAILURE);
4032 	}
4033 	if (i_psvc_value(buf, PSVC_ADDR_SPEC_ATTR, &objp->addr_spec) !=
4034 		PSVC_SUCCESS) {
4035 		i_psvc_destructor(hdlp, name, objp);
4036 		return (PSVC_FAILURE);
4037 	}
4038 
4039 	if (objp->features & PSVC_DEV_SECONDARY)
4040 		objp->enabled = PSVC_DISABLED;
4041 	else
4042 		objp->enabled = PSVC_ENABLED;
4043 
4044 	if (PSVC_GET_VERSION(objp->addr_spec) > PSVC_VERSION) {
4045 		errno = EINVAL;
4046 		i_psvc_destructor(hdlp, name, objp);
4047 		return (PSVC_FAILURE);
4048 	}
4049 
4050 	*objpp = objp;
4051 	return (PSVC_SUCCESS);
4052 
4053 }
4054 
4055 
4056 static int32_t
4057 i_psvc_not_supported()
4058 {
4059 	errno = ENOTSUP;
4060 	return (PSVC_FAILURE);
4061 }
4062 
4063 /* Temperature sensor */
4064 /* Class 0 Subclass 0 are temperature sensors that cannot be updated */
4065 static int32_t
4066 i_psvc_constructor_0_0(
4067 	EHdl_t	*hdlp,
4068 	char	*id,
4069 	EObj_t    **objpp)
4070 {
4071 	int32_t status;
4072 	char buf[BUFSZ];
4073 	ETempSensor_t *dp;
4074 
4075 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4076 		sizeof (ETempSensor_t));
4077 	if (status != PSVC_SUCCESS)
4078 		return (status);
4079 
4080 	/* Load class specific info */
4081 	dp = (ETempSensor_t *)*objpp;
4082 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4083 	    != PSVC_SUCCESS) {
4084 		i_psvc_destructor(hdlp, id, dp);
4085 		return (PSVC_FAILURE);
4086 	}
4087 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4088 	    != PSVC_SUCCESS) {
4089 		i_psvc_destructor(hdlp, id, dp);
4090 		return (PSVC_FAILURE);
4091 	}
4092 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4093 	    != PSVC_SUCCESS) {
4094 		i_psvc_destructor(hdlp, id, dp);
4095 		return (PSVC_FAILURE);
4096 	}
4097 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4098 	    != PSVC_SUCCESS) {
4099 		i_psvc_destructor(hdlp, id, dp);
4100 		return (PSVC_FAILURE);
4101 	}
4102 
4103 	dp->ld.constructor = i_psvc_constructor_0_0;
4104 	dp->ld.destructor = i_psvc_destructor;
4105 	dp->ld.get_attr = i_psvc_get_attr_0_0;
4106 	dp->ld.set_attr = i_psvc_set_attr_generic;
4107 
4108 	return (0);
4109 }
4110 
4111 /* Class 0 Subclass 1 are temperature sensors that can be updated */
4112 static int32_t
4113 i_psvc_constructor_0_1(
4114 	EHdl_t	*hdlp,
4115 	char	*id,
4116 	EObj_t    **objpp)
4117 {
4118 	int32_t status;
4119 	char buf[BUFSZ];
4120 	ETempSensor_t *dp;
4121 
4122 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4123 		sizeof (ETempSensor_t));
4124 	if (status != PSVC_SUCCESS)
4125 		return (status);
4126 
4127 	/* Load class specific info */
4128 	dp = (ETempSensor_t *)*objpp;
4129 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4130 	    != PSVC_SUCCESS) {
4131 		i_psvc_destructor(hdlp, id, dp);
4132 		return (PSVC_FAILURE);
4133 	}
4134 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4135 	    != PSVC_SUCCESS) {
4136 		i_psvc_destructor(hdlp, id, dp);
4137 		return (PSVC_FAILURE);
4138 	}
4139 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4140 	    != PSVC_SUCCESS) {
4141 		i_psvc_destructor(hdlp, id, dp);
4142 		return (PSVC_FAILURE);
4143 	}
4144 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4145 	    != PSVC_SUCCESS) {
4146 		i_psvc_destructor(hdlp, id, dp);
4147 		return (PSVC_FAILURE);
4148 	}
4149 
4150 	if ((*objpp)->features & PSVC_OPT_TEMP) {
4151 		if (i_psvc_value(buf, PSVC_OPTIMAL_TEMP_ATTR, &dp->opt_temp)
4152 		    != PSVC_SUCCESS) {
4153 			i_psvc_destructor(hdlp, id, dp);
4154 			return (PSVC_FAILURE);
4155 		}
4156 	}
4157 	if ((*objpp)->features & PSVC_HW_LOW_SHUT) {
4158 		if (i_psvc_value(buf, PSVC_HW_LO_SHUT_ATTR, &dp->hw_lo_shut)
4159 		    != PSVC_SUCCESS) {
4160 			i_psvc_destructor(hdlp, id, dp);
4161 			return (PSVC_FAILURE);
4162 		}
4163 	}
4164 	if ((*objpp)->features & PSVC_HW_HIGH_SHUT) {
4165 		if (i_psvc_value(buf, PSVC_HW_HI_SHUT_ATTR, &dp->hw_hi_shut)
4166 		    != PSVC_SUCCESS) {
4167 			i_psvc_destructor(hdlp, id, dp);
4168 			return (PSVC_FAILURE);
4169 		}
4170 	}
4171 
4172 	dp->ld.constructor = i_psvc_constructor_0_1;
4173 	dp->ld.destructor = i_psvc_destructor;
4174 	dp->ld.get_attr = i_psvc_get_attr_0_1;
4175 	dp->ld.set_attr = i_psvc_set_attr_0_1;
4176 
4177 	return (0);
4178 }
4179 
4180 /* Fan */
4181 static int32_t
4182 i_psvc_constructor_1_0(
4183 	EHdl_t	*hdlp,
4184 	char	*id,
4185 	EObj_t  **objpp)
4186 {
4187 	int32_t status;
4188 	char buf[BUFSZ];
4189 	EFan_t *dp;
4190 
4191 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4192 		sizeof (EFan_t));
4193 	if (status != PSVC_SUCCESS)
4194 		return (status);
4195 
4196 	/* Load class specific info */
4197 	dp = (EFan_t *)*objpp;
4198 	if (i_psvc_value(buf, PSVC_SETPOINT_ATTR, &dp->setpoint)
4199 	    != PSVC_SUCCESS) {
4200 		i_psvc_destructor(hdlp, id, dp);
4201 		return (PSVC_FAILURE);
4202 	}
4203 	if (i_psvc_value(buf, PSVC_HYSTERESIS_ATTR, &dp->hysteresis)
4204 	    != PSVC_SUCCESS) {
4205 		i_psvc_destructor(hdlp, id, dp);
4206 		return (PSVC_FAILURE);
4207 	}
4208 	if (i_psvc_value(buf, PSVC_LOOPGAIN_ATTR, &dp->loopgain)
4209 	    != PSVC_SUCCESS) {
4210 		i_psvc_destructor(hdlp, id, dp);
4211 		return (PSVC_FAILURE);
4212 	}
4213 	if (i_psvc_value(buf, PSVC_LOOPBIAS_ATTR, &dp->loopbias)
4214 	    != PSVC_SUCCESS) {
4215 		i_psvc_destructor(hdlp, id, dp);
4216 		return (PSVC_FAILURE);
4217 	}
4218 
4219 	dp->ld.constructor = i_psvc_constructor_1_0;
4220 	dp->ld.destructor = i_psvc_destructor;
4221 	dp->ld.get_attr = i_psvc_get_attr_1_0;
4222 	dp->ld.set_attr = i_psvc_set_attr_1_0;
4223 
4224 	return (PSVC_SUCCESS);
4225 }
4226 
4227 
4228 /* LED */
4229 static int32_t
4230 i_psvc_constructor_2_0(
4231 	EHdl_t	*hdlp,
4232 	char	*id,
4233 	EObj_t  **objpp)
4234 {
4235 	int32_t status;
4236 	char buf[BUFSZ];
4237 	ELed_t *dp;
4238 
4239 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4240 		sizeof (ELed_t));
4241 	if (status != PSVC_SUCCESS)
4242 		return (status);
4243 
4244 	/* Load class specific info */
4245 	dp = (ELed_t *)*objpp;
4246 
4247 	if (i_psvc_value(buf, PSVC_LED_COLOR_ATTR, dp->color)
4248 	    != PSVC_SUCCESS) {
4249 		i_psvc_destructor(hdlp, id, dp);
4250 		return (PSVC_FAILURE);
4251 	}
4252 
4253 	dp->ld.constructor = i_psvc_constructor_2_0;
4254 	dp->ld.destructor = i_psvc_destructor;
4255 	dp->ld.get_attr = i_psvc_get_attr_2_0;
4256 	dp->ld.set_attr = i_psvc_set_attr_2_0;
4257 
4258 	return (PSVC_SUCCESS);
4259 }
4260 
4261 static int32_t
4262 i_psvc_constructor_2_1(
4263 	EHdl_t	*hdlp,
4264 	char	*id,
4265 	EObj_t  **objpp)
4266 {
4267 	int32_t status;
4268 	char buf[BUFSZ];
4269 	ELed_t *dp;
4270 
4271 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4272 		sizeof (ELed_t));
4273 	if (status != PSVC_SUCCESS)
4274 		return (status);
4275 
4276 	/* Load class specific info */
4277 	dp = (ELed_t *)*objpp;
4278 
4279 	if (i_psvc_value(buf, PSVC_LED_COLOR_ATTR, dp->color)
4280 	    != PSVC_SUCCESS) {
4281 		i_psvc_destructor(hdlp, id, dp);
4282 		return (PSVC_FAILURE);
4283 	}
4284 
4285 	dp->ld.constructor = i_psvc_constructor_2_1;
4286 	dp->ld.destructor = i_psvc_destructor;
4287 	dp->ld.get_attr = i_psvc_get_attr_2_1;
4288 	dp->ld.set_attr = i_psvc_set_attr_2_1;
4289 
4290 	return (PSVC_SUCCESS);
4291 }
4292 
4293 static int32_t
4294 i_psvc_constructor_2_2(
4295 	EHdl_t	*hdlp,
4296 	char	*id,
4297 	EObj_t  **objpp)
4298 {
4299 	int32_t status;
4300 	char buf[BUFSZ];
4301 	ELed_t *dp;
4302 
4303 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4304 		sizeof (ELed_t));
4305 	if (status != PSVC_SUCCESS)
4306 		return (status);
4307 
4308 	/* Load class specific info */
4309 	dp = (ELed_t *)*objpp;
4310 
4311 	if (i_psvc_value(buf, PSVC_LED_COLOR_ATTR, dp->color)
4312 	    != PSVC_SUCCESS) {
4313 		i_psvc_destructor(hdlp, id, dp);
4314 		return (PSVC_FAILURE);
4315 	}
4316 	if (i_psvc_value(buf, PSVC_LED_IS_LOCATOR_ATTR, dp->is_locator)
4317 	    != PSVC_SUCCESS) {
4318 		i_psvc_destructor(hdlp, id, dp);
4319 		return (PSVC_FAILURE);
4320 	}
4321 	if (strcmp(dp->is_locator, PSVC_LOCATOR_TRUE) == 0) {
4322 		if (i_psvc_value(buf, PSVC_LED_LOCATOR_NAME_ATTR,
4323 		    dp->locator_name) != PSVC_SUCCESS) {
4324 			i_psvc_destructor(hdlp, id, dp);
4325 			return (PSVC_FAILURE);
4326 		}
4327 	} else {
4328 		strcpy(dp->locator_name, "N/A");
4329 	}
4330 
4331 	dp->ld.constructor = i_psvc_constructor_2_2;
4332 	dp->ld.destructor = i_psvc_destructor;
4333 	dp->ld.get_attr = i_psvc_get_attr_2_2;
4334 	dp->ld.set_attr = i_psvc_set_attr_2_0;
4335 
4336 	return (PSVC_SUCCESS);
4337 }
4338 
4339 /* System Device */
4340 static int32_t
4341 i_psvc_constructor_3_0(
4342 	EHdl_t	*hdlp,
4343 	char	*id,
4344 	EObj_t  **objpp)
4345 {
4346 	int32_t status;
4347 	char buf[BUFSZ];
4348 	ESystem_t *dp;
4349 
4350 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (ESystem_t));
4351 	if (status != PSVC_SUCCESS)
4352 		return (status);
4353 
4354 	/* Load class specific info */
4355 	dp = (ESystem_t *)*objpp;
4356 
4357 	dp->ld.constructor = i_psvc_constructor_3_0;
4358 	dp->ld.destructor = i_psvc_destructor;
4359 	dp->ld.get_attr = i_psvc_get_attr_generic;
4360 	dp->ld.set_attr = i_psvc_set_attr_generic;
4361 
4362 	return (PSVC_SUCCESS);
4363 }
4364 
4365 /* Digital Sensor */
4366 static int32_t
4367 i_psvc_constructor_4_0(
4368 	EHdl_t	*hdlp,
4369 	char	*id,
4370 	EObj_t  **objpp)
4371 {
4372 	int32_t status;
4373 	char buf[BUFSZ];
4374 	EDigiSensor_t *dp;
4375 
4376 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4377 		sizeof (EDigiSensor_t));
4378 	if (status != PSVC_SUCCESS) {
4379 		return (status);
4380 	}
4381 
4382 	/* Load class specific info */
4383 	dp = (EDigiSensor_t *)*objpp;
4384 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4385 	    != PSVC_SUCCESS) {
4386 		i_psvc_destructor(hdlp, id, dp);
4387 		return (PSVC_FAILURE);
4388 	}
4389 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4390 	    != PSVC_SUCCESS) {
4391 		i_psvc_destructor(hdlp, id, dp);
4392 		return (PSVC_FAILURE);
4393 	}
4394 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4395 	    != PSVC_SUCCESS) {
4396 		i_psvc_destructor(hdlp, id, dp);
4397 		return (PSVC_FAILURE);
4398 	}
4399 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4400 	    != PSVC_SUCCESS) {
4401 		i_psvc_destructor(hdlp, id, dp);
4402 		return (PSVC_FAILURE);
4403 	}
4404 
4405 	dp->ld.constructor = i_psvc_constructor_4_0;
4406 	dp->ld.destructor = i_psvc_destructor;
4407 	dp->ld.get_attr = i_psvc_get_attr_4_0;
4408 	dp->ld.set_attr = i_psvc_set_attr_generic;
4409 
4410 	return (PSVC_SUCCESS);
4411 }
4412 
4413 /* Digital Control */
4414 static int32_t
4415 i_psvc_constructor_5_0(
4416 	EHdl_t	*hdlp,
4417 	char	*id,
4418 	EObj_t  **objpp)
4419 {
4420 	int32_t status;
4421 	char buf[BUFSZ];
4422 	EDigiControl_t *dp;
4423 
4424 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4425 		sizeof (EDigiControl_t));
4426 	if (status != PSVC_SUCCESS)
4427 		return (status);
4428 
4429 	/* Load class specific info */
4430 	dp = (EDigiControl_t *)*objpp;
4431 
4432 	dp->ld.constructor = i_psvc_constructor_5_0;
4433 	dp->ld.destructor = i_psvc_destructor;
4434 	dp->ld.get_attr = i_psvc_get_attr_5_0;
4435 	dp->ld.set_attr = i_psvc_set_attr_5_0;
4436 	return (PSVC_SUCCESS);
4437 }
4438 
4439 /* Boolean GPIO */
4440 static int32_t
4441 i_psvc_constructor_6_0(
4442 	EHdl_t	*hdlp,
4443 	char	*id,
4444 	EObj_t  **objpp)
4445 {
4446 	int32_t status;
4447 	char buf[BUFSZ];
4448 	EBoolSensor_t *dp;
4449 
4450 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4451 		sizeof (EBoolSensor_t));
4452 	if (status != PSVC_SUCCESS)
4453 		return (status);
4454 
4455 	/* Load class specific info */
4456 	dp = (EBoolSensor_t *)*objpp;
4457 
4458 	dp->ld.constructor = i_psvc_constructor_6_0;
4459 	dp->ld.destructor = i_psvc_destructor;
4460 	dp->ld.get_attr = i_psvc_get_attr_6_0;
4461 	dp->ld.set_attr = i_psvc_set_attr_6_0;
4462 
4463 	return (PSVC_SUCCESS);
4464 }
4465 
4466 /* Fan Tachometer */
4467 static int32_t
4468 i_psvc_constructor_7_0(
4469 	EHdl_t	*hdlp,
4470 	char	*id,
4471 	EObj_t  **objpp)
4472 {
4473 	int32_t status;
4474 	char buf[BUFSZ];
4475 	EFanTach_t *dp;
4476 
4477 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4478 		sizeof (EFanTach_t));
4479 	if (status != PSVC_SUCCESS)
4480 		return (status);
4481 
4482 	/* Load class specific info */
4483 	dp = (EFanTach_t *)*objpp;
4484 	if (i_psvc_value(buf, PSVC_LO_WARN_ATTR, &dp->lo_warn)
4485 	    != PSVC_SUCCESS) {
4486 		i_psvc_destructor(hdlp, id, dp);
4487 		return (PSVC_FAILURE);
4488 	}
4489 	if (i_psvc_value(buf, PSVC_LO_SHUT_ATTR, &dp->lo_shut)
4490 	    != PSVC_SUCCESS) {
4491 		i_psvc_destructor(hdlp, id, dp);
4492 		return (PSVC_FAILURE);
4493 	}
4494 	if (i_psvc_value(buf, PSVC_HI_WARN_ATTR, &dp->hi_warn)
4495 	    != PSVC_SUCCESS) {
4496 		i_psvc_destructor(hdlp, id, dp);
4497 		return (PSVC_FAILURE);
4498 	}
4499 	if (i_psvc_value(buf, PSVC_HI_SHUT_ATTR, &dp->hi_shut)
4500 	    != PSVC_SUCCESS) {
4501 		i_psvc_destructor(hdlp, id, dp);
4502 		return (PSVC_FAILURE);
4503 	}
4504 
4505 	dp->ld.constructor = i_psvc_constructor_7_0;
4506 	dp->ld.destructor = i_psvc_destructor;
4507 	dp->ld.get_attr = i_psvc_get_attr_7_0;
4508 	dp->ld.set_attr = i_psvc_set_attr_generic;
4509 
4510 	return (PSVC_SUCCESS);
4511 }
4512 
4513 /* On Off Switch */
4514 static int32_t
4515 i_psvc_constructor_8_0(
4516 	EHdl_t	*hdlp,
4517 	char	*id,
4518 	EObj_t  **objpp)
4519 {
4520 	int32_t status;
4521 	char buf[BUFSZ];
4522 	ESwitch_t *dp;
4523 
4524 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4525 		sizeof (ESwitch_t));
4526 	if (status != PSVC_SUCCESS)
4527 		return (status);
4528 
4529 	/* Load class specific info */
4530 	dp = (ESwitch_t *)*objpp;
4531 
4532 	dp->ld.constructor = i_psvc_constructor_8_0;
4533 	dp->ld.destructor = i_psvc_destructor;
4534 	dp->ld.get_attr = i_psvc_get_attr_8_0;
4535 	dp->ld.set_attr = i_psvc_set_attr_8_0;
4536 
4537 	return (PSVC_SUCCESS);
4538 }
4539 
4540 /* Key Switch */
4541 static int32_t
4542 i_psvc_constructor_9_0(
4543 	EHdl_t	*hdlp,
4544 	char	*id,
4545 	EObj_t  **objpp)
4546 {
4547 	int32_t status;
4548 	char buf[BUFSZ];
4549 	EKeySwitch_t *dp;
4550 
4551 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4552 		sizeof (EKeySwitch_t));
4553 	if (status != PSVC_SUCCESS)
4554 		return (status);
4555 
4556 	/* Load class specific info */
4557 	dp = (EKeySwitch_t *)*objpp;
4558 
4559 	dp->ld.constructor = i_psvc_constructor_9_0;
4560 	dp->ld.destructor = i_psvc_destructor;
4561 	dp->ld.get_attr = i_psvc_get_attr_9_0;
4562 	dp->ld.set_attr = i_psvc_set_attr_generic;
4563 
4564 	return (PSVC_SUCCESS);
4565 }
4566 
4567 /* 8 Bit GPIO , devices with registers, calls get_reg()/set_reg() */
4568 static int32_t
4569 i_psvc_constructor_10_0(
4570 	EHdl_t	*hdlp,
4571 	char	*id,
4572 	EObj_t  **objpp)
4573 {
4574 	int32_t status;
4575 	char buf[BUFSZ];
4576 	EGPIO8_t *dp;
4577 
4578 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EGPIO8_t));
4579 	if (status != PSVC_SUCCESS)
4580 		return (status);
4581 
4582 	/* Load class specific info */
4583 	dp = (EGPIO8_t *)*objpp;
4584 
4585 	dp->ld.constructor = i_psvc_constructor_10_0;
4586 	dp->ld.destructor = i_psvc_destructor;
4587 	dp->ld.get_attr = i_psvc_get_attr_10_0;
4588 	dp->ld.set_attr = i_psvc_set_attr_10_0;
4589 
4590 	return (PSVC_SUCCESS);
4591 }
4592 
4593 /* 8 Bit GPIO , devices with ports, calls get_port()/set_port() */
4594 static int32_t
4595 i_psvc_constructor_10_1(
4596 	EHdl_t	*hdlp,
4597 	char	*id,
4598 	EObj_t  **objpp)
4599 {
4600 	int32_t status;
4601 	char buf[BUFSZ];
4602 	EGPIO8_t *dp;
4603 
4604 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EGPIO8_t));
4605 	if (status != PSVC_SUCCESS)
4606 		return (status);
4607 
4608 	/* Load class specific info */
4609 	dp = (EGPIO8_t *)*objpp;
4610 
4611 	dp->ld.constructor = i_psvc_constructor_10_1;
4612 	dp->ld.destructor = i_psvc_destructor;
4613 	dp->ld.get_attr = i_psvc_get_attr_10_1;
4614 	dp->ld.set_attr = i_psvc_set_attr_10_1;
4615 
4616 	return (PSVC_SUCCESS);
4617 }
4618 
4619 /* AT24 */
4620 static int32_t
4621 i_psvc_constructor_11_0(
4622 	EHdl_t	*hdlp,
4623 	char	*id,
4624 	EObj_t  **objpp)
4625 {
4626 	int32_t status;
4627 	char buf[BUFSZ];
4628 	EPhysDev_t *dp;
4629 
4630 	status = i_psvc_load_generic(hdlp, id, objpp, buf,
4631 		sizeof (EPhysDev_t));
4632 	if (status != PSVC_SUCCESS)
4633 		return (status);
4634 
4635 	/* Load class specific info */
4636 	dp = (EPhysDev_t *)*objpp;
4637 
4638 	dp->ld.constructor = i_psvc_constructor_11_0;
4639 	dp->ld.destructor = i_psvc_destructor;
4640 	dp->ld.get_attr = i_psvc_get_attr_11_0;
4641 	dp->ld.set_attr = i_psvc_set_attr_generic;
4642 	dp->get_temperature = i_psvc_not_supported;
4643 	dp->get_fanspeed = i_psvc_not_supported;
4644 	dp->get_input = i_psvc_not_supported;
4645 	dp->get_bit = i_psvc_not_supported;
4646 	dp->set_bit = i_psvc_not_supported;
4647 	dp->get_port = i_psvc_not_supported;
4648 	dp->set_port = i_psvc_not_supported;
4649 	dp->get_output = i_psvc_not_supported;
4650 	dp->set_output = i_psvc_not_supported;
4651 	dp->get_reg = i_psvc_get_reg_11_0;
4652 	dp->set_reg = i_psvc_not_supported;
4653 
4654 	return (PSVC_SUCCESS);
4655 }
4656 
4657 /* HPC3130 */
4658 static int32_t
4659 i_psvc_constructor_11_1(
4660 	EHdl_t	*hdlp,
4661 	char	*id,
4662 	EObj_t  **objpp)
4663 {
4664 	int32_t status;
4665 	char buf[BUFSZ];
4666 	EPhysDev_t *dp;
4667 
4668 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4669 	if (status != PSVC_SUCCESS)
4670 		return (status);
4671 
4672 	/* Load class specific info */
4673 	dp = (EPhysDev_t *)*objpp;
4674 
4675 	dp->ld.constructor = i_psvc_constructor_11_1;
4676 	dp->ld.destructor = i_psvc_destructor;
4677 	dp->ld.get_attr = i_psvc_get_attr_11_1;
4678 	dp->ld.set_attr = i_psvc_set_attr_generic;
4679 	dp->get_temperature = i_psvc_not_supported;
4680 	dp->get_fanspeed = i_psvc_not_supported;
4681 	dp->get_input = i_psvc_not_supported;
4682 	dp->get_bit = i_psvc_not_supported;
4683 	dp->set_bit = i_psvc_not_supported;
4684 	dp->get_port = i_psvc_not_supported;
4685 	dp->set_port = i_psvc_not_supported;
4686 	dp->get_output = i_psvc_not_supported;
4687 	dp->set_output = i_psvc_not_supported;
4688 	dp->get_reg = i_psvc_get_reg_11_1;
4689 	dp->set_reg = i_psvc_set_reg_11_1;
4690 
4691 	return (PSVC_SUCCESS);
4692 }
4693 
4694 /* LM75 */
4695 static int32_t
4696 i_psvc_constructor_11_2(
4697 	EHdl_t	*hdlp,
4698 	char	*id,
4699 	EObj_t  **objpp)
4700 {
4701 	int32_t status;
4702 	char buf[BUFSZ];
4703 	EPhysDev_t *dp;
4704 
4705 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4706 	if (status != PSVC_SUCCESS)
4707 		return (status);
4708 
4709 	/* Load class specific info */
4710 	dp = (EPhysDev_t *)*objpp;
4711 
4712 	dp->ld.constructor = i_psvc_constructor_11_2;
4713 	dp->ld.destructor = i_psvc_destructor;
4714 	dp->ld.get_attr = i_psvc_get_attr_11_2;
4715 	dp->ld.set_attr = i_psvc_set_attr_generic;
4716 	dp->get_temperature = i_psvc_get_temperature_11_2;
4717 	dp->get_fanspeed = i_psvc_not_supported;
4718 	dp->get_input = i_psvc_not_supported;
4719 	dp->get_bit = i_psvc_not_supported;
4720 	dp->set_bit = i_psvc_not_supported;
4721 	dp->get_port = i_psvc_not_supported;
4722 	dp->set_port = i_psvc_not_supported;
4723 	dp->get_output = i_psvc_not_supported;
4724 	dp->set_output = i_psvc_not_supported;
4725 	dp->get_reg = i_psvc_not_supported;
4726 	dp->set_reg = i_psvc_not_supported;
4727 
4728 	return (PSVC_SUCCESS);
4729 }
4730 
4731 /* LTC1427 */
4732 static int32_t
4733 i_psvc_constructor_11_3(
4734 	EHdl_t	*hdlp,
4735 	char	*id,
4736 	EObj_t  **objpp)
4737 {
4738 	int32_t status;
4739 	char buf[BUFSZ];
4740 	EPhysDev_t *dp;
4741 	char path[1024];
4742 
4743 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4744 	if (status != PSVC_SUCCESS)
4745 		return (status);
4746 
4747 	/*
4748 	 * The following code upto and including the open() call is so the
4749 	 * device driver for the ltc1427 does not get unloaded by the OS at
4750 	 * any time. This is important as the device driver is a write only
4751 	 * physical device but DOES keep readable states in the device unitp
4752 	 * structure (I2C_GET_OUTPUT) as a result this device should not
4753 	 * be unload while PSVC is up and running
4754 	 */
4755 	status = i_psvc_get_devpath(hdlp, (*objpp)->addr_spec, path);
4756 	if (status != PSVC_SUCCESS) {
4757 		return (status);
4758 	}
4759 
4760 	/*
4761 	 * We deliberately do not close our file handle, to prevent
4762 	 * any device instances from being detached.  If an instance
4763 	 * is detached, the "readable states in the device unitp"
4764 	 * will be unloaded, causing loss of control of the device
4765 	 * and incorrect error(s) to be displayed.
4766 	 */
4767 	if (open(path, O_RDWR) == -1) {
4768 		return (PSVC_FAILURE);
4769 	}
4770 	/* Load class specific info */
4771 	dp = (EPhysDev_t *)*objpp;
4772 
4773 	dp->ld.constructor = i_psvc_constructor_11_3;
4774 	dp->ld.destructor = i_psvc_destructor;
4775 	dp->ld.get_attr = i_psvc_get_attr_11_3;
4776 	dp->ld.set_attr = i_psvc_set_attr_generic;
4777 	dp->get_temperature = i_psvc_not_supported;
4778 	dp->get_fanspeed = i_psvc_not_supported;
4779 	dp->get_input = i_psvc_not_supported;
4780 	dp->get_bit = i_psvc_not_supported;
4781 	dp->set_bit = i_psvc_not_supported;
4782 	dp->get_port = i_psvc_not_supported;
4783 	dp->set_port = i_psvc_not_supported;
4784 	dp->get_output = i_psvc_get_output_11_3;
4785 	dp->set_output = i_psvc_set_output_11_3;
4786 	dp->get_reg = i_psvc_not_supported;
4787 	dp->set_reg = i_psvc_not_supported;
4788 
4789 	return (PSVC_SUCCESS);
4790 }
4791 
4792 /* MAX1617 */
4793 static int32_t
4794 i_psvc_constructor_11_4(
4795 	EHdl_t	*hdlp,
4796 	char	*id,
4797 	EObj_t  **objpp)
4798 {
4799 	int32_t status;
4800 	char buf[BUFSZ];
4801 	EPhysDev_t *dp;
4802 
4803 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4804 	if (status != PSVC_SUCCESS)
4805 		return (status);
4806 
4807 	/* Load class specific info */
4808 	dp = (EPhysDev_t *)*objpp;
4809 
4810 	dp->ld.constructor = i_psvc_constructor_11_4;
4811 	dp->ld.destructor = i_psvc_destructor;
4812 	dp->ld.get_attr = i_psvc_get_attr_11_4;
4813 	dp->ld.set_attr = i_psvc_set_attr_generic;
4814 	dp->get_temperature = i_psvc_get_temperature_11_4;
4815 	dp->get_fanspeed = i_psvc_not_supported;
4816 	dp->get_input = i_psvc_not_supported;
4817 	dp->get_bit = i_psvc_not_supported;
4818 	dp->set_bit = i_psvc_not_supported;
4819 	dp->get_port = i_psvc_not_supported;
4820 	dp->set_port = i_psvc_not_supported;
4821 	dp->get_output = i_psvc_not_supported;
4822 	dp->set_output = i_psvc_not_supported;
4823 	dp->get_reg = i_psvc_not_supported;
4824 	dp->set_reg = i_psvc_not_supported;
4825 
4826 	return (PSVC_SUCCESS);
4827 }
4828 
4829 /* PCF8574 */
4830 static int32_t
4831 i_psvc_constructor_11_5(
4832 	EHdl_t	*hdlp,
4833 	char	*id,
4834 	EObj_t  **objpp)
4835 {
4836 	int32_t status;
4837 	char buf[BUFSZ];
4838 	EPhysDev_t *dp;
4839 
4840 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4841 	if (status != PSVC_SUCCESS)
4842 		return (status);
4843 
4844 	/* Load class specific info */
4845 	dp = (EPhysDev_t *)*objpp;
4846 
4847 	dp->ld.constructor = i_psvc_constructor_11_5;
4848 	dp->ld.destructor = i_psvc_destructor;
4849 	dp->ld.get_attr = i_psvc_get_attr_11_5;
4850 	dp->ld.set_attr = i_psvc_set_attr_generic;
4851 	dp->get_temperature = i_psvc_not_supported;
4852 	dp->get_fanspeed = i_psvc_not_supported;
4853 	dp->get_input = i_psvc_not_supported;
4854 	dp->get_bit = i_psvc_get_bit_11_5;
4855 	dp->set_bit = i_psvc_set_bit_11_5;
4856 	dp->get_port = i_psvc_get_port_11_5;
4857 	dp->set_port = i_psvc_set_port_11_5;
4858 	dp->get_output = i_psvc_not_supported;
4859 	dp->set_output = i_psvc_not_supported;
4860 	dp->get_reg = i_psvc_not_supported;
4861 	dp->set_reg = i_psvc_not_supported;
4862 
4863 	return (PSVC_SUCCESS);
4864 }
4865 
4866 /* PCF8591 */
4867 static int32_t
4868 i_psvc_constructor_11_6(
4869 	EHdl_t	*hdlp,
4870 	char	*id,
4871 	EObj_t  **objpp)
4872 {
4873 	int32_t status;
4874 	char buf[BUFSZ];
4875 	EPhysDev_t *dp;
4876 
4877 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4878 	if (status != PSVC_SUCCESS)
4879 		return (status);
4880 
4881 	/* Load class specific info */
4882 	dp = (EPhysDev_t *)*objpp;
4883 
4884 	dp->ld.constructor = i_psvc_constructor_11_6;
4885 	dp->ld.destructor = i_psvc_destructor;
4886 	dp->ld.get_attr = i_psvc_get_attr_11_6;
4887 	dp->ld.set_attr = i_psvc_set_attr_generic;
4888 	dp->get_temperature = i_psvc_get_temperature_11_6;
4889 	dp->get_fanspeed = i_psvc_not_supported;
4890 	dp->get_input = i_psvc_get_input_11_6;
4891 	dp->get_bit = i_psvc_not_supported;
4892 	dp->set_bit = i_psvc_not_supported;
4893 	dp->get_port = i_psvc_not_supported;
4894 	dp->set_port = i_psvc_not_supported;
4895 	dp->get_output = i_psvc_get_output_11_6;
4896 	dp->set_output = i_psvc_set_output_11_6;
4897 	dp->get_reg = i_psvc_not_supported;
4898 	dp->set_reg = i_psvc_not_supported;
4899 
4900 	return (PSVC_SUCCESS);
4901 }
4902 
4903 /* SSC050 */
4904 static int32_t
4905 i_psvc_constructor_11_7(
4906 	EHdl_t	*hdlp,
4907 	char	*id,
4908 	EObj_t  **objpp)
4909 {
4910 	int32_t status;
4911 	char buf[BUFSZ];
4912 	EPhysDev_t *dp;
4913 
4914 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4915 	if (status != PSVC_SUCCESS)
4916 		return (status);
4917 
4918 	/* Load class specific info */
4919 	dp = (EPhysDev_t *)*objpp;
4920 
4921 	dp->ld.constructor = i_psvc_constructor_11_7;
4922 	dp->ld.destructor = i_psvc_destructor;
4923 	dp->ld.get_attr = i_psvc_get_attr_11_7;
4924 	dp->ld.set_attr = i_psvc_set_attr_generic;
4925 	dp->get_temperature = i_psvc_not_supported;
4926 	dp->get_fanspeed = i_psvc_get_fanspeed_11_7;
4927 	dp->get_input = i_psvc_not_supported;
4928 	dp->get_bit = i_psvc_get_bit_11_7;
4929 	dp->set_bit = i_psvc_set_bit_11_7;
4930 	dp->get_port = i_psvc_get_port_11_5;	/* same as for class = 11, 5 */
4931 	dp->set_port = i_psvc_set_port_11_5;
4932 	dp->get_output = i_psvc_not_supported;
4933 	dp->set_output = i_psvc_not_supported;
4934 	dp->get_reg = i_psvc_get_reg_11_7;
4935 	dp->set_reg = i_psvc_set_reg_11_7;
4936 
4937 	return (PSVC_SUCCESS);
4938 }
4939 
4940 /* TDA8444 */
4941 static int32_t
4942 i_psvc_constructor_11_8(
4943 	EHdl_t	*hdlp,
4944 	char	*id,
4945 	EObj_t  **objpp)
4946 {
4947 	int32_t status;
4948 	char buf[BUFSZ];
4949 	EPhysDev_t *dp;
4950 
4951 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4952 	if (status != PSVC_SUCCESS)
4953 		return (status);
4954 
4955 	/* Load class specific info */
4956 	dp = (EPhysDev_t *)*objpp;
4957 
4958 	dp->ld.constructor = i_psvc_constructor_11_8;
4959 	dp->ld.destructor = i_psvc_destructor;
4960 	dp->ld.get_attr = i_psvc_get_attr_11_8;
4961 	dp->ld.set_attr = i_psvc_set_attr_generic;
4962 	dp->get_temperature = i_psvc_not_supported;
4963 	dp->get_fanspeed = i_psvc_not_supported;
4964 	dp->get_input = i_psvc_not_supported;
4965 	dp->get_bit = i_psvc_not_supported;
4966 	dp->set_bit = i_psvc_not_supported;
4967 	dp->get_port = i_psvc_not_supported;
4968 	dp->set_port = i_psvc_not_supported;
4969 	dp->get_output = i_psvc_get_output_11_8;
4970 	dp->set_output = i_psvc_set_output_11_8;
4971 	dp->get_reg = i_psvc_not_supported;
4972 	dp->set_reg = i_psvc_not_supported;
4973 
4974 	return (PSVC_SUCCESS);
4975 }
4976 
4977 /* SSC100 */
4978 static int32_t
4979 i_psvc_constructor_11_9(
4980 	EHdl_t	*hdlp,
4981 	char	*id,
4982 	EObj_t  **objpp)
4983 {
4984 	int32_t status;
4985 	char buf[BUFSZ];
4986 	EPhysDev_t *dp;
4987 
4988 	status = i_psvc_load_generic(hdlp, id, objpp, buf, sizeof (EPhysDev_t));
4989 	if (status != PSVC_SUCCESS)
4990 		return (status);
4991 
4992 	/* Load class specific info */
4993 	dp = (EPhysDev_t *)*objpp;
4994 
4995 	dp->ld.constructor = i_psvc_constructor_11_9;
4996 	dp->ld.destructor = i_psvc_destructor;
4997 	dp->ld.get_attr = i_psvc_get_attr_11_9;
4998 	dp->ld.set_attr = i_psvc_set_attr_generic;
4999 	dp->get_temperature = i_psvc_not_supported;
5000 	dp->get_fanspeed = i_psvc_not_supported;
5001 	dp->get_input = i_psvc_not_supported;
5002 	dp->get_bit = i_psvc_not_supported;
5003 	dp->set_bit = i_psvc_not_supported;
5004 	dp->get_port = i_psvc_get_port_11_5;	/* Same as for class = 11, 5 */
5005 	dp->set_port = i_psvc_set_port_11_5;
5006 	dp->get_output = i_psvc_not_supported;
5007 	dp->set_output = i_psvc_not_supported;
5008 	dp->get_reg = i_psvc_not_supported;
5009 	dp->set_reg = i_psvc_not_supported;
5010 
5011 	return (PSVC_SUCCESS);
5012 }
5013 
5014 int32_t
5015 psvc_init(EHdl_t **hdlpp)
5016 {
5017 	EHdl_t *hdlp;
5018 	int    i;
5019 	char   buf[BUFSZ];
5020 	char   platform[32];
5021 	char   filename[256];
5022 	int    found;
5023 	int32_t status;
5024 	pthread_mutexattr_t mutex_attr;
5025 	uint32_t table_count;
5026 	int	forward_slash = 47;
5027 	int	new_line = 10;
5028 	char	*nl_char;
5029 
5030 	hdlp = (EHdl_t *)malloc(sizeof (EHdl_t));
5031 	if (hdlp == NULL)
5032 		return (-1);
5033 	memset(hdlp, 0, sizeof (EHdl_t));
5034 
5035 	/* Initialize the lock */
5036 	status = pthread_mutexattr_init(&mutex_attr);
5037 	if (status != 0) {
5038 		errno = status;
5039 		return (-1);
5040 	}
5041 	status = pthread_mutex_init(&hdlp->mutex, &mutex_attr);
5042 	if (status != 0) {
5043 		errno = status;
5044 		return (-1);
5045 	}
5046 	pthread_mutexattr_destroy(&mutex_attr);
5047 
5048 	if (sysinfo(SI_PLATFORM, platform, sizeof (platform)) == -1) {
5049 		return (-1);
5050 	}
5051 
5052 	snprintf(filename, sizeof (filename),
5053 	    "/usr/platform/%s/lib/psvcobj.conf", platform);
5054 	if ((hdlp->fp = fopen(filename, "r")) == NULL) {
5055 		return (-1);
5056 	}
5057 
5058 
5059 	/* Build the association ID lookup table */
5060 
5061 	hdlp->othr_count = hdlp->assoc_count = ASSOC_STR_TAB_SIZE;
5062 	if ((hdlp->othr_tbl = (EStringId_t *)malloc(sizeof (EStringId_t) *
5063 		hdlp->othr_count)) == NULL) {
5064 		return (-1);
5065 	}
5066 
5067 	for (i = 0; i < hdlp->othr_count; ++i) {
5068 		hdlp->othr_tbl[i].id = i;
5069 		strcpy(hdlp->othr_tbl[i].name, assoc_str_tab[i]);
5070 	}
5071 	qsort(hdlp->othr_tbl, hdlp->othr_count, sizeof (EStringId_t),
5072 		(int (*)(const void *, const void *))i_psvc_name_compare_qsort);
5073 
5074 	/* determine total number of objects + tables */
5075 	if (i_psvc_find_file_section(hdlp->fp, "OBJECT_INFO") == -1) {
5076 		return (-1);
5077 	}
5078 	if (i_psvc_count_records(hdlp->fp, "OBJECT_INFO_END",
5079 		&hdlp->total_obj_count) == -1) {
5080 		return (-1);
5081 	}
5082 	if (i_psvc_find_file_section(hdlp->fp, "TABLES") == PSVC_SUCCESS) {
5083 		status = i_psvc_count_tables_associations(hdlp->fp,
5084 			&table_count, "TABLE_END");
5085 		if (status == PSVC_FAILURE) {
5086 			return (status);
5087 		}
5088 		hdlp->total_obj_count += table_count;
5089 	}
5090 
5091 	/* Allocate object name to object pointer translation table */
5092 	for (i = 0; i < PSVC_MAX_TABLE_ARRAYS; i++) {
5093 		if ((hdlp->tbl_arry[i].obj_tbl =
5094 			(ENamePtr_t *)malloc(
5095 		sizeof (ENamePtr_t) *hdlp->total_obj_count)) == NULL) {
5096 			return (-1);
5097 		}
5098 		memset(hdlp->tbl_arry[i].obj_tbl, 0,
5099 		    sizeof (ENamePtr_t) * hdlp->total_obj_count);
5100 		hdlp->tbl_arry[i].obj_count = 0;
5101 	}
5102 
5103 	/* Build the association table */
5104 	if (i_psvc_load_associations(hdlp, hdlp->fp) == -1)
5105 		return (-1);
5106 
5107 	/* Build the table of device paths */
5108 	if (i_psvc_find_file_section(hdlp->fp, "DEVPATHS") == -1)
5109 		return (-1);
5110 	if (i_psvc_count_records(hdlp->fp, "DEVPATHS_END",
5111 		&hdlp->dev_count) == -1)
5112 		return (-1);
5113 	if ((hdlp->dev_tbl = (EDevice_t *)malloc(sizeof (EDevice_t) *
5114 		hdlp->dev_count)) == NULL) {
5115 		return (-1);
5116 	}
5117 	for (i = 0; i < hdlp->dev_count; ++i) {
5118 		fgets(buf, BUFSZ, hdlp->fp);
5119 		found = sscanf(buf, "%d %d %x %d",
5120 			&hdlp->dev_tbl[i].controller,
5121 			&hdlp->dev_tbl[i].bus, &hdlp->dev_tbl[i].addr,
5122 			&hdlp->dev_tbl[i].port);
5123 		if (found != 4) {
5124 			errno = EINVAL;
5125 			return (-1);
5126 		}
5127 		strcpy(hdlp->dev_tbl[i].path, strchr(buf, forward_slash));
5128 		/*
5129 		 * Replace new line character with NUL character
5130 		 */
5131 		nl_char = strchr(hdlp->dev_tbl[i].path, new_line);
5132 		*nl_char = 0;
5133 	}
5134 
5135 	/* Build the table of tables */
5136 	if (i_psvc_load_tables(hdlp, hdlp->fp) == -1)
5137 		return (-1);
5138 	*hdlpp = hdlp;
5139 	return (0);
5140 }
5141 
5142 int32_t
5143 psvc_fini(EHdl_t *hdlp)
5144 {
5145 	int32_t i, j;
5146 	ETable_Array *array;
5147 
5148 	if (hdlp == 0)
5149 		return (PSVC_SUCCESS);
5150 
5151 	for (j = 0; j < PSVC_MAX_TABLE_ARRAYS; j++) {
5152 		if (hdlp->tbl_arry[j].obj_tbl != 0) {
5153 			array = &(hdlp->tbl_arry[j]);
5154 			for (i = 0; i < array->obj_count; ++i) {
5155 				if (array->obj_tbl[i].type == PSVC_OBJ) {
5156 					if (!array->obj_tbl[i].objp) {
5157 						/* Skip non-existent object */
5158 						continue;
5159 					}
5160 					array->obj_tbl[i].objp->destructor(hdlp,
5161 					    array->obj_tbl[i].objp->label,
5162 					    array->obj_tbl[i].objp);
5163 				}
5164 
5165 				if (array->obj_tbl[i].type == PSVC_TBL) {
5166 					ETable_t *tblp =
5167 					    (ETable_t *)array->obj_tbl[i].objp;
5168 					if (tblp->table != 0)
5169 						free(tblp->table);
5170 				}
5171 			}
5172 
5173 			free(array->obj_tbl);
5174 		}
5175 	}
5176 
5177 	if (hdlp->othr_tbl != 0)
5178 		free(hdlp->othr_tbl);
5179 
5180 	if (hdlp->assoc_tbl != 0) {
5181 		for (i = 0; i < hdlp->assoc_count; ++i) {
5182 			if (hdlp->assoc_tbl[i].table != 0)
5183 				free(hdlp->assoc_tbl[i].table);
5184 		}
5185 		free(hdlp->assoc_tbl);
5186 	}
5187 
5188 	if (hdlp->dev_tbl != 0)
5189 		free(hdlp->dev_tbl);
5190 	if (hdlp->fp != 0)
5191 		fclose(hdlp->fp);
5192 	pthread_mutex_destroy(&hdlp->mutex);
5193 	free(hdlp);
5194 	return (PSVC_SUCCESS);
5195 }
5196 
5197 int32_t
5198 ioctl_retry(int fp, int request, void * arg_pointer)
5199 {
5200 	int32_t ret = PSVC_SUCCESS;
5201 	int32_t tries = 0;
5202 
5203 	/*
5204 	 * Becuase the i2c bus is a multimaster bus we need to protect
5205 	 * ourselves from bus masters that are not being good bus citizens.
5206 	 * A retry number of 10 should be sufficient to handle any bad bus
5207 	 * citizens.  After that we will simply say that there is something
5208 	 * wrong with the ioctl transaction and let it bubble back up.
5209 	 */
5210 	do {
5211 		ret = ioctl(fp, request, arg_pointer);
5212 		tries ++;
5213 	} while ((ret == -1) && (tries < 10));
5214 
5215 	return (ret);
5216 }
5217 
5218 static int32_t
5219 psvc_get_str_key(char *object)
5220 {
5221 	int32_t key = 0;
5222 	int i, length;
5223 
5224 	length = strlen(object);
5225 	for (i = 0; i < length; i++) {
5226 		if ((object[i] > 47) && (object[i] < 58)) {
5227 			key = key + ((object[i] - 50) + 2);
5228 		} else {
5229 			key = key + object[i];
5230 		}
5231 	}
5232 
5233 
5234 	return (key);
5235 }
5236