#include <memory.h>
#include <stdio.h>
#include <stdlib.h>

#include "x86_regs.h"
#include "x86_debug.h"
#include "x86_decode.h"
#include "x86_bios.h"

#include "sysenv.h"


#define OFF(addr)	(((addr) >> 0) & 0xffff)
#define SEG(addr)	(((addr) >> 4) & 0xf000)

#define BIOS_ADAPTOR_ROM_BASE	0xc0000

int pci_slot = -1;


int
main (int argc, char **argv)
{
    SysEnv sys;
    int i;

    memset(&sys, 0, sizeof(sys));
    for (i = 1; i < argc; ++i) {
	if (strcmp(argv[i], "-s") == 0) {
	    pci_slot = atoi(argv[++i]);
#ifdef DEBUG
	} else if (strcmp(argv[i], "-d") == 0) {
	    sys.x86.debug |= DEBUG_DECODE_F;
	} else if (strcmp(argv[i], "-D") == 0) {
	    sys.x86.debug |= DEBUG_DISASSEMBLE_F;
	} else if (strcmp(argv[i], "-t") == 0) {
	    sys.x86.debug |= DEBUG_TRACE_F;
	} else if (strcmp(argv[i], "-m") == 0) {
	    sys.x86.debug |= DEBUG_MEM_TRACE_F;
	} else if (strcmp(argv[i], "-i") == 0) {
	    sys.x86.debug |= DEBUG_IO_TRACE_F;
#endif
	}
    }
    sys_init(&sys);

    /*
     * Initialize Interval Timers:
     */
    outb(0x54, 0x43);	/* counter 1: refresh timer */
    outb(0x18, 0x41);

    outb(0x36, 0x43);	/* counter 0: system timer */
    outb(0x00, 0x40);
    outb(0x00, 0x40);

    outb(0xb6, 0x43);	/* counter 2: speaker */
    outb(0x31, 0x42);
    outb(0x13, 0x42);


    if (sys_rdw(&sys, 0xc0000) != 0xaa55) {
	printk("ginit: sorry, there seems to be no BIOS at 0xc0000\n");
    }
    x86_bios_init(&sys);
    sys.x86.R_CS = SEG(0xc0003);
    sys.x86.R_IP = OFF(0xc0003);
    sys.x86.R_SS = SEG(sys.mem_size - 1);
    sys.x86.R_SP = OFF(sys.mem_size - 1);
    x86_exec(&sys);

#if 1
    ((char *) sys.mem_base)[0x4000] = 0xcd;	/* INT 10 */
    ((char *) sys.mem_base)[0x4001] = 0x10;
    ((char *) sys.mem_base)[0x4002] = 0xc3;	/* RET */
    sys.x86.R_AH = 0x00;			/* set video mode 3 */
    sys.x86.R_AL = 0x03 | (1 << 7);
    sys.x86.R_CS = SEG(0x04000);
    sys.x86.R_IP = OFF(0x04000);
    sys.x86.R_SS = SEG(sys.mem_size - 1);
    sys.x86.R_SP = OFF(sys.mem_size - 1);
    x86_exec(&sys);
#endif

#if 0
    ((char *) sys.mem_base)[0x4000] = 0xcd;	/* INT 10 */
    ((char *) sys.mem_base)[0x4001] = 0x10;
    ((char *) sys.mem_base)[0x4002] = 0xc3;	/* RET */
    sys.x86.R_AX = 0x4f02 | (1 << 15);
    sys.x86.R_BX = 0x10a;	/* 132x43 */
    sys.x86.R_CS = SEG(0x04000);
    sys.x86.R_IP = OFF(0x04000);
    sys.x86.R_SS = SEG(sys.mem_size - 1);
    sys.x86.R_SP = OFF(sys.mem_size - 1);
    x86_exec(&sys);
#endif

    return 0;
}
