Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1021 lines
26 KiB

#include "insignia.h"
#include "host_def.h"
/*
* SoftPC Revision 3.0
*
* Title : vga_video.c
*
* Description : BIOS video internal routines.
*
* Author : William Gulland
*
* Notes : The following functions are defined in this module:
*
*
*
*/
/*
* static char SccsID[]="@(#)vga_video.c 1.37 06/26/95 Copyright Insignia Solutions Ltd.";
*/
#ifdef VGG
#ifdef SEGMENTATION
/*
* The following #include specifies the code segment into which this
* module will by placed by the MPW C compiler on the Mac II running
* MultiFinder.
*/
#include "VIDEO_BIOS_VGA.seg"
#endif
/*
* O/S include files.
*/
#include <stdio.h>
#include TypesH
#include FCntlH
/*
* SoftPC include files
*/
#include "xt.h"
#include CpuH
#include "error.h"
#include "config.h"
#include "bios.h"
#include "ios.h"
#include "gmi.h"
#include "sas.h"
#include "gvi.h"
#include "timer.h"
#include "gfx_upd.h"
#include "host.h"
#include "egacpu.h"
#include "egaports.h"
#include "egagraph.h"
#include "egaread.h"
#include "video.h"
#include "egavideo.h"
#include "equip.h"
#include "vga_dac.h"
#include "vgaports.h"
#include "debug.h"
#ifndef PROD
#include "trace.h"
#endif
#include "host_gfx.h"
/*
* ============================================================================
* Global data
* ============================================================================
*/
/*
* ============================================================================
* Local static data and defines
* ============================================================================
*/
#define DISABLE_REFRESH 0x20
/* the bit in the vga seq clock register that disables screen refresh */
#define VGA_COLOUR 8 /* Display Code */
typedef struct _rgb
{
byte red;
byte green;
byte blue;
} rgb_struct;
/* internal function declarations */
/* To convert to grey, set all components to 30% r, 59% g and 11% b. */
static void greyify(rgb)
rgb_struct *rgb;
{
unsigned int grey;
grey = (30*rgb->red+59*rgb->green+11*rgb->blue)/100;
rgb->red = rgb->green = rgb->blue = grey;
}
static void set_dac(dac,rgb)
half_word dac;
rgb_struct *rgb;
{
if(is_GREY())greyify(rgb);
outb(VGA_DAC_WADDR,dac);
outb(VGA_DAC_DATA,rgb->red);
outb(VGA_DAC_DATA,rgb->green);
outb(VGA_DAC_DATA,rgb->blue);
}
static void get_dac(dac,rgb)
half_word dac;
rgb_struct *rgb;
{
outb(VGA_DAC_RADDR,dac);
inb(VGA_DAC_DATA,&(rgb->red));
inb(VGA_DAC_DATA,&(rgb->green));
inb(VGA_DAC_DATA,&(rgb->blue));
}
/*
* ============================================================================
* External functions
* ============================================================================
*/
void init_vga_dac(table)
int table; /* Which table to use */
{
int loop;
byte *dac;
rgb_struct rgb;
#ifdef macintosh
/* load the required DAC in */
dac = host_load_vga_dac (table);
/* check it worked */
if (!dac)
return;
#else /* macintosh */
switch (table)
{
case 0:
dac = vga_dac;
break;
case 1:
dac = vga_low_dac;
break;
case 2:
dac = vga_256_dac;
break;
default:
assert1(FALSE,"Bad VGA DAC table %d",table);
}
#endif /* macintosh */
for(loop = 0; loop < 0x100; loop++)
{
rgb.red = *dac; rgb.green = dac[1]; rgb.blue = dac[2];
set_dac(loop,&rgb);
dac+=3;
}
#ifdef macintosh
/* and dump the DAC back into the heap */
host_dump_vga_dac ();
#endif /* macintosh */
}
/***** Routines to handle VGA 256 colour modes, called from video.c **********/
GLOBAL VOID vga_graphics_write_char
IFN6( LONG, col, LONG, row, LONG, ch, IU8, colour, LONG, page, LONG, nchs)
{
register sys_addr char_addr;
register long screen_offset;
register int i,j,k,char_height,len;
register int scan_length = 8*sas_w_at_no_check(VID_COLS);
register byte mask, val, bank;
UNUSED(page);
char_height = sas_hw_at_no_check(ega_char_height);
char_addr = follow_ptr(EGA_FONT_INT*4)+char_height*ch;
/* VGA 256 colour mode has only one page, so ignore 'page' */
/*
* Set read/write banks to zero to optimise the update_alg call
*/
set_banking( 0, 0 );
screen_offset = row*scan_length*char_height+8*col;
len = ( nchs << 3 ) - 1;
for(i=0;i<char_height;i++)
{
(*update_alg.mark_fill)( screen_offset, screen_offset + len );
val = sas_hw_at_no_check(char_addr);
char_addr++;
for(j=0;j<nchs;j++)
{
mask = 0x80;
for(k=0;k<8;k++)
{
if( val & mask )
*(IU8 *)(getVideowplane() + screen_offset) = colour;
else
*(IU8 *)(getVideowplane() + screen_offset) = 0;
screen_offset++;
mask = mask >> 1;
}
}
screen_offset += scan_length - ( nchs << 3 );
}
/*
* Set read/write banks to last value in case someone relies on this side-effect
*/
bank = ( screen_offset - ( scan_length - ( nchs << 3 ))) >> 16;
set_banking( bank, bank );
}
GLOBAL VOID vga_write_dot
IFN4(LONG, colour, LONG, page, LONG, pixcol, LONG, row)
{
#ifdef REAL_VGA
register sys_addr screen_offset;
screen_offset = video_pc_low_regen+8*row*sas_w_at_no_check(VID_COLS)+pixcol;
sas_store(screen_offset, colour); /* WOW - that's easy!! */
#else
long screen_offset;
UTINY bank;
UNUSED(page);
screen_offset = (8*row*sas_w_at_no_check(VID_COLS)+pixcol);
bank = screen_offset >> 16;
set_banking( bank, bank );
EGA_plane0123[screen_offset] = colour;
(*update_alg.mark_byte)(screen_offset);
#endif /* REAL_VGA */
}
GLOBAL VOID vga_sensible_graph_scroll_up
IFN6( LONG, row, LONG, col, LONG, rowsdiff, LONG, colsdiff, LONG, lines, LONG, attr)
{
register int col_incr = 8*sas_w_at_no_check(VID_COLS);
register int i;
register long source,dest;
register byte char_height;
boolean screen_updated;
col *= 8; colsdiff *= 8; /* 8 bytes per character */
char_height = sas_hw_at_no_check(ega_char_height);
rowsdiff *= char_height;
lines *= char_height;
#ifdef REAL_VGA
/* Not done for back M */
dest = video_pc_low_regen+sas_loadw(VID_ADDR)+
row*col_incr*char_height+col;
source = dest+lines*col_incr;
for(i=0;i<rowsdiff-lines;i++)
{
memcpy_16(dest,source,colsdiff);
source += col_incr;
dest += col_incr;
}
while(lines--)
{
memset_16(dest,attr,colsdiff);
dest += col_incr;
}
#else
dest = sas_w_at_no_check(VID_ADDR)+ row*col_incr*char_height+col;
source = dest+lines*col_incr;
screen_updated = (col+colsdiff) <= col_incr; /* Check for silly scroll */
if(screen_updated)
screen_updated = (*update_alg.scroll_up)(dest,colsdiff,rowsdiff,attr,lines,0);
for(i=0;i<rowsdiff-lines;i++)
{
memcpy(&EGA_plane0123[dest],&EGA_plane0123[source],colsdiff);
if(!screen_updated)
(*update_alg.mark_string)(dest,dest+colsdiff-1);
source += col_incr;
dest += col_incr;
}
while(lines--)
{
memset(&EGA_plane0123[dest],attr,colsdiff);
if(!screen_updated)
(*update_alg.mark_fill)(dest,dest+colsdiff-1);
dest += col_incr;
}
#endif /* REAL_VGA */
}
GLOBAL VOID vga_sensible_graph_scroll_down
IFN6( LONG, row, LONG, col, LONG, rowsdiff, LONG, colsdiff, LONG, lines, LONG, attr)
{
register int col_incr = 8*sas_w_at_no_check(VID_COLS);
register int i;
register long source,dest;
register byte char_height;
boolean screen_updated;
col *= 8; colsdiff *= 8; /* 8 bytes per character */
char_height = sas_hw_at_no_check(ega_char_height);
rowsdiff *= char_height;
lines *= char_height;
#ifdef REAL_VGA
/* Not done for back M */
dest = video_pc_low_regen+sas_loadw(VID_ADDR)+
row*col_incr*char_height+col;
dest += (rowsdiff-1)*col_incr;
source = dest-lines*col_incr;
for(i=0;i<rowsdiff-lines;i++)
{
memcpy_16(dest,source,colsdiff);
source -= col_incr;
dest -= col_incr;
}
while(lines--)
{
memset_16(dest,attr,colsdiff);
dest -= col_incr;
}
#else
dest = sas_w_at_no_check(VID_ADDR)+ row*col_incr*char_height+col;
screen_updated = (col+colsdiff) <= col_incr; /* Check for silly scroll */
if(screen_updated)
screen_updated = (*update_alg.scroll_down)(dest,colsdiff,rowsdiff,attr,lines,0);
dest += (rowsdiff-1)*col_incr;
source = dest-lines*col_incr;
for(i=0;i<rowsdiff-lines;i++)
{
memcpy(&EGA_planes[dest],&EGA_planes[source],colsdiff);
if(!screen_updated)
(*update_alg.mark_string)(dest,dest+colsdiff-1);
source -= col_incr;
dest -= col_incr;
}
while(lines--)
{
memset(&EGA_planes[dest],attr,colsdiff);
if(!screen_updated)
(*update_alg.mark_fill)(dest,dest+colsdiff-1);
dest -= col_incr;
}
#endif /* REAL_VGA */
}
GLOBAL VOID vga_read_attrib_char IFN3(LONG, col, LONG, row, LONG, page)
{
byte the_char[256];
register host_addr screen;
register int i,k;
register int scan_length = 8*sas_w_at_no_check(VID_COLS);
register byte mask;
byte char_height = sas_hw_at_no_check(ega_char_height);
UNUSED(page);
/*printf("vga_read_attrib_char(%d,%d,%d)\n",
col,row,page);*/
/* VGA 256 colour mode has only one page, so ignore 'page' */
#ifdef REAL_VGA
screen = video_pc_low_regen+row*scan_length*char_height+8*col;
#else
screen = &EGA_plane0123[row*scan_length*char_height+8*col];
#endif /* REAL_VGA */
for(i=0;i<char_height;i++)
{
mask = 0x80;
the_char[i]=0;
for(k=0;k<8;k++)
{
if(*screen++)
the_char[i] |= mask;
mask = mask >> 1;
}
screen += scan_length - 8;
}
search_font((char *)the_char,(int)char_height);
}
GLOBAL VOID vga_read_dot IFN3(LONG, page, LONG, pixcol, LONG, row)
{
register host_addr screen;
UNUSED(page);
/*printf("vga_read_dot(%d,%d,%d)\n",page,col,row);*/
#ifdef REAL_VGA
screen = video_pc_low_regen+8*row*sas_w_at_no_check(VID_COLS)+pixcol;
#else
screen = &EGA_plane0123[8*row*sas_w_at_no_check(VID_COLS)+pixcol];
#endif /* REAL_VGA */
setAL(*screen) ; /* WOW - that's easy!! */
}
/****** Routines to handle BIOS functions new to VGA *******/
void vga_set_palette()
{
/*
* Called via INT 10 AH=10, AL='not understood by ega_set_palette()'
* Sets/reads VGA DACs.
*/
int i,dac;
byte temp; /* For inb()s. */
byte mode_reg;
rgb_struct rgb_dac;
sys_addr ptr;
switch(getAL())
{
case 7: /* Read attribute register */
outb(EGA_AC_INDEX_DATA,getBL()); /* set index */
inb(EGA_AC_SECRET,&temp);
setBH(temp);
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
break;
case 8: /* Read overscan register */
outb(EGA_AC_INDEX_DATA,17); /* overscan index */
inb(EGA_AC_SECRET,&temp);
setBH(temp);
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
break;
case 9: /* Read all palette regs. + overscan */
ptr = effective_addr(getES(),getDX());
for(i=0;i<16;i++)
{
outb(EGA_AC_INDEX_DATA,i); /* set index */
inb(EGA_AC_SECRET,&temp);
sas_store(ptr, temp);
inb(EGA_IPSTAT1_REG,&temp);
ptr++;
}
outb(EGA_AC_INDEX_DATA,17); /* overscan index */
inb(EGA_AC_SECRET,&temp);
sas_store(ptr, temp);
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
break;
case 0x10: /* Set one DAC */
rgb_dac.red = getDH();
rgb_dac.green = getCH();
rgb_dac.blue = getCL();
set_dac(getBX(),&rgb_dac);
break;
case 0x12: /* Set block of DACs */
ptr = effective_addr(getES(),getDX());
dac = getBX();
for(i=0;i<getCX();i++)
{
rgb_dac.red = sas_hw_at_no_check(ptr);
rgb_dac.green = sas_hw_at_no_check(ptr+1);
rgb_dac.blue = sas_hw_at_no_check(ptr+2);
set_dac(dac,&rgb_dac);
dac++;ptr += 3;
}
break;
case 0x13: /* Set paging mode
* see Prog Guide to Video Systems, pp60-63]
* and IBM ROM BIOS pp26-27.
*/
outb(EGA_AC_INDEX_DATA,16); /* mode control index */
inb(EGA_AC_SECRET,&mode_reg); /* Old value */
if(getBL()==0)
{ /* Select paging mode */
outb(EGA_AC_INDEX_DATA,
(mode_reg & 0x7f) | (getBH()<<7));
}
else /* Select a palette page */
{
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA,20); /* pixel padding index */
if(mode_reg & 0x80)
/* 16 entry palettes
* bits 0-3of the pad register relevant */
outb(EGA_AC_INDEX_DATA,getBH());
else
/* 64 entry palette - only bits 2-3 relevent */
outb(EGA_AC_INDEX_DATA,getBH()<<2);
}
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
break;
case 0x15: /* Get value of one DAC */
get_dac(getBX(),&rgb_dac);
setDH(rgb_dac.red);
setCH(rgb_dac.green);
setCL(rgb_dac.blue);
break;
case 0x17:
ptr = effective_addr(getES(),getDX());
dac = getBX();
for(i=0;i<getCX();i++)
{
get_dac(dac,&rgb_dac);
sas_store(ptr, rgb_dac.red);
sas_store(ptr+1, rgb_dac.green);
sas_store(ptr+2, rgb_dac.blue);
dac++;
ptr += 3;
}
break;
case 0x18:
/* Set the VGA DAC mask. */
outb(VGA_DAC_MASK,getBL());
break;
case 0x19:
/* Get the VGA DAC mask. */
inb(VGA_DAC_MASK,&temp);
setBL(temp);
break;
case 0x1a:
/* Return current mode control & pixel padding */
outb(EGA_AC_INDEX_DATA,16); /* mode control index */
inb(EGA_AC_SECRET,&mode_reg);
if(mode_reg & 0x80)
setBL(1);
else
setBL(0);
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA,20); /* pixel padding index */
inb(EGA_AC_SECRET,&temp);
setBH(temp);
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
break;
case 0x1b: /* Convert set of DACs to grey scale. */
dac = getBX();
for(i=0;i<getCX();i++)
{
get_dac(dac,&rgb_dac);
greyify(&rgb_dac);
set_dac(dac,&rgb_dac);
dac++;
}
break;
default:
assert1(FALSE,"Bad set palette submode %#x",getAL());
break;
}
}
/*
* Various miscellaneous flags can be set using
* INT 10, AH 12, AL flag.
* Called from ega_alt_sel().
*/
void vga_func_12()
{
half_word seq_clock;
switch(getBL())
{
case 0x30: /* Set number of scan lines */
if(getAL() == 0)
set_VGA_lines(S200);
else if(getAL() == 1)
set_VGA_lines(S350);
else
set_VGA_lines(S400);
setAL(0x12); /* We did it */
break;
case 0x33: /* Enable/Disable Grey-Scale Summing */
if(getAL())
set_GREY(0);
else
set_GREY(GREY_SCALE);
setAL(0x12); /* We did it */
break;
case 0x34: /* Enable/disable Cursor Emulation */
set_EGA_cursor_no_emulate(getAL() & 1);
setAL(0x12); /* We did it */
break;
case 0x36: /* Enable/Disable Screen Refresh */
if (getAL() == 0)
{
outb(EGA_SEQ_INDEX, 1);
inb(EGA_SEQ_DATA, &seq_clock);
outb(EGA_SEQ_DATA, seq_clock & ~DISABLE_REFRESH);
}
else
{
outb(EGA_SEQ_INDEX, 1);
inb(EGA_SEQ_DATA, &seq_clock);
outb(EGA_SEQ_DATA, seq_clock | DISABLE_REFRESH);
}
setAL(0x12);
break;
case 0x31: /* Enable/Disable Default Palette Loading */
case 0x32: /* Enable/Disable Video */
case 0x35: /* Switch active display */
/* do not set code that means it worked */
default:
setAL(0); /* Function not supported */
break;
}
}
void vga_disp_comb()
{
/* check that we really are a VGA */
if (video_adapter != VGA)
{
/* we are not -so this function is not implemented */
not_imp();
return;
}
/*
* On a PS/2, AL=1 is (I believe) used to switch active displays.
* We ignore this.
* AL=0 returns the current display, which we can cope with.
*/
if(getAL() == 0)
{
setBH(0); /* Only one display, so no inactive one! */
setBL(VGA_COLOUR); /* VGA with colour monitor. (7 for mono) */
}
setAX(0x1A); /* Tell him we coped. */
}
void vga_disp_func()
{
/*
* This function returns masses of info. about the current
* display and screen mode.
* One of the things returned is a pointer to the display info.
* This is stored in the VGA ROM, so all we need to do is set
* the pointer up.
*
*/
sys_addr buf = effective_addr(getES(),getDI());
byte temp,mode_reg, video_mode;
#if defined(NTVDM) && defined(X86GFX)
IMPORT word vga1b_seg, vga1b_off;
#endif /* NTVDM & X86GFX */
/* check that we really are a VGA */
#ifndef HERC
if (video_adapter != VGA)
#else
if ( (video_adapter != VGA) && (video_adapter != HERCULES))
#endif /* HERC */
{
/* we are not -so this function is not implemented */
not_imp();
return;
}
#ifdef HERC
if( video_adapter == VGA)
{
#endif /* HERC */
video_mode = sas_hw_at_no_check(vd_video_mode);
#ifdef V7VGA
if ((video_mode == 1) && extensions_controller.foreground_latch_1)
video_mode = extensions_controller.foreground_latch_1;
else if (video_mode > 0x13)
video_mode += 0x4c;
#endif /* V7VGA */
/*
* Store VGA capability table pointer. Usually lives in Insignia ROM, on NT
* x86 it has to live in ntio.sys.
*/
#if defined(NTVDM) && defined(X86GFX)
sas_storew(buf, vga1b_off);
sas_storew(buf+2, vga1b_seg);
#else
sas_storew(buf,INT10_1B_DATA);
sas_storew(buf+2,EGA_SEG);
#endif /* NTVDM & X86GFX */
sas_store(buf+0x4, video_mode); /* Current video mode */
sas_storew(buf+5,sas_w_at_no_check(VID_COLS)); /* Cols on screen */
sas_storew(buf+7,sas_w_at_no_check(VID_LEN)); /* Size of screen */
sas_storew(buf+9,sas_w_at_no_check(VID_ADDR)); /* Address of screen */
sas_move_bytes_forward(VID_CURPOS,buf+0xB,16); /* Cursor positions */
sas_storew(buf+0x1b,sas_w_at_no_check(VID_CURMOD)); /* Cursor type */
sas_store(buf+0x1D, sas_hw_at_no_check(vd_current_page));
sas_storew(buf+0x1E,sas_w_at_no_check(VID_INDEX));
sas_store(buf+0x20, sas_hw_at_no_check(vd_crt_mode));
sas_store(buf+0x21, sas_hw_at_no_check(vd_crt_palette));
sas_store(buf+0x22, sas_hw_at_no_check(vd_rows_on_screen)+1);
sas_storew(buf+0x23,sas_w_at_no_check(ega_char_height));
sas_store(buf+0x25, VGA_COLOUR); /* Active display */
sas_store(buf+0x26, 0); /* Inactive display (none) */
#ifdef V7VGA
if (video_mode >= 0x60)
{
sas_storew(buf+0x27,vd_ext_graph_table[video_mode-0x60].ncols);
sas_store(buf+0x29, vd_ext_graph_table[video_mode-0x60].npages);
}
else if (video_mode >= 0x40)
{
sas_storew(buf+0x27,vd_ext_text_table[video_mode-0x40].ncols);
sas_store(buf+0x29, vd_ext_text_table[video_mode-0x40].npages);
}
else
{
sas_storew(buf+0x27,vd_mode_table[video_mode].ncols);
sas_store(buf+0x29, vd_mode_table[video_mode].npages);
}
#else
sas_storew(buf+0x27,vd_mode_table[video_mode].ncols);
sas_store(buf+0x29, vd_mode_table[video_mode].npages);
#endif /* V7VGA */
sas_store(buf+0x2A, get_scanlines());
outb(EGA_SEQ_INDEX,3);
inb(EGA_SEQ_DATA,&temp); /* Character Font select reg. */
sas_store(buf+0x2B, (temp & 3)|((temp & 0x10)>>2));
/* extract bits 410 - font B */
sas_store(buf+0x2C, ((temp & 0xC)>>2)|((temp & 0x20)>>3));
/* extract bits 532 - font A */
temp = 1; /* All modes on all displays active */
if(is_GREY())temp |= 2;
if(is_MONO())temp |= 4;
if(is_PAL_load_off())temp |=8;
if(get_EGA_cursor_no_emulate())temp |= 0x10;
inb(EGA_IPSTAT1_REG,&mode_reg); /* Clear Attribute flip-flop */
outb(EGA_AC_INDEX_DATA,16); /* mode control index */
inb(EGA_AC_SECRET,&mode_reg);
if(mode_reg & 8)temp |= 0x20;
inb(EGA_IPSTAT1_REG,&mode_reg); /* Clear Attribute flip-flop */
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
sas_store(buf+0x2D, temp);
sas_store(buf+0x31, 3); /* 256KB video memory */
setAX(0x1B); /* We did it! */
#ifdef HERC
} /* if VGA */
if( video_adapter == HERCULES)
{
video_mode = sas_hw_at(vd_video_mode);
sas_storew(buf,INT10_1B_DATA);
sas_storew(buf+2,EGA_SEG);
sas_store(buf+0x4, video_mode); /* Current video mode */
sas_storew(buf+5,sas_w_at(VID_COLS)); /* Cols on screen */
sas_storew(buf+7,sas_w_at(VID_LEN)); /* Size of screen */
sas_storew(buf+9,sas_w_at(VID_ADDR)); /* Address of screen */
sas_move_bytes_forward(VID_CURPOS,buf+0xB,16); /* Cursor positions */
sas_store(buf+0x1b, HERC_CURS_START+HERC_CURS_HEIGHT); /* Cursor end line */
sas_store(buf+0x1c, HERC_CURS_START); /* Cursor start line */
sas_store(buf+0x1D, sas_hw_at(vd_current_page));
sas_storew(buf+0x1E,sas_w_at(VID_INDEX));
sas_store(buf+0x20, sas_hw_at(vd_crt_mode));
sas_store(buf+0x21, sas_hw_at(vd_crt_palette));
sas_store(buf+0x22, sas_hw_at(vd_rows_on_screen)+1);
sas_storew(buf+0x23, 14); /* char height is 14 */
sas_store(buf+0x25,0x01 ); /* 01=MDA with monochrome display as Active display */
sas_store(buf+0x26, 0); /* Inactive display (none) */
vd_mode_table[video_mode].ncols= 2; /* Black & White 2 colors */
sas_storew(buf+0x27,vd_mode_table[video_mode].ncols);
vd_mode_table[video_mode].npages= 2; /* support 2 pages */
sas_store(buf+0x29, vd_mode_table[video_mode].npages);
sas_store(buf+0x2A, get_scanlines());
sas_store(buf+0x2B,0x00); /* Primary Font select always 0 */
sas_store(buf+0x2C,0x00); /* Secondary Font select always 0 */
sas_store(buf+0x2D, 0x30); /* MDA with Monochrome Display */
sas_store(buf+0x31, 0); /* 64KB video memory */
setAX(0x1B); /* We did it! */
} /* if HERCULES */
#endif /* HERC */
}
void vga_int_1C()
{
sys_addr buff = effective_addr(getES(),getBX());
int i;
word states;
half_word temp;
rgb_struct rgb_dac;
static word buff_sizes[] = { 0,2,2,3,0x0d,0x0e,0x0e,0x0f };
static byte const1[] = { 2,0x18,6,0x20 };
static byte const2[] = { 0xd4,3,0x20,7,0,0 };
static byte const3[] = { 0x20 };
static byte const4[] = { 0x68,0x15,0x20,0x0a,0x85,0,0,0xc0,0,0x0c,0,0xc0,0,8,0,0xc0 };
static byte const5[] = { 1,0,0xff };
/* check that we really are a VGA */
if (video_adapter != VGA)
{
/* we are not -so this function is not implemented */
not_imp();
return;
}
states = getCX() & 7;
switch (getAL())
{
case 00: /* buffer sizes into bx */
setBX(buff_sizes[states]);
setAL(0x1c);
break;
case 01: /* Save video states to es:bx */
if( states&1 ) /* Video hardware state */
sas_storew(buff, 0x0064); /* ID words. DODGY! */
if( states&2 ) /* Video BIOS state */
sas_storew(buff+2, 0x0064);
if( states&4 ) /* Video DAC state */
sas_storew(buff+4, 0x0064);
buff += 0x20;
if( states&1 ) /* Video hardware state */
{
for(i=0;i<sizeof(const1);i++)
sas_store(buff++, const1[i]);
for(i=0;i<5;i++)
{
outb(EGA_SEQ_INDEX,i);
inb(EGA_SEQ_DATA,&temp);
sas_store(buff++, temp);
}
inb(VGA_MISC_READ_REG,&temp);
sas_store(buff++, temp);
for(i=0;i<0x19;i++)
{
outb(EGA_CRTC_INDEX,i);
inb(EGA_CRTC_DATA,&temp);
sas_store(buff++, temp);
}
for(i=0;i<20;i++)
{
inb(EGA_IPSTAT1_REG,&temp); /*clear attribute flipflop*/
outb(EGA_AC_INDEX_DATA,i);
inb(EGA_AC_SECRET,&temp);
sas_store(buff++, temp);
}
/* now ensure video reenabled. First ensure
* AC reg is in 'index' state by reading Status reg 1
*/
inb(EGA_IPSTAT1_REG,&temp);
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
for(i=0;i<9;i++)
{
outb(EGA_GC_INDEX,i);
inb(EGA_GC_DATA,&temp);
sas_store(buff++, temp);
}
for(i=0;i<sizeof(const2);i++)
sas_store(buff++, const2[i]);
}
if( states&2 ) /* Video BIOS state */
{
for(i=0;i<sizeof(const3);i++)
sas_store(buff++, const3[i]);
sas_store(buff++, sas_hw_at_no_check(vd_video_mode));
sas_storew(buff,sas_w_at_no_check(VID_COLS));
buff += 2;
sas_storew(buff,sas_w_at_no_check(VID_LEN));
buff += 2;
sas_storew(buff,sas_w_at_no_check(VID_ADDR));
buff += 2;
sas_move_bytes_forward(VID_CURPOS, buff, 16);
buff += 16;
outb(EGA_CRTC_INDEX,R11_CURS_END);
inb(EGA_CRTC_DATA,&temp);
sas_store(buff++, temp & 0x1F);
outb(EGA_CRTC_INDEX,R10_CURS_START);
inb(EGA_CRTC_DATA,&temp);
sas_store(buff++, temp & 0x1F);
sas_store(buff++, sas_hw_at_no_check(vd_current_page));
sas_storew(buff,sas_w_at_no_check(VID_INDEX));
buff += 2;
sas_store(buff++, sas_hw_at_no_check(vd_crt_mode));
sas_store(buff++, sas_hw_at_no_check(vd_crt_palette));
sas_store(buff++, sas_hw_at_no_check(vd_rows_on_screen));
sas_storew(buff, sas_w_at_no_check(ega_char_height));
buff += 2;
sas_store(buff++, sas_hw_at_no_check(ega_info));
sas_store(buff++, sas_hw_at_no_check(ega_info3));
sas_store(buff++, sas_hw_at_no_check(VGA_FLAGS));
sas_store(buff++, sas_hw_at_no_check(0x48a)); /* DCC */
sas_move_bytes_forward(EGA_SAVEPTR, buff, 4);
buff += 4;
for(i=0;i<sizeof(const4);i++)
sas_store(buff++, const4[i]);
}
if( states&4 ) /* VGA DAC values */
{
for(i=0;i<sizeof(const5);i++)
sas_store(buff++, const5[i]);
for(i=0;i<256;i++)
{
get_dac(i, &rgb_dac);
sas_store(buff++, rgb_dac.red);
sas_store(buff++, rgb_dac.green);
sas_store(buff++, rgb_dac.blue);
}
}
break;
case 02: /* Restore video states from es:bx */
buff += 0x20;
if( states&1 ) /* Video hardware state */
{
buff += sizeof(const1);
for(i=0;i<5;i++)
{
outb(EGA_SEQ_INDEX,i);
outb(EGA_SEQ_DATA,sas_hw_at_no_check(buff++));
}
outb(VGA_MISC_READ_REG,sas_hw_at_no_check(buff++));
for(i=0;i<0x19;i++)
{
outb(EGA_CRTC_INDEX,i);
outb(EGA_CRTC_DATA,sas_hw_at_no_check(buff++));
}
inb(EGA_IPSTAT1_REG,&temp); /* clear attribute flip flop */
for(i=0;i<20;i++)
{
outb(EGA_AC_INDEX_DATA,i);
outb(EGA_AC_INDEX_DATA,sas_hw_at_no_check(buff++));
}
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
for(i=0;i<9;i++)
{
outb(EGA_GC_INDEX,i);
outb(EGA_GC_DATA,sas_hw_at_no_check(buff++));
}
buff += sizeof(const2);
}
if( states&2 ) /* Video BIOS state */
{
buff += sizeof(const3);
sas_store_no_check(vd_video_mode, sas_hw_at_no_check(buff++));
sas_storew_no_check(VID_COLS,sas_w_at_no_check(buff));
buff += 2;
sas_storew_no_check(VID_LEN,sas_w_at_no_check(buff));
buff += 2;
sas_storew_no_check(VID_ADDR,sas_w_at_no_check(buff));
buff += 2;
sas_move_bytes_forward(buff, VID_CURPOS, 16);
buff += 16;
outb(EGA_CRTC_INDEX,R11_CURS_END);
temp = sas_hw_at_no_check(buff++) & 0x1F;
outb(EGA_CRTC_DATA,temp);
outb(EGA_CRTC_INDEX,R10_CURS_START);
temp = sas_hw_at_no_check(buff++) & 0x1F;
outb(EGA_CRTC_DATA,temp);
sas_store_no_check(vd_current_page, sas_hw_at_no_check(buff++));
sas_storew_no_check(VID_INDEX,sas_w_at_no_check(buff));
buff += 2;
sas_store_no_check(vd_crt_mode, sas_hw_at_no_check(buff++));
sas_store_no_check(vd_crt_palette, sas_hw_at_no_check(buff++));
sas_store_no_check(vd_rows_on_screen, sas_hw_at_no_check(buff++));
sas_storew_no_check(ega_char_height, sas_w_at_no_check(buff));
buff += 2;
sas_store_no_check(ega_info, sas_hw_at_no_check(buff++));
sas_store_no_check(ega_info3, sas_hw_at_no_check(buff++));
sas_store_no_check(VGA_FLAGS, sas_hw_at_no_check(buff++));
sas_store_no_check(0x48a, sas_hw_at_no_check(buff++)); /* DCC */
sas_move_bytes_forward(buff, EGA_SAVEPTR, 4);
buff += 4;
buff += sizeof(const4);
}
if( states&4 ) /* VGA DAC values */
{
buff += sizeof(const5);
for(i=0;i<256;i++)
{
rgb_dac.red = sas_hw_at_no_check(buff++);
rgb_dac.green = sas_hw_at_no_check(buff++);
rgb_dac.blue = sas_hw_at_no_check(buff++);
set_dac(i,&rgb_dac);
}
}
break;
default:
not_imp();
break;
}
}
#endif /* VGG */