📄 pcvt_ext.c
字号:
/* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. * * Copyright (C) 1992, 1993 Soeren Schmidt. * * All rights reserved. * * For the sake of compatibility, portions of this code regarding the * X server interface are taken from Soeren Schmidt's syscons driver. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by * Hellmuth Michaelis, Joerg Wunsch and Soeren Schmidt. * 4. The name authors may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * @(#)pcvt_ext.c, 3.20, Last Edit-Date: [Thu Apr 6 10:07:45 1995] * *//*---------------------------------------------------------------------------* * * pcvt_ext.c VT220 Driver Extended Support Routines * ------------------------------------------------------ * * -hm ------------ Release 3.00 -------------- * -hm integrating NetBSD-current patches * -hm applied Onno van der Linden's patch for Cirrus BIOS upgrade * -hm pcvt_x_hook has to care about fkey labels now * -hm changed some bcopyb's to bcopy's * -hm TS_INDEX -> TS_DATA for cirrus (mail from Onno/Charles) * -jw removed kbc_8042(), and replaced by kbd_emulate_pc() * -hm X server patch from John Kohl <jtk@kolvir.blrc.ma.us> * -hm applying Joerg's patch for FreeBSD 2.0 * -hm enable 132 col support for Trident TVGA8900CL * -hm applying patch from Joerg fixing Crtat bug * -hm removed PCVT_FAKE_SYSCONS10 * -hm fastscroll/Crtat bugfix from Lon Willett * -hm bell patch from Thomas Eberhardt for NetBSD * -hm multiple X server bugfixes from Lon Willett * -hm patch from John Kohl fixing tsleep bug in usl_vt_ioctl() * -hm bugfix: clear 25th line when switching to a force 24 lines vt * -jw add some forward declarations * -hm fixing MDA re-init when leaving X * -hm patch from John Kohl fixing potential divide by 0 problem * *---------------------------------------------------------------------------*/#include "vt.h"#if NVT > 0#include <i386/isa/pcvt/pcvt_hdr.h> /* global include */#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)static int s3testwritable( void );static int et4000_col( int );static int wd90c11_col( int );static int tri9000_col( int );static int v7_1024i_col( int );static int s3_928_col( int );static int cl_gd542x_col( int );/* storage to save video timing values of 80 columns text mode */static union { u_char generic[11]; u_char et4000[11]; u_char wd90c11[12]; u_char tri9000[13]; u_char v7_1024i[17]; u_char s3_928[32]; u_char cirrus[13];}savearea;static int regsaved = 0; /* registers are saved to savearea *//*---------------------------------------------------------------------------* * * Find out which video board we are running on, taken from: * Richard Ferraro: Programmers Guide to the EGA and VGA Cards * and from David E. Wexelblat's SuperProbe Version 1.0. * When a board is found, for which 132 column switching is * provided, the global variable "can_do_132col" is set to 1, * also the global variable vga_family is set to what we found. * * ############################################################### * ## THIS IS GETTING MORE AND MORE A LARGE SPAGHETTI HACK !!!! ## * ############################################################### * *---------------------------------------------------------------------------*/u_charvga_chipset(void){ u_char *ptr; u_char byte, oldbyte, old1byte, newbyte;#if PCVT_132GENERIC can_do_132col = 1; /* assumes everyone can do 132 col */#else can_do_132col = 0; /* assumes noone can do 132 col */#endif /* PCVT_132GENERIC */ vga_family = VGA_F_NONE;/*---------------------------------------------------------------------------* * check for Western Digital / Paradise chipsets *---------------------------------------------------------------------------*/ ptr = (u_char *)Crtat; if(color) ptr += (0xc007d - 0xb8000); else ptr += (0xc007d - 0xb0000); if((*ptr++ == 'V') && (*ptr++ == 'G') && (*ptr++ == 'A') && (*ptr++ == '=')) { int wd90c10; vga_family = VGA_F_WD; outb(addr_6845, 0x2b); oldbyte = inb(addr_6845+1); outb(addr_6845+1, 0xaa); newbyte = inb(addr_6845+1); outb(addr_6845+1, oldbyte); if(newbyte != 0xaa) return(VGA_PVGA); /* PVGA1A chip */ outb(TS_INDEX, 0x12); oldbyte = inb(TS_DATA); outb(TS_DATA, oldbyte & 0xbf); newbyte = inb(TS_DATA) & 0x40; if(newbyte != 0) return(VGA_WD90C00); /* WD90C00 chip */ outb(TS_DATA, oldbyte | 0x40); newbyte = inb(TS_DATA) & 0x40; if(newbyte == 0) return(VGA_WD90C00); /* WD90C00 chip */ outb(TS_DATA, oldbyte); wd90c10 = 0; outb(TS_INDEX, 0x10); oldbyte = inb(TS_DATA); outb(TS_DATA, oldbyte & 0xfb); newbyte = inb(TS_DATA) & 0x04; if(newbyte != 0) wd90c10 = 1; outb(TS_DATA, oldbyte | 0x04); newbyte = inb(TS_DATA) & 0x04; if(newbyte == 0) wd90c10 = 1; outb(TS_DATA, oldbyte); if(wd90c10) return(VGA_WD90C10); else { can_do_132col = 1; return(VGA_WD90C11); } }/*---------------------------------------------------------------------------* * check for Trident chipsets *---------------------------------------------------------------------------*/ outb(TS_INDEX, 0x0b); oldbyte = inb(TS_DATA); outb(TS_INDEX, 0x0b); outb(TS_DATA, 0x00); byte = inb(TS_DATA); /* chipset type */ outb(TS_INDEX, 0x0e); old1byte = inb(TS_DATA); outb(TS_DATA, 0); newbyte = inb(TS_DATA); outb(TS_DATA, (old1byte ^ 0x02)); outb(TS_INDEX, 0x0b); outb(TS_DATA, oldbyte); if((newbyte & 0x0f) == 0x02) { /* is a trident chip */ vga_family = VGA_F_TRI; switch(byte) { case 0x01: return(VGA_TR8800BR); case 0x02: return(VGA_TR8800CS); case 0x03: can_do_132col = 1; return(VGA_TR8900B); case 0x04: case 0x13: /* Haven't tried, but should work */ can_do_132col = 1; return(VGA_TR8900C); case 0x23: can_do_132col = 1; return(VGA_TR9000); case 0x33: can_do_132col = 1; return(VGA_TR8900CL); case 0x83: return(VGA_TR9200); case 0x93: return(VGA_TR9100); default: return(VGA_TRUNKNOWN); } }/*---------------------------------------------------------------------------* * check for Tseng Labs ET3000/4000 chipsets *---------------------------------------------------------------------------*/ outb(GN_HERCOMPAT, 0x06); if(color) outb(GN_DMCNTLC, 0xa0); else outb(GN_DMCNTLM, 0xa0); /* read old value */ if(color) inb(GN_INPSTAT1C); else inb(GN_INPSTAT1M); outb(ATC_INDEX, ATC_MISC); oldbyte = inb(ATC_DATAR); /* write new value */ if(color) inb(GN_INPSTAT1C); else inb(GN_INPSTAT1M); outb(ATC_INDEX, ATC_MISC); newbyte = oldbyte ^ 0x10; outb(ATC_DATAW, newbyte); /* read back new value */ if(color) inb(GN_INPSTAT1C); else inb(GN_INPSTAT1M); outb(ATC_INDEX, ATC_MISC); byte = inb(ATC_DATAR); /* write back old value */ if(color) inb(GN_INPSTAT1C); else inb(GN_INPSTAT1M); outb(ATC_INDEX, ATC_MISC); outb(ATC_DATAW, oldbyte); if(byte == newbyte) /* ET3000 or ET4000 */ { vga_family = VGA_F_TSENG; outb(addr_6845, CRTC_EXTSTART); oldbyte = inb(addr_6845+1); newbyte = oldbyte ^ 0x0f; outb(addr_6845+1, newbyte); byte = inb(addr_6845+1); outb(addr_6845+1, oldbyte); if(byte == newbyte) { can_do_132col = 1; return(VGA_ET4000); } else { return(VGA_ET3000); } }/*---------------------------------------------------------------------------* * check for Video7 VGA chipsets *---------------------------------------------------------------------------*/ outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */ outb(TS_DATA, 0xea); outb(addr_6845, CRTC_STARTADRH); oldbyte = inb(addr_6845+1); outb(addr_6845+1, 0x55); newbyte = inb(addr_6845+1); outb(addr_6845, CRTC_V7ID); /* id register */ byte = inb(addr_6845+1); /* read id */ outb(addr_6845, CRTC_STARTADRH); outb(addr_6845+1, oldbyte); outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */ outb(TS_DATA, 0xae); if(byte == (0x55 ^ 0xea)) { /* is Video 7 */ vga_family = VGA_F_V7; outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */ outb(TS_DATA, 0xea); outb(TS_INDEX, TS_V7CHIPREV); byte = inb(TS_DATA); outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */ outb(TS_DATA, 0xae); if(byte < 0xff && byte >= 0x80) return(VGA_V7VEGA); if(byte < 0x7f && byte >= 0x70) return(VGA_V7FWVR); if(byte < 0x5a && byte >= 0x50) return(VGA_V7V5); if(byte < 0x4a && byte > 0x40) { can_do_132col = 1; return(VGA_V71024I); } return(VGA_V7UNKNOWN); }/*---------------------------------------------------------------------------* * check for S3 chipsets *---------------------------------------------------------------------------*/ outb(addr_6845, 0x38); /* reg 1 lock register */ old1byte = inb(addr_6845+1); /* get old value */ outb(addr_6845, 0x38); outb(addr_6845+1, 0x00); /* lock registers */ if(s3testwritable() == 0) /* check if locked */ { outb(addr_6845, 0x38); outb(addr_6845+1, 0x48); /* unlock registers */ if(s3testwritable() == 1 ) /* check if unlocked */ { vga_family = VGA_F_S3; /* FAMILY S3 */ outb(addr_6845, 0x30); /* chip id/rev reg */ byte = inb(addr_6845+1); switch(byte & 0xf0) { case 0x80: switch(byte & 0x0f) { case 0x01: outb(addr_6845, 0x38); outb(addr_6845+1, old1byte); return VGA_S3_911; case 0x02: outb(addr_6845, 0x38); outb(addr_6845+1, old1byte); return VGA_S3_924; default: outb(addr_6845, 0x38); outb(addr_6845+1, old1byte); return VGA_S3_UNKNOWN; } break; case 0xA0: outb(addr_6845, 0x38); outb(addr_6845+1, old1byte); return VGA_S3_80x; case 0x90: case 0xb0: outb(addr_6845, 0x38); outb(addr_6845+1, old1byte); can_do_132col = 1; return VGA_S3_928; default: outb(addr_6845, 0x38); outb(addr_6845+1, old1byte); return VGA_S3_UNKNOWN; } } }/*---------------------------------------------------------------------------* * check for Cirrus chipsets *---------------------------------------------------------------------------*/ outb(TS_INDEX, 6); oldbyte = inb(TS_DATA); outb(TS_INDEX, 6); outb(TS_DATA, 0x12); outb(TS_INDEX, 6); newbyte = inb(TS_DATA); outb(addr_6845, 0x27); byte = inb(addr_6845 + 1); outb(TS_INDEX, 6); outb(TS_DATA, oldbyte); if (newbyte == 0x12) { vga_family = VGA_F_CIR; can_do_132col = 1; switch ((byte & 0xfc) >> 2) { case 0x22: switch (byte & 3) { case 0: return VGA_CL_GD5402; case 1: return VGA_CL_GD5402r1; case 2: return VGA_CL_GD5420; case 3: return VGA_CL_GD5420r1; } break; case 0x23: return VGA_CL_GD5422; case 0x25: return VGA_CL_GD5424; case 0x24: return VGA_CL_GD5426; case 0x26: return VGA_CL_GD5428; } } return(VGA_UNKNOWN);}/*--------------------------------------------------------------------------- * test if index 35 lower nibble is writable (taken from SuperProbe 1.0) *---------------------------------------------------------------------------*/static ints3testwritable(void){ u_char old, new1, new2; outb(addr_6845, 0x35); old = inb(addr_6845+1); /* save */ outb(addr_6845, 0x35); outb(addr_6845+1, (old & 0xf0)); /* write 0 */ outb(addr_6845, 0x35); new1 = (inb(addr_6845+1)) & 0x0f; /* must read 0 */ outb(addr_6845, 0x35); outb(addr_6845+1, (old | 0x0f)); /* write 1 */ outb(addr_6845, 0x35); new2 = (inb(addr_6845+1)) & 0x0f; /* must read 1 */ outb(addr_6845, 0x35); outb(addr_6845+1, old); /* restore */ return((new1==0) && (new2==0x0f));}/*---------------------------------------------------------------------------* * return ptr to string describing vga type *---------------------------------------------------------------------------*/char *vga_string(int number)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -