/* RTCと時計 */

#include "bootpack.h"
#include <stdio.h>

struct clock clock;	/* 時計タスク専用 */

void clock_task(struct sheet *sht)
{
	struct task *task = task_now();
	struct timer *timer;
	char s[12];
	int fbuf[32], i;

	fifo_init(&task->fifo, task, fbuf, 128);
	task->fifo.task = task;

	/* 更新用タイマ */
	timer = timer_alloc();
	timer_init(timer, &task->fifo, 1);
	timer_set(timer, 100);

	for(;;) {
		cli();
		if(fifo_stat(&task->fifo) == 0) {
			task_sleep(task);
			sti();
		} else {
			i = fifo_get(&task->fifo);
			sti();

			if(i == 1) {
				rtc_read();
				sprintf(s, "%02d/%02d %02d:%02d", clock.month, clock.day, clock.hour, clock.min);
				graphic_fonts(sht, COLOR_C6C6C6, COLOR_000000, 2, 2, s);
				timer_set(timer, 100);
			}
		}
	}
}

void clock_tinit(struct task *task, struct sheet *sht_tbar)
{
	task = task_alloc();
	task->stack = memory_alloc(mem, 65536);
	task->tss.eip = (int) &clock_task;
	task->tss.esp = task->stack + 65536 - 8;
	task->tss.es = 1 * 8;
	task->tss.cs = 2 * 8;
	task->tss.ss = 1 * 8;
	task->tss.ds = 1 * 8;
	task->tss.fs = 1 * 8;
	task->tss.gs = 1 * 8;

	*((int *) (task->tss.esp + 4)) = (int) sht_tbar;
	task_run(task, 1, 1);
	return;
}

void clock_get(struct clock *clck)
{
	clck->sec = clock.sec;
	clck->min = clock.min;
	clck->hour = clock.hour;
	clck->day = clock.day;
	clck->month = clock.month;
	clck->year = clock.year;
	return;
}

int cmos_read(unsigned char addr)
{
	outb(PORT_RTC_SREG, addr);
	return inb(PORT_RTC_DATA);
}

void rtc_read(void)
{
	static unsigned char addr[7] = {
		0x00, 0x02, 0x04, 0x07, 0x08, 0x09, 0x32
	};	/* 秒、分、時、日、月、年のアドレス */
	static unsigned char max[7] = {
		0x60, 0x59, 0x23, 0x31, 0x12, 0x99, 0x99
	};	/* 秒、分、時、日、月、年の最大数 */
	int i;
	unsigned char t[8];
	char err;

	for(;;) {	/* 読み込みが成功するまで繰り返す */
		err = 0;
		for(i = 0; i < 7; i++) {
			outb(PORT_RTC_SREG, addr[i]);
			t[i] = inb(PORT_RTC_DATA);
		}
		for(i = 0; i < 7; i++) {
			outb(PORT_RTC_SREG, addr[i]);
			if((int) t[i] != inb(PORT_RTC_DATA) || ((int) t[i] & 0x0f) > 9 || (int) t[i] > (int) max) {
				err = 1;
			}
		}
		if(err == 0) {	/* 情報を格納 */
			clock.sec = (t[0] >> 4) * 10 + (t[0] & 0x0f);
			clock.min = (t[1] >> 4) * 10 + (t[1] & 0x0f);
			clock.hour = (t[2] >> 4) * 10 + (t[2] & 0x0f);
			clock.day = (t[3] >> 4) * 10 + (t[3] & 0x0f);
			clock.month = (t[4] >> 4) * 10 + (t[4] & 0x0f);
			clock.year = (t[6] >> 4) * 1000 + (t[6] & 0x0f) * 100 + (t[5] >> 4) * 10 + (t[5] & 0x0f);
			return;
		}
	}
	return;
}
