📄 tvga8900.c
字号:
/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen *//* *//* This library is free software; you can redistribute it and/or *//* modify it without any restrictions. This library is distributed *//* in the hope that it will be useful, but without any warranty. *//* Multi-chipset support Copyright (C) 1993 Harm Hanemaayer *//* Modified by Hartmut Schirmer *//* TVGA 8900c code taken from tvgalib by Toomas Losin *//* TVGA 9440 code added by ARK 29-OCT-97 *//* (root@ark.dyn.ml.org, ark@lhq.com) [nitc?] *//* updated 9-NOV-97 to support more regs *//* this should alllow it to work on 9680's as well *//* Thanks to Albert Erdmann (theone@miami.gdi.net) *//* for blindly testing files and mailing me results *//* for the 9680 registers */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include "vga.h"#include "libvga.h"#include "driver.h"#include "tvga8900.regs"#include "tvga9440.regs"#include "tvga9680.regs"/* static int tvga_chiptype; */static int tvga8900_memory; /* amount of video memory in K */static int tvga8900_nonint; /* nonzero if non-interlaced jumper set */static int tvga8900_init(int, int, int);static int tvga8900_interlaced(int mode);static int reg_0c = 0xad; /* value for 256k cards */static int tvga_model = 8900; /* set to 8900, 9440, or 9680 based on model *//* Mode table */#define ModeEntry94(res) { G##res, g##res##_regs94 }#define ModeEntry96(res) { G##res, g##res##_regs96 }static ModeTable tvga_modes_2048_96[] ={ /* 2M modes for the 9680 */ ModeEntry96(800x600x16), ModeEntry96(1024x768x16), ModeEntry96(1280x1024x16), ModeEntry96(1600x1200x16), ModeEntry96(640x480x256), ModeEntry96(800x600x256), ModeEntry96(1024x768x256), ModeEntry96(1280x1024x256), ModeEntry96(1600x1200x256), ModeEntry96(320x200x32K), ModeEntry96(640x480x32K), ModeEntry96(800x600x32K), ModeEntry96(1024x768x32K), ModeEntry96(320x200x64K), ModeEntry96(640x480x64K), ModeEntry96(800x600x64K), ModeEntry96(1024x768x64K), ModeEntry96(320x200x16M), ModeEntry96(640x480x16M), ModeEntry96(800x600x16M), END_OF_MODE_TABLE};static ModeTable tvga_modes_1024_96[] ={ /* 1M modes for the 9680 */ ModeEntry96(800x600x16), ModeEntry96(1024x768x16), ModeEntry96(1280x1024x16), ModeEntry96(1600x1200x16), ModeEntry96(640x480x256), ModeEntry96(800x600x256), ModeEntry96(1024x768x256), ModeEntry96(320x200x32K), ModeEntry96(640x480x32K), ModeEntry96(800x600x32K), ModeEntry96(320x200x64K), ModeEntry96(640x480x64K), ModeEntry96(800x600x64K), ModeEntry96(320x200x16M), ModeEntry96(640x480x16M), END_OF_MODE_TABLE};static ModeTable tvga_modes_512_96[] ={ /* 512K modes for the 9680 */ ModeEntry96(800x600x16), ModeEntry96(1024x768x16), ModeEntry96(640x480x256), ModeEntry96(800x600x256), ModeEntry96(320x200x32K), ModeEntry96(320x200x64K), ModeEntry96(320x200x16M), END_OF_MODE_TABLE};static ModeTable tvga_modes_1024_94[] ={ /* 1M modes for the 9440 */ ModeEntry94(800x600x16), ModeEntry94(1024x768x16), ModeEntry94(1280x1024x16), ModeEntry94(1600x1200x16), ModeEntry94(640x480x256), ModeEntry94(800x600x256), ModeEntry94(1024x768x256), ModeEntry94(320x200x32K), ModeEntry94(640x480x32K), ModeEntry94(800x600x32K), ModeEntry94(320x200x64K), ModeEntry94(640x480x64K), ModeEntry94(800x600x64K), ModeEntry94(320x200x16M), ModeEntry94(640x480x16M), END_OF_MODE_TABLE};static ModeTable tvga_modes_512_94[] ={ /* 512K modes for the 9440 */ ModeEntry94(800x600x16), ModeEntry94(1024x768x16), ModeEntry94(640x480x256), ModeEntry94(800x600x256), ModeEntry94(320x200x32K), ModeEntry94(320x200x64K), ModeEntry94(320x200x16M), END_OF_MODE_TABLE};static ModeTable tvga_modes_1024[] ={ /* 1Mb, non-interlace jumper set *//* *INDENT-OFF* */ OneModeEntry(640x480x256), OneModeEntry(800x600x256), OneModeEntry(1024x768x256), END_OF_MODE_TABLE/* *INDENT-ON* */};#define INTERL(res,i) { G##res, g##res##i##_regs }static ModeTable tvga_modes_1024i[] ={ /* 1Mb, jumper set to interlaced *//* *INDENT-OFF* */ INTERL(640x480x256, i), INTERL(800x600x256, i), INTERL(1024x768x256, i), END_OF_MODE_TABLE/* *INDENT-ON* */};static ModeTable tvga_modes_512[] ={ /* 512K *//* *INDENT-OFF* */ INTERL(640x480x256, i), INTERL(800x600x256, i1), END_OF_MODE_TABLE/* *INDENT-ON* */};static ModeTable *tvga_modes = NULL;static void nothing(void){}/* Fill in chipset specific mode information */static void tvga8900_getmodeinfo(int mode, vga_modeinfo * modeinfo){ if (modeinfo->bytesperpixel > 0) modeinfo->maxpixels = tvga8900_memory * 1024 / modeinfo->bytesperpixel; else modeinfo->maxpixels = tvga8900_memory * 1024; modeinfo->maxlogicalwidth = 2040; modeinfo->startaddressrange = 0xfffff; if (mode == G320x200x256) { /* Special case: bank boundary may not fall within display. */ modeinfo->startaddressrange = 0xf0000; /* Hack: disable page flipping capability for the moment. */ modeinfo->startaddressrange = 0xffff; modeinfo->maxpixels = 65536; } modeinfo->haveblit = 0; if (tvga8900_interlaced(mode)) modeinfo->flags |= IS_INTERLACED; modeinfo->flags &= ~HAVE_RWPAGE;}/* select the correct register table */static void setup_registers(void){ if (tvga_modes == NULL) { if (tvga_model == 9440) { if (tvga8900_memory < 1024) tvga_modes = tvga_modes_512_94; else tvga_modes = tvga_modes_1024_94; } else if (tvga_model == 9680) { if (tvga8900_memory < 1024) tvga_modes = tvga_modes_512_96; else if (tvga8900_memory < 2048) tvga_modes = tvga_modes_1024_96; else tvga_modes = tvga_modes_2048_96; } else { if (tvga8900_memory < 1024) tvga_modes = tvga_modes_512; if (tvga8900_nonint) tvga_modes = tvga_modes_1024; else tvga_modes = tvga_modes_1024i; } }}/* Read and store chipset-specific registers */static int tvga8900_saveregs(unsigned char regs[]){ int i; /* I know goto is bad, but i didnt want to indent all the old code.. */ /* the 9680 uses the same regs, just completely different values */ if (tvga_model == 9440 || tvga_model == 9680) goto tvga9440_saveregs; /* save extended CRT registers */ for (i = 0; i < 7; i++) { port_out(0x18 + i, __svgalib_CRT_I); regs[EXT + i] = port_in(__svgalib_CRT_D); } /* now do the sequencer mode regs */ port_out(0x0b, SEQ_I); /* force old mode regs */ port_out(port_in(SEQ_D), SEQ_D); /* by writing */ /* outw(SEQ_I, 0x820E); */ /* unlock conf. reg */ /* port_out(0x0c, SEQ_I); */ /* save conf. reg */ /* regs[EXT + 11] = port_in(SEQ_D); */ port_out(0x0d, SEQ_I); /* old reg 13 */ regs[EXT + 7] = port_in(SEQ_D); port_out(0x0e, SEQ_I); /* old reg 14 */ regs[EXT + 8] = port_in(SEQ_D); port_out(0x0b, SEQ_I); /* now use new regs */ port_in(SEQ_D); port_out(0x0d, SEQ_I); /* new reg 13 */ regs[EXT + 9] = port_in(SEQ_D); port_out(0x0e, SEQ_I); /* new reg 14 */ regs[EXT + 10] = port_in(SEQ_D) ^ 0x02; /* we do the ^ 0x02 so that when the regs are restored */ /* later we don't have a special case; see trident.doc */ return 12; /* tridents requires 12 additional registers */ /* 9440 code added by ARK */ tvga9440_saveregs: /* unprotect some trident regs */ port_out(0x0E, SEQ_I); port_out(port_in(SEQ_D) | 0x80, SEQ_D); /* save sequencer regs */ port_out(0x0B, SEQ_I); regs[EXT + 0] = port_in(SEQ_D); port_out(0x0D, SEQ_I); regs[EXT + 1] = port_in(SEQ_D); port_out(0x0E, SEQ_I); regs[EXT + 2] = port_in(SEQ_D); port_out(0x0F, SEQ_I); regs[EXT + 3] = port_in(SEQ_D); /* save extended CRT registers */ port_out(0x19, __svgalib_CRT_I); regs[EXT + 4] = port_in(__svgalib_CRT_D); port_out(0x1E, __svgalib_CRT_I); regs[EXT + 5] = port_in(__svgalib_CRT_D); port_out(0x1F, __svgalib_CRT_I); regs[EXT + 6] = port_in(__svgalib_CRT_D); port_out(0x21, __svgalib_CRT_I); regs[EXT + 7] = port_in(__svgalib_CRT_D); port_out(0x25, __svgalib_CRT_I); regs[EXT + 8] = port_in(__svgalib_CRT_D); port_out(0x27, __svgalib_CRT_I); regs[EXT + 9] = port_in(__svgalib_CRT_D); port_out(0x29, __svgalib_CRT_I); regs[EXT + 10] = port_in(__svgalib_CRT_D); /* Extended regs 11/12 are clobbered by vga.c */ port_out(0x2A, __svgalib_CRT_I); regs[EXT + 13] = port_in(__svgalib_CRT_D); port_out(0x2F, __svgalib_CRT_I); regs[EXT + 14] = port_in(__svgalib_CRT_D); port_out(0x30, __svgalib_CRT_I); regs[EXT + 15] = port_in(__svgalib_CRT_D); port_out(0x36, __svgalib_CRT_I); regs[EXT + 16] = port_in(__svgalib_CRT_D); port_out(0x38, __svgalib_CRT_I); regs[EXT + 17] = port_in(__svgalib_CRT_D); port_out(0x50, __svgalib_CRT_I); regs[EXT + 18] = port_in(__svgalib_CRT_D); /* grfx controller */ port_out(0x0F, GRA_I); regs[EXT + 19] = port_in(GRA_D); port_out(0x2F, GRA_I); regs[EXT + 20] = port_in(GRA_D); /* trident specific ports */ regs[EXT + 21] = port_in(0x43C8); regs[EXT + 22] = port_in(0x43C9); regs[EXT + 23] = port_in(0x83C6); regs[EXT + 24] = port_in(0x83C8); for(i=0;i<5;i++) port_in(PEL_MSK); regs[EXT + 25] = port_in(PEL_MSK); /* reprotect the regs to avoid conflicts */ port_out(0x0E, SEQ_I); port_out(port_in(SEQ_D) & 0x7F, SEQ_D); return 26; /* The 9440 requires 26 additional registers */}/* Set chipset-specific registers */static void tvga8900_setregs(const unsigned char regs[], int mode){ int i; int crtc31 = 0; /* 7 extended CRT registers */ /* 4 extended Sequencer registers (old and new) */ /* CRTC reg 0x1f is apparently dependent */ /* on the amount of memory installed. */ switch (tvga8900_memory >> 8) { case 1: crtc31 = 0x94; reg_0c = 0xad; break; /* 256K */ case 2: case 3: crtc31 = 0x98; reg_0c = 0xcd; break; /* 512/768K */ case 4: /* 1024K */ crtc31 = 0x18; reg_0c = 0xcd; if (mode == G1024x768x256) { reg_0c = 0xed; crtc31 = 0x98; } else if (mode == G640x480x256 || mode == G800x600x256) reg_0c = 0xed; break; } if (tvga_model == 9440 || tvga_model == 9680) goto tvga9440_setregs; if (mode == TEXT) { reg_0c = regs[EXT + 11]; crtc31 = regs[EXT + 12]; }#ifdef REG_DEBUG printf("Setting extended registers\n");#endif /* write extended CRT registers */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -