#include <stdio.h> #include <stdtypes.h> #include "testbios.h" extern int verbose; #ifndef _PC /* * This is derived from a number of PC system BIOS'es. The intent here is to * provide very primitive video support, before an EGA/VGA BIOS installs its * own interrupt vector. Here, "Ignored" calls should remain so. "Not * Implemented" denotes functionality that can be implemented should the need * arise. What are "Not Implemented" throughout are video memory accesses. * Also, very little input validity checking is done here. */ int int42_handler(void) { #if 0 if (verbose && X86_AH != 0x0e) { printf("int%x\n", current->num); x86emu_dump_xregs(); } switch (X86_AH) { case 0x00: /* Set Video Mode */ /* Enter: AL = video mode number */ /* Leave: Nothing */ /* Implemented (except for clearing the screen) */ { /* Localise */ int i; u16 ioport, int1d, regvals, tmp; u8 mode, cgamode, cgacolour; /* * Ignore all mode numbers but 0x00-0x13. Some systems also ignore * 0x0B and 0x0C, but don't do that here. */ if (X86_AL > 0x13) break; /* * You didn't think that was really the mode set, did you? There * are only so many slots in the video parameter table... */ mode = X86_AL; ioport = 0x03D4; switch (MEM_RB(0x0410) & 0x30) { case 0x30: /* MDA */ mode = 0x07; /* Force mode to 0x07 */ ioport = 0x03B4; break; case 0x10: /* CGA 40x25 */ if (mode >= 0x07) mode = 0x01; break; case 0x20: /* CGA 80x25 (MCGA?) */ if (mode >= 0x07) mode = 0x03; break; case 0x00: /* EGA/VGA */ if (mode >= 0x07) /* Don't try MDA timings */ mode = 0x01; /* !?!?! */ break; } /* Locate data in video parameter table */ int1d = MEM_RW(0x1d << 2); regvals = ((mode >> 1) << 4) + int1d; cgacolour = 0x30; if (mode == 0x06) { regvals -= 0x10; cgacolour = 0x3F; } /** Update BIOS Data Area **/ /* Video mode */ MEM_WB(0x0449, mode); /* Columns */ tmp = MEM_RB(mode + int1d + 0x48); MEM_WW(0x044A, tmp); /* Page length */ tmp = MEM_RW((mode & 0x06) + int1d + 0x40); MEM_WW(0x044C, tmp); /* Start Address */ MEM_WW(0x044E, 0); /* Cursor positions, one for each display page */ for (i = 0x0450; i < 0x0460; i += 2) MEM_WW(i, 0); /* Cursor start & end scanlines */ tmp = MEM_RB(regvals + 0x0B); MEM_WB(0x0460, tmp); tmp = MEM_RB(regvals + 0x0A); MEM_WB(0x0461, tmp); /* Current display page number */ MEM_WB(0x0462, 0); /* CRTC I/O address */ MEM_WW(0x0463, ioport); /* CGA Mode register value */ cgamode = MEM_RB(mode + int1d + 0x50); MEM_WB(0x0465, cgamode); /* CGA Colour register value */ MEM_WB(0x0466, cgacolour); /* Rows */ MEM_WB(0x0484, (25 - 1)); /* Programme the mode */ outb(ioport + 4, cgamode & 0x37); /* Turn off screen */ for (i = 0; i < 0x10; i++) { tmp = MEM_RB(regvals + i); outb(ioport, i); outb(ioport + 1, tmp); } outb(ioport + 5, cgacolour); /* Select colour mode */ outb(ioport + 4, cgamode); /* Turn on screen */ } break; case 0x01: /* Set Cursor Type */ /* Enter: CH = starting line for cursor */ /* CL = ending line for cursor */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ u16 ioport = MEM_RW(0x0463); MEM_WB(0x0460, X86_CL); MEM_WB(0x0461, X86_CH); outb(ioport, 0x0A); outb(ioport + 1, X86_CH); outb(ioport, 0x0B); outb(ioport + 1, X86_CL); } break; case 0x02: /* Set Cursor Position */ /* Enter: BH = display page number */ /* DH = row */ /* DL = column */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ u16 offset, ioport; MEM_WB((X86_BH << 1) + 0x0450, X86_DL); MEM_WB((X86_BH << 1) + 0x0451, X86_DH); if (X86_BH != MEM_RB(0x0462)) break; offset = (X86_DH * MEM_RW(0x044A)) + X86_DL; offset += MEM_RW(0x044E) << 1; ioport = MEM_RW(0x0463); outb(ioport, 0x0E); outb(ioport + 1, offset >> 8); outb(ioport, 0x0F); outb(ioport + 1, offset & 0xFF); } break; case 0x03: /* Get Cursor Position */ /* Enter: BH = display page number */ /* Leave: CH = starting line for cursor */ /* CL = ending line for cursor */ /* DH = row */ /* DL = column */ /* Implemented */ { /* Localise */ X86_CL = MEM_RB(0x0460); X86_CH = MEM_RB(0x0461); X86_DL = MEM_RB((X86_BH << 1) + 0x0450); X86_DH = MEM_RB((X86_BH << 1) + 0x0451); } break; case 0x04: /* Get Light Pen Position */ /* Enter: Nothing */ /* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */ /* BX = pixel column */ /* CX = pixel row */ /* DH = character row */ /* DL = character column */ /* Not Implemented */ { /* Localise */ printf("int%x - Get Light Pen Position. " "Function not implemented.\n", current->num); x86emu_dump_xregs(); X86_AH = X86_BX = X86_CX = X86_DX = 0; } break; case 0x05: /* Set Display Page */ /* Enter: AL = display page number */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ u16 start, ioport = MEM_RW(0x0463); u8 x, y; /* Calculate new start address */ MEM_WB(0x0462, X86_AL); start = X86_AL * MEM_RW(0x044C); MEM_WW(0x044E, start); start <<= 1; /* Update start address */ outb(ioport, 0x0C); outb(ioport + 1, start >> 8); outb(ioport, 0x0D); outb(ioport + 1, start & 0xFF); /* Switch cursor position */ y = MEM_RB((X86_AL << 1) + 0x0450); x = MEM_RB((X86_AL << 1) + 0x0451); start += (y * MEM_RW(0x044A)) + x; /* Update cursor position */ outb(ioport, 0x0E); outb(ioport + 1, start >> 8); outb(ioport, 0x0F); outb(ioport + 1, start & 0xFF); } break; case 0x06: /* Initialise or Scroll Window Up */ /* Enter: AL = lines to scroll up */ /* BH = attribute for blank */ /* CH = upper y of window */ /* CL = left x of window */ /* DH = lower y of window */ /* DL = right x of window */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printf("int%x: Initialise or Scroll Window Up - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); } break; case 0x07: /* Initialise or Scroll Window Down */ /* Enter: AL = lines to scroll down */ /* BH = attribute for blank */ /* CH = upper y of window */ /* CL = left x of window */ /* DH = lower y of window */ /* DL = right x of window */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printf("int%x: Initialise or Scroll Window Down - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); } break; case 0x08: /* Read Character and Attribute at Cursor */ /* Enter: BH = display page number */ /* Leave: AH = attribute */ /* AL = character */ /* Not Implemented */ { /* Localise */ printf ("int%x: Read Character and Attribute at Cursor - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); X86_AX = 0; } break; case 0x09: /* Write Character and Attribute at Cursor */ /* Enter: AL = character */ /* BH = display page number */ /* BL = attribute (text) or colour (graphics) */ /* CX = replication count */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printf ("int%x: Write Character and Attribute at Cursor - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); } break; case 0x0a: /* Write Character at Cursor */ /* Enter: AL = character */ /* BH = display page number */ /* BL = colour */ /* CX = replication count */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printf("int%x: Write Character at Cursor - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); } break; case 0x0b: /* Set Palette, Background or Border */ /* Enter: BH = 0x00 or 0x01 */ /* BL = colour or palette (respectively) */ /* Leave: Nothing */ /* Implemented */ { /* Localise */ u16 ioport = MEM_RW(0x0463) + 5; u8 cgacolour = MEM_RB(0x0466); if (X86_BH) { cgacolour &= 0xDF; cgacolour |= (X86_BL & 0x01) << 5; } else { cgacolour &= 0xE0; cgacolour |= X86_BL & 0x1F; } MEM_WB(0x0466, cgacolour); outb(ioport, cgacolour); } break; case 0x0c: /* Write Graphics Pixel */ /* Enter: AL = pixel value */ /* BH = display page number */ /* CX = column */ /* DX = row */ /* Leave: Nothing */ /* Not Implemented */ { /* Localise */ printf("int%x: Write Graphics Pixel - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); } break; case 0x0d: /* Read Graphics Pixel */ /* Enter: BH = display page number */ /* CX = column */ /* DX = row */ /* Leave: AL = pixel value */ /* Not Implemented */ { /* Localise */ printf("int%x: Write Graphics Pixel - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); X86_AL = 0; } break; case 0x0e: /* Write Character in Teletype Mode */ /* Enter: AL = character */ /* BH = display page number */ /* BL = foreground colour */ /* Leave: Nothing */ /* Not Implemented */ /* WARNING: Emulation of BEL characters will require */ /* emulation of RTC and PC speaker I/O. */ /* Also, this recurses through int 0x10 */ /* which might or might not have been */ /* installed yet. */ { /* Localise */ #ifdef PARANOID printf("int%x: Write Character in Teletype Mode - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); #endif printf("%c", X86_AL); } break; case 0x0f: /* Get Video Mode */ /* Enter: Nothing */ /* Leave: AH = number of columns */ /* AL = video mode number */ /* BH = display page number */ /* Implemented */ { /* Localise */ X86_AH = MEM_RW(0x044A); X86_AL = MEM_RB(0x0449); X86_BH = MEM_RB(0x0462); } break; case 0x10: /* Colour Control (subfunction in AL) */ /* Enter: Various */ /* Leave: Various */ /* Ignored */ break; case 0x11: /* Font Control (subfunction in AL) */ /* Enter: Various */ /* Leave: Various */ /* Ignored */ break; case 0x12: /* Miscellaneous (subfunction in BL) */ /* Enter: Various */ /* Leave: Various */ /* Ignored. Previous code here optionally allowed */ /* the enabling and disabling of VGA, but no system */ /* BIOS I've come across actually implements it. */ break; case 0x13: /* Write String in Teletype Mode */ /* Enter: AL = write mode */ /* BL = attribute (if (AL & 0x02) == 0) */ /* CX = string length */ /* DH = row */ /* DL = column */ /* ES:BP = string segment:offset */ /* Leave: Nothing */ /* Not Implemented */ /* WARNING: Emulation of BEL characters will require */ /* emulation of RTC and PC speaker I/O. */ /* Also, this recurses through int 0x10 */ /* which might or might not have been */ /* installed yet. */ { /* Localise */ printf("int%x: Write String in Teletype Mode - " "Function not implemented.\n", current->num); x86emu_dump_xregs(); } break; default: /* Various extensions */ /* Enter: Various */ /* Leave: Various */ /* Ignored */ break; } #endif return 1; } #endif