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