Add initial support for apmbios code.
This commit is contained in:
parent
180a959053
commit
95b2f78f97
2
Makefile
2
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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue