#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 #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> 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> 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 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