//Functions.c
//05/07/03 Josh Holtrop
//for HOS
//Modified: 10/30/03

//Writes a byte out to a port
inline void outportb(unsigned int port, unsigned char value)		// Output a byte to a port
{
    asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value));
};

//Writes a word out to a port
inline void outportw(unsigned int port, unsigned int value)		// Output a word to a port
{
    asm volatile ("outw %%ax,%%dx"::"d" (port), "a" (value));
};

//Reads a byte from a port
inline byte inportb(unsigned short port)
{
	unsigned char ret_val;

	asm volatile("inb %w1,%b0"
		: "=a"(ret_val)
		: "d"(port));
	return ret_val;
};

//Enables (SeTs) Interrupt Flag on the processor
inline void enable_ints()
{
	asm("sti");
};

//Disables (CLears) Interrupt Flag on the processor
inline void disable_ints()
{
	asm("cli");
};

//Re-maps the Programmable Interrupr Controllers so IRQ0->pic1 base address, IRG8->pic2 base address
void remap_pics(int pic1, int pic2)
{
	byte	a1, a2;

	a1 = inportb(PIC1_DATA);      //0x21
	a2 = inportb(PIC2_DATA);      //0xA1

	outportb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);	//0x20, 0x10+0x01 00010001b
	outportb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);	//0xA0, 0x10+0x01 00010001b
	outportb(PIC1_DATA, pic1);			//0x21, pic1
	outportb(PIC2_DATA, pic2);			//0xA1, pic2
	outportb(PIC1_DATA, 4);				//0x21, 0x04      00000100b
	outportb(PIC2_DATA, 2);				//0xA1, 0x02      00000010b
	outportb(PIC1_DATA, ICW4_8086);			//0x21, 0x01      00000001b
	outportb(PIC2_DATA, ICW4_8086);			//0xA1, 0x01      00000001b

	outportb(PIC1_DATA, a1);			//0x21
	outportb(PIC2_DATA, a2);			//0xA1
}

//Masks interrupts on first Programmable Interrupt Controller
inline void pic1_mask(byte mask)
{
	outportb(PIC1_DATA, mask);			//0x21, maskfield *OCW1*
}

//Masks interrupts on second Programmable Interrupt Controller
inline void pic2_mask(byte mask)
{
 	outportb(PIC2_DATA, mask);			//0xA1, maskfield *OCW1*
}

//Restarts the computer
inline void restart()
{
 	byte temp;
	do
	{
		temp = inportb(0x64);
		if (temp & 1)
		inportb(0x60);
	} while(temp & 2);


	outportb (0x64, 0xfe);
	for (;;)
	{
	}
}

//Halts (freezes) the computer
inline void halt()
{
 	asm("cli");
 	asm("hlt");
 	while (1)
 	;
}

//Initializes 8253 Programmable Interrupt Timer
inline void init_timer()
{
 	//set timer : 2e9c = 100hz
	outportb(0x43, 0x34);
	outportb(0x40, 0x9c); //lsb
	outportb(0x40, 0x2e); //msb
}


//Invalidates the page tables to re-cache the Translation Lookaside Buffer
/*inline void invlpg()
{
	asm("invlpg");
}*/

//Signals an End Of Interrupt signal to the first PIC
inline void eoi()
{
	outportb(0x20, 0x20);
}

//Signals an End Of Interrupt signal to both the second and first PIC unit
inline void eoi2()
{
 	outportb(0xA0, 0x20);
 	outportb(0x20, 0x20);
}

//Returns the size of the kernel (code & data)
// - this does not include the bss section
// - this should be 4kb aligned per the linker script
// - this should be the size of kernel.bin
inline dword kernel_size()
{
	return (dword)(&_bss)-(dword)(&_code);
}









