Hi Sebastian,
Do you have a test case for int1589 bios support? I've coded what I
think is a working implementation (see below), but I'm not sure how to
test it.
BTW, I think the Bochs BIOS implementation has bh and bl backwards.
-Kevin
diff --git a/src/pic.c b/src/pic.c
index f421bec..8992a8b 100644
--- a/src/pic.c
+++ b/src/pic.c
@@ -10,15 +10,14 @@
#include "config.h" // CONFIG_*
void
-pic_setup(void)
+set_pics(u8 irq0, u8 irq8)
{
- dprintf(3, "init pic\n");
// Send ICW1 (select OCW1 + will send ICW4)
outb(0x11, PORT_PIC1_CMD);
outb(0x11, PORT_PIC2_CMD);
// Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15)
- outb(0x08, PORT_PIC1_DATA);
- outb(0x70, PORT_PIC2_DATA);
+ outb(irq0, PORT_PIC1_DATA);
+ outb(irq8, PORT_PIC2_DATA);
// Send ICW3 (cascaded pic ids)
outb(0x04, PORT_PIC1_DATA);
outb(0x02, PORT_PIC2_DATA);
@@ -30,6 +29,13 @@ pic_setup(void)
outb(~0, PORT_PIC2_DATA);
}
+void
+pic_setup(void)
+{
+ dprintf(3, "init pic\n");
+ set_pics(0x08, 0x70);
+}
+
// Handler for otherwise unused hardware irqs.
void VISIBLE16
handle_hwpic1(struct bregs *regs)
diff --git a/src/pic.h b/src/pic.h
index 290fcb0..586ef38 100644
--- a/src/pic.h
+++ b/src/pic.h
@@ -98,6 +98,7 @@ __enable_hwirq(int hwirq, void (*func)(void))
__enable_hwirq(irq, func); \
} while (0)
+void set_pics(u8 irq0, u8 irq8);
void pic_setup(void);
#endif // pic.h
diff --git a/src/system.c b/src/system.c
index ffcced9..bf1fc62 100644
--- a/src/system.c
+++ b/src/system.c
@@ -182,6 +182,47 @@ handle_1588(struct bregs *regs)
set_success(regs);
}
+// Switch to protected mode
+static void
+handle_1589(struct bregs *regs)
+{
+ set_a20(1);
+
+ set_pics(regs->bl, regs->bh);
+
+ u64 *gdt_far = (void*)(regs->si + 0);
+ u16 gdt_seg = regs->es;
+ SET_FARVAR(gdt_seg, gdt_far[7], GDT_CODE | GDT_LIMIT(0x0ffff)
+ | GDT_BASE(0xf0000));
+
+ regs->ds = 3<<3; // 3rd gdt descriptor is %ds
+ regs->es = 4<<3; // 4th gdt descriptor is %es
+ regs->code.seg = 6<<3; // 6th gdt descriptor is %cs
+
+ set_code_success(regs);
+
+ asm volatile(
+ // Load new descriptor tables
+ " lgdtw %%es:(1<<3)(%%si)\n"
+ " lidtw %%es:(2<<3)(%%si)\n"
+
+ // Enable protected mode
+ " movl %%cr0, %%eax\n"
+ " orl $" __stringify(CR0_PE) ", %%eax\n"
+ " movl %%eax, %%cr0\n"
+
+ // far jump to flush CPU queue after transition to protected mode
+ " ljmpw $(7<<3), $1f\n"
+
+ // GDT points to valid descriptor table, now load SS
+ "1:movw $(5<<3), %%ax\n"
+ " movw %%ax, %%ds\n"
+ " movw %%ax, %%ss\n"
+ :
+ : "S"(gdt_far)
+ : "eax", "cc");
+}
+
// Device busy interrupt. Called by Int 16h when no key available
static void
handle_1590(struct bregs *regs)
@@ -309,6 +350,7 @@ handle_15(struct bregs *regs)
case 0x86: handle_1586(regs); break;
case 0x87: handle_1587(regs); break;
case 0x88: handle_1588(regs); break;
+ case 0x89: handle_1589(regs); break;
case 0x90: handle_1590(regs); break;
case 0x91: handle_1591(regs); break;
case 0xc0: handle_15c0(regs); break;