#ifndef __IOPORT_H__
#define __IOPORT_H__

#include "types.h"

class IoPortLib
{
public:
    enum IoPort {
        PIC0_ICW1 = 0x20,
        PIC0_ICW2 = 0x21,
        PIC0_ICW3 = 0x21,
        PIC0_ICW4 = 0x21,
        PIC0_OCW1 = 0x21,
        PIC0_OCW2 = 0x20,
        PIC0_OCW3 = 0x20,
        PIC0_IMR  = 0x21,
        PIC1_ICW1 = 0xa0,
        PIC1_ICW2 = 0xa1,
        PIC1_ICW3 = 0xa1,
        PIC1_ICW4 = 0xa1,
        PIC1_OCW1 = 0xa1,
        PIC1_OCW2 = 0xa0,
        PIC1_OCW3 = 0xa0,
        PIC1_IMR  = 0xa1,

        PIT_CNT0  = 0x40,
        PIT_CNT1  = 0x41,
        PIT_CNT2  = 0x42,
        PIT_CTRL  = 0x43,

        KBD_DATA = 0x60,
        KBD_STS  = 0x61,
    };

    static __inline void out8(uint16 port, uint8 value) {
        __asm__ __volatile__ ("outb %%al, %%dx" :: "d" (port), "a" (value));
    }

    static void out16(IoPort port, uint16 value) {
        __asm__ __volatile__ ("outw %%ax, %%dx" :: "d" (port), "a" (value));
    }

    static void out32(IoPort port, uint32 value) {
        __asm__ __volatile__ ("outl %%eax, %%dx" :: "d" (port), "a" (value));
    }

    static uint8 in8(IoPort port) {
        uint8 value;
        __asm__ __volatile__ ("inb %%dx, %%al" : "=a" (value) : "d" (port));
        return value; 
    }

    static uint8 in16(IoPort port) {
        uint16 value;
        __asm__ __volatile__ ("inw %%dx, %%ax" : "=a" (value) : "d" (port));
        return value; 
    }

    static uint8 in32(IoPort port) {
        uint32 value;
        __asm__ __volatile__ ("inl %%dx, %%eax" : "=a" (value) : "d" (port));
        return value; 
    }
};

#endif /* __IOPORT_H__ */
