int main(void) { CLKPR = 0x80; CLKPR = 0x00; init_ports(); init_timer1(); init_timer2(); init_analog(); TWAR = 1 << 1; TWCR = 0x45; TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); sei(); state = WAIT_ZCROSS; //state = TEST; while (1) { _delay_ms(10000); } clr_led(); cli(); boot_main(); }
static void end_led_test(led_dtls_t *dtls, int disk) { /* * There is a problem with a disk coming on-line. * All its leds are lit for 10 seconds to meet the led-test * requirement. The true state for the fault led can be determined * immediately, but determination of whether to light blue or green * requires a response from libdevinfo. Device reconfiguration logic * (likely to be active at this time) holds a long term * lock preventing devinfo calls from completing. Rather than * leave a contradictory led indication showing during this * period, it is better to anticipate the green led result * and correct it when the facts are known. */ clr_led(disk, FCAL_REMOK_LED, dtls); clr_led(disk, FCAL_FAULT_LED, dtls); dtls->led_state[FCAL_READY_LED - LED_PROPS_START - 1][disk] = LED_STATE_ON; }
/*ARGSUSED*/ void * fcal_leds_thread(void *args) { led_dtls_t *dtls = g_led_dtls; int c, v; int err = 0; int events = 0; int fd_bkplane; i2c_port_t port; int lastVal = I2C_IOCTL_INIT; int ws; int mask; /* * generate a mask for presence and fault status bits */ mask = 0; for (c = 0; c < dtls->n_disks; c++) { mask |= dtls->presence[c]; mask |= dtls->faults[c]; } /* * enter poll loop */ for (;;) { /* * see if a LED-test timer has expired */ for (c = 0; c < dtls->n_disks; c++) { if (dtls->led_test_end[c] > 0) { if (!dtls->polling) { /* poll thread failure, end led-test */ dtls->led_test_end[c] = 0; } else if ((events & FCAL_EV_POLL) != 0) { dtls->led_test_end[c]--; } if (dtls->led_test_end[c] == 0) { /* * clear blue and amber leds */ end_led_test(dtls, c); /* treat any status as a change */ lastVal = I2C_IOCTL_INIT; } } } fd_bkplane = open(dtls->fcal_status, O_RDONLY); if (fd_bkplane < 0) { SYSLOG(LOG_ERR, EM_CANT_OPEN, dtls->fcal_status); err = errno; break; } port.value = 0; /* * the direction and dir_mask fields are ignored, * so one can only guess at their possible use */ port.direction = DIR_INPUT; port.dir_mask = (uint8_t)mask; c = ioctl(fd_bkplane, I2C_GET_PORT, &port); if (c < 0) { err = errno; (void) close(fd_bkplane); if (lastVal != I2C_IOCTL_FAIL) { SYSLOG(LOG_ERR, EM_I2C_GET_PORT, mystrerror(err)); lastVal = I2C_IOCTL_FAIL; events |= FCAL_EV_CONFIG; } } else { (void) close(fd_bkplane); ws = port.value & mask; } if ((c == 0) && (ws != lastVal)) { events |= FCAL_EV_CONFIG; lastVal = ws; for (c = 0; c < dtls->n_disks; c++) { /* * first get the value of the relevant * presence bit (as 0 or 1) */ v = ((lastVal & dtls->presence[c]) != 0); /* hold previous presence value */ ws = dtls->disk_detected[c]; /* * the disk is present if the backplane * status bit for this disk is equal to the * configured assert_presence value */ dtls->disk_detected[c] = (v == dtls->assert_presence); /* * Don't add disk-unit node here for * newly arrived disks. While the led * test is running (and beyond) * libdevinfo is locked out and we * can't get port or target info. */ if ((!ws) && dtls->disk_detected[c]) { /* * disk has just come on-line */ start_led_test(dtls, c); } /* * clear leds and ready status * for disks which have been removed */ if (ws && (!dtls->disk_detected[c])) { clr_led(c, FCAL_REMOK_LED, dtls); clr_led(c, FCAL_FAULT_LED, dtls); clr_led(c, FCAL_READY_LED, dtls); dtls->disk_ready[c] = NO_MINORS; dtls->disk_prev[c] = NO_MINORS; v = update_picl(dtls, c); /* * set or clear retry flag */ dtls->picl_retry[c] = (v == EAGAIN); } /* * for present disks which are not doing a * led test, adjust fault LED */ if ((dtls->led_test_end[c] != 0) || (!dtls->disk_detected[c])) continue; v = ((lastVal & dtls->faults[c]) != 0); if (v == dtls->assert_fault) set_led(c, FCAL_FAULT_LED, dtls); else clr_led(c, FCAL_FAULT_LED, dtls); } } /* * For detected disks whose status has changed, choose between * ready and ok to remove. * libdevinfo can be locked out for the entire duration of a * disk spin-up. So it is best not to seek this info while * a led-test is in progress. Otherwise the leds can be stuck * on for about 40 seconds. * Note that chk_minors() returns 0 unless a status change * has occurred. */ if (!is_led_test(dtls) && chk_minors(dtls) != 0) { events = FCAL_EV_CONFIG; for (c = 0; c < dtls->n_disks; c++) { if (!dtls->disk_detected[c]) continue; /* * When disk_ready changes, disk_prev is set * to its previous value. This allows the * direction of the last transistion to be * determined. */ if ((dtls->disk_prev[c] == HAS_MINORS) && (dtls->disk_ready[c] == NO_MINORS)) { clr_led(c, FCAL_READY_LED, dtls); set_led(c, FCAL_REMOK_LED, dtls); } else { set_led(c, FCAL_READY_LED, dtls); clr_led(c, FCAL_REMOK_LED, dtls); } } } /* * Update PICL (disk-unit) for newly attached disks * ** see note in header file for significance * of disk_prev and disk_ready flags. */ for (c = 0; c < dtls->n_disks; c++) { if ((dtls->disk_prev[c] == NO_MINORS) && (dtls->disk_ready[c] == HAS_MINORS)) { dtls->disk_prev[c] = HAS_MINORS; v = update_picl(dtls, c); /* * set or clear retry flag */ dtls->picl_retry[c] = (v == EAGAIN); } } if ((events & FCAL_EV_CONFIG) != 0) { /* * set fast polling */ dtls->fast_poll_end = dtls->relax_time_ticks; } /* * if updating a led failed (e.g. I2C busy), try again */ if (dtls->led_retry) retry_led(dtls); events = wait_a_while(); /* * when picl is recycled, wait_a_while sleeps until the * init routine has been called again. * This is the moment when dtls may have become stale. */ if (dtls != g_led_dtls) { dtls = g_led_dtls; lastVal = I2C_IOCTL_INIT; /* * re-generate the presence and fault status mask * in case the .conf file has changed */ mask = 0; for (c = 0; c < dtls->n_disks; c++) { mask |= dtls->presence[c]; mask |= dtls->faults[c]; } } /* * count down relaxation time counter if a poll event */ if ((events & FCAL_EV_POLL) != 0) { if (dtls->fast_poll_end > 0) dtls->fast_poll_end--; } /* * if updating PICL needs retrying, try it now */ for (c = 0; c < dtls->n_disks; c++) { if (dtls->picl_retry[c]) { v = update_picl(dtls, c); dtls->picl_retry[c] = (v == EAGAIN); } } } return ((void *)err); }