xref: /titanic_50/usr/src/cmd/sf880drd/sf880drd.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2000, 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
29*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/i2c/clients/i2c_client.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/hpc3130_events.h>
33*7c478bd9Sstevel@tonic-gate #include <values.h>		/* for BITSPERBYTE */
34*7c478bd9Sstevel@tonic-gate #include <unistd.h>
35*7c478bd9Sstevel@tonic-gate #include <stdio.h>
36*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
37*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
38*7c478bd9Sstevel@tonic-gate #include <strings.h>
39*7c478bd9Sstevel@tonic-gate #include <poll.h>
40*7c478bd9Sstevel@tonic-gate #include <libintl.h>
41*7c478bd9Sstevel@tonic-gate #include <errno.h>
42*7c478bd9Sstevel@tonic-gate #include <assert.h>
43*7c478bd9Sstevel@tonic-gate #include <config_admin.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/daktari.h>
45*7c478bd9Sstevel@tonic-gate #include "sf880drd.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate /*
48*7c478bd9Sstevel@tonic-gate  * Hotplug Controller addresses.
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate static const unsigned char controller_names[NUM_CONTROLLERS] =
51*7c478bd9Sstevel@tonic-gate 	{ 0xe2, 0xe6, 0xe8, 0xec };
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #define	INDEX2SLOT(INDEX)	((INDEX)%4) /* cf init_poll_events() */
54*7c478bd9Sstevel@tonic-gate #define	INDEX2CONTROLLER(INDEX)	((INDEX)/4) /* cf init_poll_events() */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  *  Local variables.
58*7c478bd9Sstevel@tonic-gate  */
59*7c478bd9Sstevel@tonic-gate static struct pollfd fds[NUM_FDS];
60*7c478bd9Sstevel@tonic-gate static unsigned int fault_leds[2];
61*7c478bd9Sstevel@tonic-gate static unsigned int ok2rem_leds[2];
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate /*
64*7c478bd9Sstevel@tonic-gate  *  Local prototypes.
65*7c478bd9Sstevel@tonic-gate  */
66*7c478bd9Sstevel@tonic-gate static void init_poll_events(void);
67*7c478bd9Sstevel@tonic-gate static void process_event(int);
68*7c478bd9Sstevel@tonic-gate static void report_cfgadm_error(int, char *);
69*7c478bd9Sstevel@tonic-gate static void set_front_panel_led(uint8_t, boolean_t);
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static int i2c_set_bit(int, int, uint8_t);
72*7c478bd9Sstevel@tonic-gate static void report_syscall_error(char *);
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate static void pushbutton_event(char *);
75*7c478bd9Sstevel@tonic-gate static void fault_led_event(hpc3130_event_type_t, int);
76*7c478bd9Sstevel@tonic-gate static void removable_led_event(hpc3130_event_type_t, int);
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate /*
79*7c478bd9Sstevel@tonic-gate  * main(): loops forever looking for events.
80*7c478bd9Sstevel@tonic-gate  */
81*7c478bd9Sstevel@tonic-gate int
main()82*7c478bd9Sstevel@tonic-gate main()
83*7c478bd9Sstevel@tonic-gate {
84*7c478bd9Sstevel@tonic-gate 	int	i;
85*7c478bd9Sstevel@tonic-gate 	int	rv;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	init_poll_events();
88*7c478bd9Sstevel@tonic-gate 	for (;;) {
89*7c478bd9Sstevel@tonic-gate 		/* sleep in poll() waiting an event */
90*7c478bd9Sstevel@tonic-gate 		rv = poll(fds, NUM_FDS, -1);
91*7c478bd9Sstevel@tonic-gate 		if (rv < 0) {
92*7c478bd9Sstevel@tonic-gate 			report_syscall_error("poll");
93*7c478bd9Sstevel@tonic-gate 			continue;
94*7c478bd9Sstevel@tonic-gate 		}
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 		/* woken up from poll() process the event */
97*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < NUM_FDS; ++i) {
98*7c478bd9Sstevel@tonic-gate 			if (fds[i].revents == POLLIN)
99*7c478bd9Sstevel@tonic-gate 				process_event(i);
100*7c478bd9Sstevel@tonic-gate 		}
101*7c478bd9Sstevel@tonic-gate 	}
102*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
103*7c478bd9Sstevel@tonic-gate 	return (0);
104*7c478bd9Sstevel@tonic-gate }
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate /*
107*7c478bd9Sstevel@tonic-gate  * Set up poll fds.
108*7c478bd9Sstevel@tonic-gate  */
109*7c478bd9Sstevel@tonic-gate static void
init_poll_events()110*7c478bd9Sstevel@tonic-gate init_poll_events()
111*7c478bd9Sstevel@tonic-gate {
112*7c478bd9Sstevel@tonic-gate 	int c;
113*7c478bd9Sstevel@tonic-gate 	int p;
114*7c478bd9Sstevel@tonic-gate 	int i = 0;
115*7c478bd9Sstevel@tonic-gate 	char buf[sizeof (HPC3130_DEV_FMT)+8];
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	for (c = 0; c < NUM_CONTROLLERS; ++c) {
118*7c478bd9Sstevel@tonic-gate 		for (p = 0; p < SLOTS_PER_CONTROLLER; ++p) {
119*7c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, HPC3130_DEV_FMT,
120*7c478bd9Sstevel@tonic-gate 			    controller_names[c], p);
121*7c478bd9Sstevel@tonic-gate 			fds[i].events = POLLIN;
122*7c478bd9Sstevel@tonic-gate 			fds[i].fd = open(buf, O_RDWR);
123*7c478bd9Sstevel@tonic-gate 			if (fds[i].fd == -1) {
124*7c478bd9Sstevel@tonic-gate 				report_syscall_error(buf);
125*7c478bd9Sstevel@tonic-gate 				exit(-1);
126*7c478bd9Sstevel@tonic-gate 			}
127*7c478bd9Sstevel@tonic-gate 			i++;
128*7c478bd9Sstevel@tonic-gate 		}
129*7c478bd9Sstevel@tonic-gate 	}
130*7c478bd9Sstevel@tonic-gate }
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate /*
133*7c478bd9Sstevel@tonic-gate  * Process poll events.
134*7c478bd9Sstevel@tonic-gate  */
135*7c478bd9Sstevel@tonic-gate static void
process_event(int fdi)136*7c478bd9Sstevel@tonic-gate process_event(int fdi)
137*7c478bd9Sstevel@tonic-gate {
138*7c478bd9Sstevel@tonic-gate 	struct hpc3130_event e;
139*7c478bd9Sstevel@tonic-gate 	int rv;
140*7c478bd9Sstevel@tonic-gate 	int slot = INDEX2SLOT(fdi);
141*7c478bd9Sstevel@tonic-gate 	int cntr = INDEX2CONTROLLER(fdi);
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 	rv = ioctl(fds[fdi].fd, HPC3130_GET_EVENT, &e);
144*7c478bd9Sstevel@tonic-gate 	if (rv == -1) {
145*7c478bd9Sstevel@tonic-gate 		report_syscall_error("HPC3130_GET_EVENT");
146*7c478bd9Sstevel@tonic-gate 		return;
147*7c478bd9Sstevel@tonic-gate 	}
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	switch (e.id) {
150*7c478bd9Sstevel@tonic-gate 	case HPC3130_EVENT_INSERTION:
151*7c478bd9Sstevel@tonic-gate 	case HPC3130_EVENT_REMOVAL:
152*7c478bd9Sstevel@tonic-gate 	case HPC3130_EVENT_POWERON:
153*7c478bd9Sstevel@tonic-gate 	case HPC3130_EVENT_POWEROFF:
154*7c478bd9Sstevel@tonic-gate 		break;
155*7c478bd9Sstevel@tonic-gate 	case HPC3130_EVENT_BUTTON:
156*7c478bd9Sstevel@tonic-gate 		DPRINTF(("\nBUTTON EVENT slot (%s)\n", e.name));
157*7c478bd9Sstevel@tonic-gate 		pushbutton_event(e.name);
158*7c478bd9Sstevel@tonic-gate 		break;
159*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_FAULT_ON:
160*7c478bd9Sstevel@tonic-gate 		DPRINTF(("\nFAULT LED ON EVENT\n"));
161*7c478bd9Sstevel@tonic-gate 		fault_led_event(e.id, fdi);
162*7c478bd9Sstevel@tonic-gate 		break;
163*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_FAULT_OFF:
164*7c478bd9Sstevel@tonic-gate 		DPRINTF(("\nFAULT LED OFF EVENT\n"));
165*7c478bd9Sstevel@tonic-gate 		fault_led_event(e.id, fdi);
166*7c478bd9Sstevel@tonic-gate 		break;
167*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_REMOVABLE_ON:
168*7c478bd9Sstevel@tonic-gate 		DPRINTF(("\nREMOVABLE LED ON EVENT\n"));
169*7c478bd9Sstevel@tonic-gate 		removable_led_event(e.id, fdi);
170*7c478bd9Sstevel@tonic-gate 		break;
171*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_REMOVABLE_OFF:
172*7c478bd9Sstevel@tonic-gate 		DPRINTF(("\nREMOVABLE LED OFF EVENT\n"));
173*7c478bd9Sstevel@tonic-gate 		removable_led_event(e.id, fdi);
174*7c478bd9Sstevel@tonic-gate 		break;
175*7c478bd9Sstevel@tonic-gate 	default:
176*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "WARNING: bogus event: %x\n", e.id);
177*7c478bd9Sstevel@tonic-gate 	}
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate /*
181*7c478bd9Sstevel@tonic-gate  * Button Event handler.
182*7c478bd9Sstevel@tonic-gate  */
183*7c478bd9Sstevel@tonic-gate static void
pushbutton_event(char * ap_id)184*7c478bd9Sstevel@tonic-gate pushbutton_event(char *ap_id)
185*7c478bd9Sstevel@tonic-gate {
186*7c478bd9Sstevel@tonic-gate 	char			*errstr = NULL;
187*7c478bd9Sstevel@tonic-gate 	struct cfga_list_data	*stat = NULL;
188*7c478bd9Sstevel@tonic-gate 	int			nlist;
189*7c478bd9Sstevel@tonic-gate 	cfga_cmd_t		cmd;
190*7c478bd9Sstevel@tonic-gate 	cfga_err_t		rv;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 	rv = config_list_ext(1, &ap_id, &stat, &nlist,
193*7c478bd9Sstevel@tonic-gate 	    NULL, NULL, &errstr, 0);
194*7c478bd9Sstevel@tonic-gate 	if (rv != CFGA_OK) {
195*7c478bd9Sstevel@tonic-gate 		report_cfgadm_error(rv, errstr);
196*7c478bd9Sstevel@tonic-gate 		goto out;
197*7c478bd9Sstevel@tonic-gate 	}
198*7c478bd9Sstevel@tonic-gate 	assert(nlist == 1);
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	/* The only types of hotplug with buttons */
201*7c478bd9Sstevel@tonic-gate 	assert(!(strcmp(stat->ap_class, "pci")));
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	switch (stat->ap_o_state) {
204*7c478bd9Sstevel@tonic-gate 	case CFGA_STAT_UNCONFIGURED:
205*7c478bd9Sstevel@tonic-gate 		cmd = CFGA_CMD_CONFIGURE;
206*7c478bd9Sstevel@tonic-gate 		break;
207*7c478bd9Sstevel@tonic-gate 	case CFGA_STAT_CONFIGURED:
208*7c478bd9Sstevel@tonic-gate 		cmd = CFGA_CMD_DISCONNECT;
209*7c478bd9Sstevel@tonic-gate 		break;
210*7c478bd9Sstevel@tonic-gate 	default:
211*7c478bd9Sstevel@tonic-gate 		/* Should never get here */
212*7c478bd9Sstevel@tonic-gate 		assert(0);
213*7c478bd9Sstevel@tonic-gate 	}
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate 	/*
216*7c478bd9Sstevel@tonic-gate 	 * confp & msgp are NULL: when using the pushbutton,
217*7c478bd9Sstevel@tonic-gate 	 * simply fail if prompting is required.
218*7c478bd9Sstevel@tonic-gate 	 */
219*7c478bd9Sstevel@tonic-gate 	rv = config_change_state(cmd, 1, &ap_id, NULL, NULL, NULL, &errstr, 0);
220*7c478bd9Sstevel@tonic-gate 	if (rv != CFGA_OK) {
221*7c478bd9Sstevel@tonic-gate 		report_cfgadm_error(rv, errstr);
222*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU to "out" */
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate out:
226*7c478bd9Sstevel@tonic-gate 	if (errstr)
227*7c478bd9Sstevel@tonic-gate 		free(errstr);
228*7c478bd9Sstevel@tonic-gate 	if (stat)
229*7c478bd9Sstevel@tonic-gate 		free(stat);
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate static void
fault_led_event(hpc3130_event_type_t event,int fdi)233*7c478bd9Sstevel@tonic-gate fault_led_event(hpc3130_event_type_t event, int fdi)
234*7c478bd9Sstevel@tonic-gate {
235*7c478bd9Sstevel@tonic-gate 	int		side = 0;
236*7c478bd9Sstevel@tonic-gate 	unsigned int	old;
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	if (INDEX2CONTROLLER(fdi) != GPTWO_CONTROLLER) {
239*7c478bd9Sstevel@tonic-gate 		/* It's a PCI slot; left side of chassis */
240*7c478bd9Sstevel@tonic-gate 		side = 1;
241*7c478bd9Sstevel@tonic-gate 	}
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	old = fault_leds[side];
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	assert(fdi <= sizeof (fault_leds[side]) * BITSPERBYTE);
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	switch (event) {
248*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_FAULT_ON:
249*7c478bd9Sstevel@tonic-gate 		fault_leds[side] |= (1<<fdi);
250*7c478bd9Sstevel@tonic-gate 		DPRINTF(("fault_led_event: HPC3130_LED_FAULT_ON\n"));
251*7c478bd9Sstevel@tonic-gate 		break;
252*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_FAULT_OFF:
253*7c478bd9Sstevel@tonic-gate 		fault_leds[side] &= ~(1<<fdi);
254*7c478bd9Sstevel@tonic-gate 		DPRINTF(("fault_led_event: HPC3130_LED_FAULT_OFF\n"));
255*7c478bd9Sstevel@tonic-gate 		break;
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	DPRINTF(("fault_led_event: old(0x%x), fault_leds[%d](0x%x)\n",
259*7c478bd9Sstevel@tonic-gate 	    old, side, fault_leds[side]));
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 	if ((old == 0) != (fault_leds[side] == 0) && ok2rem_leds[side] == 0) {
262*7c478bd9Sstevel@tonic-gate 		/*
263*7c478bd9Sstevel@tonic-gate 		 * The first FAULT LED has come on, or the last one has gone
264*7c478bd9Sstevel@tonic-gate 		 * off on this side, and all the OK2REMOVE LEDS are off on this
265*7c478bd9Sstevel@tonic-gate 		 * side.  So we have to update the front panel ARROW LED.
266*7c478bd9Sstevel@tonic-gate 		 */
267*7c478bd9Sstevel@tonic-gate 		set_front_panel_led(side ? LEFT_DOOR_ATTEN_LED :
268*7c478bd9Sstevel@tonic-gate 		    RIGHT_DOOR_ATTEN_LED,
269*7c478bd9Sstevel@tonic-gate 		    fault_leds[side] ? LED_ON : LED_OFF);
270*7c478bd9Sstevel@tonic-gate 	}
271*7c478bd9Sstevel@tonic-gate }
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate static void
removable_led_event(hpc3130_event_type_t event,int fdi)274*7c478bd9Sstevel@tonic-gate removable_led_event(hpc3130_event_type_t event, int fdi)
275*7c478bd9Sstevel@tonic-gate {
276*7c478bd9Sstevel@tonic-gate 	int		side = 0;
277*7c478bd9Sstevel@tonic-gate 	unsigned int	old;
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	if (INDEX2CONTROLLER(fdi) != GPTWO_CONTROLLER) {
280*7c478bd9Sstevel@tonic-gate 		/* It's a PCI slot; left side of chassis */
281*7c478bd9Sstevel@tonic-gate 		side = 1;
282*7c478bd9Sstevel@tonic-gate 	}
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	old = ok2rem_leds[side];
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	assert(fdi <= sizeof (ok2rem_leds[side]) * BITSPERBYTE);
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	switch (event) {
289*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_REMOVABLE_ON:
290*7c478bd9Sstevel@tonic-gate 		ok2rem_leds[side] |= (1<<fdi);
291*7c478bd9Sstevel@tonic-gate 		DPRINTF(("removable_led_event: HPC3130_LED_REMOVABLE_ON\n"));
292*7c478bd9Sstevel@tonic-gate 		break;
293*7c478bd9Sstevel@tonic-gate 	case HPC3130_LED_REMOVABLE_OFF:
294*7c478bd9Sstevel@tonic-gate 		ok2rem_leds[side] &= ~(1<<fdi);
295*7c478bd9Sstevel@tonic-gate 		DPRINTF(("removable_led_event: HPC3130_LED_REMOVABLE_OFF\n"));
296*7c478bd9Sstevel@tonic-gate 		break;
297*7c478bd9Sstevel@tonic-gate 	}
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	DPRINTF(("removable_led_event: old(0x%x), ok2rem_leds[%d](0x%x)\n",
300*7c478bd9Sstevel@tonic-gate 	    old, side, ok2rem_leds[side]));
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if ((old == 0) != (ok2rem_leds[side] == 0)) {
303*7c478bd9Sstevel@tonic-gate 		/*
304*7c478bd9Sstevel@tonic-gate 		 * The first OKAY2REMOVE LED has come on, or the last
305*7c478bd9Sstevel@tonic-gate 		 * one has gone off (on this side).  We may have to update
306*7c478bd9Sstevel@tonic-gate 		 * the front panel LEDs.
307*7c478bd9Sstevel@tonic-gate 		 */
308*7c478bd9Sstevel@tonic-gate 		if (ok2rem_leds[!side] == 0) {
309*7c478bd9Sstevel@tonic-gate 			/*
310*7c478bd9Sstevel@tonic-gate 			 * The OK2REMOVE LEDs are all off on the other
311*7c478bd9Sstevel@tonic-gate 			 * side of the chassis, so this side determines
312*7c478bd9Sstevel@tonic-gate 			 * whether the front OK2REMOVE is on or off.
313*7c478bd9Sstevel@tonic-gate 			 */
314*7c478bd9Sstevel@tonic-gate 			set_front_panel_led(SYS_OK2REMOVE_LED,
315*7c478bd9Sstevel@tonic-gate 			    ok2rem_leds[side] ? LED_ON : LED_OFF);
316*7c478bd9Sstevel@tonic-gate 		}
317*7c478bd9Sstevel@tonic-gate 		if (fault_leds[side] == 0) {
318*7c478bd9Sstevel@tonic-gate 			/*
319*7c478bd9Sstevel@tonic-gate 			 * All the FAULT LEDs are off on this side.  So the
320*7c478bd9Sstevel@tonic-gate 			 * OK2REMOVE LEDs determine whether the ARROW LED is on.
321*7c478bd9Sstevel@tonic-gate 			 */
322*7c478bd9Sstevel@tonic-gate 		set_front_panel_led(side ? LEFT_DOOR_ATTEN_LED :
323*7c478bd9Sstevel@tonic-gate 		    RIGHT_DOOR_ATTEN_LED,
324*7c478bd9Sstevel@tonic-gate 		    ok2rem_leds[side] ? LED_ON : LED_OFF);
325*7c478bd9Sstevel@tonic-gate 		}
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate }
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate /*
330*7c478bd9Sstevel@tonic-gate  * Set front panel system leds either on or off.
331*7c478bd9Sstevel@tonic-gate  */
332*7c478bd9Sstevel@tonic-gate static void
set_front_panel_led(uint8_t bit_num,boolean_t on_off)333*7c478bd9Sstevel@tonic-gate set_front_panel_led(uint8_t bit_num, boolean_t on_off)
334*7c478bd9Sstevel@tonic-gate {
335*7c478bd9Sstevel@tonic-gate 	int		fd;
336*7c478bd9Sstevel@tonic-gate 	int		rv;
337*7c478bd9Sstevel@tonic-gate 	i2c_bit_t	arg;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	fd = open(SSC050_LED_PORT, O_RDWR);
340*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
341*7c478bd9Sstevel@tonic-gate 		report_syscall_error("ssc050");
342*7c478bd9Sstevel@tonic-gate 		return;
343*7c478bd9Sstevel@tonic-gate 	}
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	arg.bit_num = bit_num;
346*7c478bd9Sstevel@tonic-gate 	arg.bit_value = on_off;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	rv = ioctl(fd, I2C_SET_BIT, &arg);
349*7c478bd9Sstevel@tonic-gate 	if (rv == -1)
350*7c478bd9Sstevel@tonic-gate 		report_syscall_error("LED I2C_SET_BIT");
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
353*7c478bd9Sstevel@tonic-gate }
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate static int
i2c_set_bit(int fp,int bit,uint8_t value)356*7c478bd9Sstevel@tonic-gate i2c_set_bit(int fp, int bit, uint8_t value)
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate 	int		rv;
359*7c478bd9Sstevel@tonic-gate 	i2c_bit_t	passin;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	passin.bit_num = (uchar_t)bit;
362*7c478bd9Sstevel@tonic-gate 	passin.bit_value = value;
363*7c478bd9Sstevel@tonic-gate 	rv = ioctl(fp, I2C_SET_BIT, &passin);
364*7c478bd9Sstevel@tonic-gate 	return (rv);
365*7c478bd9Sstevel@tonic-gate }
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate static void
report_cfgadm_error(int cfgerrnum,char * errstr)368*7c478bd9Sstevel@tonic-gate report_cfgadm_error(int cfgerrnum, char *errstr)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate 	const char	*ep;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	ep = config_strerror(cfgerrnum);
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	if (ep == NULL)
375*7c478bd9Sstevel@tonic-gate 		ep = gettext("configuration administration unknown error");
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	if (errstr != NULL && *errstr != '\0') {
378*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s\n", ep, errstr);
379*7c478bd9Sstevel@tonic-gate 	} else {
380*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s\n", ep);
381*7c478bd9Sstevel@tonic-gate 	}
382*7c478bd9Sstevel@tonic-gate }
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate static void
report_syscall_error(char * msg)385*7c478bd9Sstevel@tonic-gate report_syscall_error(char *msg)
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate 	if (errno != EINTR)
388*7c478bd9Sstevel@tonic-gate 		perror(msg);
389*7c478bd9Sstevel@tonic-gate }
390