// bit 0 : 16 bit interface supported
// bit 1 : 32 bit interface supported
regs->cx = 0x03;
- set_cf(regs, 0);
+ set_success(regs);
}
// APM real mode interface connect
static void
handle_155301(struct bregs *regs)
{
- set_cf(regs, 0);
+ set_success(regs);
}
// Assembler entry points defined in romlayout.S
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);
+ set_success(regs);
}
// APM 32 bit protected mode interface connect
regs->esi = 0xfff0fff0;
regs->dx = SEG_BIOS; // data segment address
regs->di = 0xfff0; // data segment length
- set_cf(regs, 0);
+ set_success(regs);
}
// APM interface disconnect
static void
handle_155304(struct bregs *regs)
{
- set_cf(regs, 0);
+ set_success(regs);
}
// APM cpu idle
{
irq_enable();
hlt();
- set_cf(regs, 0);
+ set_success(regs);
}
// APM Set Power State
handle_155307(struct bregs *regs)
{
if (regs->bx != 1) {
- set_cf(regs, 0);
+ set_success(regs);
return;
}
switch (regs->cx) {
hlt();
break;
}
- set_cf(regs, 0);
+ set_success(regs);
}
static void
handle_155308(struct bregs *regs)
{
- set_cf(regs, 0);
+ set_success(regs);
}
// Get Power Status
regs->cl = 0xff; // unknown remaining time
regs->dx = 0xffff; // unknown remaining time
regs->si = 0x00; // zero battery
- set_cf(regs, 0);
+ set_success(regs);
}
// Get PM Event
static void
handle_15530b(struct bregs *regs)
{
+ set_fail(regs);
regs->ah = 0x80; // no event pending
- set_cf(regs, 1);
}
// APM Driver Version
{
regs->ah = 1;
regs->al = 2;
- set_cf(regs, 0);
+ set_success(regs);
}
// APM Engage / Disengage
static void
handle_15530f(struct bregs *regs)
{
- set_cf(regs, 0);
+ set_success(regs);
}
// APM Get Capabilities
{
regs->bl = 0;
regs->cx = 0;
- set_cf(regs, 0);
+ set_success(regs);
}
static void
handle_1553XX(struct bregs *regs)
{
- set_cf(regs, 1);
+ set_fail(regs);
}
void VISIBLE16
static void
cdrom_1349(struct bregs *regs, u8 device)
{
+ set_fail(regs);
// always send changed ??
regs->ah = DISK_RET_ECHANGED;
- set_cf(regs, 1);
}
static void
regs->dx = ticks;
regs->al = GET_BDA(timer_rollover);
SET_BDA(timer_rollover, 0); // reset flag
- set_cf(regs, 0);
+ set_success(regs);
}
// Set Current Clock Count
SET_BDA(timer_counter, ticks);
SET_BDA(timer_rollover, 0); // reset flag
regs->ah = 0;
- set_cf(regs, 0);
+ set_success(regs);
}
// Read CMOS Time
handle_1a02(struct bregs *regs)
{
if (rtc_updating()) {
- set_cf(regs, 1);
+ set_fail(regs);
return;
}
regs->dl = inb_cmos(CMOS_STATUS_B) & 0x01;
regs->ah = 0;
regs->al = regs->ch;
- set_cf(regs, 0);
+ set_success(regs);
}
// Set CMOS Time
outb_cmos(val8, CMOS_STATUS_B);
regs->ah = 0;
regs->al = val8; // val last written to Reg B
- set_cf(regs, 0);
+ set_success(regs);
}
// Read CMOS Date
{
regs->ah = 0;
if (rtc_updating()) {
- set_cf(regs, 1);
+ set_fail(regs);
return;
}
regs->cl = inb_cmos(CMOS_RTC_YEAR);
regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH);
regs->ch = inb_cmos(CMOS_CENTURY);
regs->al = regs->ch;
- set_cf(regs, 0);
+ set_success(regs);
}
// Set CMOS Date
// My assumption: RegB = (RegB & 01111111b)
if (rtc_updating()) {
init_rtc();
- set_cf(regs, 1);
+ set_fail(regs);
return;
}
outb_cmos(regs->cl, CMOS_RTC_YEAR);
outb_cmos(val8, CMOS_STATUS_B);
regs->ah = 0;
regs->al = val8; // AL = val last written to Reg B
- set_cf(regs, 0);
+ set_success(regs);
}
// Set Alarm Time in CMOS
regs->ax = 0;
if (val8 & 0x20) {
// Alarm interrupt enabled already
- set_cf(regs, 1);
+ set_fail(regs);
return;
}
if (rtc_updating()) {
outb(inb(PORT_PIC2_DATA) & ~PIC2_IRQ8, PORT_PIC2_DATA); // enable IRQ 8
// enable Status Reg B alarm bit, clear halt clock bit
outb_cmos((val8 & 0x7f) | 0x20, CMOS_STATUS_B);
- set_cf(regs, 0);
+ set_success(regs);
}
// Turn off Alarm
outb_cmos(val8 & 0x57, CMOS_STATUS_B); // disable alarm bit
regs->ah = 0;
regs->al = val8; // val last written to Reg B
- set_cf(regs, 0);
+ set_success(regs);
}
static void
handle_1ab1(struct bregs *regs)
{
// XXX - pcibios stuff
- set_cf(regs, 1);
+ set_fail(regs);
}
// Unsupported
static void
handle_1aXX(struct bregs *regs)
{
- set_cf(regs, 1);
+ set_fail(regs);
}
// INT 1Ah Time-of-day Service Entry Point
case 0xb1: handle_1ab1(regs); break;
default: handle_1aXX(regs); break;
}
- debug_exit(regs);
}
// User Timer Tick
if (GET_BDA(rtc_wait_flag) & RWS_WAIT_PENDING) {
// Interval already set.
DEBUGF("int15: Func 83h, failed, already waiting.\n" );
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
}
// Interval not already set.
SET_BDA(rtc_wait_flag, RWS_WAIT_PENDING); // Set status byte.
u8 bRegister = inb_cmos(CMOS_STATUS_B);
outb_cmos(CMOS_STATUS_B, bRegister | CSB_EN_ALARM_IRQ);
- set_cf(regs, 0); // XXX - no set ah?
+ set_success(regs); // XXX - no set ah?
}
// Clear interval requested
// Turn off the Periodic Interrupt timer
u8 bRegister = inb_cmos(CMOS_STATUS_B);
outb_cmos(CMOS_STATUS_B, bRegister & ~CSB_EN_ALARM_IRQ);
- set_cf(regs, 0); // XXX - no set ah?
+ set_success(regs); // XXX - no set ah?
}
static void
handle_1583XX(struct bregs *regs)
{
+ set_code_fail(regs, RET_EUNSUPPORTED);
regs->al--;
- handle_ret(regs, RET_EUNSUPPORTED);
}
void
{
debug_enter(regs);
handle_legacy_disk(regs, regs->dl);
- debug_exit(regs);
}
// INT 13h Fixed Disk Services Entry Point
if (CONFIG_CDROM_BOOT) {
if (regs->ah == 0x4b) {
cdemu_134b(regs);
- goto done;
+ return;
}
if (GET_EBDA(cdemu.active)) {
if (drive == GET_EBDA(cdemu.emulated_drive)) {
cdemu_13(regs);
- goto done;
+ return;
}
if (drive < 0xe0)
drive--;
}
}
handle_legacy_disk(regs, drive);
-done:
- debug_exit(regs);
}
// record completion in BIOS task complete flag
static inline void
floppy_ret(struct bregs *regs, u8 code)
{
- regs->ah = code;
SET_BDA(floppy_last_status, code);
- set_cf(regs, code);
+ if (code)
+ set_code_fail(regs, code);
+ else
+ set_code_success(regs);
}
static inline void
floppy_fail(struct bregs *regs, u8 code)
{
- regs->al = 0; // no sectors read
floppy_ret(regs, code);
+ regs->al = 0; // no sectors read
}
static u16
if (data[0] & 0xc0) {
if (data[1] & 0x02) {
+ set_fail(regs);
regs->ax = 0x0300;
- set_cf(regs, 1);
return;
}
BX_PANIC("int13_diskette_function: read error\n");
if (data[0] & 0xc0) {
if (data[1] & 0x02) {
+ set_fail(regs);
regs->ax = 0x0300;
- set_cf(regs, 1);
return;
}
BX_PANIC("int13_diskette_function: read error\n");
regs->es = 0;
regs->di = 0;
regs->dl = num_floppies;
- set_cf(regs, 0);
+ set_success(regs);
return;
}
{
DEBUGF("floppy f15\n");
if (drive > 1) {
+ set_fail(regs);
regs->ah = 0; // only 2 drives supported
// set_diskette_ret_status here ???
- set_cf(regs, 1);
return;
}
u8 drive_type = get_drive_type(drive);
regs->ah = (drive_type != 0);
- set_cf(regs, 0);
+ set_success(regs);
}
// get diskette change line status
send_to_mouse_ctrl(0xF5); // disable mouse command
u8 mouse_data1;
get_mouse_data(&mouse_data1);
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
}
#define BX_DEBUG_INT15(args...)
u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
if ((mouse_flags_2 & 0x80) == 0) {
BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n");
- handle_ret(regs, RET_ENOHANDLER);
+ set_code_fail(regs, RET_ENOHANDLER);
return;
}
inhibit_mouse_int_and_events(); // disable IRQ12 and packets
get_mouse_data(&mouse_data1);
if (mouse_data1 == 0xFA) {
enable_mouse_int_and_events(); // turn IRQ12 and packet generation on
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
return;
}
- handle_ret(regs, RET_ENEEDRESEND);
+ set_code_fail(regs, RET_ENEEDRESEND);
}
static void
mouse_15c200XX(struct bregs *regs)
{
- handle_ret(regs, RET_EINVFUNCTION);
+ set_code_fail(regs, RET_EINVFUNCTION);
}
// Disable/Enable Mouse
get_mouse_data(&mouse_data3);
// if no mouse attached, it will return RESEND
if (mouse_data3 == 0xfe) {
- handle_ret(regs, RET_ENEEDRESEND);
+ set_code_fail(regs, RET_ENEEDRESEND);
return;
}
if (mouse_data3 != 0xfa)
enable_mouse_int_and_events();
regs->bl = mouse_data1;
regs->bh = mouse_data2;
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
}
// Set Sample Rate
mouse_15c202(struct bregs *regs)
{
if (regs->bh >= 7) {
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
return;
}
u8 mouse_data1 = regs->bh * 20;
get_mouse_data(&mouse_data2);
send_to_mouse_ctrl(mouse_data1);
get_mouse_data(&mouse_data2);
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
}
// Set Resolution
// 3 = 200 dpi, 8 counts per millimeter
u8 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
if (regs->bh >= 4) {
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
goto done;
}
send_to_mouse_ctrl(0xE8); // set resolution command
if (mouse_data1 != 0xfa)
BX_PANIC("Mouse status returned %02x (should be ack)\n"
, (unsigned)mouse_data1);
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
done:
set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
get_mouse_data(&mouse_data1);
get_mouse_data(&mouse_data2);
regs->bh = mouse_data2;
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
}
// Initialize Mouse
mouse_15c205(struct bregs *regs)
{
if (regs->bh != 3) {
- handle_ret(regs, RET_EINTERFACE);
+ set_code_fail(regs, RET_EINTERFACE);
return;
}
SET_EBDA(mouse_flag1, 0x00);
regs->bl = mouse_data1;
regs->cl = mouse_data2;
regs->dl = mouse_data3;
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
}
u8 mouse_data1;
get_mouse_data(&mouse_data1);
if (mouse_data1 != 0xFA)
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
else
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
}
mouse_flags_2 |= 0x80;
}
SET_EBDA(mouse_flag2, mouse_flags_2);
- handle_ret(regs, RET_SUCCESS);
+ set_code_success(regs);
}
static void
mouse_15c2XX(struct bregs *regs)
{
- handle_ret(regs, RET_EINVFUNCTION);
+ set_code_fail(regs, RET_EINVFUNCTION);
}
void
//debug_stub(regs);
if (! CONFIG_PS2_MOUSE) {
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
return;
}
}
void
-__debug_exit(const char *fname, struct bregs *regs)
+__debug_fail(const char *fname, struct bregs *regs)
{
- if (! (regs->flags & F_CF))
- return;
- dump_regs(fname, "exit", regs);
+ dump_regs(fname, "fail", regs);
}
void
getComAddr(struct bregs *regs)
{
if (regs->dx >= 4) {
- set_cf(regs, 1);
+ set_fail(regs);
return 0;
}
u16 addr = GET_BDA(port_com[regs->dx]);
if (! addr)
- set_cf(regs, 1);
+ set_fail(regs);
return addr;
}
outb(regs->al & 0x1F, addr+3);
regs->ah = inb(addr+5);
regs->al = inb(addr+6);
- set_cf(regs, 0);
+ set_success(regs);
}
static void
regs->ah = inb(addr+5);
if (!timeout)
regs->ah |= 0x80;
- set_cf(regs, 0);
+ set_success(regs);
}
static void
} else {
regs->ah = inb(addr+5);
}
- set_cf(regs, 0);
+ set_success(regs);
}
static void
return;
regs->ah = inb(addr+5);
regs->al = inb(addr+6);
- set_cf(regs, 0);
+ set_success(regs);
}
static void
handle_14XX(struct bregs *regs)
{
// Unsupported
- set_cf(regs, 1);
+ set_fail(regs);
}
// INT 14h Serial Communications Service Entry Point
case 0x03: handle_1403(regs); break;
default: handle_14XX(regs); break;
}
- debug_exit(regs);
}
getLptAddr(struct bregs *regs)
{
if (regs->dx >= 3) {
- set_cf(regs, 1);
+ set_fail(regs);
return 0;
}
u16 addr = GET_BDA(port_lpt[regs->dx]);
if (! addr)
- set_cf(regs, 1);
+ set_fail(regs);
return addr;
}
regs->ah = (val8 ^ 0x48);
if (!timeout)
regs->ah |= 0x01;
- set_cf(regs, 0);
+ set_success(regs);
}
// INT 17 - PRINTER - WRITE CHARACTER
handle_17XX(struct bregs *regs)
{
// Unsupported
- set_cf(regs, 1);
+ set_fail(regs);
}
// INT17h : Printer Service Entry Point
case 0x02: handle_1702(regs); break;
default: handle_17XX(regs); break;
}
- debug_exit(regs);
}
handle_152400(struct bregs *regs)
{
set_a20(0);
- handle_ret(regs, 0);
+ set_code_success(regs);
}
static void
handle_152401(struct bregs *regs)
{
set_a20(1);
- handle_ret(regs, 0);
+ set_code_success(regs);
}
static void
handle_152402(struct bregs *regs)
{
regs->al = !!(inb(PORT_A20) & 0x20);
- handle_ret(regs, 0);
+ set_code_success(regs);
}
static void
handle_152403(struct bregs *regs)
{
regs->bx = 3;
- handle_ret(regs, 0);
+ set_code_success(regs);
}
static void
handle_1524XX(struct bregs *regs)
{
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
}
static void
static void
handle_1552(struct bregs *regs)
{
- handle_ret(regs, 0);
+ set_code_success(regs);
}
// Wait for CX:DX microseconds. currently using the
set_a20(prev_a20_enable);
- handle_ret(regs, 0);
+ set_code_success(regs);
}
// Get the amount of extended memory (above 1M)
// but real machines mostly return max. 63M.
if (regs->ax > 0xffc0)
regs->ax = 0xffc0;
- set_cf(regs, 0);
+ set_success(regs);
}
// Device busy interrupt. Called by Int 16h when no key available
static void
handle_154f(struct bregs *regs)
{
+ // set_fail(regs); -- don't report this failure.
set_cf(regs, 1);
}
{
regs->es = SEG_BIOS;
regs->bx = (u16)&BIOS_CONFIG_TABLE;
- handle_ret(regs, 0);
+ set_code_success(regs);
}
static void
handle_15c1(struct bregs *regs)
{
regs->es = GET_BDA(ebda_seg);
- set_cf(regs, 0);
+ set_success(regs);
}
static void
regs->ax = regs->cx;
regs->bx = regs->dx;
- set_cf(regs, 0);
+ set_success(regs);
}
#define ACPI_DATA_SIZE 0x00010000L
handle_15e820(struct bregs *regs)
{
if (regs->edx != 0x534D4150) {
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
return;
}
regs->ebx = 1;
regs->eax = 0x534D4150;
regs->ecx = 0x14;
- set_cf(regs, 0);
+ set_success(regs);
break;
case 1:
set_e820_range(regs->di, 0x0009fc00L, 0x000a0000L, E820_RESERVED);
regs->ebx = 2;
regs->eax = 0x534D4150;
regs->ecx = 0x14;
- set_cf(regs, 0);
+ set_success(regs);
break;
case 2:
set_e820_range(regs->di, 0x000e8000L, 0x00100000L, E820_RESERVED);
regs->ebx = 3;
regs->eax = 0x534D4150;
regs->ecx = 0x14;
- set_cf(regs, 0);
+ set_success(regs);
break;
case 3:
set_e820_range(regs->di, 0x00100000L,
regs->ebx = 4;
regs->eax = 0x534D4150;
regs->ecx = 0x14;
- set_cf(regs, 0);
+ set_success(regs);
break;
case 4:
set_e820_range(regs->di,
set_cf(regs, 0);
break;
default: /* AX=E820, DX=534D4150, BX unrecognized */
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
}
}
static void
handle_15e8XX(struct bregs *regs)
{
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
}
static void
static void
handle_15XX(struct bregs *regs)
{
- handle_ret(regs, RET_EUNSUPPORTED);
+ set_code_fail(regs, RET_EUNSUPPORTED);
}
// INT 15h System Services Entry Point
case 0xe8: handle_15e8(regs); break;
default: handle_15XX(regs); break;
}
- //debug_exit(regs);
}
// INT 12h Memory Size Service Entry Point
{
debug_enter(regs);
regs->ax = GET_BDA(mem_size_kb);
- debug_exit(regs);
}
// INT 11h Equipment List Service Entry Point
{
debug_enter(regs);
regs->ax = GET_BDA(equipment_list_flags);
- debug_exit(regs);
}
// INT 05h Print Screen Service Entry Point
void bprintf(u16 action, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
void __debug_enter(const char *fname, struct bregs *regs);
-void __debug_exit(const char *fname, struct bregs *regs);
+void __debug_fail(const char *fname, struct bregs *regs);
void __debug_stub(const char *fname, struct bregs *regs);
void __debug_isr(const char *fname, struct bregs *regs);
#define debug_enter(regs) \
__debug_enter(__func__, regs)
-#define debug_exit(regs) \
- __debug_exit(__func__, regs)
#define debug_stub(regs) \
__debug_stub(__func__, regs)
#define debug_isr(regs) \
#define printf(fmt, args...) \
bprintf(1, fmt , ##args )
+// Frequently used return codes
+#define RET_EUNSUPPORTED 0x86
+static inline void
+set_success(struct bregs *regs)
+{
+ set_cf(regs, 0);
+}
+
+static inline void
+set_code_success(struct bregs *regs)
+{
+ regs->ah = 0;
+ set_cf(regs, 0);
+}
+
+#define set_fail(regs) do { \
+ __debug_fail(__func__, (regs)); \
+ set_cf((regs), 1); \
+ } while (0)
+
+#define set_code_fail(regs, code) do { \
+ (regs)->ah = (code); \
+ set_fail(regs); \
+ } while (0)
+
// kbd.c
void handle_15c2(struct bregs *regs);
// apm.c
void VISIBLE16 handle_1553(struct bregs *regs);
-// Frequent bios return helper
-#define RET_EUNSUPPORTED 0x86
-static inline void
-handle_ret(struct bregs *regs, u8 code)
-{
- regs->ah = code;
- set_cf(regs, code);
-}
-
// util.c
void usleep(u32 count);