479 lines
15 KiB
C
479 lines
15 KiB
C
|
#include <stdio.h>
|
||
|
#include "test.h"
|
||
|
#include "pci.h"
|
||
|
|
||
|
void x86emu_dump_xregs(void);
|
||
|
extern ptr current;
|
||
|
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()
|
||
|
{
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
#endif
|