/*

	○shutdownをGUIで表示させる 3/12

	(;´Д｀)m
	元々はshutdownコマンドで殺らせる予定だったが
	シェルにシステムのデータを送るのが面倒だったので別タスク化した。
	どうもタスクの優先度の仕組みがなかなか難しいので
	task_runで設定しているpriorityとlvevelは空いてるっぽい数値にしている。
	
	○変更履歴詳細
	3/19 BIOSファンクションコール0x19を使用した再起動もできるようにした by is2os

*/
#include "bootpack.h"

struct SHEET *open_shutdown(struct SHTCTL *shtctl,  unsigned char *back_buffer,
							struct SHEET *back_sheet, struct TASK *sys_task, 
							struct TASK *clock_task)
{
	const int window_h = 160, window_w = 315; 
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct SHEET *sht = sheet_alloc(shtctl);
	unsigned char *buf = (unsigned char *)memman_alloc_4k(memman, window_w * window_h);
	struct TASK *task = task_alloc();
	int *shutdown_fifo = (int *)memman_alloc_4k(memman, 128 * 4);
	sht->flags |= SHEET_SHTDWN_FLAGS;
	sheet_setbuf(sht, buf, window_w, window_h, -1);
	make_window8(buf, window_w, window_h, "Shutdown", 0);
	putfonts8_asc(sht->buf, sht->bxsize, 12, 30, COL8_000000, "If you want to shutdown this computer");
	putfonts8_asc(sht->buf, sht->bxsize, 70, 50, COL8_000000, "You should push S key!");
	putfonts8_asc(sht->buf, sht->bxsize, 12, 70, COL8_000000, "Or you want to reboot this computer");
	putfonts8_asc(sht->buf, sht->bxsize, 70, 90, COL8_000000, "You should push R Key!");
	putfonts8_asc(sht->buf, sht->bxsize, 20, 130, COL8_FF0000, "But APM need version upper than 1.1");
	task->ds_base = memman_alloc_4k(memman, 64 * 1024);
	task->tss.esp = task->ds_base + 64 * 1024 - 40;
	task->tss.eip = (int)&shutdown_task;
 	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)back_buffer;
	*((int *)(task->tss.esp + 8)) = (int)back_sheet;
	*((int *)(task->tss.esp + 12)) = (int)sys_task;
	*((int *)(task->tss.esp + 16)) = (int)clock_task;
	task_run(task, 4, 2, "shutdown");	/* ここの優先度は具合に応じて変更 */
	sht->task = task;
	fifo32_init(&task->fifo, 128, shutdown_fifo, task);
	return sht;
}

void close_shutdown(struct SHEET *sht, struct TASK *task, unsigned long size)
{
	struct MEMMAN *memman = (struct MEMMAN *)MEMMAN_ADDR;
	memman_free_4k(memman, task->ds_base, 64 * 1024);
	memman_free_4k(memman, (int)task->fifo.buf, 128 * 4);
	task_sleep(sht->task);
	sht->task->flags = 0;
	memman_free_4k(memman, (int)sht->buf, size);
	sheet_free(sht);
	return;
}
	
void shutdown_task(unsigned char *back_buffer, struct SHEET *back_sheet, 
				  			 struct TASK *sys_task, struct TASK *clock_task)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct TASK *task = task_now();
	int i;
	
	for (;;) {
		io_cli();
		if (fifo32_status(&task->fifo) == 0) {
			task_sleep(task);
			io_sti();
		} else {
			i = fifo32_get(&task->fifo);
			io_sti();
			if (256 <= i && i <= 511) {
				if (i == 256 + 's') {
					if (*((short *)ADDRESS_FOUND_APM) >= 101) {
						/* 
						  ○開放処理
						  negitoroの本体システムが動いているとAPM処理を
						  例外でキャッチしてしまうので全てのタスクはここで殺っておく
						  処理不良があったらここに書き足すべし
						*/
						close_clocktask(clock_task);
						task_sleep(back_sheet->task);
						back_sheet->task->flags = 0;
						memman_free_4k(memman, (int)back_buffer, binfo->scrnx * binfo->scrny);
						sheet_free(back_sheet);
						task_sleep(sys_task);
						sys_task->flags = 0;

						/* 16ビットモード移行＆APM電源切断 */
						stop_system();
						change_system16();	
						apm_shutdown();
					}
				} else if (i == 256 + 'r') {
					/* ○開放処理 */
					close_clocktask(clock_task);
					task_sleep(back_sheet->task);
					back_sheet->task->flags = 0;
					memman_free_4k(memman, (int)back_buffer, binfo->scrnx * binfo->scrny);
					sheet_free(back_sheet);
					task_sleep(sys_task);
					sys_task->flags = 0;
					
					/* BIOSの0x19で再起動 */
					stop_system();
					change_system16();	
					system_reboot();
				}
			}
		}
	}
	return;
}

