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
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.
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]
23 * Copyright 2000, 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/types.h>
29 #include <sys/sunddi.h>
31 #include <sys/i2c/clients/i2c_client.h>
32 #include <sys/hpc3130_events.h>
33 #include <values.h> /* for BITSPERBYTE */
43 #include <config_admin.h>
44 #include <sys/daktari.h>
48 * Hotplug Controller addresses.
50 static const unsigned char controller_names
[NUM_CONTROLLERS
] =
51 { 0xe2, 0xe6, 0xe8, 0xec };
53 #define INDEX2SLOT(INDEX) ((INDEX)%4) /* cf init_poll_events() */
54 #define INDEX2CONTROLLER(INDEX) ((INDEX)/4) /* cf init_poll_events() */
59 static struct pollfd fds
[NUM_FDS
];
60 static unsigned int fault_leds
[2];
61 static unsigned int ok2rem_leds
[2];
66 static void init_poll_events(void);
67 static void process_event(int);
68 static void report_cfgadm_error(int, char *);
69 static void set_front_panel_led(uint8_t, boolean_t
);
71 static int i2c_set_bit(int, int, uint8_t);
72 static void report_syscall_error(char *);
74 static void pushbutton_event(char *);
75 static void fault_led_event(hpc3130_event_type_t
, int);
76 static void removable_led_event(hpc3130_event_type_t
, int);
79 * main(): loops forever looking for events.
89 /* sleep in poll() waiting an event */
90 rv
= poll(fds
, NUM_FDS
, -1);
92 report_syscall_error("poll");
96 /* woken up from poll() process the event */
97 for (i
= 0; i
< NUM_FDS
; ++i
) {
98 if (fds
[i
].revents
== POLLIN
)
115 char buf
[sizeof (HPC3130_DEV_FMT
)+8];
117 for (c
= 0; c
< NUM_CONTROLLERS
; ++c
) {
118 for (p
= 0; p
< SLOTS_PER_CONTROLLER
; ++p
) {
119 (void) sprintf(buf
, HPC3130_DEV_FMT
,
120 controller_names
[c
], p
);
121 fds
[i
].events
= POLLIN
;
122 fds
[i
].fd
= open(buf
, O_RDWR
);
123 if (fds
[i
].fd
== -1) {
124 report_syscall_error(buf
);
133 * Process poll events.
136 process_event(int fdi
)
138 struct hpc3130_event e
;
140 int slot
= INDEX2SLOT(fdi
);
141 int cntr
= INDEX2CONTROLLER(fdi
);
143 rv
= ioctl(fds
[fdi
].fd
, HPC3130_GET_EVENT
, &e
);
145 report_syscall_error("HPC3130_GET_EVENT");
150 case HPC3130_EVENT_INSERTION
:
151 case HPC3130_EVENT_REMOVAL
:
152 case HPC3130_EVENT_POWERON
:
153 case HPC3130_EVENT_POWEROFF
:
155 case HPC3130_EVENT_BUTTON
:
156 DPRINTF(("\nBUTTON EVENT slot (%s)\n", e
.name
));
157 pushbutton_event(e
.name
);
159 case HPC3130_LED_FAULT_ON
:
160 DPRINTF(("\nFAULT LED ON EVENT\n"));
161 fault_led_event(e
.id
, fdi
);
163 case HPC3130_LED_FAULT_OFF
:
164 DPRINTF(("\nFAULT LED OFF EVENT\n"));
165 fault_led_event(e
.id
, fdi
);
167 case HPC3130_LED_REMOVABLE_ON
:
168 DPRINTF(("\nREMOVABLE LED ON EVENT\n"));
169 removable_led_event(e
.id
, fdi
);
171 case HPC3130_LED_REMOVABLE_OFF
:
172 DPRINTF(("\nREMOVABLE LED OFF EVENT\n"));
173 removable_led_event(e
.id
, fdi
);
176 (void) fprintf(stderr
, "WARNING: bogus event: %x\n", e
.id
);
181 * Button Event handler.
184 pushbutton_event(char *ap_id
)
187 struct cfga_list_data
*stat
= NULL
;
192 rv
= config_list_ext(1, &ap_id
, &stat
, &nlist
,
193 NULL
, NULL
, &errstr
, 0);
195 report_cfgadm_error(rv
, errstr
);
200 /* The only types of hotplug with buttons */
201 assert(!(strcmp(stat
->ap_class
, "pci")));
203 switch (stat
->ap_o_state
) {
204 case CFGA_STAT_UNCONFIGURED
:
205 cmd
= CFGA_CMD_CONFIGURE
;
207 case CFGA_STAT_CONFIGURED
:
208 cmd
= CFGA_CMD_DISCONNECT
;
211 /* Should never get here */
216 * confp & msgp are NULL: when using the pushbutton,
217 * simply fail if prompting is required.
219 rv
= config_change_state(cmd
, 1, &ap_id
, NULL
, NULL
, NULL
, &errstr
, 0);
221 report_cfgadm_error(rv
, errstr
);
222 /* FALLTHRU to "out" */
233 fault_led_event(hpc3130_event_type_t event
, int fdi
)
238 if (INDEX2CONTROLLER(fdi
) != GPTWO_CONTROLLER
) {
239 /* It's a PCI slot; left side of chassis */
243 old
= fault_leds
[side
];
245 assert(fdi
<= sizeof (fault_leds
[side
]) * BITSPERBYTE
);
248 case HPC3130_LED_FAULT_ON
:
249 fault_leds
[side
] |= (1<<fdi
);
250 DPRINTF(("fault_led_event: HPC3130_LED_FAULT_ON\n"));
252 case HPC3130_LED_FAULT_OFF
:
253 fault_leds
[side
] &= ~(1<<fdi
);
254 DPRINTF(("fault_led_event: HPC3130_LED_FAULT_OFF\n"));
258 DPRINTF(("fault_led_event: old(0x%x), fault_leds[%d](0x%x)\n",
259 old
, side
, fault_leds
[side
]));
261 if ((old
== 0) != (fault_leds
[side
] == 0) && ok2rem_leds
[side
] == 0) {
263 * The first FAULT LED has come on, or the last one has gone
264 * off on this side, and all the OK2REMOVE LEDS are off on this
265 * side. So we have to update the front panel ARROW LED.
267 set_front_panel_led(side
? LEFT_DOOR_ATTEN_LED
:
268 RIGHT_DOOR_ATTEN_LED
,
269 fault_leds
[side
] ? LED_ON
: LED_OFF
);
274 removable_led_event(hpc3130_event_type_t event
, int fdi
)
279 if (INDEX2CONTROLLER(fdi
) != GPTWO_CONTROLLER
) {
280 /* It's a PCI slot; left side of chassis */
284 old
= ok2rem_leds
[side
];
286 assert(fdi
<= sizeof (ok2rem_leds
[side
]) * BITSPERBYTE
);
289 case HPC3130_LED_REMOVABLE_ON
:
290 ok2rem_leds
[side
] |= (1<<fdi
);
291 DPRINTF(("removable_led_event: HPC3130_LED_REMOVABLE_ON\n"));
293 case HPC3130_LED_REMOVABLE_OFF
:
294 ok2rem_leds
[side
] &= ~(1<<fdi
);
295 DPRINTF(("removable_led_event: HPC3130_LED_REMOVABLE_OFF\n"));
299 DPRINTF(("removable_led_event: old(0x%x), ok2rem_leds[%d](0x%x)\n",
300 old
, side
, ok2rem_leds
[side
]));
302 if ((old
== 0) != (ok2rem_leds
[side
] == 0)) {
304 * The first OKAY2REMOVE LED has come on, or the last
305 * one has gone off (on this side). We may have to update
306 * the front panel LEDs.
308 if (ok2rem_leds
[!side
] == 0) {
310 * The OK2REMOVE LEDs are all off on the other
311 * side of the chassis, so this side determines
312 * whether the front OK2REMOVE is on or off.
314 set_front_panel_led(SYS_OK2REMOVE_LED
,
315 ok2rem_leds
[side
] ? LED_ON
: LED_OFF
);
317 if (fault_leds
[side
] == 0) {
319 * All the FAULT LEDs are off on this side. So the
320 * OK2REMOVE LEDs determine whether the ARROW LED is on.
322 set_front_panel_led(side
? LEFT_DOOR_ATTEN_LED
:
323 RIGHT_DOOR_ATTEN_LED
,
324 ok2rem_leds
[side
] ? LED_ON
: LED_OFF
);
330 * Set front panel system leds either on or off.
333 set_front_panel_led(uint8_t bit_num
, boolean_t on_off
)
339 fd
= open(SSC050_LED_PORT
, O_RDWR
);
341 report_syscall_error("ssc050");
345 arg
.bit_num
= bit_num
;
346 arg
.bit_value
= on_off
;
348 rv
= ioctl(fd
, I2C_SET_BIT
, &arg
);
350 report_syscall_error("LED I2C_SET_BIT");
356 i2c_set_bit(int fp
, int bit
, uint8_t value
)
361 passin
.bit_num
= (uchar_t
)bit
;
362 passin
.bit_value
= value
;
363 rv
= ioctl(fp
, I2C_SET_BIT
, &passin
);
368 report_cfgadm_error(int cfgerrnum
, char *errstr
)
372 ep
= config_strerror(cfgerrnum
);
375 ep
= gettext("configuration administration unknown error");
377 if (errstr
!= NULL
&& *errstr
!= '\0') {
378 (void) fprintf(stderr
, "%s: %s\n", ep
, errstr
);
380 (void) fprintf(stderr
, "%s\n", ep
);
385 report_syscall_error(char *msg
)