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.
27 #include <sys/types.h>
28 #include <sys/sunddi.h>
30 #include <sys/i2c/clients/i2c_client.h>
31 #include <sys/hpc3130_events.h>
32 #include <values.h> /* for BITSPERBYTE */
42 #include <config_admin.h>
43 #include <sys/daktari.h>
47 * Hotplug Controller addresses.
49 static const unsigned char controller_names
[NUM_CONTROLLERS
] =
50 { 0xe2, 0xe6, 0xe8, 0xec };
52 #define INDEX2SLOT(INDEX) ((INDEX)%4) /* cf init_poll_events() */
53 #define INDEX2CONTROLLER(INDEX) ((INDEX)/4) /* cf init_poll_events() */
58 static struct pollfd fds
[NUM_FDS
];
59 static unsigned int fault_leds
[2];
60 static unsigned int ok2rem_leds
[2];
65 static void init_poll_events(void);
66 static void process_event(int);
67 static void report_cfgadm_error(int, char *);
68 static void set_front_panel_led(uint8_t, boolean_t
);
70 static int i2c_set_bit(int, int, uint8_t);
71 static void report_syscall_error(char *);
73 static void pushbutton_event(char *);
74 static void fault_led_event(hpc3130_event_type_t
, int);
75 static void removable_led_event(hpc3130_event_type_t
, int);
78 * main(): loops forever looking for events.
88 /* sleep in poll() waiting an event */
89 rv
= poll(fds
, NUM_FDS
, -1);
91 report_syscall_error("poll");
95 /* woken up from poll() process the event */
96 for (i
= 0; i
< NUM_FDS
; ++i
) {
97 if (fds
[i
].revents
== POLLIN
)
114 char buf
[sizeof (HPC3130_DEV_FMT
)+8];
116 for (c
= 0; c
< NUM_CONTROLLERS
; ++c
) {
117 for (p
= 0; p
< SLOTS_PER_CONTROLLER
; ++p
) {
118 (void) sprintf(buf
, HPC3130_DEV_FMT
,
119 controller_names
[c
], p
);
120 fds
[i
].events
= POLLIN
;
121 fds
[i
].fd
= open(buf
, O_RDWR
);
122 if (fds
[i
].fd
== -1) {
123 report_syscall_error(buf
);
132 * Process poll events.
135 process_event(int fdi
)
137 struct hpc3130_event e
;
139 int slot
= INDEX2SLOT(fdi
);
140 int cntr
= INDEX2CONTROLLER(fdi
);
142 rv
= ioctl(fds
[fdi
].fd
, HPC3130_GET_EVENT
, &e
);
144 report_syscall_error("HPC3130_GET_EVENT");
149 case HPC3130_EVENT_INSERTION
:
150 case HPC3130_EVENT_REMOVAL
:
151 case HPC3130_EVENT_POWERON
:
152 case HPC3130_EVENT_POWEROFF
:
154 case HPC3130_EVENT_BUTTON
:
155 DPRINTF(("\nBUTTON EVENT slot (%s)\n", e
.name
));
156 pushbutton_event(e
.name
);
158 case HPC3130_LED_FAULT_ON
:
159 DPRINTF(("\nFAULT LED ON EVENT\n"));
160 fault_led_event(e
.id
, fdi
);
162 case HPC3130_LED_FAULT_OFF
:
163 DPRINTF(("\nFAULT LED OFF EVENT\n"));
164 fault_led_event(e
.id
, fdi
);
166 case HPC3130_LED_REMOVABLE_ON
:
167 DPRINTF(("\nREMOVABLE LED ON EVENT\n"));
168 removable_led_event(e
.id
, fdi
);
170 case HPC3130_LED_REMOVABLE_OFF
:
171 DPRINTF(("\nREMOVABLE LED OFF EVENT\n"));
172 removable_led_event(e
.id
, fdi
);
175 (void) fprintf(stderr
, "WARNING: bogus event: %x\n", e
.id
);
180 * Button Event handler.
183 pushbutton_event(char *ap_id
)
186 struct cfga_list_data
*stat
= NULL
;
191 rv
= config_list_ext(1, &ap_id
, &stat
, &nlist
,
192 NULL
, NULL
, &errstr
, 0);
194 report_cfgadm_error(rv
, errstr
);
199 /* The only types of hotplug with buttons */
200 assert(!(strcmp(stat
->ap_class
, "pci")));
202 switch (stat
->ap_o_state
) {
203 case CFGA_STAT_UNCONFIGURED
:
204 cmd
= CFGA_CMD_CONFIGURE
;
206 case CFGA_STAT_CONFIGURED
:
207 cmd
= CFGA_CMD_DISCONNECT
;
210 /* Should never get here */
215 * confp & msgp are NULL: when using the pushbutton,
216 * simply fail if prompting is required.
218 rv
= config_change_state(cmd
, 1, &ap_id
, NULL
, NULL
, NULL
, &errstr
, 0);
220 report_cfgadm_error(rv
, errstr
);
221 /* FALLTHRU to "out" */
230 fault_led_event(hpc3130_event_type_t event
, int fdi
)
235 if (INDEX2CONTROLLER(fdi
) != GPTWO_CONTROLLER
) {
236 /* It's a PCI slot; left side of chassis */
240 old
= fault_leds
[side
];
242 assert(fdi
<= sizeof (fault_leds
[side
]) * BITSPERBYTE
);
245 case HPC3130_LED_FAULT_ON
:
246 fault_leds
[side
] |= (1<<fdi
);
247 DPRINTF(("fault_led_event: HPC3130_LED_FAULT_ON\n"));
249 case HPC3130_LED_FAULT_OFF
:
250 fault_leds
[side
] &= ~(1<<fdi
);
251 DPRINTF(("fault_led_event: HPC3130_LED_FAULT_OFF\n"));
255 DPRINTF(("fault_led_event: old(0x%x), fault_leds[%d](0x%x)\n",
256 old
, side
, fault_leds
[side
]));
258 if ((old
== 0) != (fault_leds
[side
] == 0) && ok2rem_leds
[side
] == 0) {
260 * The first FAULT LED has come on, or the last one has gone
261 * off on this side, and all the OK2REMOVE LEDS are off on this
262 * side. So we have to update the front panel ARROW LED.
264 set_front_panel_led(side
? LEFT_DOOR_ATTEN_LED
:
265 RIGHT_DOOR_ATTEN_LED
,
266 fault_leds
[side
] ? LED_ON
: LED_OFF
);
271 removable_led_event(hpc3130_event_type_t event
, int fdi
)
276 if (INDEX2CONTROLLER(fdi
) != GPTWO_CONTROLLER
) {
277 /* It's a PCI slot; left side of chassis */
281 old
= ok2rem_leds
[side
];
283 assert(fdi
<= sizeof (ok2rem_leds
[side
]) * BITSPERBYTE
);
286 case HPC3130_LED_REMOVABLE_ON
:
287 ok2rem_leds
[side
] |= (1<<fdi
);
288 DPRINTF(("removable_led_event: HPC3130_LED_REMOVABLE_ON\n"));
290 case HPC3130_LED_REMOVABLE_OFF
:
291 ok2rem_leds
[side
] &= ~(1<<fdi
);
292 DPRINTF(("removable_led_event: HPC3130_LED_REMOVABLE_OFF\n"));
296 DPRINTF(("removable_led_event: old(0x%x), ok2rem_leds[%d](0x%x)\n",
297 old
, side
, ok2rem_leds
[side
]));
299 if ((old
== 0) != (ok2rem_leds
[side
] == 0)) {
301 * The first OKAY2REMOVE LED has come on, or the last
302 * one has gone off (on this side). We may have to update
303 * the front panel LEDs.
305 if (ok2rem_leds
[!side
] == 0) {
307 * The OK2REMOVE LEDs are all off on the other
308 * side of the chassis, so this side determines
309 * whether the front OK2REMOVE is on or off.
311 set_front_panel_led(SYS_OK2REMOVE_LED
,
312 ok2rem_leds
[side
] ? LED_ON
: LED_OFF
);
314 if (fault_leds
[side
] == 0) {
316 * All the FAULT LEDs are off on this side. So the
317 * OK2REMOVE LEDs determine whether the ARROW LED is on.
319 set_front_panel_led(side
? LEFT_DOOR_ATTEN_LED
:
320 RIGHT_DOOR_ATTEN_LED
,
321 ok2rem_leds
[side
] ? LED_ON
: LED_OFF
);
327 * Set front panel system leds either on or off.
330 set_front_panel_led(uint8_t bit_num
, boolean_t on_off
)
336 fd
= open(SSC050_LED_PORT
, O_RDWR
);
338 report_syscall_error("ssc050");
342 arg
.bit_num
= bit_num
;
343 arg
.bit_value
= on_off
;
345 rv
= ioctl(fd
, I2C_SET_BIT
, &arg
);
347 report_syscall_error("LED I2C_SET_BIT");
353 i2c_set_bit(int fp
, int bit
, uint8_t value
)
358 passin
.bit_num
= (uchar_t
)bit
;
359 passin
.bit_value
= value
;
360 rv
= ioctl(fp
, I2C_SET_BIT
, &passin
);
365 report_cfgadm_error(int cfgerrnum
, char *errstr
)
369 ep
= config_strerror(cfgerrnum
);
372 ep
= gettext("configuration administration unknown error");
374 if (errstr
!= NULL
&& *errstr
!= '\0') {
375 (void) fprintf(stderr
, "%s: %s\n", ep
, errstr
);
377 (void) fprintf(stderr
, "%s\n", ep
);
382 report_syscall_error(char *msg
)