The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/pcvt/pcvt_ext.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999, 2002 Hellmuth Michaelis
    3  *
    4  * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
    5  *
    6  * Copyright (C) 1992, 1993 Soeren Schmidt.
    7  *
    8  * All rights reserved.
    9  *
   10  * For the sake of compatibility, portions of this code regarding the
   11  * X server interface are taken from Soeren Schmidt's syscons driver.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. All advertising materials mentioning features or use of this software
   22  *    must display the following acknowledgement:
   23  *      This product includes software developed by
   24  *      Hellmuth Michaelis, Joerg Wunsch and Soeren Schmidt.
   25  * 4. The name authors may not be used to endorse or promote products
   26  *    derived from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   29  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   30  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   31  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   33  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   35  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   36  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   37  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*---------------------------------------------------------------------------*
   41  *
   42  *      pcvt_ext.c      VT220 Driver Extended Support Routines
   43  *      ------------------------------------------------------
   44  *
   45  *      Last Edit-Date: [Fri Mar  8 19:57:55 2002]
   46  *
   47  * $FreeBSD: releng/6.0/sys/i386/isa/pcvt/pcvt_ext.c 139790 2005-01-06 22:18:23Z imp $
   48  *
   49  *---------------------------------------------------------------------------*/
   50 
   51 #include <i386/isa/pcvt/pcvt_hdr.h>     /* global include */
   52 
   53 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
   54 
   55 static int  s3testwritable( void );
   56 static int  et4000_col( int );
   57 static int  wd90c11_col( int );
   58 static int  tri9000_col( int );
   59 static int  v7_1024i_col( int );
   60 static int  s3_928_col( int );
   61 static int  cl_gd542x_col( int );
   62 
   63 #ifdef XSERVER
   64 static void fallback_to_auto(struct video_state *vsx);
   65 #endif
   66 
   67 /* storage to save video timing values of 80 columns text mode */
   68 static union {
   69         u_char generic[11];
   70         u_char et4000[11];
   71         u_char wd90c11[12];
   72         u_char tri9000[13];
   73         u_char v7_1024i[17];
   74         u_char s3_928[32];
   75         u_char cirrus[13];
   76 }
   77 savearea;
   78 
   79 static int regsaved = 0;        /* registers are saved to savearea */
   80 
   81 /*---------------------------------------------------------------------------*
   82  *
   83  *      Find out which video board we are running on, taken from:
   84  *      Richard Ferraro: Programmers Guide to the EGA and VGA Cards
   85  *      and from David E. Wexelblat's SuperProbe Version 1.0.
   86  *      When a board is found, for which 132 column switching is
   87  *      provided, the global variable "can_do_132col" is set to 1,
   88  *      also the global variable vga_family is set to what we found.
   89  *
   90  *      ###############################################################
   91  *      ## THIS IS GETTING MORE AND MORE A LARGE SPAGHETTI HACK !!!! ##
   92  *      ###############################################################
   93  *
   94  *---------------------------------------------------------------------------*/
   95 u_char
   96 vga_chipset(void)
   97 {
   98         u_char *ptr;
   99         u_char byte, oldbyte, old1byte, newbyte;
  100 
  101 #if PCVT_132GENERIC
  102         can_do_132col = 1;      /* assumes everyone can do 132 col */
  103 #else
  104         can_do_132col = 0;      /* assumes noone can do 132 col */
  105 #endif /* PCVT_132GENERIC */
  106 
  107         vga_family = VGA_F_NONE;
  108 
  109 /*---------------------------------------------------------------------------*
  110  *      check for Western Digital / Paradise chipsets
  111  *---------------------------------------------------------------------------*/
  112 
  113         ptr = (u_char *)Crtat;
  114 
  115         if(color)
  116                 ptr += (0xc007d - 0xb8000);
  117         else
  118                 ptr += (0xc007d - 0xb0000);
  119 
  120         if((*ptr++ == 'V') && (*ptr++ == 'G') &&
  121            (*ptr++ == 'A') && (*ptr++ == '='))
  122         {
  123                 int wd90c10;
  124 
  125                 vga_family = VGA_F_WD;
  126 
  127                 outb(addr_6845, 0x2b);
  128                 oldbyte = inb(addr_6845+1);
  129                 outb(addr_6845+1, 0xaa);
  130                 newbyte = inb(addr_6845+1);
  131                 outb(addr_6845+1, oldbyte);
  132                 if(newbyte != 0xaa)
  133                         return(VGA_PVGA);       /* PVGA1A chip */
  134 
  135                 outb(TS_INDEX, 0x12);
  136                 oldbyte = inb(TS_DATA);
  137                 outb(TS_DATA, oldbyte & 0xbf);
  138                 newbyte = inb(TS_DATA) & 0x40;
  139                 if(newbyte != 0)
  140                         return(VGA_WD90C00);    /* WD90C00 chip */
  141 
  142                 outb(TS_DATA, oldbyte | 0x40);
  143                 newbyte = inb(TS_DATA) & 0x40;
  144                 if(newbyte == 0)
  145                         return(VGA_WD90C00);    /* WD90C00 chip */
  146 
  147                 outb(TS_DATA, oldbyte);
  148 
  149                 wd90c10 = 0;
  150                 outb(TS_INDEX, 0x10);
  151                 oldbyte = inb(TS_DATA);
  152 
  153                 outb(TS_DATA, oldbyte & 0xfb);
  154                 newbyte = inb(TS_DATA) & 0x04;
  155                 if(newbyte != 0)
  156                         wd90c10 = 1;
  157 
  158                 outb(TS_DATA, oldbyte | 0x04);
  159                 newbyte = inb(TS_DATA) & 0x04;
  160                 if(newbyte == 0)
  161                         wd90c10 = 1;
  162 
  163                 outb(TS_DATA, oldbyte);
  164 
  165                 if(wd90c10)
  166                         return(VGA_WD90C10);
  167                 else
  168                 {
  169                         can_do_132col = 1;
  170                         return(VGA_WD90C11);
  171                 }
  172         }
  173 
  174 /*---------------------------------------------------------------------------*
  175  *      check for Trident chipsets
  176  *---------------------------------------------------------------------------*/
  177 
  178         outb(TS_INDEX, 0x0b);
  179         oldbyte = inb(TS_DATA);
  180 
  181 
  182         outb(TS_INDEX, 0x0b);
  183         outb(TS_DATA, 0x00);
  184 
  185         byte = inb(TS_DATA);    /* chipset type */
  186 
  187 
  188         outb(TS_INDEX, 0x0e);
  189         old1byte = inb(TS_DATA);
  190 
  191         outb(TS_DATA, 0);
  192         newbyte = inb(TS_DATA);
  193 
  194         outb(TS_DATA, (old1byte ^ 0x02));
  195 
  196         outb(TS_INDEX, 0x0b);
  197         outb(TS_DATA, oldbyte);
  198 
  199         if((newbyte & 0x0f) == 0x02)
  200         {
  201                 /* is a trident chip */
  202 
  203                 vga_family = VGA_F_TRI;
  204 
  205                 switch(byte)
  206                 {
  207                         case 0x01:
  208                                 return(VGA_TR8800BR);
  209 
  210                         case 0x02:
  211                                 return(VGA_TR8800CS);
  212 
  213                         case 0x03:
  214                                 can_do_132col = 1;
  215                                 return(VGA_TR8900B);
  216 
  217                         case 0x04:
  218                         case 0x13:
  219         /* Haven't tried, but should work */
  220                                 can_do_132col = 1;
  221                                 return(VGA_TR8900C);
  222 
  223                         case 0x23:
  224                                 can_do_132col = 1;
  225                                 return(VGA_TR9000);
  226 
  227                         case 0x33:
  228                                 can_do_132col = 1;
  229                                 return(VGA_TR8900CL);
  230 
  231                         case 0x83:
  232                                 return(VGA_TR9200);
  233 
  234                         case 0x93:
  235                                 return(VGA_TR9100);
  236 
  237                         default:
  238                                 return(VGA_TRUNKNOWN);
  239                 }
  240         }
  241 
  242 /*---------------------------------------------------------------------------*
  243  *      check for Tseng Labs ET3000/4000 chipsets
  244  *---------------------------------------------------------------------------*/
  245 
  246         outb(GN_HERCOMPAT, 0x06);
  247         if(color)
  248                 outb(GN_DMCNTLC, 0xa0);
  249         else
  250                 outb(GN_DMCNTLM, 0xa0);
  251 
  252         /* read old value */
  253 
  254         if(color)
  255                 inb(GN_INPSTAT1C);
  256         else
  257                 inb(GN_INPSTAT1M);
  258         outb(ATC_INDEX, ATC_MISC);
  259         oldbyte = inb(ATC_DATAR);
  260 
  261         /* write new value */
  262 
  263         if(color)
  264                 inb(GN_INPSTAT1C);
  265         else
  266                 inb(GN_INPSTAT1M);
  267         outb(ATC_INDEX, ATC_MISC);
  268         newbyte = oldbyte ^ 0x10;
  269         outb(ATC_DATAW, newbyte);
  270 
  271         /* read back new value */
  272         if(color)
  273                 inb(GN_INPSTAT1C);
  274         else
  275                 inb(GN_INPSTAT1M);
  276         outb(ATC_INDEX, ATC_MISC);
  277         byte = inb(ATC_DATAR);
  278 
  279         /* write back old value */
  280         if(color)
  281                 inb(GN_INPSTAT1C);
  282         else
  283                 inb(GN_INPSTAT1M);
  284         outb(ATC_INDEX, ATC_MISC);
  285         outb(ATC_DATAW, oldbyte);
  286 
  287         if(byte == newbyte)     /* ET3000 or ET4000 */
  288         {
  289                 vga_family = VGA_F_TSENG;
  290 
  291                 outb(addr_6845, CRTC_EXTSTART);
  292                 oldbyte = inb(addr_6845+1);
  293                 newbyte = oldbyte ^ 0x0f;
  294                 outb(addr_6845+1, newbyte);
  295                 byte = inb(addr_6845+1);
  296                 outb(addr_6845+1, oldbyte);
  297 
  298                 if(byte == newbyte)
  299                 {
  300                         can_do_132col = 1;
  301                         return(VGA_ET4000);
  302                 }
  303                 else
  304                 {
  305                         return(VGA_ET3000);
  306                 }
  307         }
  308 
  309 /*---------------------------------------------------------------------------*
  310  *      check for Video7 VGA chipsets
  311  *---------------------------------------------------------------------------*/
  312 
  313         outb(TS_INDEX, TS_EXTCNTL);     /* enable extensions */
  314         outb(TS_DATA, 0xea);
  315 
  316         outb(addr_6845, CRTC_STARTADRH);
  317         oldbyte = inb(addr_6845+1);
  318 
  319         outb(addr_6845+1, 0x55);
  320         newbyte = inb(addr_6845+1);
  321 
  322         outb(addr_6845, CRTC_V7ID);     /* id register */
  323         byte = inb(addr_6845+1);        /* read id */
  324 
  325         outb(addr_6845, CRTC_STARTADRH);
  326         outb(addr_6845+1, oldbyte);
  327 
  328         outb(TS_INDEX, TS_EXTCNTL);     /* disable extensions */
  329         outb(TS_DATA, 0xae);
  330 
  331         if(byte == (0x55 ^ 0xea))
  332         {                                       /* is Video 7 */
  333 
  334                 vga_family = VGA_F_V7;
  335 
  336                 outb(TS_INDEX, TS_EXTCNTL);     /* enable extensions */
  337                 outb(TS_DATA, 0xea);
  338 
  339                 outb(TS_INDEX, TS_V7CHIPREV);
  340                 byte = inb(TS_DATA);
  341 
  342                 outb(TS_INDEX, TS_EXTCNTL);     /* disable extensions */
  343                 outb(TS_DATA, 0xae);
  344 
  345                 if(byte < 0xff && byte >= 0x80)
  346                         return(VGA_V7VEGA);
  347                 if(byte < 0x7f && byte >= 0x70)
  348                         return(VGA_V7FWVR);
  349                 if(byte < 0x5a && byte >= 0x50)
  350                         return(VGA_V7V5);
  351                 if(byte < 0x4a && byte > 0x40)
  352                 {
  353                         can_do_132col = 1;
  354                         return(VGA_V71024I);
  355                 }
  356                 return(VGA_V7UNKNOWN);
  357         }
  358 
  359 /*---------------------------------------------------------------------------*
  360  *      check for S3 chipsets
  361  *---------------------------------------------------------------------------*/
  362 
  363         outb(addr_6845, 0x38);          /* reg 1 lock register */
  364         old1byte = inb(addr_6845+1);    /* get old value */
  365 
  366         outb(addr_6845, 0x38);
  367         outb(addr_6845+1, 0x00);        /* lock registers */
  368 
  369         if(s3testwritable() == 0)       /* check if locked */
  370         {
  371                 outb(addr_6845, 0x38);
  372                 outb(addr_6845+1, 0x48);        /* unlock registers */
  373 
  374                 if(s3testwritable() == 1 )      /* check if unlocked */
  375                 {
  376                         vga_family = VGA_F_S3;  /* FAMILY S3  */
  377 
  378                         outb(addr_6845, 0x30);  /* chip id/rev reg */
  379                         byte = inb(addr_6845+1);
  380 
  381                         switch(byte & 0xf0)
  382                         {
  383                                 case 0x80:
  384                                         switch(byte & 0x0f)
  385                                         {
  386                                                 case 0x01:
  387                                                         outb(addr_6845, 0x38);
  388                                                         outb(addr_6845+1, old1byte);
  389                                                         return VGA_S3_911;
  390 
  391                                                 case 0x02:
  392                                                         outb(addr_6845, 0x38);
  393                                                         outb(addr_6845+1, old1byte);
  394                                                         return VGA_S3_924;
  395 
  396                                                 default:
  397                                                         outb(addr_6845, 0x38);
  398                                                         outb(addr_6845+1, old1byte);
  399                                                         return VGA_S3_UNKNOWN;
  400                                         }
  401                                         break;
  402 
  403                                 case 0xA0:
  404                                         outb(addr_6845, 0x38);
  405                                         outb(addr_6845+1, old1byte);
  406                                         return VGA_S3_80x;
  407 
  408                                 case 0x90:
  409                                 case 0xb0:
  410                                         outb(addr_6845, 0x38);
  411                                         outb(addr_6845+1, old1byte);
  412                                         can_do_132col = 1;
  413                                         return VGA_S3_928;
  414 
  415                                 default:
  416                                         outb(addr_6845, 0x38);
  417                                         outb(addr_6845+1, old1byte);
  418                                         return VGA_S3_UNKNOWN;
  419                         }
  420                 }
  421         }
  422 
  423 /*---------------------------------------------------------------------------*
  424  *      check for Cirrus chipsets
  425  *---------------------------------------------------------------------------*/
  426 
  427         outb(TS_INDEX, 6);
  428         oldbyte = inb(TS_DATA);
  429         outb(TS_INDEX, 6);
  430         outb(TS_DATA, 0x12);
  431         outb(TS_INDEX, 6);
  432         newbyte = inb(TS_DATA);
  433         outb(addr_6845, 0x27);
  434         byte = inb(addr_6845 + 1);
  435         outb(TS_INDEX, 6);
  436         outb(TS_DATA, oldbyte);
  437         if (newbyte == 0x12) {
  438                 vga_family = VGA_F_CIR;
  439                 can_do_132col = 1;
  440                 switch ((byte & 0xfc) >> 2) {
  441                 case 0x22:
  442                         switch (byte & 3) {
  443                         case 0:
  444                                 return VGA_CL_GD5402;
  445                         case 1:
  446                                 return VGA_CL_GD5402r1;
  447                         case 2:
  448                                 return VGA_CL_GD5420;
  449                         case 3:
  450                                 return VGA_CL_GD5420r1;
  451                         }
  452                         break;
  453                 case 0x23:
  454                         return VGA_CL_GD5422;
  455                 case 0x25:
  456                         return VGA_CL_GD5424;
  457                 case 0x24:
  458                         return VGA_CL_GD5426;
  459                 case 0x26:
  460                         return VGA_CL_GD5428;
  461                 }
  462         }
  463 
  464         return(VGA_UNKNOWN);
  465 }
  466 
  467 /*---------------------------------------------------------------------------
  468  * test if index 35 lower nibble is writable (taken from SuperProbe 1.0)
  469  *---------------------------------------------------------------------------*/
  470 static int
  471 s3testwritable(void)
  472 {
  473         u_char old, new1, new2;
  474 
  475         outb(addr_6845, 0x35);
  476         old = inb(addr_6845+1);                 /* save */
  477 
  478         outb(addr_6845, 0x35);
  479         outb(addr_6845+1, (old & 0xf0));        /* write 0 */
  480 
  481         outb(addr_6845, 0x35);
  482         new1 = (inb(addr_6845+1)) & 0x0f;       /* must read 0 */
  483 
  484         outb(addr_6845, 0x35);
  485         outb(addr_6845+1, (old | 0x0f));        /* write 1 */
  486 
  487         outb(addr_6845, 0x35);
  488         new2 = (inb(addr_6845+1)) & 0x0f;       /* must read 1 */
  489 
  490         outb(addr_6845, 0x35);
  491         outb(addr_6845+1, old);                 /* restore */
  492 
  493         return((new1==0) && (new2==0x0f));
  494 }
  495 
  496 /*---------------------------------------------------------------------------*
  497  *      return ptr to string describing vga type
  498  *---------------------------------------------------------------------------*/
  499 char *
  500 vga_string(int number)
  501 {
  502         static char *vga_tab[] = {
  503                 "generic",
  504                 "et4000",
  505                 "et3000",
  506                 "pvga1a",
  507                 "wd90c00",
  508                 "wd90c10",
  509                 "wd90c11",
  510                 "v7 vega",
  511                 "v7 fast",
  512                 "v7 ver5",
  513                 "v7 1024i",
  514                 "unknown v7",
  515                 "tvga 8800br",
  516                 "tvga 8800cs",
  517                 "tvga 8900b",
  518                 "tvga 8900c",
  519                 "tvga 8900cl",
  520                 "tvga 9000",
  521                 "tvga 9100",
  522                 "tvga 9200",
  523                 "unknown trident",
  524                 "s3 911",
  525                 "s3 924",
  526                 "s3 801/805",
  527                 "s3 928",
  528                 "unkown s3",
  529                 "cl-gd5402",
  530                 "cl-gd5402r1",
  531                 "cl-gd5420",
  532                 "cl-gd5420r1",
  533                 "cl-gd5422",
  534                 "cl-gd5424",
  535                 "cl-gd5426",
  536                 "cl-gd5428"
  537         };
  538         return(vga_tab[number]);
  539 }
  540 
  541 /*---------------------------------------------------------------------------*
  542  *      toggle vga 80/132 column operation
  543  *---------------------------------------------------------------------------*/
  544 int
  545 vga_col(struct video_state *svsp, int cols)
  546 {
  547         int ret = 0;
  548 
  549         if(adaptor_type != VGA_ADAPTOR)
  550                 return(0);
  551 
  552         switch(vga_type)
  553         {
  554                 case VGA_ET4000:
  555                         ret = et4000_col(cols);
  556                         break;
  557 
  558                 case VGA_WD90C11:
  559                         ret = wd90c11_col(cols);
  560                         break;
  561 
  562                 case VGA_TR8900B:
  563                 case VGA_TR8900C:
  564                 case VGA_TR8900CL:
  565                 case VGA_TR9000:
  566                         ret = tri9000_col(cols);
  567                         break;
  568 
  569                 case VGA_V71024I:
  570                         ret = v7_1024i_col(cols);
  571                         break;
  572 
  573                 case VGA_S3_928:
  574                         ret = s3_928_col(cols);
  575                         break;
  576 
  577                 case VGA_CL_GD5402:
  578                 case VGA_CL_GD5402r1:
  579                 case VGA_CL_GD5420:
  580                 case VGA_CL_GD5420r1:
  581                 case VGA_CL_GD5422:
  582                 case VGA_CL_GD5424:
  583                 case VGA_CL_GD5426:
  584                 case VGA_CL_GD5428:
  585                         ret = cl_gd542x_col(cols);
  586                         break;
  587 
  588                 default:
  589 
  590 #if PCVT_132GENERIC
  591                         ret = generic_col(cols);
  592 #endif /* PCVT_132GENERIC */
  593 
  594                         break;
  595         }
  596 
  597         if(ret == 0)
  598                 return(0);      /* failed */
  599 
  600         svsp->maxcol = cols;
  601 
  602         return(1);
  603 }
  604 
  605 #if PCVT_132GENERIC
  606 /*---------------------------------------------------------------------------*
  607  *      toggle 80/132 column operation for "generic" SVGAs
  608  *      NB: this is supposed to work on any (S)VGA as long as the monitor
  609  *      is able to sync down to 21.5 kHz horizontally. The resulting
  610  *      vertical frequency is only 50 Hz, so if there is some better board
  611  *      specific algorithm, we avoid using this generic one.
  612  *      REPORT ANY FAILURES SO WE CAN IMPROVE THIS
  613  *---------------------------------------------------------------------------*/
  614 
  615 #if PCVT_EXP_132COL
  616 /*
  617  *      Some improved (i.e. higher scan rates) figures for the horizontal
  618  *      timing. USE AT YOUR OWN RISK, THIS MIGHT DAMAGE YOUR MONITOR DUE
  619  *      TO A LOSS OF HORIZONTAL SYNC!
  620  *      The figures have been tested with an ET3000 board along with a
  621  *      NEC MultiSync 3D monitor. If you are playing here, consider
  622  *      testing with several screen pictures (dark background vs. light
  623  *      background, even enlightening the border color may impact the
  624  *      result - you can do this e.g. by "scon -p black,42,42,42")
  625  *      Remember that all horizontal timing values must be dividable
  626  *      by 8! (The scheme below is taken so that nifty kernel hackers
  627  *      are able to patch the figures at run-time.)
  628  *
  629  *      The actual numbers result in 23 kHz line scan and 54 Hz vertical
  630  *      scan.
  631  */
  632 #endif /* PCVT_EXP_132COL */
  633 
  634 int
  635 generic_col(int cols)
  636 {
  637         u_char *sp;
  638         u_char byte;
  639 
  640 #if !PCVT_EXP_132COL
  641 
  642         /* stable figures for any multisync monitor that syncs down to 22 kHz*/
  643         static volatile u_short htotal = 1312;
  644         static volatile u_short displayend = 1056;
  645         static volatile u_short blankstart = 1072;
  646         static volatile u_short syncstart = 1112;
  647         static volatile u_short syncend = 1280;
  648 
  649 #else /* PCVT_EXP_132COL */
  650 
  651         /* reduced sync-pulse width and sync delays */
  652         static volatile u_short htotal = 1232;
  653         static volatile u_short displayend = 1056;
  654         static volatile u_short blankstart = 1056;
  655         static volatile u_short syncstart = 1104;
  656         static volatile u_short syncend = 1168;
  657 
  658 #endif /* PCVT_EXP_132COL */
  659 
  660         vga_screen_off();
  661 
  662         /* enable access to first 7 CRTC registers */
  663 
  664         outb(addr_6845, CRTC_VSYNCE);
  665         byte = inb(addr_6845+1);
  666         outb(addr_6845, CRTC_VSYNCE);
  667         outb(addr_6845+1, byte & 0x7f);
  668 
  669         if(cols == SCR_COL132)          /* switch 80 -> 132 */
  670         {
  671                 /* save state of board for 80 columns */
  672 
  673                 if(!regsaved)
  674                 {
  675                         regsaved = 1;
  676 
  677                         sp = savearea.generic;
  678 
  679                         outb(addr_6845, 0x00);  /* Horizontal Total */
  680                         *sp++ = inb(addr_6845+1);
  681                         outb(addr_6845, 0x01);  /* Horizontal Display End */
  682                         *sp++ = inb(addr_6845+1);
  683                         outb(addr_6845, 0x02);  /* Horizontal Blank Start */
  684                         *sp++ = inb(addr_6845+1);
  685                         outb(addr_6845, 0x03);  /* Horizontal Blank End */
  686                         *sp++ = inb(addr_6845+1);
  687                         outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
  688                         *sp++ = inb(addr_6845+1);
  689                         outb(addr_6845, 0x05);  /* Horizontal Retrace End */
  690                         *sp++ = inb(addr_6845+1);
  691 
  692                         outb(addr_6845, 0x13);  /* Row Offset Register */
  693                         *sp++ = inb(addr_6845+1);
  694 
  695                         outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
  696                         *sp++ = inb(TS_DATA);
  697 
  698                         if(color)
  699                                 inb(GN_INPSTAT1C);
  700                         else
  701                                 inb(GN_INPSTAT1M);
  702                         /* ATC Mode control */
  703                         outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
  704                         *sp++ = inb(ATC_DATAR);
  705 
  706                         if(color)
  707                                 inb(GN_INPSTAT1C);
  708                         else
  709                                 inb(GN_INPSTAT1M);
  710                         /* ATC Horizontal Pixel Panning */
  711                         outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
  712                         *sp++ = inb(ATC_DATAR);
  713 
  714                         *sp++ = inb(GN_MISCOUTR); /* Misc output register */
  715                 }
  716 
  717                 /* setup chipset for 132 column operation */
  718 
  719 
  720                 outb(addr_6845, 0x00);  /* Horizontal Total */
  721                 outb(addr_6845+1, (htotal / 8) - 5);
  722                 outb(addr_6845, 0x01);  /* Horizontal Display End */
  723                 outb(addr_6845+1, (displayend / 8) - 1);
  724                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
  725                 outb(addr_6845+1, blankstart / 8);
  726                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
  727                 outb(addr_6845+1, ((syncend / 8) & 0x1f) | 0x80);
  728                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
  729                 outb(addr_6845+1, syncstart / 8);
  730                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
  731                 outb(addr_6845+1,
  732                      (((syncend / 8) & 0x20) * 4)
  733                      | ((syncend / 8) & 0x1f));
  734 
  735                 outb(addr_6845, 0x13);  /* Row Offset Register */
  736                 outb(addr_6845+1, 0x42);
  737 
  738                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
  739                 outb(TS_DATA, 0x01);    /* 8 dot char clock */
  740 
  741                 if(color)
  742                         inb(GN_INPSTAT1C);
  743                 else
  744                         inb(GN_INPSTAT1M);
  745                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
  746                 outb(ATC_DATAW, 0x08);  /* Line graphics disable */
  747 
  748                 if(color)
  749                         inb(GN_INPSTAT1C);
  750                 else
  751                         inb(GN_INPSTAT1M);
  752                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
  753                 outb(ATC_DATAW, 0x00);
  754 
  755                 /* Misc output register */
  756                 /* use the 28.322 MHz clock */
  757                 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | 4);
  758         }
  759         else    /* switch 132 -> 80 */
  760         {
  761                 if(!regsaved)                   /* failsafe */
  762                 {
  763                         /* disable access to first 7 CRTC registers */
  764                         outb(addr_6845, CRTC_VSYNCE);
  765                         outb(addr_6845+1, byte);
  766                         vga_screen_on();
  767                         return(0);
  768                 }
  769 
  770                 sp = savearea.generic;
  771 
  772                 outb(addr_6845, 0x00);  /* Horizontal Total */
  773                 outb(addr_6845+1, *sp++);
  774                 outb(addr_6845, 0x01);  /* Horizontal Display End */
  775                 outb(addr_6845+1, *sp++);
  776                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
  777                 outb(addr_6845+1, *sp++);
  778                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
  779                 outb(addr_6845+1, *sp++);
  780                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
  781                 outb(addr_6845+1, *sp++);
  782                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
  783                 outb(addr_6845+1, *sp++);
  784 
  785                 outb(addr_6845, 0x13);  /* Row Offset Register */
  786                 outb(addr_6845+1, *sp++);
  787 
  788                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
  789                 outb(TS_DATA, *sp++);
  790 
  791                 if(color)
  792                         inb(GN_INPSTAT1C);
  793                 else
  794                         inb(GN_INPSTAT1M);
  795                 /* ATC Mode control */
  796                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
  797                 outb(ATC_DATAW, *sp++);
  798 
  799                 if(color)
  800                         inb(GN_INPSTAT1C);
  801                 else
  802                         inb(GN_INPSTAT1M);
  803                 /* ATC Horizontal Pixel Panning */
  804                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
  805                 outb(ATC_DATAW, *sp++);
  806 
  807                 outb(GN_MISCOUTW, *sp++);       /* Misc output register */
  808         }
  809 
  810         /* disable access to first 7 CRTC registers */
  811 
  812         outb(addr_6845, CRTC_VSYNCE);
  813         outb(addr_6845+1, byte);
  814 
  815         vga_screen_on();
  816 
  817         return(1);
  818 }
  819 #endif /* PCVT_132GENERIC */
  820 
  821 /*---------------------------------------------------------------------------*
  822  *      toggle 80/132 column operation for ET4000 based boards
  823  *---------------------------------------------------------------------------*/
  824 int
  825 et4000_col(int cols)
  826 {
  827         u_char *sp;
  828         u_char byte;
  829 
  830         vga_screen_off();
  831 
  832         /* enable access to first 7 CRTC registers */
  833 
  834         outb(addr_6845, CRTC_VSYNCE);
  835         byte = inb(addr_6845+1);
  836         outb(addr_6845, CRTC_VSYNCE);
  837         outb(addr_6845+1, byte & 0x7f);
  838 
  839         if(cols == SCR_COL132)          /* switch 80 -> 132 */
  840         {
  841                 /* save state of board for 80 columns */
  842 
  843                 if(!regsaved)
  844                 {
  845                         regsaved = 1;
  846 
  847                         sp = savearea.et4000;
  848 
  849                         outb(addr_6845, 0x00);  /* Horizontal Total */
  850                         *sp++ = inb(addr_6845+1);
  851                         outb(addr_6845, 0x01);  /* Horizontal Display End */
  852                         *sp++ = inb(addr_6845+1);
  853                         outb(addr_6845, 0x02);  /* Horizontal Blank Start */
  854                         *sp++ = inb(addr_6845+1);
  855 
  856                         outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
  857                         *sp++ = inb(addr_6845+1);
  858                         outb(addr_6845, 0x05);  /* Horizontal Retrace End */
  859                         *sp++ = inb(addr_6845+1);
  860 
  861                         outb(addr_6845, 0x13);  /* Row Offset Register */
  862                         *sp++ = inb(addr_6845+1);
  863 
  864                         outb(addr_6845, 0x34);  /* 6845 Compatibility */
  865                         *sp++ = inb(addr_6845+1);
  866 
  867                         outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
  868                         *sp++ = inb(TS_DATA);
  869 
  870                         if(color)
  871                                 inb(GN_INPSTAT1C);
  872                         else
  873                                 inb(GN_INPSTAT1M);
  874                         /* ATC Mode control */
  875                         outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
  876                         *sp++ = inb(ATC_DATAR);
  877 
  878                         if(color)
  879                                 inb(GN_INPSTAT1C);
  880                         else
  881                                 inb(GN_INPSTAT1M);
  882                         /* ATC Horizontal Pixel Panning */
  883                         outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
  884                         *sp++ = inb(ATC_DATAR);
  885 
  886                         *sp++ = inb(GN_MISCOUTR);       /* Misc output register */
  887                 }
  888 
  889                 /* setup chipset for 132 column operation */
  890 
  891                 outb(addr_6845, 0x00);  /* Horizontal Total */
  892                 outb(addr_6845+1, 0x9f);
  893                 outb(addr_6845, 0x01);  /* Horizontal Display End */
  894                 outb(addr_6845+1, 0x83);
  895                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
  896                 outb(addr_6845+1, 0x84);
  897 
  898                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
  899                 outb(addr_6845+1, 0x8b);
  900                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
  901                 outb(addr_6845+1, 0x80);
  902 
  903                 outb(addr_6845, 0x13);  /* Row Offset Register */
  904                 outb(addr_6845+1, 0x42);
  905 
  906                 outb(addr_6845, 0x34);  /* 6845 Compatibility */
  907                 outb(addr_6845+1, 0x0a);
  908 
  909                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
  910                 outb(TS_DATA, 0x01);    /* 8 dot char clock */
  911 
  912                 if(color)
  913                         inb(GN_INPSTAT1C);
  914                 else
  915                         inb(GN_INPSTAT1M);
  916                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
  917                 outb(ATC_DATAW, 0x08);  /* Line graphics disable */
  918 
  919                 if(color)
  920                         inb(GN_INPSTAT1C);
  921                 else
  922                         inb(GN_INPSTAT1M);
  923                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
  924                 outb(ATC_DATAW, 0x00);
  925 
  926                 /* Misc output register */
  927 
  928                 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c));
  929         }
  930         else    /* switch 132 -> 80 */
  931         {
  932                 if(!regsaved)                   /* failsafe */
  933                 {
  934                         /* disable access to first 7 CRTC registers */
  935                         outb(addr_6845, CRTC_VSYNCE);
  936                         outb(addr_6845+1, byte);
  937                         vga_screen_on();
  938                         return(0);
  939                 }
  940 
  941                 sp = savearea.et4000;
  942 
  943                 outb(addr_6845, 0x00);  /* Horizontal Total */
  944                 outb(addr_6845+1, *sp++);
  945 
  946                 outb(addr_6845, 0x01);  /* Horizontal Display End */
  947                 outb(addr_6845+1, *sp++);
  948                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
  949                 outb(addr_6845+1, *sp++);
  950 
  951 
  952                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
  953                 outb(addr_6845+1, *sp++);
  954                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
  955                 outb(addr_6845+1, *sp++);
  956 
  957                 outb(addr_6845, 0x13);  /* Row Offset Register */
  958                 outb(addr_6845+1, *sp++);
  959 
  960                 outb(addr_6845, 0x34);  /* 6845 Compatibility */
  961                 outb(addr_6845+1, *sp++);
  962 
  963                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
  964                 outb(TS_DATA, *sp++);
  965 
  966                 if(color)
  967                         inb(GN_INPSTAT1C);
  968                 else
  969                         inb(GN_INPSTAT1M);
  970                 /* ATC Mode control */
  971                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
  972                 outb(ATC_DATAW, *sp++);
  973 
  974                 if(color)
  975                         inb(GN_INPSTAT1C);
  976                 else
  977                         inb(GN_INPSTAT1M);
  978                 /* ATC Horizontal Pixel Panning */
  979                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
  980                 outb(ATC_DATAW, *sp++);
  981 
  982                 outb(GN_MISCOUTW, *sp++);       /* Misc output register */
  983         }
  984 
  985         /* disable access to first 7 CRTC registers */
  986 
  987         outb(addr_6845, CRTC_VSYNCE);
  988         outb(addr_6845+1, byte);
  989 
  990         vga_screen_on();
  991 
  992         return(1);
  993 }
  994 
  995 /*---------------------------------------------------------------------------*
  996  *      toggle 80/132 column operation for WD/Paradise based boards
  997  *
  998  *      when this card does 132 cols, the char map select register (TS_INDEX,
  999  *      TS_FONTSEL) function bits get REDEFINED. whoever did design this,
 1000  *      please don't cross my way ever .......
 1001  *
 1002  *---------------------------------------------------------------------------*/
 1003 int
 1004 wd90c11_col(int cols)
 1005 {
 1006         u_char *sp;
 1007         u_char byte;
 1008         int i;
 1009 
 1010         vga_screen_off();
 1011 
 1012         /* enable access to first 7 CRTC registers */
 1013 
 1014         outb(addr_6845, CRTC_VSYNCE);
 1015         byte = inb(addr_6845+1);
 1016         outb(addr_6845, CRTC_VSYNCE);
 1017         outb(addr_6845+1, byte & 0x7f);
 1018 
 1019         /* enable access to WD/Paradise "control extensions" */
 1020 
 1021         outb(GDC_INDEX, GDC_PR5GPLOCK);
 1022         outb(GDC_INDEX, 0x05);
 1023         outb(addr_6845, CRTC_PR10);
 1024         outb(addr_6845, 0x85);
 1025         outb(TS_INDEX, TS_UNLOCKSEQ);
 1026         outb(TS_DATA, 0x48);
 1027 
 1028         if(cols == SCR_COL132)          /* switch 80 -> 132 */
 1029         {
 1030                 /* save state of board for 80 columns */
 1031 
 1032                 if(!regsaved)
 1033                 {
 1034                         regsaved = 1;
 1035 
 1036                         /* save current fonts */
 1037 
 1038                         sp = savearea.wd90c11;
 1039 
 1040                         outb(addr_6845, 0x00);  /* Horizontal Total */
 1041                         *sp++ = inb(addr_6845+1);
 1042                         outb(addr_6845, 0x01);  /* Horizontal Display End */
 1043                         *sp++ = inb(addr_6845+1);
 1044                         outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1045                         *sp++ = inb(addr_6845+1);
 1046                         outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1047                         *sp++ = inb(addr_6845+1);
 1048                         outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1049                         *sp++ = inb(addr_6845+1);
 1050                         outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1051                         *sp++ = inb(addr_6845+1);
 1052 
 1053                         outb(addr_6845, 0x13);  /* Row Offset Register */
 1054                         *sp++ = inb(addr_6845+1);
 1055 
 1056                         outb(addr_6845, 0x2e);  /* misc 1 */
 1057                         *sp++ = inb(addr_6845+1);
 1058                         outb(addr_6845, 0x2f);  /* misc 2 */
 1059                         *sp++ = inb(addr_6845+1);
 1060 
 1061                         outb(TS_INDEX, 0x10);/* Timing Sequencer */
 1062                         *sp++ = inb(TS_DATA);
 1063                         outb(TS_INDEX, 0x12);/* Timing Sequencer */
 1064                         *sp++ = inb(TS_DATA);
 1065 
 1066                         *sp++ = inb(GN_MISCOUTR);       /* Misc output register */
 1067                 }
 1068 
 1069                 /* setup chipset for 132 column operation */
 1070 
 1071                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1072                 outb(addr_6845+1, 0x9c);
 1073                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1074                 outb(addr_6845+1, 0x83);
 1075                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1076                 outb(addr_6845+1, 0x84);
 1077                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1078                 outb(addr_6845+1, 0x9f);
 1079                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1080                 outb(addr_6845+1, 0x8a);
 1081                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1082                 outb(addr_6845+1, 0x1c);
 1083 
 1084                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1085                 outb(addr_6845+1, 0x42);
 1086 
 1087                 outb(addr_6845, 0x2e);  /* misc 1 */
 1088                 outb(addr_6845+1, 0x04);
 1089                 outb(addr_6845, 0x2f);  /* misc 2 */
 1090                 outb(addr_6845+1, 0x00);
 1091 
 1092                 outb(TS_INDEX, 0x10);/* Timing Sequencer */
 1093                 outb(TS_DATA, 0x21);
 1094                 outb(TS_INDEX, 0x12);/* Timing Sequencer */
 1095                 outb(TS_DATA, 0x14);
 1096 
 1097                 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x08));   /* Misc output register */
 1098 
 1099                 vsp->wd132col = 1;
 1100         }
 1101         else    /* switch 132 -> 80 */
 1102         {
 1103                 if(!regsaved)                   /* failsafe */
 1104                 {
 1105                         /* disable access to first 7 CRTC registers */
 1106 
 1107                         outb(addr_6845, CRTC_VSYNCE);
 1108                         outb(addr_6845+1, byte);
 1109 
 1110                         /* disable access to WD/Paradise "control extensions" */
 1111 
 1112                         outb(GDC_INDEX, GDC_PR5GPLOCK);
 1113                         outb(GDC_INDEX, 0x00);
 1114                         outb(addr_6845, CRTC_PR10);
 1115                         outb(addr_6845, 0x00);
 1116                         outb(TS_INDEX, TS_UNLOCKSEQ);
 1117                         outb(TS_DATA, 0x00);
 1118 
 1119                         vga_screen_on();
 1120 
 1121                         return(0);
 1122                 }
 1123 
 1124                 sp = savearea.wd90c11;
 1125 
 1126                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1127                 outb(addr_6845+1, *sp++);
 1128                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1129                 outb(addr_6845+1, *sp++);
 1130                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1131                 outb(addr_6845+1, *sp++);
 1132                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1133                 outb(addr_6845+1, *sp++);
 1134                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1135                 outb(addr_6845+1, *sp++);
 1136                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1137                 outb(addr_6845+1, *sp++);
 1138 
 1139                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1140                 outb(addr_6845+1, *sp++);
 1141 
 1142                 outb(addr_6845, 0x2e);  /* misc 1 */
 1143                 outb(addr_6845+1, *sp++);
 1144                 outb(addr_6845, 0x2f);  /* misc 2 */
 1145                 outb(addr_6845+1, *sp++);
 1146 
 1147                 outb(TS_INDEX, 0x10);/* Timing Sequencer */
 1148                 outb(addr_6845+1, *sp++);
 1149                 outb(TS_INDEX, 0x12);/* Timing Sequencer */
 1150                 outb(addr_6845+1, *sp++);
 1151 
 1152                 outb(GN_MISCOUTW, *sp++);       /* Misc output register */
 1153 
 1154                 vsp->wd132col = 0;
 1155         }
 1156 
 1157         /* restore fonts */
 1158 
 1159         for(i = 0; i < totalfonts; i++)
 1160                 if(saved_charsets[i])
 1161                         vga_move_charset(i, 0, 0);
 1162 
 1163         select_vga_charset(vsp->vga_charset);
 1164 
 1165         /* disable access to first 7 CRTC registers */
 1166 
 1167         outb(addr_6845, CRTC_VSYNCE);
 1168         outb(addr_6845+1, byte);
 1169 
 1170         /* disable access to WD/Paradise "control extensions" */
 1171 
 1172         outb(GDC_INDEX, GDC_PR5GPLOCK);
 1173         outb(GDC_INDEX, 0x00);
 1174         outb(addr_6845, CRTC_PR10);
 1175         outb(addr_6845, 0x00);
 1176         outb(TS_INDEX, TS_UNLOCKSEQ);
 1177         outb(TS_DATA, 0x00);
 1178 
 1179         vga_screen_on();
 1180 
 1181         return(1);
 1182 }
 1183 
 1184 /*---------------------------------------------------------------------------*
 1185  *      toggle 80/132 column operation for TRIDENT 9000 based boards
 1186  *---------------------------------------------------------------------------*/
 1187 int
 1188 tri9000_col(int cols)
 1189 {
 1190         u_char *sp;
 1191         u_char byte;
 1192 
 1193         vga_screen_off();
 1194 
 1195         /* sync reset is necessary to preserve memory contents ... */
 1196 
 1197         outb(TS_INDEX, TS_SYNCRESET);
 1198         outb(TS_DATA, 0x01);    /* synchronous reset */
 1199 
 1200         /* disable protection of misc out and other regs */
 1201 
 1202         outb(addr_6845, CRTC_MTEST);
 1203         byte = inb(addr_6845+1);
 1204         outb(addr_6845, CRTC_MTEST);
 1205         outb(addr_6845+1, byte & ~0x50);
 1206 
 1207         /* enable access to first 7 CRTC registers */
 1208 
 1209         outb(addr_6845, CRTC_VSYNCE);
 1210         byte = inb(addr_6845+1);
 1211         outb(addr_6845, CRTC_VSYNCE);
 1212         outb(addr_6845+1, byte & 0x7f);
 1213 
 1214         if(cols == SCR_COL132)          /* switch 80 -> 132 */
 1215         {
 1216                 /* save state of board for 80 columns */
 1217 
 1218                 if(!regsaved)
 1219                 {
 1220                         regsaved = 1;
 1221 
 1222                         sp = savearea.tri9000;
 1223 
 1224                         outb(addr_6845, 0x00);  /* Horizontal Total */
 1225                         *sp++ = inb(addr_6845+1);
 1226                         outb(addr_6845, 0x01);  /* Horizontal Display End */
 1227                         *sp++ = inb(addr_6845+1);
 1228                         outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1229                         *sp++ = inb(addr_6845+1);
 1230                         outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1231                         *sp++ = inb(addr_6845+1);
 1232                         outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1233                         *sp++ = inb(addr_6845+1);
 1234                         outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1235                         *sp++ = inb(addr_6845+1);
 1236 
 1237                         outb(addr_6845, 0x13);
 1238                         *sp++ = inb(addr_6845+1);
 1239 
 1240                         outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1241                         *sp++ = inb(TS_DATA);
 1242 
 1243                         outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
 1244                         outb(TS_DATA, 0x00);      /* write ANYTHING switches to OLD */
 1245                         outb(TS_INDEX, TS_MODEC2);
 1246                         *sp++ = inb(TS_DATA);
 1247 
 1248                         outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
 1249                         inb(TS_DATA);             /* read switches to NEW */
 1250                         outb(TS_INDEX, TS_MODEC2);
 1251                         *sp++ = inb(TS_DATA);
 1252 
 1253                         if(color)
 1254                                 inb(GN_INPSTAT1C);
 1255                         else
 1256                                 inb(GN_INPSTAT1M);
 1257                         /* ATC Mode control */
 1258                         outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 1259                         *sp++ = inb(ATC_DATAR);
 1260 
 1261                         if(color)
 1262                                 inb(GN_INPSTAT1C);
 1263                         else
 1264                                 inb(GN_INPSTAT1M);
 1265                         /* ATC Horizontal Pixel Panning */
 1266                         outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 1267                         *sp++ = inb(ATC_DATAR);
 1268 
 1269                         *sp++ = inb(GN_MISCOUTR);       /* Misc output register */
 1270                 }
 1271 
 1272                 /* setup chipset for 132 column operation */
 1273 
 1274                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1275                 outb(addr_6845+1, 0x9b);
 1276                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1277                 outb(addr_6845+1, 0x83);
 1278                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1279                 outb(addr_6845+1, 0x84);
 1280                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1281                 outb(addr_6845+1, 0x1e);
 1282                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1283                 outb(addr_6845+1, 0x87);
 1284                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1285                 outb(addr_6845+1, 0x1a);
 1286 
 1287                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1288                 outb(addr_6845+1, 0x42);
 1289 
 1290                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1291                 outb(TS_DATA, 0x01);    /* 8 dot char clock */
 1292 
 1293                 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
 1294                 outb(TS_DATA, 0x00);      /* write ANYTHING switches to OLD */
 1295                 outb(TS_INDEX, TS_MODEC2);
 1296                 outb(TS_DATA, 0x00);
 1297 
 1298                 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
 1299                 inb(TS_DATA);             /* read switches to NEW */
 1300                 outb(TS_INDEX, TS_MODEC2);
 1301                 outb(TS_DATA, 0x01);
 1302 
 1303                 if(color)
 1304                         inb(GN_INPSTAT1C);
 1305                 else
 1306                         inb(GN_INPSTAT1M);
 1307                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
 1308                 outb(ATC_DATAW, 0x08);  /* Line graphics disable */
 1309 
 1310                 if(color)
 1311                         inb(GN_INPSTAT1C);
 1312                 else
 1313                         inb(GN_INPSTAT1M);
 1314                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
 1315                 outb(ATC_DATAW, 0x00);
 1316 
 1317                 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c));   /* Misc output register */
 1318         }
 1319         else    /* switch 132 -> 80 */
 1320         {
 1321                 if(!regsaved)                   /* failsafe */
 1322                 {
 1323                         /* disable access to first 7 CRTC registers */
 1324                         outb(addr_6845, CRTC_VSYNCE);
 1325                         outb(addr_6845+1, byte);
 1326 
 1327                         outb(TS_INDEX, TS_SYNCRESET);
 1328                         outb(TS_DATA, 0x03);    /* clear synchronous reset */
 1329 
 1330                         vga_screen_on();
 1331 
 1332                         return(0);
 1333                 }
 1334 
 1335                 sp = savearea.tri9000;
 1336 
 1337                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1338                 outb(addr_6845+1, *sp++);
 1339                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1340                 outb(addr_6845+1, *sp++);
 1341                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1342                 outb(addr_6845+1, *sp++);
 1343                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1344                 outb(addr_6845+1, *sp++);
 1345                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1346                 outb(addr_6845+1, *sp++);
 1347                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1348                 outb(addr_6845+1, *sp++);
 1349 
 1350                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1351                 outb(addr_6845+1, *sp++);
 1352 
 1353                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1354                 outb(TS_DATA, *sp++);
 1355 
 1356                 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
 1357                 outb(TS_DATA, 0x00);      /* write ANYTHING switches to OLD */
 1358                 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
 1359                 outb(TS_DATA, *sp++);
 1360 
 1361                 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
 1362                 inb(TS_DATA);             /* read switches to NEW */
 1363                 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
 1364                 outb(TS_DATA, *sp++);
 1365 
 1366                 if(color)
 1367                         inb(GN_INPSTAT1C);
 1368                 else
 1369                         inb(GN_INPSTAT1M);
 1370                 /* ATC Mode control */
 1371                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 1372                 outb(ATC_DATAW, *sp++);
 1373 
 1374                 if(color)
 1375                         inb(GN_INPSTAT1C);
 1376                 else
 1377                         inb(GN_INPSTAT1M);
 1378                 /* ATC Horizontal Pixel Panning */
 1379                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 1380                 outb(ATC_DATAW, *sp++);
 1381 
 1382                 outb(GN_MISCOUTW, *sp++);       /* Misc output register */
 1383         }
 1384 
 1385         /* disable access to first 7 CRTC registers */
 1386 
 1387         outb(addr_6845, CRTC_VSYNCE);
 1388         outb(addr_6845+1, byte);
 1389 
 1390         outb(TS_INDEX, TS_SYNCRESET);
 1391         outb(TS_DATA, 0x03);    /* clear synchronous reset */
 1392 
 1393         vga_screen_on();
 1394 
 1395         return(1);
 1396 }
 1397 
 1398 /*---------------------------------------------------------------------------*
 1399  *      toggle 80/132 column operation for Video7 VGA 1024i
 1400  *---------------------------------------------------------------------------*/
 1401 int
 1402 v7_1024i_col(int cols)
 1403 {
 1404         u_char *sp;
 1405         u_char byte;
 1406         u_char save__byte;
 1407 
 1408         vga_screen_off();
 1409 
 1410         /* enable access to first 7 CRTC registers */
 1411 
 1412         /* first, enable read access to vertical retrace start/end */
 1413         outb(addr_6845, CRTC_HBLANKE);
 1414         byte = inb(addr_6845+1);
 1415         outb(addr_6845, CRTC_HBLANKE);
 1416         outb(addr_6845+1, (byte | 0x80));
 1417 
 1418         /* second, enable access to protected registers */
 1419         outb(addr_6845, CRTC_VSYNCE);
 1420         save__byte = byte = inb(addr_6845+1);
 1421         byte |= 0x20;   /* no irq 2 */
 1422         byte &= 0x6f;   /* wr enable, clr irq flag */
 1423         outb(addr_6845, CRTC_VSYNCE);
 1424         outb(addr_6845+1, byte);
 1425 
 1426         outb(TS_INDEX, TS_EXTCNTL);     /* enable extensions */
 1427         outb(TS_DATA, 0xea);
 1428 
 1429 
 1430         if(cols == SCR_COL132)          /* switch 80 -> 132 */
 1431         {
 1432                 /* save state of board for 80 columns */
 1433 
 1434                 if(!regsaved)
 1435                 {
 1436                         regsaved = 1;
 1437 
 1438                         sp = savearea.v7_1024i;
 1439 
 1440                         outb(addr_6845, 0x00);  /* Horizontal Total */
 1441                         *sp++ = inb(addr_6845+1);
 1442                         outb(addr_6845, 0x01);  /* Horizontal Display End */
 1443                         *sp++ = inb(addr_6845+1);
 1444                         outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1445                         *sp++ = inb(addr_6845+1);
 1446                         outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1447                         *sp++ = inb(addr_6845+1);
 1448                         outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1449                         *sp++ = inb(addr_6845+1);
 1450                         outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1451                         *sp++ = inb(addr_6845+1);
 1452 
 1453                         outb(addr_6845, 0x13);  /* Row Offset Register */
 1454                         *sp++ = inb(addr_6845+1);
 1455 
 1456                         outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1457                         *sp++ = inb(TS_DATA);
 1458 
 1459                         if(color)
 1460                                 inb(GN_INPSTAT1C);
 1461                         else
 1462                                 inb(GN_INPSTAT1M);
 1463                         /* ATC Mode control */
 1464                         outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 1465                         *sp++ = inb(ATC_DATAR);
 1466 
 1467                         if(color)
 1468                                 inb(GN_INPSTAT1C);
 1469                         else
 1470                                 inb(GN_INPSTAT1M);
 1471                         /* ATC Horizontal Pixel Panning */
 1472                         outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 1473                         *sp++ = inb(ATC_DATAR);
 1474 
 1475                         outb(TS_INDEX, 0x83);
 1476                         *sp++ = inb(TS_DATA);
 1477 
 1478                         outb(TS_INDEX, 0xa4);
 1479                         *sp++ = inb(TS_DATA);
 1480 
 1481                         outb(TS_INDEX, 0xe0);
 1482                         *sp++ = inb(TS_DATA);
 1483 
 1484                         outb(TS_INDEX, 0xe4);
 1485                         *sp++ = inb(TS_DATA);
 1486 
 1487                         outb(TS_INDEX, 0xf8);
 1488                         *sp++ = inb(TS_DATA);
 1489 
 1490                         outb(TS_INDEX, 0xfd);
 1491                         *sp++ = inb(TS_DATA);
 1492 
 1493                         *sp++ = inb(GN_MISCOUTR);       /* Misc output register */
 1494                 }
 1495 
 1496                 /* setup chipset for 132 column operation */
 1497 
 1498                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1499                 outb(addr_6845+1, 0x9c);
 1500                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1501                 outb(addr_6845+1, 0x83);
 1502                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1503                 outb(addr_6845+1, 0x86);
 1504                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1505                 outb(addr_6845+1, 0x9e);
 1506                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1507                 outb(addr_6845+1, 0x89);
 1508                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1509                 outb(addr_6845+1, 0x1c);
 1510 
 1511                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1512                 outb(addr_6845+1, 0x42);
 1513 
 1514                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1515                 outb(TS_DATA, 0x01);    /* 8 dot char clock */
 1516 
 1517                 if(color)
 1518                         inb(GN_INPSTAT1C);
 1519                 else
 1520                         inb(GN_INPSTAT1M);
 1521                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
 1522                 outb(ATC_DATAW, 0x08);  /* Line graphics disable */
 1523 
 1524                 if(color)
 1525                         inb(GN_INPSTAT1C);
 1526                 else
 1527                         inb(GN_INPSTAT1M);
 1528                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
 1529                 outb(ATC_DATAW, 0x00);
 1530 
 1531                 outb(TS_INDEX, TS_SYNCRESET);
 1532                 outb(TS_DATA, 0x01);    /* synchronous reset */
 1533 
 1534                 outb(TS_INDEX, 0x83);
 1535                 outb(TS_DATA, 0xa0);
 1536 
 1537                 outb(TS_INDEX, 0xa4);
 1538                 outb(TS_DATA, 0x1c);
 1539 
 1540                 outb(TS_INDEX, 0xe0);
 1541                 outb(TS_DATA, 0x00);
 1542 
 1543                 outb(TS_INDEX, 0xe4);
 1544                 outb(TS_DATA, 0xfe);
 1545 
 1546                 outb(TS_INDEX, 0xf8);
 1547                 outb(TS_DATA, 0x1b);
 1548 
 1549                 outb(TS_INDEX, 0xfd);
 1550                 outb(TS_DATA, 0x33);
 1551 
 1552                 byte = inb(GN_MISCOUTR);
 1553                 byte |= 0x0c;
 1554                 outb(GN_MISCOUTW, byte);        /* Misc output register */
 1555 
 1556                 outb(TS_INDEX, TS_SYNCRESET);
 1557                 outb(TS_DATA, 0x03);    /* clear synchronous reset */
 1558         }
 1559         else    /* switch 132 -> 80 */
 1560         {
 1561                 if(!regsaved)                   /* failsafe */
 1562                 {
 1563                         outb(TS_INDEX, TS_EXTCNTL);     /* disable extensions */
 1564                         outb(TS_DATA, 0xae);
 1565 
 1566                         /* disable access to first 7 CRTC registers */
 1567                         outb(addr_6845, CRTC_VSYNCE);
 1568                         outb(addr_6845+1, byte);
 1569                         vga_screen_on();
 1570                         return(0);
 1571                 }
 1572 
 1573                 sp = savearea.v7_1024i;
 1574 
 1575                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1576                 outb(addr_6845+1, *sp++);
 1577                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1578                 outb(addr_6845+1, *sp++);
 1579                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1580                 outb(addr_6845+1, *sp++);
 1581                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1582                 outb(addr_6845+1, *sp++);
 1583                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1584                 outb(addr_6845+1, *sp++);
 1585                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1586                 outb(addr_6845+1, *sp++);
 1587 
 1588                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1589                 outb(addr_6845+1, *sp++);
 1590 
 1591                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1592                 outb(TS_DATA, *sp++);
 1593 
 1594                 if(color)
 1595                         inb(GN_INPSTAT1C);
 1596                 else
 1597                         inb(GN_INPSTAT1M);
 1598                 /* ATC Mode control */
 1599                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 1600                 outb(ATC_DATAW, *sp++);
 1601 
 1602                 if(color)
 1603                         inb(GN_INPSTAT1C);
 1604                 else
 1605                         inb(GN_INPSTAT1M);
 1606                 /* ATC Horizontal Pixel Panning */
 1607                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 1608                 outb(ATC_DATAW, *sp++);
 1609 
 1610                 outb(TS_INDEX, TS_SYNCRESET);
 1611                 outb(TS_DATA, 0x01);    /* synchronous reset */
 1612 
 1613                 outb(TS_INDEX, 0x83);
 1614                 outb(TS_DATA, *sp++);
 1615 
 1616                 outb(TS_INDEX, 0xa4);
 1617                 outb(TS_DATA, *sp++);
 1618 
 1619                 outb(TS_INDEX, 0xe0);
 1620                 outb(TS_DATA, *sp++);
 1621 
 1622                 outb(TS_INDEX, 0xe4);
 1623                 outb(TS_DATA, *sp++);
 1624 
 1625                 outb(TS_INDEX, 0xf8);
 1626                 outb(TS_DATA, *sp++);
 1627 
 1628                 outb(TS_INDEX, 0xfd);
 1629                 outb(TS_DATA, *sp++);
 1630 
 1631                 outb(GN_MISCOUTW, *sp++);       /* Misc output register */
 1632 
 1633                 outb(TS_INDEX, TS_SYNCRESET);
 1634                 outb(TS_DATA, 0x03);    /* clear synchronous reset */
 1635         }
 1636 
 1637         outb(TS_INDEX, TS_EXTCNTL);     /* disable extensions */
 1638         outb(TS_DATA, 0xae);
 1639 
 1640         /* disable access to first 7 CRTC registers */
 1641 
 1642         outb(addr_6845, CRTC_VSYNCE);
 1643         outb(addr_6845+1, save__byte);
 1644 
 1645         vga_screen_on();
 1646 
 1647         return(1);
 1648 }
 1649 
 1650 /*---------------------------------------------------------------------------*
 1651  *      toggle 80/132 column operation for S3 86C928 based boards
 1652  *---------------------------------------------------------------------------*/
 1653 int
 1654 s3_928_col(int cols)
 1655 {
 1656         u_char *sp;
 1657         u_char byte;
 1658 
 1659         vga_screen_off();
 1660 
 1661         outb(addr_6845, 0x38);
 1662         outb(addr_6845+1, 0x48);        /* unlock registers */
 1663         outb(addr_6845, 0x39);
 1664         outb(addr_6845+1, 0xa0);        /* unlock registers */
 1665 
 1666         /* enable access to first 7 CRTC registers */
 1667 
 1668         outb(addr_6845, CRTC_VSYNCE);
 1669         byte = inb(addr_6845+1);
 1670         outb(addr_6845, CRTC_VSYNCE);
 1671         outb(addr_6845+1, byte & 0x7f);
 1672 
 1673         if(cols == SCR_COL132)          /* switch 80 -> 132 */
 1674         {
 1675                 /* save state of board for 80 columns */
 1676 
 1677                 if(!regsaved)
 1678                 {
 1679                         regsaved = 1;
 1680 
 1681                         sp = savearea.s3_928;
 1682 
 1683                         outb(addr_6845, 0x00);  /* Horizontal Total */
 1684                         *sp++ = inb(addr_6845+1);
 1685                         outb(addr_6845, 0x01);  /* Horizontal Display End */
 1686                         *sp++ = inb(addr_6845+1);
 1687                         outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1688                         *sp++ = inb(addr_6845+1);
 1689                         outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1690                         *sp++ = inb(addr_6845+1);
 1691                         outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1692                         *sp++ = inb(addr_6845+1);
 1693                         outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1694                         *sp++ = inb(addr_6845+1);
 1695 
 1696                         outb(addr_6845, 0x13);  /* Row Offset Register */
 1697                         *sp++ = inb(addr_6845+1);
 1698 
 1699                         outb(addr_6845, 0x34);  /* Backward Compat 3 Reg */
 1700                         *sp++ = inb(addr_6845+1);
 1701                         outb(addr_6845, 0x3b);  /* Data Xfer Exec Position */
 1702                         *sp++ = inb(addr_6845+1);
 1703 
 1704                         outb(addr_6845, 0x42);  /* (Clock) Mode Control */
 1705                         *sp++ = inb(addr_6845+1);
 1706 
 1707                         outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1708                         *sp++ = inb(TS_DATA);
 1709 
 1710                         if(color)
 1711                                 inb(GN_INPSTAT1C);
 1712                         else
 1713                                 inb(GN_INPSTAT1M);
 1714                         /* ATC Mode control */
 1715                         outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 1716                         *sp++ = inb(ATC_DATAR);
 1717 
 1718                         if(color)
 1719                                 inb(GN_INPSTAT1C);
 1720                         else
 1721                                 inb(GN_INPSTAT1M);
 1722                         /* ATC Horizontal Pixel Panning */
 1723                         outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 1724                         *sp++ = inb(ATC_DATAR);
 1725 
 1726                         *sp++ = inb(GN_MISCOUTR);       /* Misc output register */
 1727                 }
 1728 
 1729                 /* setup chipset for 132 column operation */
 1730 
 1731                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1732                 outb(addr_6845+1, 0x9a);
 1733                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1734                 outb(addr_6845+1, 0x83);
 1735                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1736                 outb(addr_6845+1, 0x86);
 1737                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1738                 outb(addr_6845+1, 0x9d);
 1739                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1740                 outb(addr_6845+1, 0x87);
 1741                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1742                 outb(addr_6845+1, 0x1b);
 1743 
 1744                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1745                 outb(addr_6845+1, 0x42);
 1746 
 1747                 outb(addr_6845, 0x34);
 1748                 outb(addr_6845+1, 0x10);/* enable data xfer pos control */
 1749                 outb(addr_6845, 0x3b);
 1750                 outb(addr_6845+1, 0x90);/* set data xfer pos value */
 1751 
 1752                 outb(addr_6845, 0x42);  /* (Clock) Mode Control */
 1753                 outb(addr_6845+1, 0x02);/* Select 40MHz Clock */
 1754 
 1755                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1756                 outb(TS_DATA, 0x01);    /* 8 dot char clock */
 1757 
 1758                 if(color)
 1759                         inb(GN_INPSTAT1C);
 1760                 else
 1761                         inb(GN_INPSTAT1M);
 1762                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
 1763                 outb(ATC_DATAW, 0x08);  /* Line graphics disable */
 1764 
 1765                 if(color)
 1766                         inb(GN_INPSTAT1C);
 1767                 else
 1768                         inb(GN_INPSTAT1M);
 1769                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
 1770                 outb(ATC_DATAW, 0x00);
 1771 
 1772                 /* Misc output register */
 1773 
 1774                 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c));
 1775         }
 1776         else    /* switch 132 -> 80 */
 1777         {
 1778                 if(!regsaved)                   /* failsafe */
 1779                 {
 1780                         /* disable access to first 7 CRTC registers */
 1781                         outb(addr_6845, CRTC_VSYNCE);
 1782                         outb(addr_6845+1, byte);
 1783 
 1784                         outb(addr_6845, 0x38);
 1785                         outb(addr_6845+1, 0x00);        /* lock registers */
 1786                         outb(addr_6845, 0x39);
 1787                         outb(addr_6845+1, 0x00);        /* lock registers */
 1788 
 1789                         vga_screen_on();
 1790                         return(0);
 1791                 }
 1792 
 1793                 sp = savearea.s3_928;
 1794 
 1795                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1796                 outb(addr_6845+1, *sp++);
 1797                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1798                 outb(addr_6845+1, *sp++);
 1799                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1800                 outb(addr_6845+1, *sp++);
 1801                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1802                 outb(addr_6845+1, *sp++);
 1803                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1804                 outb(addr_6845+1, *sp++);
 1805                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1806                 outb(addr_6845+1, *sp++);
 1807 
 1808                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1809                 outb(addr_6845+1, *sp++);
 1810 
 1811                 outb(addr_6845, 0x34);
 1812                 outb(addr_6845+1, *sp++);
 1813                 outb(addr_6845, 0x3b);
 1814                 outb(addr_6845+1, *sp++);
 1815 
 1816                 outb(addr_6845, 0x42);  /* Mode control */
 1817                 outb(addr_6845+1, *sp++);
 1818 
 1819                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1820                 outb(TS_DATA, *sp++);
 1821 
 1822                 if(color)
 1823                         inb(GN_INPSTAT1C);
 1824                 else
 1825                         inb(GN_INPSTAT1M);
 1826                 /* ATC Mode control */
 1827                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 1828                 outb(ATC_DATAW, *sp++);
 1829 
 1830                 if(color)
 1831                         inb(GN_INPSTAT1C);
 1832                 else
 1833                         inb(GN_INPSTAT1M);
 1834                 /* ATC Horizontal Pixel Panning */
 1835                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 1836                 outb(ATC_DATAW, *sp++);
 1837 
 1838                 outb(GN_MISCOUTW, *sp++);       /* Misc output register */
 1839         }
 1840 
 1841         /* disable access to first 7 CRTC registers */
 1842 
 1843         outb(addr_6845, CRTC_VSYNCE);
 1844         outb(addr_6845+1, byte);
 1845 
 1846         outb(addr_6845, 0x38);
 1847         outb(addr_6845+1, 0x00);        /* lock registers */
 1848         outb(addr_6845, 0x39);
 1849         outb(addr_6845+1, 0x00);        /* lock registers */
 1850 
 1851         vga_screen_on();
 1852 
 1853         return(1);
 1854 }
 1855 
 1856 /*---------------------------------------------------------------------------*
 1857  *      toggle 80/132 column operation for Cirrus Logic 542x based boards
 1858  *---------------------------------------------------------------------------*/
 1859 int
 1860 cl_gd542x_col(int cols)
 1861 {
 1862         u_char *sp;
 1863         u_char byte;
 1864 
 1865         vga_screen_off();
 1866 
 1867         /* enable access to first 7 CRTC registers */
 1868 
 1869         outb(addr_6845, CRTC_VSYNCE);
 1870         byte = inb(addr_6845+1);
 1871         outb(addr_6845, CRTC_VSYNCE);
 1872         outb(addr_6845+1, byte & 0x7f);
 1873 
 1874         /* enable access to cirrus extension registers */
 1875         outb(TS_INDEX, 6);
 1876         outb(TS_DATA, 0x12);
 1877 
 1878         if(cols == SCR_COL132)          /* switch 80 -> 132 */
 1879         {
 1880                 /* save state of board for 80 columns */
 1881 
 1882                 if(!regsaved)
 1883                 {
 1884                         regsaved = 1;
 1885 
 1886                         sp = savearea.cirrus;
 1887 
 1888                         outb(addr_6845, 0x00);  /* Horizontal Total */
 1889                         *sp++ = inb(addr_6845+1);
 1890                         outb(addr_6845, 0x01);  /* Horizontal Display End */
 1891                         *sp++ = inb(addr_6845+1);
 1892                         outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1893                         *sp++ = inb(addr_6845+1);
 1894                         outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1895                         *sp++ = inb(addr_6845+1);
 1896                         outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1897                         *sp++ = inb(addr_6845+1);
 1898                         outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1899                         *sp++ = inb(addr_6845+1);
 1900 
 1901                         outb(addr_6845, 0x13);  /* Row Offset Register */
 1902                         *sp++ = inb(addr_6845+1);
 1903 
 1904                         outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1905                         *sp++ = inb(TS_DATA);
 1906 
 1907 
 1908                         if(color)
 1909                                 inb(GN_INPSTAT1C);
 1910                         else
 1911                                 inb(GN_INPSTAT1M);
 1912                         /* ATC Mode control */
 1913                         outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 1914                         *sp++ = inb(ATC_DATAR);
 1915 
 1916                         if(color)
 1917                                 inb(GN_INPSTAT1C);
 1918                         else
 1919                                 inb(GN_INPSTAT1M);
 1920                         /* ATC Horizontal Pixel Panning */
 1921                         outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 1922                         *sp++ = inb(ATC_DATAR);
 1923 
 1924                         /* VCLK2 Numerator Register */
 1925                         outb(TS_INDEX, 0xd);
 1926                         *sp++ = inb(TS_DATA);
 1927 
 1928                         /* VCLK2 Denominator and Post-Scalar Value Register */
 1929                         outb(TS_INDEX, 0x1d);
 1930                         *sp++ = inb(TS_DATA);
 1931 
 1932                         /* Misc output register */
 1933                         *sp++ = inb(GN_MISCOUTR);
 1934                 }
 1935 
 1936                 /* setup chipset for 132 column operation */
 1937 
 1938                 outb(addr_6845, 0x00);  /* Horizontal Total */
 1939                 outb(addr_6845+1, 0x9f);
 1940                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 1941                 outb(addr_6845+1, 0x83);
 1942                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 1943                 outb(addr_6845+1, 0x84);
 1944                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 1945                 outb(addr_6845+1, 0x82);
 1946                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 1947                 outb(addr_6845+1, 0x8a);
 1948                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 1949                 outb(addr_6845+1, 0x9e);
 1950 
 1951                 outb(addr_6845, 0x13);  /* Row Offset Register */
 1952                 outb(addr_6845+1, 0x42);
 1953 
 1954                 /* set VCLK2 to 41.164 MHz ..... */
 1955                 outb(TS_INDEX, 0xd);    /* VCLK2 Numerator Register */
 1956                 outb(TS_DATA, 0x45);
 1957 
 1958                 outb(TS_INDEX, 0x1d);   /* VCLK2 Denominator and */
 1959                 outb(TS_DATA, 0x30);   /* Post-Scalar Value Register */
 1960 
 1961                 /* and use it. */
 1962                 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | (2 << 2));
 1963 
 1964                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 1965                 outb(TS_DATA, 0x01);    /* 8 dot char clock */
 1966 
 1967                 if(color)
 1968                         inb(GN_INPSTAT1C);
 1969                 else
 1970                         inb(GN_INPSTAT1M);
 1971                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
 1972                 outb(ATC_DATAW, 0x08);  /* Line graphics disable */
 1973 
 1974                 if(color)
 1975                         inb(GN_INPSTAT1C);
 1976                 else
 1977                         inb(GN_INPSTAT1M);
 1978                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
 1979                 outb(ATC_DATAW, 0x00);
 1980         }
 1981         else    /* switch 132 -> 80 */
 1982         {
 1983                 if(!regsaved)                   /* failsafe */
 1984                 {
 1985                         /* disable access to first 7 CRTC registers */
 1986                         outb(addr_6845, CRTC_VSYNCE);
 1987                         outb(addr_6845+1, byte);
 1988 
 1989                         /* disable access to cirrus extension registers */
 1990                         outb(TS_INDEX, 6);
 1991                         outb(TS_DATA, 0);
 1992 
 1993                         vga_screen_on();
 1994                         return(0);
 1995                 }
 1996 
 1997                 sp = savearea.cirrus;
 1998 
 1999                 outb(addr_6845, 0x00);  /* Horizontal Total */
 2000                 outb(addr_6845+1, *sp++);
 2001                 outb(addr_6845, 0x01);  /* Horizontal Display End */
 2002                 outb(addr_6845+1, *sp++);
 2003                 outb(addr_6845, 0x02);  /* Horizontal Blank Start */
 2004                 outb(addr_6845+1, *sp++);
 2005                 outb(addr_6845, 0x03);  /* Horizontal Blank End */
 2006                 outb(addr_6845+1, *sp++);
 2007                 outb(addr_6845, 0x04);  /* Horizontal Retrace Start */
 2008                 outb(addr_6845+1, *sp++);
 2009                 outb(addr_6845, 0x05);  /* Horizontal Retrace End */
 2010                 outb(addr_6845+1, *sp++);
 2011 
 2012                 outb(addr_6845, 0x13);  /* Row Offset Register */
 2013                 outb(addr_6845+1, *sp++);
 2014 
 2015                 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
 2016                 outb(TS_DATA, *sp++);
 2017 
 2018                 if(color)
 2019                         inb(GN_INPSTAT1C);
 2020                 else
 2021                         inb(GN_INPSTAT1M);
 2022                 /* ATC Mode control */
 2023                 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
 2024                 outb(ATC_DATAW, *sp++);
 2025 
 2026                 if(color)
 2027                         inb(GN_INPSTAT1C);
 2028                 else
 2029                         inb(GN_INPSTAT1M);
 2030                 /* ATC Horizontal Pixel Panning */
 2031                 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
 2032                 outb(ATC_DATAW, *sp++);
 2033 
 2034                 /* VCLK2 Numerator Register */
 2035                 outb(TS_INDEX, 0xd);
 2036                 outb(TS_DATA, *sp++);
 2037 
 2038                 /* VCLK2 Denominator and Post-Scalar Value Register */
 2039                 outb(TS_INDEX, 0x1d);
 2040                 outb(TS_DATA, *sp++);
 2041 
 2042                 outb(GN_MISCOUTW, *sp++);       /* Misc output register */
 2043         }
 2044 
 2045         /* disable access to cirrus extension registers */
 2046         outb(TS_INDEX, 6);
 2047         outb(TS_DATA, 0);
 2048 
 2049         /* disable access to first 7 CRTC registers */
 2050 
 2051         outb(addr_6845, CRTC_VSYNCE);
 2052         outb(addr_6845+1, byte);
 2053 
 2054         vga_screen_on();
 2055 
 2056         return(1);
 2057 }
 2058 
 2059 #ifdef XSERVER
 2060 /*---------------------------------------------------------------------------*
 2061  *      switch screen from text mode to X-mode and vice versa
 2062  *---------------------------------------------------------------------------*/
 2063 void
 2064 switch_screen(int n, int oldgrafx, int newgrafx)
 2065 {
 2066 #if PCVT_SCREENSAVER
 2067         static unsigned saved_scrnsv_tmo = 0;
 2068 #endif  /* PCVT_SCREENSAVER */
 2069 
 2070         int cols = vsp->maxcol;         /* get current col val */
 2071 
 2072         if(n < 0 || n >= totalscreens)
 2073                 return;
 2074 
 2075         if(!oldgrafx && newgrafx)
 2076         {
 2077                 /* switch from text to graphics */
 2078 
 2079 #if PCVT_SCREENSAVER
 2080                 if((saved_scrnsv_tmo = scrnsv_timeout))
 2081                         pcvt_set_scrnsv_tmo(0); /* screensaver off */
 2082 #endif /* PCVT_SCREENSAVER */
 2083 
 2084                 async_update(UPDATE_STOP);      /* status display off */
 2085         }
 2086 
 2087         if(!oldgrafx)
 2088         {
 2089                 /* switch from text mode */
 2090 
 2091                 /* video board memory -> kernel memory */
 2092                 bcopy(vsp->Crtat, vsp->Memory,
 2093                       vsp->screen_rows * vsp->maxcol * CHR);
 2094 
 2095                 vsp->Crtat = vsp->Memory;       /* operate in memory now */
 2096         }
 2097 
 2098         /* update global screen pointers/variables */
 2099         current_video_screen = n;       /* current screen no */
 2100 
 2101         vsp = &vs[n];                   /* current video state ptr */
 2102 
 2103         if(oldgrafx && !newgrafx)
 2104         {
 2105                 /* switch from graphics to text mode */
 2106                 unsigned i;
 2107 
 2108                 /* restore fonts */
 2109                 for(i = 0; i < totalfonts; i++)
 2110                         if(saved_charsets[i])
 2111                                 vga_move_charset(i, 0, 0);
 2112 
 2113 #if PCVT_SCREENSAVER
 2114                 /* activate screen saver */
 2115                 if(saved_scrnsv_tmo)
 2116                         pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
 2117 #endif /* PCVT_SCREENSAVER */
 2118 
 2119                 /* re-initialize lost MDA information */
 2120                 if(adaptor_type == MDA_ADAPTOR)
 2121                 {
 2122                     /*
 2123                      * Due to the fact that HGC registers are write-only,
 2124                      * the Xserver can only make guesses about the state
 2125                      * the HGC adaptor has been before turning on X mode.
 2126                      * Thus, the display must be re-enabled now, and the
 2127                      * cursor shape and location restored.
 2128                      */
 2129                     outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
 2130                     outb(addr_6845, CRTC_CURSORH); /* select high register */
 2131                     outb(addr_6845+1,
 2132                          ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
 2133                     outb(addr_6845, CRTC_CURSORL); /* select low register */
 2134                     outb(addr_6845+1,
 2135                          ((vsp->Crtat + vsp->cur_offset) - Crtat));
 2136 
 2137                     outb(addr_6845, CRTC_CURSTART); /* select high register */
 2138                     outb(addr_6845+1, vsp->cursor_start);
 2139                     outb(addr_6845, CRTC_CUREND); /* select low register */
 2140                     outb(addr_6845+1, vsp->cursor_end);
 2141                 }
 2142 
 2143                 /* make status display happy */
 2144                 async_update(UPDATE_START);
 2145         }
 2146 
 2147         if(!newgrafx)
 2148         {
 2149                 /* to text mode */
 2150 
 2151                 /* kernel memory -> video board memory */
 2152                 bcopy(vsp->Crtat, Crtat,
 2153                       vsp->screen_rows * vsp->maxcol * CHR);
 2154 
 2155                 vsp->Crtat = Crtat;             /* operate on screen now */
 2156 
 2157                 outb(addr_6845, CRTC_STARTADRH);
 2158                 outb(addr_6845+1, 0);
 2159                 outb(addr_6845, CRTC_STARTADRL);
 2160                 outb(addr_6845+1, 0);
 2161         }
 2162 
 2163         select_vga_charset(vsp->vga_charset);
 2164 
 2165         if(vsp->maxcol != cols)
 2166                 vga_col(vsp, vsp->maxcol);      /* select 80/132 columns */
 2167 
 2168         outb(addr_6845, CRTC_CURSORH);  /* select high register */
 2169         outb(addr_6845+1, vsp->cur_offset >> 8);
 2170         outb(addr_6845, CRTC_CURSORL);  /* select low register */
 2171         outb(addr_6845+1, vsp->cur_offset);
 2172 
 2173         if(vsp->cursor_on)
 2174         {
 2175                 outb(addr_6845, CRTC_CURSTART); /* select high register */
 2176                 outb(addr_6845+1, vsp->cursor_start);
 2177                 outb(addr_6845, CRTC_CUREND);   /* select low register */
 2178                 outb(addr_6845+1, vsp->cursor_end);
 2179         }
 2180         else
 2181         {
 2182                 sw_cursor(0);
 2183         }
 2184 
 2185         if(adaptor_type == VGA_ADAPTOR)
 2186         {
 2187                 unsigned i;
 2188 
 2189                 /* switch VGA DAC palette entries */
 2190                 for(i = 0; i < NVGAPEL; i++)
 2191                         vgapaletteio(i, &vsp->palette[i], 1);
 2192         }
 2193 
 2194         if(!newgrafx)
 2195         {
 2196                 update_led();   /* update led's */
 2197                 update_hp(vsp); /* update fkey labels, if present */
 2198 
 2199                 /* if we switch to a vt with force 24 lines mode and    */
 2200                 /* pure VT emulation and 25 rows charset, then we have  */
 2201                 /* to clear the last line on display ...                */
 2202 
 2203                 if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) &&
 2204                         (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS))
 2205                 {
 2206                         fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol,
 2207                                 vsp->maxcol);
 2208                 }
 2209         }
 2210 }
 2211 
 2212 /*---------------------------------------------------------------------------*
 2213  *      Change specified vt to VT_AUTO mode
 2214  *      xxx Maybe this should also reset VT_GRAFX mode; since switching and
 2215  *      graphics modes are not going to work without VT_PROCESS mode.
 2216  *---------------------------------------------------------------------------*/
 2217 static void
 2218 set_auto_mode (struct video_state *vsx)
 2219 {
 2220         unsigned ostatus = vsx->vt_status;
 2221         vsx->smode.mode = VT_AUTO;
 2222         vsx->proc = NULL;
 2223         vsx->pid = 0;
 2224         vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK);
 2225 
 2226         if (ostatus & VT_WAIT_ACK)
 2227         {
 2228                 if(vsp == vsx && vt_switch_pending == current_video_screen + 1)
 2229                         vt_switch_pending = 0;
 2230         }
 2231         if (ostatus & VT_WAIT_REL)
 2232         {
 2233                 int new_screen = vt_switch_pending - 1;
 2234                 if (vsp == vsx && vt_switch_pending)
 2235                 {
 2236                         vt_switch_pending = 0;
 2237                         vgapage (new_screen);
 2238                 }
 2239         }
 2240 }
 2241 
 2242 /*---------------------------------------------------------------------------*
 2243  *      Exported function; to be called when a vt is closed down.
 2244  *
 2245  *      Ideally, we would like to be able to recover from an X server crash;
 2246  *      but in reality, if the server crashes hard while in control of the
 2247  *      vga board, then you're not likely to be able to use pcvt ttys
 2248  *      without rebooting.
 2249  *---------------------------------------------------------------------------*/
 2250 void
 2251 reset_usl_modes (struct video_state *vsx)
 2252 {
 2253         /* Clear graphics mode */
 2254         if (vsx->vt_status & VT_GRAFX) {
 2255             vsx->vt_status &= ~VT_GRAFX;
 2256             if (vsp == vsx)
 2257                 switch_screen(current_video_screen, 1, 0);
 2258         }
 2259 
 2260         /* Take kbd out of raw mode */
 2261         if (pcvt_kbd_raw && vsp == vsx) {
 2262 #if PCVT_SCANSET > 1
 2263                 kbd_emulate_pc(0);
 2264 #endif /* PCVT_SCANSET > 1 */
 2265                 pcvt_kbd_raw = 0;
 2266         }
 2267 
 2268         /* Clear process controlled mode */
 2269         set_auto_mode (vsx);
 2270 }
 2271 
 2272 /*
 2273  * Fallback to VT_AUTO if controlling process died.
 2274  */
 2275 static void
 2276 fallback_to_auto(struct video_state *vsx)
 2277 {
 2278         struct proc *p;
 2279 
 2280         if(vsx->proc) {
 2281                 p = pfind(vsx->pid);
 2282                 if (p != NULL) {
 2283                         PROC_UNLOCK(p);
 2284                         if (vsx->proc != p)
 2285                                 set_auto_mode(vsx);
 2286                 }
 2287         }
 2288 }
 2289 
 2290 /*---------------------------------------------------------------------------*
 2291  *      switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version
 2292  *      (the name vgapage() stands for historical reasons)
 2293  *---------------------------------------------------------------------------*/
 2294 int
 2295 vgapage(int new_screen)
 2296 {
 2297         int x;
 2298 
 2299         if(new_screen < 0 || new_screen >= totalscreens)
 2300                 return EINVAL;
 2301 
 2302         /* fallback to VT_AUTO if controlling processes died */
 2303         fallback_to_auto(vsp);
 2304         fallback_to_auto(&vs[new_screen]);
 2305 
 2306         if (!vt_switch_pending && new_screen == current_video_screen)
 2307                 return 0;
 2308 
 2309         if(vt_switch_pending && vt_switch_pending != new_screen + 1) {
 2310                 /* Try resignaling uncooperative X-window servers */
 2311                 if (vsp->smode.mode == VT_PROCESS) {
 2312                         if (vsp->vt_status & VT_WAIT_REL) {
 2313                                 if(vsp->smode.relsig) {
 2314                                         PROC_LOCK(vsp->proc);
 2315                                         psignal(vsp->proc, vsp->smode.relsig);
 2316                                         PROC_UNLOCK(vsp->proc);
 2317                                 }
 2318                         } else if (vsp->vt_status & VT_WAIT_ACK) {
 2319                                 if(vsp->smode.acqsig) {
 2320                                         PROC_LOCK(vsp->proc);
 2321                                         psignal(vsp->proc, vsp->smode.acqsig);
 2322                                         PROC_UNLOCK(vsp->proc);
 2323                                 }
 2324                         }
 2325                 }
 2326                 return EAGAIN;
 2327         }
 2328 
 2329         vt_switch_pending = new_screen + 1;
 2330 
 2331         if(vsp->smode.mode == VT_PROCESS)
 2332         {
 2333                 /* we cannot switch immediately here */
 2334                 vsp->vt_status |= VT_WAIT_REL;
 2335                 if(vsp->smode.relsig) {
 2336                         PROC_LOCK(vsp->proc);
 2337                         psignal(vsp->proc, vsp->smode.relsig);
 2338                         PROC_UNLOCK(vsp->proc);
 2339                 }
 2340         }
 2341         else
 2342         {
 2343                 struct video_state *old_vsp = vsp;
 2344 
 2345                 switch_screen(new_screen,
 2346                               vsp->vt_status & VT_GRAFX,
 2347                               vs[new_screen].vt_status & VT_GRAFX);
 2348 
 2349                 x = spltty();
 2350 
 2351                 if(old_vsp->vt_status & VT_WAIT_ACT)
 2352                 {
 2353                         old_vsp->vt_status &= ~VT_WAIT_ACT;
 2354                         wakeup(&old_vsp->smode);
 2355                 }
 2356 
 2357                 if(vsp->vt_status & VT_WAIT_ACT)
 2358                 {
 2359                         vsp->vt_status &= ~VT_WAIT_ACT;
 2360                         wakeup(&vsp->smode);
 2361                 }
 2362 
 2363                 splx(x);
 2364 
 2365                 if(vsp->smode.mode == VT_PROCESS)
 2366                 {
 2367                         /* if _new_ vt is under process control... */
 2368                         vsp->vt_status |= VT_WAIT_ACK;
 2369                         if(vsp->smode.acqsig) {
 2370                                 PROC_LOCK(vsp->proc);
 2371                                 psignal(vsp->proc, vsp->smode.acqsig);
 2372                                 PROC_UNLOCK(vsp->proc);
 2373                         }
 2374                 }
 2375                 else
 2376                 {
 2377                         /* we are committed */
 2378                         vt_switch_pending = 0;
 2379 
 2380                         /*
 2381                          * XXX: If pcvt is acting as the systems console,
 2382                          * avoid panics going to the debugger while we are in
 2383                          * process mode.
 2384                          */
 2385                         if(pcvt_is_console)
 2386                                 cnavailable(pcvt_consptr, TRUE);
 2387                 }
 2388         }
 2389         return 0;
 2390 }
 2391 
 2392 /*---------------------------------------------------------------------------*
 2393  *      ioctl handling for VT_USL mode
 2394  *---------------------------------------------------------------------------*/
 2395 int
 2396 usl_vt_ioctl(struct cdev *dev, int cmd, caddr_t data, int flag, struct thread *td)
 2397 {
 2398         struct proc *p;
 2399         int i, j, error, opri;
 2400         struct vt_mode newmode;
 2401 
 2402         switch(cmd)
 2403         {
 2404 
 2405         case VT_SETMODE:
 2406                 newmode = *(struct vt_mode *)data;
 2407                 p = td->td_proc;
 2408 
 2409                 opri = spltty();
 2410 
 2411                 if (newmode.mode != VT_PROCESS) {
 2412                         struct video_state *vsx = &vs[minor(dev)];
 2413                         if (vsx->smode.mode == VT_PROCESS) {
 2414                                 if (vsx->proc != p) {
 2415                                         splx(opri);
 2416                                         return EPERM;
 2417                                 }
 2418                                 set_auto_mode(vsx);
 2419                         }
 2420                         splx(opri);
 2421                         return 0;
 2422                 }
 2423 
 2424                 /*
 2425                  * NB: XFree86-3.1.1 does the following:
 2426                  *              VT_ACTIVATE (vtnum)
 2427                  *              VT_WAITACTIVE (vtnum)
 2428                  *              VT_SETMODE (VT_PROCESS)
 2429                  * So it is possible that the screen was switched
 2430                  * between the WAITACTIVE and the SETMODE (here).  This
 2431                  * can actually happen quite frequently, and it was
 2432                  * leading to dire consequences. Now it is detected by
 2433                  * requiring that minor(dev) match current_video_screen.
 2434                  * An alternative would be to operate on vs[minor(dev)]
 2435                  * instead of *vsp, but that would leave the server
 2436                  * confused, because it would believe that its vt was
 2437                  * currently activated.
 2438                  */
 2439                 if (minor(dev) != current_video_screen) {
 2440                         splx(opri);
 2441                         return EPERM;
 2442                 }
 2443 
 2444                 /* Check for server died */
 2445                 fallback_to_auto(vsp);
 2446 
 2447                 /* Check for server already running */
 2448                 if (vsp->smode.mode == VT_PROCESS && vsp->proc != p)
 2449                 {
 2450                         splx(opri);
 2451                         return EBUSY; /* already in use on this VT */
 2452                 }
 2453 
 2454                 if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig)
 2455                     || !ISSIGVALID(newmode.frsig))
 2456                 {
 2457                         splx(opri);
 2458                         return EINVAL;
 2459                 }
 2460 
 2461                 vsp->smode = newmode;
 2462                 vsp->proc = p;
 2463                 vsp->pid = p->p_pid;
 2464 
 2465                 /*
 2466                  * XXX: If pcvt is acting as the systems console,
 2467                  * avoid panics going to the debugger while we are in
 2468                  * process mode.
 2469                  */
 2470                 if(pcvt_is_console)
 2471                         cnavailable(pcvt_consptr, (newmode.mode != VT_PROCESS));
 2472 
 2473                 splx(opri);
 2474                 return 0;
 2475 
 2476         case VT_GETMODE:
 2477                 *(struct vt_mode *)data = vsp->smode;
 2478                 return 0;
 2479 
 2480         case VT_RELDISP:
 2481                 p = td->td_proc;
 2482 
 2483                 if (minor(dev) != current_video_screen)
 2484                         return EPERM;
 2485                 if (vsp->smode.mode != VT_PROCESS)
 2486                         return EINVAL;
 2487                 if (vsp->proc != p)
 2488                         return EPERM;
 2489                 switch(*(int *)data) {
 2490                 case VT_FALSE:
 2491                         /* process refuses to release screen; abort */
 2492                         if(vt_switch_pending
 2493                            && (vsp->vt_status & VT_WAIT_REL)) {
 2494                                 vsp->vt_status &= ~VT_WAIT_REL;
 2495                                 vt_switch_pending = 0;
 2496                                 return 0;
 2497                         }
 2498                         break;
 2499 
 2500                 case VT_TRUE:
 2501                         /* process releases its VT */
 2502                         if(vt_switch_pending
 2503                            && (vsp->vt_status & VT_WAIT_REL)) {
 2504                                 int new_screen = vt_switch_pending - 1;
 2505                                 struct video_state *old_vsp = vsp;
 2506 
 2507                                 vsp->vt_status &= ~VT_WAIT_REL;
 2508 
 2509                                 switch_screen(new_screen,
 2510                                               vsp->vt_status & VT_GRAFX,
 2511                                               vs[new_screen].vt_status
 2512                                               & VT_GRAFX);
 2513 
 2514                                 opri = spltty();
 2515                                 if(old_vsp->vt_status & VT_WAIT_ACT)
 2516                                 {
 2517                                         old_vsp->vt_status &= ~VT_WAIT_ACT;
 2518                                         wakeup(&old_vsp->smode);
 2519                                 }
 2520                                 if(vsp->vt_status & VT_WAIT_ACT)
 2521                                 {
 2522                                         vsp->vt_status &= ~VT_WAIT_ACT;
 2523                                         wakeup(&vsp->smode);
 2524                                 }
 2525                                 splx(opri);
 2526 
 2527                                 if(vsp->smode.mode == VT_PROCESS) {
 2528                                         /*
 2529                                          * if the new vt is also in process
 2530                                          * mode, we have to wait until its
 2531                                          * controlling process acknowledged
 2532                                          * the switch
 2533                                          */
 2534                                         vsp->vt_status
 2535                                                 |= VT_WAIT_ACK;
 2536                                         if(vsp->smode.acqsig) {
 2537                                                 PROC_LOCK(vsp->proc);
 2538                                                 psignal(vsp->proc,
 2539                                                         vsp->smode.acqsig);
 2540                                                 PROC_UNLOCK(vsp->proc);
 2541                                         }
 2542                                 }
 2543                                 else
 2544                                 {
 2545                                         /* we are committed */
 2546                                         vt_switch_pending = 0;
 2547 
 2548                                         /* XXX */
 2549                                         if(pcvt_is_console)
 2550                                                 cnavailable(pcvt_consptr, TRUE);
 2551                                 }
 2552                                 return 0;
 2553                         }
 2554                         break;
 2555 
 2556                 case VT_ACKACQ:
 2557                         /* new vts controlling process acknowledged */
 2558                         if(vsp->vt_status & VT_WAIT_ACK) {
 2559                                 vt_switch_pending = 0;
 2560                                 vsp->vt_status &= ~VT_WAIT_ACK;
 2561 
 2562                                 /* XXX */
 2563                                 if(pcvt_is_console)
 2564                                         cnavailable(pcvt_consptr, FALSE);
 2565 
 2566                                 return 0;
 2567                         }
 2568                         break;
 2569                 }
 2570                 return EINVAL;  /* end case VT_RELDISP */
 2571 
 2572 
 2573         case VT_OPENQRY:
 2574                 /* return free vt */
 2575                 for(i = 0; i < PCVT_NSCREENS; i++)
 2576                         if(!vs[i].openf) {
 2577                                 *(int *)data = i + 1;
 2578                                 return 0;
 2579                         }
 2580                 return EAGAIN;
 2581 
 2582         case VT_GETACTIVE:
 2583                 *(int *)data = current_video_screen + 1;
 2584                 return 0;
 2585 
 2586         case VT_ACTIVATE:
 2587                 return vgapage(*(int *)data - 1);
 2588 
 2589         case VT_WAITACTIVE:
 2590                 /* sleep until vt switch happened */
 2591                 i = *(int *)data - 1;
 2592 
 2593                 if(i != -1
 2594                    && (i < 0 || i >= PCVT_NSCREENS))
 2595                         return EINVAL;
 2596 
 2597                 if(i != -1 && current_video_screen == i)
 2598                         return 0;
 2599 
 2600                 if(i == -1)
 2601                         i = minor(dev);
 2602 
 2603                 {
 2604                         int x = spltty();
 2605                         error = 0;
 2606                         while (current_video_screen != i &&
 2607                                (error == 0 || error == ERESTART))
 2608                         {
 2609                                 vs[i].vt_status |= VT_WAIT_ACT;
 2610                                 error = tsleep(&vs[i].smode,
 2611                                                PZERO | PCATCH, "waitvt", 0);
 2612                         }
 2613                         splx(x);
 2614                 }
 2615                 return error;
 2616 
 2617         case KDENABIO:
 2618                 /* grant the process IO access; only allowed if euid == 0 */
 2619                 /* and insecure */
 2620         {
 2621                 struct trapframe *fp = td->td_frame;
 2622 
 2623                 error = suser(td);
 2624                 if (error != 0)
 2625                         return (error);
 2626                 error = securelevel_gt(td->td_ucred, 0);
 2627                 if (error != 0)
 2628                         return (error);
 2629 
 2630                 fp->tf_eflags |= PSL_IOPL;
 2631 
 2632                 return 0;
 2633         }
 2634 
 2635         case KDDISABIO:
 2636                 /* abandon IO access permission */
 2637         {
 2638                 struct trapframe *fp = td->td_frame;
 2639                 fp->tf_eflags &= ~PSL_IOPL;
 2640                 return 0;
 2641         }
 2642 
 2643         case KDSETMODE:
 2644         {
 2645                 struct video_state *vsx = &vs[minor(dev)];
 2646                 int haschanged = 0;
 2647 
 2648                 if(adaptor_type != VGA_ADAPTOR
 2649                    && adaptor_type != MDA_ADAPTOR)
 2650                         /* X will only run on those adaptors */
 2651                         return (EINVAL);
 2652 
 2653                 /* set text/graphics mode of current vt */
 2654                 switch(*(int *)data)
 2655                 {
 2656                 case KD_TEXT:
 2657                         haschanged = (vsx->vt_status & VT_GRAFX) != 0;
 2658                         vsx->vt_status &= ~VT_GRAFX;
 2659                         if(haschanged && vsx == vsp)
 2660                                 switch_screen(current_video_screen, 1, 0);
 2661                         return 0;
 2662 
 2663                 case KD_GRAPHICS:
 2664                         /* xxx It might be a good idea to require that
 2665                            the vt be in process controlled mode here,
 2666                            and that the calling process is the owner */
 2667                         haschanged = (vsx->vt_status & VT_GRAFX) == 0;
 2668                         vsx->vt_status |= VT_GRAFX;
 2669                         if(haschanged && vsx == vsp)
 2670                                 switch_screen(current_video_screen, 0, 1);
 2671                         return 0;
 2672 
 2673                 }
 2674                 return EINVAL;  /* end case KDSETMODE */
 2675         }
 2676 
 2677         case KDSETRAD:
 2678                 /* set keyboard repeat and delay */
 2679                 return kbdioctl(dev, KBDSTPMAT, data, flag);
 2680 
 2681         case KDSKBMODE:
 2682                 switch(*(int *)data)
 2683                 {
 2684                 case K_RAW:
 2685 
 2686 #if PCVT_SCANSET > 1
 2687                         /* put keyboard to return ancient PC scan codes */
 2688                         kbd_emulate_pc(1);
 2689 #endif /* PCVT_SCANSET > 1 */
 2690 
 2691                         pcvt_kbd_raw = 1;
 2692                         shift_down = meta_down = altgr_down = ctrl_down = 0;
 2693                         return 0;
 2694 
 2695                 case K_XLATE:
 2696 
 2697 #if PCVT_SCANSET > 1
 2698                         kbd_emulate_pc(0);
 2699 #endif /* PCVT_SCANSET > 1 */
 2700 
 2701                         pcvt_kbd_raw = 0;
 2702                         return 0;
 2703                 }
 2704                 return EINVAL;  /* end KDSKBMODE */
 2705 
 2706         case KDMKTONE:
 2707                 /* ring the speaker */
 2708                 if(data)
 2709                 {
 2710                         int duration = *(int *)data >> 16;
 2711                         int pitch = *(int *)data & 0xffff;
 2712 
 2713                         sysbeep(pitch, duration * hz / 3000);
 2714                 }
 2715                 else
 2716                 {
 2717                         sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
 2718                 }
 2719                 return 0;
 2720 
 2721         case KDSETLED:
 2722                 /* set kbd LED status */
 2723                 /* unfortunately, the LED definitions between pcvt and */
 2724                 /* USL differ some way :-( */
 2725                 i = *(int *)data;
 2726                 j = (i & LED_CAP? KBD_CAPSLOCK: 0)
 2727                         + (i & LED_NUM? KBD_NUMLOCK: 0)
 2728                         + (i & LED_SCR? KBD_SCROLLLOCK: 0);
 2729                 return kbdioctl(dev, KBDSLOCK, (caddr_t)&j, flag);
 2730 
 2731         case KDGETLED:
 2732                 /* get kbd LED status */
 2733                 if((error = kbdioctl(dev, KBDGLOCK, (caddr_t)&j, flag)))
 2734                         return error;
 2735                 i = (j & KBD_CAPSLOCK? LED_CAP: 0)
 2736                         + (j & KBD_NUMLOCK? LED_NUM: 0)
 2737                         + (j & KBD_SCROLLLOCK? LED_SCR: 0);
 2738                 *(int *)data = i;
 2739                 return 0;
 2740 
 2741         case GIO_KEYMAP:
 2742                 get_usl_keymap((keymap_t *)data);
 2743                 return 0;
 2744         }                       /* end case cmd */
 2745 
 2746         return -1;              /* inappropriate usl_vt_compat ioctl */
 2747 }
 2748 #endif /* XSERVER */
 2749 
 2750 /* ------------------------- E O F ------------------------------------------*/

Cache object: 928b434caeb8f69edec207ab813c0214


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.