gdt
[3sys] / sys1 / kern / src / desc.c
diff --git a/sys1/kern/src/desc.c b/sys1/kern/src/desc.c
new file mode 100644 (file)
index 0000000..d02c5fc
--- /dev/null
@@ -0,0 +1,45 @@
+#include "desc.h"
+
+#define SEG_TYPE_SYSTEM        0
+#define SEG_TYPE_CODE  0x00001800
+#define SEG_TYPE_DATA  0x00001000
+#define SEG_TYPE_TSS   0x00000100
+#define SEG_TYPE_INTR  0x00000e00
+#define SEG_TYPE_TRAP  0x00000f00
+
+#define SEG_ACCESSED   0x00000100
+#define SEG_PRESENT            0x00008000
+#define SEG_AVL                        0x00100000
+#define SEG_GRAN               0x00800000
+
+/* data segment type flags */
+#define SEG_WR                 0x00000200
+#define SEG_EXPDN              0x00000400
+#define SEG_BIG                        0x00400000
+/* code segment type flags */
+#define SEG_RD                 0x00000200
+#define SEG_CONFORM            0x00000400
+#define SEG_DEF                        0x00400000
+
+
+void desc_seg(struct desc *desc, int type, uint32_t base, uint32_t limit, int dpl)
+{
+       if(type == SEG_NULL) {
+               desc->d[0] = desc->d[1] = 0;
+               return;
+       }
+
+       desc->d[0] = (limit & 0xffff) | (base << 16);
+       desc->d[1] = ((base >> 16) & 0xff) | (type << 8) | SEG_PRESENT | (dpl << 13);
+       desc->d[1] |= (base & 0xff000000) | (limit & 0xf0000) | SEG_AVL | SEG_GRAN;
+
+       switch(type) {
+       case SEG_CODE:
+               desc->d[1] |= (3 << 11) | SEG_DEF | SEG_RD;
+               break;
+
+       case SEG_DATA:
+               desc->d[1] |= (2 << 11) | SEG_WR;
+               break;
+       }
+}