#ifndef __GDT_H__
#define __GDT_H__

#include "types.h"
#include "descripter.h"

struct GdtEntry 
{
    enum {
        G_FLAG   = 0x0800,
        D_FLAG   = 0x0400,
        AVL_FLAG = 0x0100,
        P_FLAG   = 0x0080,
        DPL0     = 0x0000,
        DPL1     = 0x0020,
        DPL2     = 0x0040,
        DPL3     = 0x0060,
        S_FLAG   = 0x0010,
        TYPE_CS  = 0x000A,
        TYPE_DS  = 0x0002,
        TYPE_SS  = 0x0006,
        A_FLAG   = 0x0001
    };
    uint16 limit_low;
    uint16 segbase_low;
    uint8  segbase_mid;
    uint8  type_low;
    uint8  type_hi  :4;
    uint8  limit_hi :4;
    uint8  segbase_hi;
} __attribute__ ((packed));

class Gdt 
{
public:
    static const int NUM = 8192;

    enum {
        NULL_S    = 0,
        KERNEL_CS = 1,
        KERNEL_DS = 2
    };

    static const uint16 KERNEL_CS_FLAG = 
        (GdtEntry::G_FLAG | GdtEntry::D_FLAG | GdtEntry::P_FLAG | 
         GdtEntry::DPL0   | GdtEntry::S_FLAG | GdtEntry::TYPE_CS); 
    static const uint16 KERNEL_DS_FLAG = 
        (GdtEntry::G_FLAG | GdtEntry::D_FLAG | GdtEntry::P_FLAG | 
         GdtEntry::DPL0   | GdtEntry::S_FLAG | GdtEntry::TYPE_DS); 

    void init(void);
    void set(int index, uint32 segbase, uint32 limit, uint16 type);
    void load(void) const;

private:
    DescripterTable table      __attribute__((aligned(8)));
    GdtEntry        entry[NUM] __attribute__((aligned(8)));
};

#endif /* __GDT_H__ */
