- Add some more x86 instructions to emulate,

- emulate VGA read mode 0,
- emulate VGA write mode 1,
- minor cleanup.

Protel's Easytrax, a free PCB layout program, almost runs now; there are
still some problems with the keyboard emulation, but the graphics are fine
(albeit a bit slow).
This commit is contained in:
Thomas Gellekum 2001-07-30 12:03:38 +00:00
parent 6ab657cc56
commit 86c393fc09
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=80632
4 changed files with 268 additions and 137 deletions

View File

@ -29,14 +29,16 @@
#include "doscmd.h"
#include "video.h"
static u_int32_t decode_modrm(u_int8_t *, u_int16_t, regcontext_t *, int *);
static u_int8_t reg8(u_int8_t c, regcontext_t *);
static u_int16_t reg16(u_int8_t c, regcontext_t *);
static u_int32_t decode_modrm(u_int8_t *, u_int16_t,
regcontext_t *, int *);
static u_int8_t *reg8(u_int8_t c, regcontext_t *);
static u_int16_t *reg16(u_int8_t c, regcontext_t *);
#if 0
static u_int32_t reg32(u_int8_t c, regcontext_t *);
static u_int32_t *reg32(u_int8_t c, regcontext_t *);
#endif
static void write_byte(u_int32_t, u_int8_t);
static void write_word(u_int32_t, u_int16_t);
static u_int8_t read_byte(u_int32_t);
static void write_byte(u_int32_t, u_int8_t);
static void write_word(u_int32_t, u_int16_t);
/*
** Hardware /0 interrupt
@ -120,90 +122,163 @@ emu_instr(regcontext_t *REGS)
int prefix = 1;
u_int8_t *cs = (u_int8_t *)(R_CS << 4);
int ip = R_IP;
int instrlen;
int dir;
u_int16_t value;
u_int16_t seg = R_DS;
u_int32_t addr, endaddr;
int dir, i, instrlen;
u_int8_t *r8;
u_int8_t val8;
u_int16_t val16;
u_int16_t *seg = &R_DS;
u_int32_t addr, toaddr;
while (prefix) {
prefix = 0;
switch (cs[ip]) {
case 0x08: /* or r/m8, r8 */
addr = decode_modrm(cs + ip, *seg, REGS, &instrlen);
r8 = reg8(cs[ip + 1], REGS);
val8 = read_byte(addr) | *r8;
write_byte(addr, val8);
/* clear carry and overflow; check zero, sign, parity */
R_EFLAGS &= ~PSL_C | ~PSL_V;
if (val8 == 0)
R_EFLAGS |= PSL_Z;
if (val8 % 2 != 0)
R_EFLAGS |= PSL_PF;
if (val8 & 0x80)
R_EFLAGS |= PSL_N;
ip += 2 + instrlen;
break;
case 0x22: /* and r8, r/m8 */
addr = decode_modrm(cs + ip, *seg, REGS, &instrlen);
r8 = reg8(cs[ip + 1], REGS);
*r8 &= read_byte(addr);
/* clear carry and overflow; check zero, sign, parity */
R_EFLAGS &= ~PSL_C | ~PSL_V;
if (*r8 == 0)
R_EFLAGS |= PSL_Z;
if (*r8 % 2 != 0)
R_EFLAGS |= PSL_PF;
if (*r8 & 0x80)
R_EFLAGS |= PSL_N;
ip += 2 + instrlen;
break;
case 0x26: /* Segment Override ES */
seg = R_ES;
seg = &R_ES;
prefix = 1;
ip++;
break;
case 0x2e: /* Segment Override CS */
seg = R_CS;
seg = &R_CS;
prefix = 1;
ip++;
break;
case 0x36: /* Segment Override SS */
seg = R_SS;
seg = &R_SS;
prefix = 1;
ip++;
break;
case 0x3e: /* Segment Override DS */
seg = R_DS;
seg = &R_DS;
prefix = 1;
ip++;
break;
case 0x64: /* Segment Override FS */
seg = R_FS;
seg = &R_FS;
prefix = 1;
ip++;
break;
case 0x65: /* Segment Override GS */
seg = R_GS;
seg = &R_GS;
prefix = 1;
ip++;
break;
case 0x88: /* mov r/m8, r8 */
addr = decode_modrm(cs + ip, seg, REGS, &instrlen);
write_byte(addr, reg8(cs[ip + 1], REGS));
addr = decode_modrm(cs + ip, *seg, REGS, &instrlen);
write_byte(addr, *reg8(cs[ip + 1], REGS));
ip += 2 + instrlen;
break;
case 0x8a: /* mov r8, r/m8 */
addr = decode_modrm(cs + ip, *seg, REGS, &instrlen);
r8 = reg8(cs[ip + 1], REGS);
*r8 = read_byte(addr);
ip += 2 + instrlen;
break;
case 0xc6: /* mov r/m8, imm8 */
addr = decode_modrm(cs + ip, seg, REGS, &instrlen);
addr = decode_modrm(cs + ip, *seg, REGS, &instrlen);
write_byte(addr, cs[ip + 2 + instrlen]);
ip += 2 + instrlen + 1;
break;
case 0xc7: /* mov r/m32/16, imm32/16 */
addr = decode_modrm(cs + ip, seg, REGS, &instrlen);
value = *(u_int16_t *)&cs[ip + 2 + instrlen];
write_word(addr, value);
addr = decode_modrm(cs + ip, *seg, REGS, &instrlen);
val16 = *(u_int16_t *)&cs[ip + 2 + instrlen];
write_word(addr, val16);
ip += 2 + instrlen + 2;
break;
case 0xa4: /* movs m8, m8 */
write_byte(MAKEPTR(R_ES, R_DI), read_byte(MAKEPTR(*seg, R_SI)));
dir = (R_EFLAGS & PSL_D) ? -1 : 1;
R_DI += dir;
R_SI += dir;
ip++;
break;
case 0xaa: /* stos m8 */
addr = MAKEPTR(R_ES, R_DI);
write_byte(addr, R_AL);
R_DI += (R_EFLAGS & PSL_D) ? -1 : 1;
ip++;
break;
case 0xab: /* stos m32/16*/
addr = MAKEPTR(R_ES, R_DI);
write_word(addr, R_AX);
R_DI += (R_EFLAGS & PSL_D) ? -2 : 2;
ip++;
break;
case 0xf3: /* rep */
switch (cs[++ip]) {
case 0xab: /* stos m32/16 */
value = R_AX;
case 0xa4: /* movs m8, m8 */
/* XXX Possible optimization: if both source and target
addresses lie within the video memory and write mode 1 is
selected, we can use memcpy(). */
dir = (R_EFLAGS & PSL_D) ? -1 : 1;
addr = MAKEPTR(R_ES, R_DI);
toaddr = MAKEPTR(*seg, R_SI);
for (i = R_CX; i > 0; i--) {
write_byte(addr, read_byte(toaddr));
addr += dir;
toaddr += dir;
}
PUTPTR(R_ES, R_DI, addr);
PUTPTR(*seg, R_SI, toaddr);
ip++;
break;
case 0xaa: /* stos m8 */
/* direction */
dir = (R_EFLAGS & PSL_D) ? -1 : 1;
addr = MAKEPTR(R_ES, R_DI);
endaddr = MAKEPTR(R_ES, R_DI) + dir * R_CX;
if (addr <= endaddr)
while (addr <= endaddr) {
write_word(addr, value);
addr += 2;
}
else
while (addr >= endaddr) {
write_word(addr, value);
addr -= 2;
}
ip += 2;
for (i = R_CX; i > 0; i--) {
write_byte(addr, R_AL);
addr += dir;
}
PUTPTR(R_ES, R_DI, addr);
ip++;
break;
case 0xab: /* stos m32/16 */
/* direction */
dir = (R_EFLAGS & PSL_D) ? -2 : 2;
addr = MAKEPTR(R_ES, R_DI);
for (i = R_CX; i > 0; i--) {
write_word(addr, R_AX);
addr += dir;
}
PUTPTR(R_ES, R_DI, addr);
ip++;
break;
default:
R_IP = ip--; /* Move IP back to the 'rep' instruction */
R_IP = --ip; /* Move IP back to the 'rep' instruction. */
return -1;
}
break;
default:
/* unknown instruction, get out of here and let trap.c:sigbus()
/* Unknown instruction, get out of here and let trap.c:sigbus()
catch it. */
return -1;
}
@ -243,9 +318,9 @@ decode_modrm(u_int8_t *c, u_int16_t seg, regcontext_t *REGS, int *instrlen)
break;
case 0xc0: /* reg in R/M */
if (c[0] & 1) /* 16-bit reg */
return reg16(c[1], REGS);
return *reg16(c[1], REGS);
else /* 8-bit reg */
return reg8(c[1], REGS);
return *reg8(c[1], REGS);
break;
}
@ -284,50 +359,63 @@ decode_modrm(u_int8_t *c, u_int16_t seg, regcontext_t *REGS, int *instrlen)
return addr;
}
static u_int8_t
static u_int8_t *
reg8(u_int8_t c, regcontext_t *REGS)
{
u_int8_t r8[] = {R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH};
u_int8_t *r8[] = {&R_AL, &R_CL, &R_DL, &R_BL,
&R_AH, &R_CH, &R_DH, &R_BH};
/* select 'rrr' bits in ModR/M */
return r8[(c & 0x34) >> 3];
}
static u_int16_t
static u_int16_t *
reg16(u_int8_t c, regcontext_t *REGS)
{
u_int16_t r16[] = {R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI};
u_int16_t *r16[] = {&R_AX, &R_CX, &R_DX, &R_BX,
&R_SP, &R_BP, &R_SI, &R_DI};
return r16[(c & 0x34) >> 3];
}
#if 0
/* not yet */
static u_int32_t
static u_int32_t *
reg32(u_int8_t c, regcontext_t *REGS)
{
u_int32_t r32[] = {R_EAX, R_ECX, R_EDX, R_EBX,
R_ESP, R_EBP, R_ESI, R_EDI};
u_int32_t *r32[] = {&R_EAX, &R_ECX, &R_EDX, &R_EBX,
&R_ESP, &R_EBP, &R_ESI, &R_EDI};
return r32[(c & 0x34) >> 3];
}
#endif
/* Read an 8-bit value from the location specified by 'addr'. If 'addr' lies
within the video memory, we call 'video.c:vga_read()'. */
static u_int8_t
read_byte(u_int32_t addr)
{
if (addr >= 0xa0000 && addr < 0xb0000)
return vga_read(addr);
else
return *(u_int8_t *)addr;
}
/* Write an 8-bit value to the location specified by 'addr'. If 'addr' lies
within the video memory region, we call video.c:vga_write(). */
within the video memory region, we call 'video.c:vga_write()'. */
static void
write_byte(u_int32_t addr, u_int8_t val)
{
if (addr >= 0xa0000 && addr < 0xb0000) {
if (addr >= 0xa0000 && addr < 0xb0000)
vga_write(addr, val);
} else
else
*(u_int8_t *)addr = val;
return;
}
/* Write a 16-bit value to the location specified by 'addr'. If 'addr' lies
within the video memory region, we call video.c:vga_write(). */
within the video memory region, we call 'video.c:vga_write()'. */
static void
write_word(u_int32_t addr, u_int16_t val)
{

View File

@ -115,7 +115,7 @@ typedef struct TextLine {
u_char max_length; /* Not used, but here for future use */
u_char changed:1;
} TextLine;
TextLine *lines;
TextLine *lines = NULL;
int kbd_fd = -1;
int kbd_read = 0;
@ -133,14 +133,14 @@ SetVREGCur()
VGA_CRTC[CRTC_CurLocLo] = cp & 0xff;
}
void _kbd_event(void *);
void debug_event(void *);
int video_event();
void video_async_event(void *);
void tty_cooked();
unsigned char inb_port60(int);
void kbd_event(int fd, REGISTERS);
u_short read_raw_kbd(int fd, u_short *code);
void _kbd_event(void *);
void debug_event(void *);
int video_event();
void video_async_event(void *);
void tty_cooked();
unsigned char inb_port60(int);
void kbd_event(int);
u_short read_raw_kbd(int, u_short *);
/* Local functions */
#ifndef NO_X
@ -364,7 +364,7 @@ video_update(regcontext_t *REGS)
static int icnt = 3;
if (kbd_read)
kbd_event(kbd_fd, REGS);
kbd_event(kbd_fd);
if (--icnt == 0) {
icnt = 3;
@ -791,7 +791,7 @@ inb_port60(int port)
}
void
kbd_event(int fd, REGISTERS)
kbd_event(int fd)
{
kbd_read = 0;
@ -998,7 +998,7 @@ video_async_event(void *pfd)
int x;
fd_set fdset;
XEvent ev;
static struct timeval tv = { 0 };
static struct timeval tv;
/*
* Handle any events just sitting around...
@ -1042,7 +1042,7 @@ video_async_event(void *pfd)
}
void
kbd_async_event(int fd, REGISTERS)
kbd_async_event(int fd)
{
unsigned char c;
@ -2182,7 +2182,7 @@ get_ximage()
XDestroyImage(xi);
err(1, "Could not get memory for ximage data");
}
return;
#endif
}
@ -2193,14 +2193,31 @@ get_lines()
{
int i;
if (!(lines = (TextLine *)malloc(sizeof(TextLine) * height)))
err(1, "Could not allocate data structure for text lines\n");
for (i = 0; i < height; ++i) {
lines[i].max_length = width;
if (!(lines[i].data = (u_short *)malloc(width * sizeof(u_short))))
if (lines == NULL) {
lines = (TextLine *)malloc(sizeof(TextLine) * height);
if (lines == NULL)
err(1, "Could not allocate data structure for text lines\n");
lines[i].changed = 1;
for (i = 0; i < height; ++i) {
lines[i].max_length = width;
lines[i].data = (u_short *)malloc(width * sizeof(u_short));
if (lines[i].data == NULL)
err(1, "Could not allocate data structure for text lines\n");
lines[i].changed = 1;
}
} else {
lines = (TextLine *)realloc(lines, sizeof(TextLine) * height);
if (lines == NULL)
err(1, "Could not allocate data structure for text lines\n");
for (i = 0; i < height; ++i) {
lines[i].max_length = width;
lines[i].data = (u_short *)realloc(lines[i].data,
width * sizeof(u_short));
if (lines[i].data == NULL)
err(1, "Could not allocate data structure for text lines\n");
lines[i].changed = 1;
}
}
}
@ -2258,7 +2275,8 @@ resize_window()
sh->min_height = sh->max_height = sh->base_height;
sh->flags = USSize | PMinSize | PMaxSize | PSize;
debug(D_VIDEO, "window size %dx%d\n", sh->base_width, sh->base_height);
debug(D_VIDEO, "VGA: Set window size %dx%d\n",
sh->base_width, sh->base_height);
XSetWMNormalHints(dpy, win, sh);
XResizeWindow(dpy, win, sh->base_width, sh->base_height);

View File

@ -175,7 +175,7 @@ video_outb(int port, u_int8_t value)
col = cp % DpyCols;
break;
default:
debug(D_VIDEO, "outb 0x%04x, 0x%02x at index 0x%02x\n",
debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
port, value, crtc_index);
break;
}
@ -190,7 +190,7 @@ video_outb(int port, u_int8_t value)
VGA_ATC[atc_index] = value;
switch (atc_index) {
default:
debug(D_VIDEO, "outb 0x%04x, 0x%02x at index 0x%02x\n",
debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
port, value, crtc_index);
break;
}
@ -204,7 +204,7 @@ video_outb(int port, u_int8_t value)
VGA_TSC[tsc_index] = value;
switch (tsc_index) {
default:
debug(D_VIDEO, "outb 0x%04x, 0x%02x at index 0x%02x\n",
debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
port, value, crtc_index);
break;
}
@ -217,7 +217,7 @@ video_outb(int port, u_int8_t value)
#if 0
switch (gdc_index) {
default:
debug(D_VIDEO, "outb 0x%04x, 0x%02x at index 0x%02x\n",
debug(D_VIDEO, "VGA: outb 0x%04x, 0x%02x at index 0x%02x\n",
port, value, crtc_index);
break;
@ -225,7 +225,7 @@ video_outb(int port, u_int8_t value)
#endif
break;
default:
debug(D_ALWAYS, "Unknown port 0x%4x\n", port);
debug(D_ALWAYS, "VGA: Unknown port 0x%4x\n", port);
break;
}
@ -385,7 +385,7 @@ init_mode(int mode)
int idx; /* Index into vmode */
int pidx; /* Index into videoparams */
debug(D_VIDEO, "Set video mode to 0x%02x\n", mode);
debug(D_VIDEO, "VGA: Set video mode to 0x%02x\n", mode);
idx = find_vmode(mode & 0x7f);
if (idx == -1 || vmodelist[idx].type == NOMODE)
@ -466,7 +466,7 @@ init_mode(int mode)
0xaffff will generate a T_PAGEFAULT trap in VM86 mode (aside: why not a
SIGSEGV?), which is handled in 'trap.c:sigbus()'. */
if (vmode.type == GRAPHICS) {
vmem = mmap((void *)0xa0000, 64 * 1024, PROT_READ,
vmem = mmap((void *)0xa0000, 64 * 1024, PROT_NONE,
MAP_ANON | MAP_FIXED | MAP_INHERIT | MAP_SHARED, -1, 0);
if (vmem == NULL)
fatal("Could not mmap() video memory");
@ -493,7 +493,7 @@ init_mode(int mode)
'videoparams' array. */
int find_vmode(int mode)
{
int i;
unsigned i;
for (i = 0; i < NUMMODES; i++)
if (vmodelist[i].modenumber == mode)
@ -502,8 +502,6 @@ int find_vmode(int mode)
return -1;
}
/* Handle access to the graphics memory.
Simply changing the protection for the memory is not enough, unfortunately.
@ -534,6 +532,35 @@ vmem_pageflt(struct sigframe *sf)
return emu_instr(REGS);
}
/* We need to keep track of the latches' contents.*/
static u_int8_t latch0, latch1, latch2, latch3;
/* Read a byte from the video memory. 'vga_read()' is called from
'cpu.c:read_byte()' and will emulate the VGA read modes. */
u_int8_t
vga_read(u_int32_t addr)
{
u_int32_t dst;
/* 'addr' lies between 0xa0000 and 0xaffff. */
dst = addr - 0xa0000;
/* Fill latches. */
latch0 = vplane0[dst];
latch1 = vplane1[dst];
latch2 = vplane2[dst];
latch3 = vplane3[dst];
/* Select read mode. */
if ((VGA_GDC[GDC_Mode] & 0x80) == 0)
/* Read Mode 0; return the byte from the selected bit plane. */
return vram[dst + (VGA_GDC[GDC_ReadMapSelect] & 3) * 0x10000];
/* Read Mode 1 */
debug(D_ALWAYS, "VGA: Read Mode 1 not implemented\n");
return 0;
}
/* Write a byte to the video memory. 'vga_write()' is called from
'cpu.c:write_word()' and will emulate the VGA write modes. Not all four
modes are implemented yet, nor are the addressing modes (odd/even, chain4).
@ -543,46 +570,41 @@ void
vga_write(u_int32_t addr, u_int8_t val)
{
u_int32_t dst;
u_int8_t *latch0, *latch1, *latch2, *latch3;
u_int8_t c0, c1, c2, c3;
u_int8_t m0, m1, m2, m3;
u_int8_t mask;
#if 0
int i;
unsigned i;
debug(D_VIDEO, "Write 0x%02x to 0x%x\n", val, addr);
debug(D_VIDEO, "GDC: ");
debug(D_VIDEO, "VGA: Write 0x%02x to 0x%x\n", val, addr);
debug(D_VIDEO, " GDC: ");
for (i = 0; i < sizeof(VGA_GDC); i++)
debug(D_VIDEO, "%02x ", VGA_GDC[i]);
debug(D_VIDEO, "\n");
debug(D_VIDEO, "TSC: ");
debug(D_VIDEO, " TSC: ");
for (i = 0; i < sizeof(VGA_TSC); i++)
debug(D_VIDEO, "%02x ", VGA_TSC[i]);
debug(D_VIDEO, "\n");
#endif
/* 'addr' lies between 0xa0000 and 0xaffff */
/* 'addr' lies between 0xa0000 and 0xaffff. */
dst = addr - 0xa0000;
/* fill latches */
latch0 = vplane0 + dst;
latch1 = vplane1 + dst;
latch2 = vplane2 + dst;
latch3 = vplane3 + dst;
c0 = *latch0;
c1 = *latch1;
c2 = *latch2;
c3 = *latch3;
c0 = latch0;
c1 = latch1;
c2 = latch2;
c3 = latch3;
/* select write mode */
/* Select write mode. */
switch (VGA_GDC[GDC_Mode] & 3) {
case 0:
/* XXX to do: Enable Set Reset register */
mask = VGA_GDC[GDC_BitMask];
/* select function */
if (VGA_GDC[GDC_DataRotate] & 7)
debug(D_ALWAYS, "VGA: Data Rotate != 0\n");
/* Select function. */
switch (VGA_GDC[GDC_DataRotate] & 0x18) {
case 0x00: /* replace */
m0 = VGA_GDC[GDC_SetReset] & 1 ? mask : 0x00;
@ -590,53 +612,54 @@ vga_write(u_int32_t addr, u_int8_t val)
m2 = VGA_GDC[GDC_SetReset] & 4 ? mask : 0x00;
m3 = VGA_GDC[GDC_SetReset] & 8 ? mask : 0x00;
c0 &= ~mask;
c1 &= ~mask;
c2 &= ~mask;
c3 &= ~mask;
c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 & ~mask : val & ~mask;
c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 & ~mask : val & ~mask;
c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 & ~mask : val & ~mask;
c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 & ~mask : val & ~mask;
c0 |= m0;
c1 |= m1;
c2 |= m2;
c3 |= m3;
break;
case 0x08: /* and */
case 0x08: /* AND */
m0 = VGA_GDC[GDC_SetReset] & 1 ? 0xff : ~mask;
m1 = VGA_GDC[GDC_SetReset] & 2 ? 0xff : ~mask;
m2 = VGA_GDC[GDC_SetReset] & 4 ? 0xff : ~mask;
m3 = VGA_GDC[GDC_SetReset] & 8 ? 0xff : ~mask;
c0 &= m0;
c1 &= m1;
c2 &= m2;
c3 &= m3;
c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 & m0 : val & m0;
c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 & m1 : val & m1;
c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 & m2 : val & m2;
c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 & m3 : val & m3;
break;
case 0x10: /* or */
case 0x10: /* OR */
m0 = VGA_GDC[GDC_SetReset] & 1 ? mask : 0x00;
m1 = VGA_GDC[GDC_SetReset] & 2 ? mask : 0x00;
m2 = VGA_GDC[GDC_SetReset] & 4 ? mask : 0x00;
m3 = VGA_GDC[GDC_SetReset] & 8 ? mask : 0x00;
c0 |= m0;
c1 |= m1;
c2 |= m2;
c3 |= m3;
c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 | m0 : val | m0;
c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 | m1 : val | m1;
c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 | m2 : val | m2;
c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 | m3 : val | m3;
break;
case 0x18: /* xor */
case 0x18: /* XOR */
m0 = VGA_GDC[GDC_SetReset] & 1 ? mask : 0x00;
m1 = VGA_GDC[GDC_SetReset] & 2 ? mask : 0x00;
m2 = VGA_GDC[GDC_SetReset] & 4 ? mask : 0x00;
m3 = VGA_GDC[GDC_SetReset] & 8 ? mask : 0x00;
c0 ^= m0;
c1 ^= m1;
c2 ^= m2;
c3 ^= m3;
c0 = VGA_GDC[GDC_EnableSetReset] & 1 ? c0 ^ m0 : val ^ m0;
c1 = VGA_GDC[GDC_EnableSetReset] & 2 ? c1 ^ m1 : val ^ m1;
c2 = VGA_GDC[GDC_EnableSetReset] & 4 ? c2 ^ m2 : val ^ m2;
c3 = VGA_GDC[GDC_EnableSetReset] & 8 ? c3 ^ m3 : val ^ m3;
break;
}
break;
case 1:
/* not yet */
/* Just copy the latches' content to the desired destination
address. */
break;
case 2:
mask = VGA_GDC[GDC_BitMask];
@ -696,18 +719,19 @@ vga_write(u_int32_t addr, u_int8_t val)
break;
case 3:
/* not yet */
debug(D_ALWAYS, "VGA: Write Mode 3 not implemented\n");
break;
}
/* write back changed byte, depending on Map Mask register */
/* Write back changed byte, depending on Map Mask register. */
if (VGA_TSC[TSC_MapMask] & 1)
*latch0 = c0;
vplane0[dst] = c0;
if (VGA_TSC[TSC_MapMask] & 2)
*latch1 = c1;
vplane1[dst] = c1;
if (VGA_TSC[TSC_MapMask] & 4)
*latch2 = c2;
vplane2[dst] = c2;
if (VGA_TSC[TSC_MapMask] & 8)
*latch3 = c3;
vplane3[dst] = c3;
return;
}

View File

@ -364,13 +364,14 @@ extern vmode_t vmodelist[];
#define FONT8x16 "vga8x16" /* same as FONTVGA */
/* External functions in 'video.c'. */
extern void init_mode(int);
extern int find_vmode(int);
extern void vga_write(u_int32_t, u_int8_t);
extern void video_bios_init(void);
extern void video_init(void);
extern int vmem_pageflt(struct sigframe *);
void init_mode(int);
int find_vmode(int);
u_int8_t vga_read(u_int32_t);
void vga_write(u_int32_t, u_int8_t);
void video_bios_init(void);
void video_init(void);
int vmem_pageflt(struct sigframe *);
/* Other external variables, mostly from tty.c. Needs to be cleaned up. */
extern int vattr;
void write_vram(void *);
extern int vattr;
void write_vram(void *);