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