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