aboutsummaryrefslogtreecommitdiff
path: root/src/system.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2010-01-04 20:48:20 -0500
committerKevin O'Connor <kevin@koconnor.net>2010-01-04 20:48:20 -0500
commit643062f9bc208911e3f27265c697dbde151d4f56 (patch)
tree5e85a225c69eb106ee98b76803ffe58d2572a726 /src/system.c
parent085debd93f52d36381ea13ef27e7f72e87fe62f5 (diff)
downloadseabios-hppa-643062f9bc208911e3f27265c697dbde151d4f56.zip
seabios-hppa-643062f9bc208911e3f27265c697dbde151d4f56.tar.gz
seabios-hppa-643062f9bc208911e3f27265c697dbde151d4f56.tar.bz2
Add int1589 support.
Int1589 switches into protected mode for the caller. Also, consistently use BUILD_BIOS_ADDR/SIZE in GDT macros.
Diffstat (limited to 'src/system.c')
-rw-r--r--src/system.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/src/system.c b/src/system.c
index ffcced9..f72151b 100644
--- a/src/system.c
+++ b/src/system.c
@@ -111,8 +111,8 @@ handle_1587(struct bregs *regs)
SET_FARVAR(gdt_seg, gdt_far[1], GDT_DATA | GDT_LIMIT((6*sizeof(u64))-1)
| GDT_BASE(loc));
// Initialize CS descriptor
- SET_FARVAR(gdt_seg, gdt_far[4], GDT_CODE | GDT_LIMIT(0x0ffff)
- | GDT_BASE(0xf0000));
+ SET_FARVAR(gdt_seg, gdt_far[4], GDT_CODE | GDT_LIMIT(BUILD_BIOS_SIZE-1)
+ | GDT_BASE(BUILD_BIOS_ADDR));
// Initialize SS descriptor
loc = (u32)MAKE_FLATPTR(GET_SEG(SS), 0);
SET_FARVAR(gdt_seg, gdt_far[5], GDT_DATA | GDT_LIMIT(0x0ffff)
@@ -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(BUILD_BIOS_SIZE-1)
+ | GDT_BASE(BUILD_BIOS_ADDR));
+
+ 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;