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 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 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 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 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 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 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 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 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 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 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