Add initial support for apmbios code.
authorKevin O'Connor <kevin@koconnor.net>
Thu, 6 Mar 2008 00:52:06 +0000 (19:52 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Thu, 6 Mar 2008 00:52:06 +0000 (19:52 -0500)
Makefile
src/apm.c [new file with mode: 0644]
src/system.c
src/util.h

index 1376a27..bb078f4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ OUT=out/
 
 # Source files
 SRC16=floppy.c disk.c system.c clock.c serial.c kbd.c mouse.c output.c \
-      boot.c ata.c cdrom.c
+      boot.c ata.c cdrom.c apm.c
 SRC32=post.c output.c
 TABLESRC=font.c cbt.c floppy_dbt.c
 
diff --git a/src/apm.c b/src/apm.c
new file mode 100644 (file)
index 0000000..9b6d1e3
--- /dev/null
+++ b/src/apm.c
@@ -0,0 +1,193 @@
+// Basic support for apmbios callbacks.
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2005 Struan Bartlett
+// Copyright (C) 2004 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "farptr.h" // GET_VAR
+#include "biosvar.h" // struct bregs
+#include "ioport.h" // outb
+#include "util.h" // irq_enable
+
+static void
+out_str(const char *str_cs)
+{
+    u8 *s = (u8*)str_cs;
+    for (;;) {
+        u8 c = GET_VAR(CS, *s);
+        if (!c)
+            break;
+        outb(c, 0x8900);
+        s++;
+    }
+}
+
+// APM installation check
+static void
+handle_155300(struct bregs *regs)
+{
+    regs->ah = 1; // APM major version
+    regs->al = 2; // APM minor version
+    regs->bh = 'P';
+    regs->bl = 'M';
+    // bit 0 : 16 bit interface supported
+    // bit 1 : 32 bit interface supported
+    regs->cx = 0x03;
+    set_cf(regs, 0);
+}
+
+// APM real mode interface connect
+static void
+handle_155301(struct bregs *regs)
+{
+    set_cf(regs, 0);
+}
+
+// APM 16 bit protected mode interface connect
+static void
+handle_155302(struct bregs *regs)
+{
+    regs->bx = 0; // XXX - apm16_entry
+    regs->ax = SEG_BIOS; // 16 bit code segment base
+    regs->si = 0xfff0;   // 16 bit code segment size
+    regs->cx = SEG_BIOS; // data segment address
+    regs->di = 0xfff0;   // data segment length
+    set_cf(regs, 0);
+}
+
+// APM 32 bit protected mode interface connect
+static void
+handle_155303(struct bregs *regs)
+{
+    regs->ax = 0xf000; // 32 bit code segment base
+    regs->ebx = 0; // XXX - apm32_entry
+    regs->cx = 0xf000; // 16 bit code segment base
+    // 32 bit code segment size (low 16 bits)
+    // 16 bit code segment size (high 16 bits)
+    regs->esi = 0xfff0fff0;
+    regs->dx = 0xf000; // data segment address
+    regs->di = 0xfff0; // data segment length
+    set_cf(regs, 0);
+}
+
+// APM interface disconnect
+static void
+handle_155304(struct bregs *regs)
+{
+    set_cf(regs, 0);
+}
+
+// APM cpu idle
+static void
+handle_155305(struct bregs *regs)
+{
+    irq_enable();
+    hlt();
+    set_cf(regs, 0);
+}
+
+// APM Set Power State
+static void
+handle_155307(struct bregs *regs)
+{
+    if (regs->bx != 1) {
+        set_cf(regs, 0);
+        return;
+    }
+    switch (regs->cx) {
+    case 1:
+        out_str("Standby");
+        break;
+    case 2:
+        out_str("Suspend");
+        break;
+    case 3:
+        irq_disable();
+        out_str("Shutdown");
+        for (;;)
+            hlt();
+        break;
+    }
+    set_cf(regs, 0);
+}
+
+static void
+handle_155308(struct bregs *regs)
+{
+    set_cf(regs, 0);
+}
+
+// Get Power Status
+static void
+handle_15530a(struct bregs *regs)
+{
+    regs->bh = 0x01; // on line
+    regs->bl = 0xff; // unknown battery status
+    regs->ch = 0x80; // no system battery
+    regs->cl = 0xff; // unknown remaining time
+    regs->dx = 0xffff; // unknown remaining time
+    regs->si = 0x00; // zero battery
+    set_cf(regs, 0);
+}
+
+// Get PM Event
+static void
+handle_15530b(struct bregs *regs)
+{
+    regs->ah = 0x80; // no event pending
+    set_cf(regs, 1);
+}
+
+// APM Driver Version
+static void
+handle_15530e(struct bregs *regs)
+{
+    regs->ah = 1;
+    regs->al = 2;
+    set_cf(regs, 0);
+}
+
+// APM Engage / Disengage
+static void
+handle_15530f(struct bregs *regs)
+{
+    set_cf(regs, 0);
+}
+
+// APM Get Capabilities
+static void
+handle_155310(struct bregs *regs)
+{
+    regs->bl = 0;
+    regs->cx = 0;
+    set_cf(regs, 0);
+}
+
+static void
+handle_1553XX(struct bregs *regs)
+{
+    set_cf(regs, 1);
+}
+
+void
+handle_1553(struct bregs *regs)
+{
+    switch (regs->al) {
+    case 0x00: handle_155300(regs); break;
+    case 0x01: handle_155301(regs); break;
+    case 0x02: handle_155302(regs); break;
+    case 0x03: handle_155303(regs); break;
+    case 0x04: handle_155304(regs); break;
+    case 0x05: handle_155305(regs); break;
+    case 0x07: handle_155307(regs); break;
+    case 0x08: handle_155308(regs); break;
+    case 0x0a: handle_15530a(regs); break;
+    case 0x0b: handle_15530b(regs); break;
+    case 0x0e: handle_15530e(regs); break;
+    case 0x0f: handle_15530f(regs); break;
+    case 0x10: handle_155310(regs); break;
+    default:   handle_1553XX(regs); break;
+    }
+}
index e09797b..29f0052 100644 (file)
@@ -78,13 +78,6 @@ handle_1552(struct bregs *regs)
     handle_ret(regs, 0);
 }
 
-static void
-handle_1553(struct bregs *regs)
-{
-    // XXX - APM call
-    handle_ret(regs, RET_EUNSUPPORTED);
-}
-
 // Sleep for n microseconds. currently using the
 // refresh request port 0x61 bit4, toggling every 15usec
 static void
index 29446b3..e84c7d8 100644 (file)
@@ -37,6 +37,11 @@ static inline void nop(void)
     asm volatile("nop");
 }
 
+static inline void hlt(void)
+{
+    asm volatile("hlt");
+}
+
 #define BX_PANIC(fmt, args...) bprintf(0, fmt , ##args)
 #define BX_INFO(fmt, args...) bprintf(0, fmt , ##args)
 
@@ -121,6 +126,9 @@ void handle_15c2(struct bregs *regs);
 // clock.c
 void handle_1583(struct bregs *regs);
 
+// apm.c
+void handle_1553(struct bregs *regs);
+
 // Frequent bios return helper
 #define RET_EUNSUPPORTED 0x86
 static inline void