home *** CD-ROM | disk | FTP | other *** search
- /*
- pcmode.c
-
- % pc_ mode routines
-
- 7/9/88 by Ted.
-
- OWL-PC 1.2
- Copyright (c) 1988, by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 1/31/89 ted Changed pc_ModeSupport so it supports mode 7 even when an
- EGA/VGA is installed.
- 6/29/89 ted Converted pcinfo.asm to C; moved it here from pcinfo.asm.
- 7/12/89 ted Added OSTATIC's and '_func' macros.
- 7/17/89 ted Fixed newbios_modesupport: modebyte = 40 +, not 0x40 +.
- 8/01/89 ted Moved pc_init/restoremode to pcdisp.c.
-
- 9/29/89 jsm Fixed CGA mode 0 and 1 bug - as detailed by TED
- 3/28/90 jmd ansi-fied
- 6/07/90 ted Added comments in ram_testword and cursport_test.
- 6/22/90 ted added "void"s to no-parameter functions per ansii.
- 10/17/90 ted added cursport_test & EGA mono test to pc_IsHerc().
- 12/07/90 jsm/ted changed newbios_modesupport to return a 0 or 1 (not a bit mask).
- */
-
- #include "pcpriv.h"
-
- OSTATIC void DIGPRIV pc_sethflag(byte vf);
- OSTATIC boolean DIGPRIV ega_ismono(byte inbh);
- OSTATIC boolean DIGPRIV ega_modesupport(int mode);
- OSTATIC boolean DIGPRIV newbios(void);
- OSTATIC boolean DIGPRIV newbios_modesupport(int mode);
- OSTATIC boolean DIGPRIV vga_getinfo(byte *buf);
- OSTATIC boolean DIGPRIV ram_testword(unsigned seg, unsigned offs);
- OSTATIC boolean DIGPRIV cursport_test(int port);
-
- /* -------------------------------------------------------------------------- */
-
- void pc_SetMode(int mode)
- /*
- Sets the current video mode of the display adapter to the given mode.
- Clears the screen in the new mode.
- */
- {
- OREGS regs;
-
- switch (mode) {
- default:
- if (mode == 0x07 || mode == 0x0F) {
- pc_sethflag(PCHFLAG_MONO);
- if (pc_IsHerc()) { /* Restore herc card to text mode */
- herc_settmode();
- }
- }
- else {
- pc_sethflag(PCHFLAG_COLO);
- }
- if (mode == PCMODE_CPQ40) {
- mode = 0x40;
- }
- regs.h.al = (byte)mode;
- regs.h.ah = VIDINT_SETVM;
- regs.h.bh = TEXT_RPAGE;
- oakint86(BIOS_VIDINT, ®s);
- break;
- case PCMODE_EGA43:
- case PCMODE_VGA50:
- pc_sethflag(PCHFLAG_COLO);
-
- /* In case this is a VGA, set the proper number of scanlines */
- /* (EGA will not respond to this call and stay at 350) */
- regs.h.ah = VIDINT_ALTSEL; /* alternate select */
- regs.h.bl = ALTSEL_SETLINES; /* set # of scanlines */
- if (mode == PCMODE_EGA43) {
- regs.h.al = SETLINES_350;
- }
- else {
- regs.h.al = SETLINES_400;
- }
- oakint86(BIOS_VIDINT, ®s);
-
- regs.h.al = 0x03; /* These modes are based on mode 3 */
- regs.h.bh = TEXT_RPAGE;
- regs.h.ah = VIDINT_SETVM; /* reset video mode (see ega docs) */
- oakint86(BIOS_VIDINT, ®s);
-
- regs.h.ah = VIDINT_CHARGEN; /* character generator command */
- regs.h.al = CHARGEN_ROM8X8; /* choose 8x8 cell */
- regs.h.bl = 0;
- oakint86(BIOS_VIDINT, ®s); /* setup 43/50 line */
-
- regs.h.ah = VIDINT_ALTSEL; /* alternate select */
- regs.h.bl = ALTSEL_NEWPRTSCR; /* new print screen routine */
- oakint86(BIOS_VIDINT, ®s); /* setup new prt scrn */
-
- break;
- case PCMODE_HERC0:
- case PCMODE_HERC1:
- herc_setgmode(mode != PCMODE_HERC0);
- break;
- }
- }
- /* -------------------------------------------------------------------------- */
-
- int pc_GetMode(void)
- /*
- Returns the current video mode of the display adapter.
- */
- {
- OREGS regs;
- int mode;
- byte rows;
-
- regs.h.ah = VIDINT_GETVM;
- oakint86(BIOS_VIDINT, ®s);
- mode = (int)(regs.h.al & 0x7F); /* knock out hi noclear bit */
-
- /* Check for 43 or 50 line mode */
- if (mode == 0x03) {
- if (pc_IsEGA()) {
- ram_segtomem(0x40, 0x84, &rows, 1); /* Get Rows from BIOS data area */
- if (rows == 43-1) mode = PCMODE_EGA43;
- if (rows == 50-1) mode = PCMODE_VGA50;
- }
- }
- /* Check for herc graphics mode */
- if (mode == 0x05 || mode == 0x06 || mode == 0x07) {
- if (pc_IsHerc()) {
- if (herc_getlines() > 0xF00) {
- ram_segtomem(0x40, 0x49, &rows, 1); /* Get vidmode from BIOS */
- if (rows != 5) {
- mode = PCMODE_HERC0;
- }
- else mode = PCMODE_HERC1;
- }
- }
- }
- /* Check for Compaq mode 40 */
- if (mode == 0x40) {
- mode = PCMODE_CPQ40;
- }
- return(mode);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_ModeSupport(int mode)
- /* Return TRUE if mode is supported on current hardware */
- {
- if (mode == PCMODE_HERC0) {
- return(pc_IsHerc());
- }
- if (mode == PCMODE_HERC1) {
- return(pc_IsHerc() && !pc_IsCGA());
- }
- if (mode == PCMODE_CPQ40) {
- return(pc_IsCompaqPlasma() && !pc_IsEGA() && !pc_IsMDA());
- }
- if (newbios()) { /* vga/mcga bios gives supported modes */
- if (newbios_modesupport(mode)) {
- return(TRUE);
- }
- }
- if (pc_IsEGA()) {
- if (ega_modesupport(mode)) {
- return(TRUE);
- }
- }
- switch(mode) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- return(pc_IsCGA());
- case 0x07:
- return(pc_IsMDA());
- default:
- return(FALSE);
- }
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_IsHerc(void)
- {
- return(cursport_test(VID_MDAPORT) && herc_present() &&
- !(pc_IsEGA() && ega_ismono(0)));
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_IsMDA(void)
- {
- return(ram_testword(VID_MONOADDR, 4000) && cursport_test(VID_MDAPORT));
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_IsCGA(void)
- {
- return(ram_testword(VID_CGAADDR, 16000) && cursport_test(VID_CGAPORT));
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_IsEGA(void)
- {
- if (!ega_ismono(1)) {
- return(TRUE); /* ega is present, not mono */
- }
- else {
- if (ega_ismono(0)) {
- return(TRUE); /* ega is present */
- }
- }
- return(FALSE); /* ega not present */
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_IsMCGA(void)
- {
- return(newbios_modesupport(0x13));
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_IsVGA(void)
- {
- return(newbios_modesupport(0x12));
- }
- /* -------------------------------------------------------------------------- */
-
- boolean pc_IsCompaqPlasma(void)
- {
- OREGS regs;
-
- if (!pc_IsCompaq()) {
- return(FALSE);
- }
- regs.h.ah = VIDINT_CPQINFO; /* alternate select function */
- regs.h.al = 3;
- regs.x.cx = 0;
- oakint86(BIOS_VIDINT, ®s);
-
- return((regs.h.cl & CPQINFO_PLASMABIT) != 0);
- }
- /* -------------------------------------------------------------------------- */
- /* -------------------------------------------------------------------------- */
-
- static void DIGPRIV pc_sethflag(byte vf)
- {
- byte hf;
-
- /* Put Hardware Equip Flag Video bits to BIOS data area */
- ram_segtomem(0x40, 0x10, &hf, 1);
- hf &= ~0x30;
- hf |= vf & 0x30;
- ram_memtoseg(0x40, 0x10, &hf, 1);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV ega_ismono(byte inbh)
- {
- OREGS regs;
-
- regs.h.ah = VIDINT_ALTSEL; /* alternate select function */
- regs.h.bl = ALTSEL_GETINFO; /* return ega info */
- regs.h.bh = inbh;
- oakint86(BIOS_VIDINT, ®s);
-
- return(regs.h.bh == 1);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV ega_modesupport(int mode)
- {
- switch(mode) {
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x0D:
- case 0x0E:
- case 0x10:
- case PCMODE_EGA43:
- return(!ega_ismono(0));
- case 0x07:
- case 0x0F:
- return(ega_ismono(0));
- default:
- return(FALSE);
- }
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV newbios(void)
- {
- byte info[0x50];
-
- return(vga_getinfo(info));
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV newbios_modesupport(int mode)
- {
- byte info[0x50];
- unsigned modebit;
- int modebyte;
-
- if (vga_getinfo(info)) {
- if (mode == PCMODE_EGA43 || mode == PCMODE_VGA50) mode = 0x03;
- if (mode <= 0x13) {
- modebyte = 0x40 + mode/8;
- modebit = 1 << (mode % 8);
- return((boolean)((info[modebyte] & modebit) != 0));
- }
- }
- return(FALSE);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean DIGPRIV vga_getinfo(byte *buf)
- /*
- Load up a 50-byte buffer with vga mode info.
- */
- {
- OREGS regs;
- unsigned seg, offs;
-
- /* Call BIOS get-mode-info function to read info into buf */
- regs.a.esdx = buf;
- regs.x.di = regs.x.dx;
- regs.h.ah = VIDINT_MODEINFO;
- regs.h.al = 0;
- regs.x.bx = 0;
- oakint86es(BIOS_VIDINT, ®s, 0x40);
-
- if (regs.h.al == VIDINT_MODEINFO && regs.x.bx == 0) {
- /* Move extra info into end of buf using pointer from start of buf */
- offs = ((unsigned short *) buf)[0];
- seg = ((unsigned short *) buf)[1];
- ram_segtomem(seg, offs, &buf[0x40], 0x10);
- return(TRUE);
- }
- else return(FALSE);
- }
- /* -------------------------------------------------------------------------- */
- #define TESTVAL 0x56D4
-
- static boolean DIGPRIV ram_testword(unsigned seg, unsigned offs)
- /*
- Tests to see whether any graphics memory is present by writing a
- dummy value and then reading it again to see if it stayed written.
- */
- {
- unsigned oldval, tdummy, dummy;
-
- ram_segtomem(seg, offs, (byte *)&oldval, 2); /* read current val */
-
- dummy = TESTVAL;
- if (oldval == dummy) dummy++; /* If it's already dummy, change dummy */
-
- ram_memtoseg(seg, offs, (byte *)&dummy, 2); /* write dummy */
- tdummy = 0; /* kill time, settle bus */
- ram_segtomem(seg, offs, (byte *)&tdummy, 2); /* read back dummy */
-
- if (tdummy == dummy) { /* If dummy stayed written */
- ram_memtoseg(seg, offs, (byte *)&oldval, 2); /* restore old val */
- return(TRUE);
- }
- else return(FALSE);
- }
- /* -------------------------------------------------------------------------- */
- #define TESTPOS 4
-
- static boolean DIGPRIV cursport_test(int port)
- /*
- Tests to see whether a 6845 graphics controller is present by writing a
- dummy value to its cursor port and then reading it again to see if it stayed
- written.
- */
- {
- int oldval, tdummy, dummy;
-
- outp(port, 0x0F); /* Select the cursor port */
- oldval = inp(port+1); /* Read the current value */
-
- dummy = TESTPOS;
- if (oldval == dummy) dummy++; /* If it's already dummy, change dummy */
-
- outp(port, 0x0F); /* Select the cursor port */
- outp(port+1, dummy); /* Set dummy value */
-
- tdummy = 0; /* delay statement to avoid back-to back i/o */
- outp(port, 0x0F); /* Select the cursor port */
- tdummy = inp(port+1); /* Read the dummy value back */
-
- if (tdummy == dummy) { /* If we read back the same as what we wrote */
- outp(port, 0x0F); /* Select the cursor port */
- outp(port+1, oldval); /* Restore the starting value */
- return(TRUE);
- }
- else return(FALSE);
- }
- /* -------------------------------------------------------------------------- */
-
-