Exemplo n.º 1
0
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();
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/*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);
}