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/5.0/sys/i386/isa/pcvt/pcvt_ext.c 93593 2002-04-01 21:31:13Z jhb $
   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         pcvt_ttyp = &pcvt_tty[n];               /* current tty */
 2102 
 2103         vsp = &vs[n];                   /* current video state ptr */
 2104 
 2105         if(oldgrafx && !newgrafx)
 2106         {
 2107                 /* switch from graphics to text mode */
 2108                 unsigned i;
 2109 
 2110                 /* restore fonts */
 2111                 for(i = 0; i < totalfonts; i++)
 2112                         if(saved_charsets[i])
 2113                                 vga_move_charset(i, 0, 0);
 2114 
 2115 #if PCVT_SCREENSAVER
 2116                 /* activate screen saver */
 2117                 if(saved_scrnsv_tmo)
 2118                         pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
 2119 #endif /* PCVT_SCREENSAVER */
 2120 
 2121                 /* re-initialize lost MDA information */
 2122                 if(adaptor_type == MDA_ADAPTOR)
 2123                 {
 2124                     /*
 2125                      * Due to the fact that HGC registers are write-only,
 2126                      * the Xserver can only make guesses about the state
 2127                      * the HGC adaptor has been before turning on X mode.
 2128                      * Thus, the display must be re-enabled now, and the
 2129                      * cursor shape and location restored.
 2130                      */
 2131                     outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
 2132                     outb(addr_6845, CRTC_CURSORH); /* select high register */
 2133                     outb(addr_6845+1,
 2134                          ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
 2135                     outb(addr_6845, CRTC_CURSORL); /* select low register */
 2136                     outb(addr_6845+1,
 2137                          ((vsp->Crtat + vsp->cur_offset) - Crtat));
 2138 
 2139                     outb(addr_6845, CRTC_CURSTART); /* select high register */
 2140                     outb(addr_6845+1, vsp->cursor_start);
 2141                     outb(addr_6845, CRTC_CUREND); /* select low register */
 2142                     outb(addr_6845+1, vsp->cursor_end);
 2143                 }
 2144 
 2145                 /* make status display happy */
 2146                 async_update(UPDATE_START);
 2147         }
 2148 
 2149         if(!newgrafx)
 2150         {
 2151                 /* to text mode */
 2152 
 2153                 /* kernel memory -> video board memory */
 2154                 bcopy(vsp->Crtat, Crtat,
 2155                       vsp->screen_rows * vsp->maxcol * CHR);
 2156 
 2157                 vsp->Crtat = Crtat;             /* operate on screen now */
 2158 
 2159                 outb(addr_6845, CRTC_STARTADRH);
 2160                 outb(addr_6845+1, 0);
 2161                 outb(addr_6845, CRTC_STARTADRL);
 2162                 outb(addr_6845+1, 0);
 2163         }
 2164 
 2165         select_vga_charset(vsp->vga_charset);
 2166 
 2167         if(vsp->maxcol != cols)
 2168                 vga_col(vsp, vsp->maxcol);      /* select 80/132 columns */
 2169 
 2170         outb(addr_6845, CRTC_CURSORH);  /* select high register */
 2171         outb(addr_6845+1, vsp->cur_offset >> 8);
 2172         outb(addr_6845, CRTC_CURSORL);  /* select low register */
 2173         outb(addr_6845+1, vsp->cur_offset);
 2174 
 2175         if(vsp->cursor_on)
 2176         {
 2177                 outb(addr_6845, CRTC_CURSTART); /* select high register */
 2178                 outb(addr_6845+1, vsp->cursor_start);
 2179                 outb(addr_6845, CRTC_CUREND);   /* select low register */
 2180                 outb(addr_6845+1, vsp->cursor_end);
 2181         }
 2182         else
 2183         {
 2184                 sw_cursor(0);
 2185         }
 2186 
 2187         if(adaptor_type == VGA_ADAPTOR)
 2188         {
 2189                 unsigned i;
 2190 
 2191                 /* switch VGA DAC palette entries */
 2192                 for(i = 0; i < NVGAPEL; i++)
 2193                         vgapaletteio(i, &vsp->palette[i], 1);
 2194         }
 2195 
 2196         if(!newgrafx)
 2197         {
 2198                 update_led();   /* update led's */
 2199                 update_hp(vsp); /* update fkey labels, if present */
 2200 
 2201                 /* if we switch to a vt with force 24 lines mode and    */
 2202                 /* pure VT emulation and 25 rows charset, then we have  */
 2203                 /* to clear the last line on display ...                */
 2204 
 2205                 if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) &&
 2206                         (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS))
 2207                 {
 2208                         fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol,
 2209                                 vsp->maxcol);
 2210                 }
 2211         }
 2212 }
 2213 
 2214 /*---------------------------------------------------------------------------*
 2215  *      Change specified vt to VT_AUTO mode
 2216  *      xxx Maybe this should also reset VT_GRAFX mode; since switching and
 2217  *      graphics modes are not going to work without VT_PROCESS mode.
 2218  *---------------------------------------------------------------------------*/
 2219 static void
 2220 set_auto_mode (struct video_state *vsx)
 2221 {
 2222         unsigned ostatus = vsx->vt_status;
 2223         vsx->smode.mode = VT_AUTO;
 2224         vsx->proc = NULL;
 2225         vsx->pid = 0;
 2226         vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK);
 2227 
 2228         if (ostatus & VT_WAIT_ACK)
 2229         {
 2230                 if(vsp == vsx && vt_switch_pending == current_video_screen + 1)
 2231                         vt_switch_pending = 0;
 2232         }
 2233         if (ostatus & VT_WAIT_REL)
 2234         {
 2235                 int new_screen = vt_switch_pending - 1;
 2236                 if (vsp == vsx && vt_switch_pending)
 2237                 {
 2238                         vt_switch_pending = 0;
 2239                         vgapage (new_screen);
 2240                 }
 2241         }
 2242 }
 2243 
 2244 /*---------------------------------------------------------------------------*
 2245  *      Exported function; to be called when a vt is closed down.
 2246  *
 2247  *      Ideally, we would like to be able to recover from an X server crash;
 2248  *      but in reality, if the server crashes hard while in control of the
 2249  *      vga board, then you're not likely to be able to use pcvt ttys
 2250  *      without rebooting.
 2251  *---------------------------------------------------------------------------*/
 2252 void
 2253 reset_usl_modes (struct video_state *vsx)
 2254 {
 2255         /* Clear graphics mode */
 2256         if (vsx->vt_status & VT_GRAFX) {
 2257             vsx->vt_status &= ~VT_GRAFX;
 2258             if (vsp == vsx)
 2259                 switch_screen(current_video_screen, 1, 0);
 2260         }
 2261 
 2262         /* Take kbd out of raw mode */
 2263         if (pcvt_kbd_raw && vsp == vsx) {
 2264 #if PCVT_SCANSET > 1
 2265                 kbd_emulate_pc(0);
 2266 #endif /* PCVT_SCANSET > 1 */
 2267                 pcvt_kbd_raw = 0;
 2268         }
 2269 
 2270         /* Clear process controlled mode */
 2271         set_auto_mode (vsx);
 2272 }
 2273 
 2274 /*
 2275  * Fallback to VT_AUTO if controlling process died.
 2276  */
 2277 static void
 2278 fallback_to_auto(struct video_state *vsx)
 2279 {
 2280         struct proc *p;
 2281 
 2282         if(vsx->proc) {
 2283                 p = pfind(vsx->pid);
 2284                 if (p != NULL) {
 2285                         PROC_UNLOCK(p);
 2286                         if (vsx->proc != p)
 2287                                 set_auto_mode(vsx);
 2288                 }
 2289         }
 2290 }
 2291 
 2292 /*---------------------------------------------------------------------------*
 2293  *      switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version
 2294  *      (the name vgapage() stands for historical reasons)
 2295  *---------------------------------------------------------------------------*/
 2296 int
 2297 vgapage(int new_screen)
 2298 {
 2299         int x;
 2300 
 2301         if(new_screen < 0 || new_screen >= totalscreens)
 2302                 return EINVAL;
 2303 
 2304         /* fallback to VT_AUTO if controlling processes died */
 2305         fallback_to_auto(vsp);
 2306         fallback_to_auto(&vs[new_screen]);
 2307 
 2308         if (!vt_switch_pending && new_screen == current_video_screen)
 2309                 return 0;
 2310 
 2311         if(vt_switch_pending && vt_switch_pending != new_screen + 1) {
 2312                 /* Try resignaling uncooperative X-window servers */
 2313                 if (vsp->smode.mode == VT_PROCESS) {
 2314                         if (vsp->vt_status & VT_WAIT_REL) {
 2315                                 if(vsp->smode.relsig) {
 2316                                         PROC_LOCK(vsp->proc);
 2317                                         psignal(vsp->proc, vsp->smode.relsig);
 2318                                         PROC_UNLOCK(vsp->proc);
 2319                                 }
 2320                         } else if (vsp->vt_status & VT_WAIT_ACK) {
 2321                                 if(vsp->smode.acqsig) {
 2322                                         PROC_LOCK(vsp->proc);
 2323                                         psignal(vsp->proc, vsp->smode.acqsig);
 2324                                         PROC_UNLOCK(vsp->proc);
 2325                                 }
 2326                         }
 2327                 }
 2328                 return EAGAIN;
 2329         }
 2330 
 2331         vt_switch_pending = new_screen + 1;
 2332 
 2333         if(vsp->smode.mode == VT_PROCESS)
 2334         {
 2335                 /* we cannot switch immediately here */
 2336                 vsp->vt_status |= VT_WAIT_REL;
 2337                 if(vsp->smode.relsig) {
 2338                         PROC_LOCK(vsp->proc);
 2339                         psignal(vsp->proc, vsp->smode.relsig);
 2340                         PROC_UNLOCK(vsp->proc);
 2341                 }
 2342         }
 2343         else
 2344         {
 2345                 struct video_state *old_vsp = vsp;
 2346 
 2347                 switch_screen(new_screen,
 2348                               vsp->vt_status & VT_GRAFX,
 2349                               vs[new_screen].vt_status & VT_GRAFX);
 2350 
 2351                 x = spltty();
 2352 
 2353                 if(old_vsp->vt_status & VT_WAIT_ACT)
 2354                 {
 2355                         old_vsp->vt_status &= ~VT_WAIT_ACT;
 2356                         wakeup((caddr_t)&old_vsp->smode);
 2357                 }
 2358 
 2359                 if(vsp->vt_status & VT_WAIT_ACT)
 2360                 {
 2361                         vsp->vt_status &= ~VT_WAIT_ACT;
 2362                         wakeup((caddr_t)&vsp->smode);
 2363                 }
 2364 
 2365                 splx(x);
 2366 
 2367                 if(vsp->smode.mode == VT_PROCESS)
 2368                 {
 2369                         /* if _new_ vt is under process control... */
 2370                         vsp->vt_status |= VT_WAIT_ACK;
 2371                         if(vsp->smode.acqsig) {
 2372                                 PROC_LOCK(vsp->proc);
 2373                                 psignal(vsp->proc, vsp->smode.acqsig);
 2374                                 PROC_UNLOCK(vsp->proc);
 2375                         }
 2376                 }
 2377                 else
 2378                 {
 2379                         /* we are committed */
 2380                         vt_switch_pending = 0;
 2381 
 2382                         /*
 2383                          * XXX: If pcvt is acting as the systems console,
 2384                          * avoid panics going to the debugger while we are in
 2385                          * process mode.
 2386                          */
 2387                         if(pcvt_is_console)
 2388                                 cons_unavail = 0;
 2389                 }
 2390         }
 2391         return 0;
 2392 }
 2393 
 2394 /*---------------------------------------------------------------------------*
 2395  *      ioctl handling for VT_USL mode
 2396  *---------------------------------------------------------------------------*/
 2397 int
 2398 usl_vt_ioctl(dev_t dev, int cmd, caddr_t data, int flag, struct thread *td)
 2399 {
 2400         struct proc *p = td->td_proc;
 2401         int i, j, error, opri;
 2402         struct vt_mode newmode;
 2403 
 2404         switch(cmd)
 2405         {
 2406 
 2407         case VT_SETMODE:
 2408                 newmode = *(struct vt_mode *)data;
 2409 
 2410                 opri = spltty();
 2411 
 2412                 if (newmode.mode != VT_PROCESS) {
 2413                         struct video_state *vsx = &vs[minor(dev)];
 2414                         if (vsx->smode.mode == VT_PROCESS) {
 2415                                 if (vsx->proc != p) {
 2416                                         splx(opri);
 2417                                         return EPERM;
 2418                                 }
 2419                                 set_auto_mode(vsx);
 2420                         }
 2421                         splx(opri);
 2422                         return 0;
 2423                 }
 2424 
 2425                 /*
 2426                  * NB: XFree86-3.1.1 does the following:
 2427                  *              VT_ACTIVATE (vtnum)
 2428                  *              VT_WAITACTIVE (vtnum)
 2429                  *              VT_SETMODE (VT_PROCESS)
 2430                  * So it is possible that the screen was switched
 2431                  * between the WAITACTIVE and the SETMODE (here).  This
 2432                  * can actually happen quite frequently, and it was
 2433                  * leading to dire consequences. Now it is detected by
 2434                  * requiring that minor(dev) match current_video_screen.
 2435                  * An alternative would be to operate on vs[minor(dev)]
 2436                  * instead of *vsp, but that would leave the server
 2437                  * confused, because it would believe that its vt was
 2438                  * currently activated.
 2439                  */
 2440                 if (minor(dev) != current_video_screen) {
 2441                         splx(opri);
 2442                         return EPERM;
 2443                 }
 2444 
 2445                 /* Check for server died */
 2446                 fallback_to_auto(vsp);
 2447 
 2448                 /* Check for server already running */
 2449                 if (vsp->smode.mode == VT_PROCESS && vsp->proc != p)
 2450                 {
 2451                         splx(opri);
 2452                         return EBUSY; /* already in use on this VT */
 2453                 }
 2454 
 2455                 if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig)
 2456                     || !ISSIGVALID(newmode.frsig))
 2457                 {
 2458                         splx(opri);
 2459                         return EINVAL;
 2460                 }
 2461 
 2462                 vsp->smode = newmode;
 2463                 vsp->proc = p;
 2464                 vsp->pid = p->p_pid;
 2465 
 2466                 /*
 2467                  * XXX: If pcvt is acting as the systems console,
 2468                  * avoid panics going to the debugger while we are in
 2469                  * process mode.
 2470                  */
 2471                 if(pcvt_is_console)
 2472                         cons_unavail = (newmode.mode == VT_PROCESS);
 2473 
 2474                 splx(opri);
 2475                 return 0;
 2476 
 2477         case VT_GETMODE:
 2478                 *(struct vt_mode *)data = vsp->smode;
 2479                 return 0;
 2480 
 2481         case VT_RELDISP:
 2482                 if (minor(dev) != current_video_screen)
 2483                         return EPERM;
 2484                 if (vsp->smode.mode != VT_PROCESS)
 2485                         return EINVAL;
 2486                 if (vsp->proc != p)
 2487                         return EPERM;
 2488                 switch(*(int *)data) {
 2489                 case VT_FALSE:
 2490                         /* process refuses to release screen; abort */
 2491                         if(vt_switch_pending
 2492                            && (vsp->vt_status & VT_WAIT_REL)) {
 2493                                 vsp->vt_status &= ~VT_WAIT_REL;
 2494                                 vt_switch_pending = 0;
 2495                                 return 0;
 2496                         }
 2497                         break;
 2498 
 2499                 case VT_TRUE:
 2500                         /* process releases its VT */
 2501                         if(vt_switch_pending
 2502                            && (vsp->vt_status & VT_WAIT_REL)) {
 2503                                 int new_screen = vt_switch_pending - 1;
 2504                                 struct video_state *old_vsp = vsp;
 2505 
 2506                                 vsp->vt_status &= ~VT_WAIT_REL;
 2507 
 2508                                 switch_screen(new_screen,
 2509                                               vsp->vt_status & VT_GRAFX,
 2510                                               vs[new_screen].vt_status
 2511                                               & VT_GRAFX);
 2512 
 2513                                 opri = spltty();
 2514                                 if(old_vsp->vt_status & VT_WAIT_ACT)
 2515                                 {
 2516                                         old_vsp->vt_status &= ~VT_WAIT_ACT;
 2517                                         wakeup((caddr_t)&old_vsp->smode);
 2518                                 }
 2519                                 if(vsp->vt_status & VT_WAIT_ACT)
 2520                                 {
 2521                                         vsp->vt_status &= ~VT_WAIT_ACT;
 2522                                         wakeup((caddr_t)&vsp->smode);
 2523                                 }
 2524                                 splx(opri);
 2525 
 2526                                 if(vsp->smode.mode == VT_PROCESS) {
 2527                                         /*
 2528                                          * if the new vt is also in process
 2529                                          * mode, we have to wait until its
 2530                                          * controlling process acknowledged
 2531                                          * the switch
 2532                                          */
 2533                                         vsp->vt_status
 2534                                                 |= VT_WAIT_ACK;
 2535                                         if(vsp->smode.acqsig) {
 2536                                                 PROC_LOCK(vsp->proc);
 2537                                                 psignal(vsp->proc,
 2538                                                         vsp->smode.acqsig);
 2539                                                 PROC_UNLOCK(vsp->proc);
 2540                                         }
 2541                                 }
 2542                                 else
 2543                                 {
 2544                                         /* we are committed */
 2545                                         vt_switch_pending = 0;
 2546 
 2547                                         /* XXX */
 2548                                         if(pcvt_is_console)
 2549                                                 cons_unavail = 0;
 2550                                 }
 2551                                 return 0;
 2552                         }
 2553                         break;
 2554 
 2555                 case VT_ACKACQ:
 2556                         /* new vts controlling process acknowledged */
 2557                         if(vsp->vt_status & VT_WAIT_ACK) {
 2558                                 vt_switch_pending = 0;
 2559                                 vsp->vt_status &= ~VT_WAIT_ACK;
 2560 
 2561                                 /* XXX */
 2562                                 if(pcvt_is_console)
 2563                                         cons_unavail = 1;
 2564 
 2565                                 return 0;
 2566                         }
 2567                         break;
 2568                 }
 2569                 return EINVAL;  /* end case VT_RELDISP */
 2570 
 2571 
 2572         case VT_OPENQRY:
 2573                 /* return free vt */
 2574                 for(i = 0; i < PCVT_NSCREENS; i++)
 2575                         if(!vs[i].openf) {
 2576                                 *(int *)data = i + 1;
 2577                                 return 0;
 2578                         }
 2579                 return EAGAIN;
 2580 
 2581         case VT_GETACTIVE:
 2582                 *(int *)data = current_video_screen + 1;
 2583                 return 0;
 2584 
 2585         case VT_ACTIVATE:
 2586                 return vgapage(*(int *)data - 1);
 2587 
 2588         case VT_WAITACTIVE:
 2589                 /* sleep until vt switch happened */
 2590                 i = *(int *)data - 1;
 2591 
 2592                 if(i != -1
 2593                    && (i < 0 || i >= PCVT_NSCREENS))
 2594                         return EINVAL;
 2595 
 2596                 if(i != -1 && current_video_screen == i)
 2597                         return 0;
 2598 
 2599                 if(i == -1)
 2600                         i = minor(dev);
 2601 
 2602                 {
 2603                         int x = spltty();
 2604                         error = 0;
 2605                         while (current_video_screen != i &&
 2606                                (error == 0 || error == ERESTART))
 2607                         {
 2608                                 vs[i].vt_status |= VT_WAIT_ACT;
 2609                                 error = tsleep((caddr_t)&vs[i].smode,
 2610                                                PZERO | PCATCH, "waitvt", 0);
 2611                         }
 2612                         splx(x);
 2613                 }
 2614                 return error;
 2615 
 2616         case KDENABIO:
 2617                 /* grant the process IO access; only allowed if euid == 0 */
 2618                 /* and insecure */
 2619         {
 2620                 struct trapframe *fp = td->td_frame;
 2621 
 2622                 error = suser(td);
 2623                 if (error != 0)
 2624                         return (error);
 2625                 error = securelevel_gt(td->td_ucred, 0);
 2626                 if (error != 0)
 2627                         return (error);
 2628 
 2629                 fp->tf_eflags |= PSL_IOPL;
 2630 
 2631                 return 0;
 2632         }
 2633 
 2634         case KDDISABIO:
 2635                 /* abandon IO access permission */
 2636         {
 2637                 struct trapframe *fp = td->td_frame;
 2638                 fp->tf_eflags &= ~PSL_IOPL;
 2639                 return 0;
 2640         }
 2641 
 2642         case KDSETMODE:
 2643         {
 2644                 struct video_state *vsx = &vs[minor(dev)];
 2645                 int haschanged = 0;
 2646 
 2647                 if(adaptor_type != VGA_ADAPTOR
 2648                    && adaptor_type != MDA_ADAPTOR)
 2649                         /* X will only run on those adaptors */
 2650                         return (EINVAL);
 2651 
 2652                 /* set text/graphics mode of current vt */
 2653                 switch(*(int *)data)
 2654                 {
 2655                 case KD_TEXT:
 2656                         haschanged = (vsx->vt_status & VT_GRAFX) != 0;
 2657                         vsx->vt_status &= ~VT_GRAFX;
 2658                         if(haschanged && vsx == vsp)
 2659                                 switch_screen(current_video_screen, 1, 0);
 2660                         return 0;
 2661 
 2662                 case KD_GRAPHICS:
 2663                         /* xxx It might be a good idea to require that
 2664                            the vt be in process controlled mode here,
 2665                            and that the calling process is the owner */
 2666                         haschanged = (vsx->vt_status & VT_GRAFX) == 0;
 2667                         vsx->vt_status |= VT_GRAFX;
 2668                         if(haschanged && vsx == vsp)
 2669                                 switch_screen(current_video_screen, 0, 1);
 2670                         return 0;
 2671 
 2672                 }
 2673                 return EINVAL;  /* end case KDSETMODE */
 2674         }
 2675 
 2676         case KDSETRAD:
 2677                 /* set keyboard repeat and delay */
 2678                 return kbdioctl(dev, KBDSTPMAT, data, flag);
 2679 
 2680         case KDSKBMODE:
 2681                 switch(*(int *)data)
 2682                 {
 2683                 case K_RAW:
 2684 
 2685 #if PCVT_SCANSET > 1
 2686                         /* put keyboard to return ancient PC scan codes */
 2687                         kbd_emulate_pc(1);
 2688 #endif /* PCVT_SCANSET > 1 */
 2689 
 2690                         pcvt_kbd_raw = 1;
 2691                         shift_down = meta_down = altgr_down = ctrl_down = 0;
 2692                         return 0;
 2693 
 2694                 case K_XLATE:
 2695 
 2696 #if PCVT_SCANSET > 1
 2697                         kbd_emulate_pc(0);
 2698 #endif /* PCVT_SCANSET > 1 */
 2699 
 2700                         pcvt_kbd_raw = 0;
 2701                         return 0;
 2702                 }
 2703                 return EINVAL;  /* end KDSKBMODE */
 2704 
 2705         case KDMKTONE:
 2706                 /* ring the speaker */
 2707                 if(data)
 2708                 {
 2709                         int duration = *(int *)data >> 16;
 2710                         int pitch = *(int *)data & 0xffff;
 2711 
 2712                         sysbeep(pitch, duration * hz / 3000);
 2713                 }
 2714                 else
 2715                 {
 2716                         sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
 2717                 }
 2718                 return 0;
 2719 
 2720         case KDSETLED:
 2721                 /* set kbd LED status */
 2722                 /* unfortunately, the LED definitions between pcvt and */
 2723                 /* USL differ some way :-( */
 2724                 i = *(int *)data;
 2725                 j = (i & LED_CAP? KBD_CAPSLOCK: 0)
 2726                         + (i & LED_NUM? KBD_NUMLOCK: 0)
 2727                         + (i & LED_SCR? KBD_SCROLLLOCK: 0);
 2728                 return kbdioctl(dev, KBDSLOCK, (caddr_t)&j, flag);
 2729 
 2730         case KDGETLED:
 2731                 /* get kbd LED status */
 2732                 if((error = kbdioctl(dev, KBDGLOCK, (caddr_t)&j, flag)))
 2733                         return error;
 2734                 i = (j & KBD_CAPSLOCK? LED_CAP: 0)
 2735                         + (j & KBD_NUMLOCK? LED_NUM: 0)
 2736                         + (j & KBD_SCROLLLOCK? LED_SCR: 0);
 2737                 *(int *)data = i;
 2738                 return 0;
 2739 
 2740         case GIO_KEYMAP:
 2741                 get_usl_keymap((keymap_t *)data);
 2742                 return 0;
 2743         }                       /* end case cmd */
 2744 
 2745         return -1;              /* inappropriate usl_vt_compat ioctl */
 2746 }
 2747 #endif /* XSERVER */
 2748 
 2749 /* ------------------------- E O F ------------------------------------------*/

Cache object: 549b573ef2587947be770bbfc43d2983


[ 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.