2 * Copyright (c) 1999, 2002 Hellmuth Michaelis
4 * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
6 * Copyright (C) 1992, 1993 Soeren Schmidt.
10 * For the sake of compatibility, portions of this code regarding the
11 * X server interface are taken from Soeren Schmidt's syscons driver.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
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.
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.
40 /*---------------------------------------------------------------------------*
42 * pcvt_ext.c VT220 Driver Extended Support Routines
43 * ------------------------------------------------------
45 * Last Edit-Date: [Fri Mar 8 19:57:55 2002]
49 *---------------------------------------------------------------------------*/
51 #include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
53 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
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 );
64 static void fallback_to_auto(struct video_state *vsx);
67 /* storage to save video timing values of 80 columns text mode */
79 static int regsaved = 0; /* registers are saved to savearea */
81 /*---------------------------------------------------------------------------*
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.
90 * ###############################################################
91 * ## THIS IS GETTING MORE AND MORE A LARGE SPAGHETTI HACK !!!! ##
92 * ###############################################################
94 *---------------------------------------------------------------------------*/
99 u_char byte, oldbyte, old1byte, newbyte;
102 can_do_132col = 1; /* assumes everyone can do 132 col */
104 can_do_132col = 0; /* assumes noone can do 132 col */
105 #endif /* PCVT_132GENERIC */
107 vga_family = VGA_F_NONE;
109 /*---------------------------------------------------------------------------*
110 * check for Western Digital / Paradise chipsets
111 *---------------------------------------------------------------------------*/
113 ptr = (u_char *)Crtat;
116 ptr += (0xc007d - 0xb8000);
118 ptr += (0xc007d - 0xb0000);
120 if((*ptr++ == 'V') && (*ptr++ == 'G') &&
121 (*ptr++ == 'A') && (*ptr++ == '='))
125 vga_family = VGA_F_WD;
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);
133 return(VGA_PVGA); /* PVGA1A chip */
135 outb(TS_INDEX, 0x12);
136 oldbyte = inb(TS_DATA);
137 outb(TS_DATA, oldbyte & 0xbf);
138 newbyte = inb(TS_DATA) & 0x40;
140 return(VGA_WD90C00); /* WD90C00 chip */
142 outb(TS_DATA, oldbyte | 0x40);
143 newbyte = inb(TS_DATA) & 0x40;
145 return(VGA_WD90C00); /* WD90C00 chip */
147 outb(TS_DATA, oldbyte);
150 outb(TS_INDEX, 0x10);
151 oldbyte = inb(TS_DATA);
153 outb(TS_DATA, oldbyte & 0xfb);
154 newbyte = inb(TS_DATA) & 0x04;
158 outb(TS_DATA, oldbyte | 0x04);
159 newbyte = inb(TS_DATA) & 0x04;
163 outb(TS_DATA, oldbyte);
174 /*---------------------------------------------------------------------------*
175 * check for Trident chipsets
176 *---------------------------------------------------------------------------*/
178 outb(TS_INDEX, 0x0b);
179 oldbyte = inb(TS_DATA);
182 outb(TS_INDEX, 0x0b);
185 byte = inb(TS_DATA); /* chipset type */
188 outb(TS_INDEX, 0x0e);
189 old1byte = inb(TS_DATA);
192 newbyte = inb(TS_DATA);
194 outb(TS_DATA, (old1byte ^ 0x02));
196 outb(TS_INDEX, 0x0b);
197 outb(TS_DATA, oldbyte);
199 if((newbyte & 0x0f) == 0x02)
201 /* is a trident chip */
203 vga_family = VGA_F_TRI;
208 return(VGA_TR8800BR);
211 return(VGA_TR8800CS);
219 /* Haven't tried, but should work */
229 return(VGA_TR8900CL);
238 return(VGA_TRUNKNOWN);
242 /*---------------------------------------------------------------------------*
243 * check for Tseng Labs ET3000/4000 chipsets
244 *---------------------------------------------------------------------------*/
246 outb(GN_HERCOMPAT, 0x06);
248 outb(GN_DMCNTLC, 0xa0);
250 outb(GN_DMCNTLM, 0xa0);
258 outb(ATC_INDEX, ATC_MISC);
259 oldbyte = inb(ATC_DATAR);
261 /* write new value */
267 outb(ATC_INDEX, ATC_MISC);
268 newbyte = oldbyte ^ 0x10;
269 outb(ATC_DATAW, newbyte);
271 /* read back new value */
276 outb(ATC_INDEX, ATC_MISC);
277 byte = inb(ATC_DATAR);
279 /* write back old value */
284 outb(ATC_INDEX, ATC_MISC);
285 outb(ATC_DATAW, oldbyte);
287 if(byte == newbyte) /* ET3000 or ET4000 */
289 vga_family = VGA_F_TSENG;
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);
309 /*---------------------------------------------------------------------------*
310 * check for Video7 VGA chipsets
311 *---------------------------------------------------------------------------*/
313 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
316 outb(addr_6845, CRTC_STARTADRH);
317 oldbyte = inb(addr_6845+1);
319 outb(addr_6845+1, 0x55);
320 newbyte = inb(addr_6845+1);
322 outb(addr_6845, CRTC_V7ID); /* id register */
323 byte = inb(addr_6845+1); /* read id */
325 outb(addr_6845, CRTC_STARTADRH);
326 outb(addr_6845+1, oldbyte);
328 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
331 if(byte == (0x55 ^ 0xea))
334 vga_family = VGA_F_V7;
336 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
339 outb(TS_INDEX, TS_V7CHIPREV);
342 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
345 if(byte < 0xff && byte >= 0x80)
347 if(byte < 0x7f && byte >= 0x70)
349 if(byte < 0x5a && byte >= 0x50)
351 if(byte < 0x4a && byte > 0x40)
356 return(VGA_V7UNKNOWN);
359 /*---------------------------------------------------------------------------*
360 * check for S3 chipsets
361 *---------------------------------------------------------------------------*/
363 outb(addr_6845, 0x38); /* reg 1 lock register */
364 old1byte = inb(addr_6845+1); /* get old value */
366 outb(addr_6845, 0x38);
367 outb(addr_6845+1, 0x00); /* lock registers */
369 if(s3testwritable() == 0) /* check if locked */
371 outb(addr_6845, 0x38);
372 outb(addr_6845+1, 0x48); /* unlock registers */
374 if(s3testwritable() == 1 ) /* check if unlocked */
376 vga_family = VGA_F_S3; /* FAMILY S3 */
378 outb(addr_6845, 0x30); /* chip id/rev reg */
379 byte = inb(addr_6845+1);
387 outb(addr_6845, 0x38);
388 outb(addr_6845+1, old1byte);
392 outb(addr_6845, 0x38);
393 outb(addr_6845+1, old1byte);
397 outb(addr_6845, 0x38);
398 outb(addr_6845+1, old1byte);
399 return VGA_S3_UNKNOWN;
404 outb(addr_6845, 0x38);
405 outb(addr_6845+1, old1byte);
410 outb(addr_6845, 0x38);
411 outb(addr_6845+1, old1byte);
416 outb(addr_6845, 0x38);
417 outb(addr_6845+1, old1byte);
418 return VGA_S3_UNKNOWN;
423 /*---------------------------------------------------------------------------*
424 * check for Cirrus chipsets
425 *---------------------------------------------------------------------------*/
428 oldbyte = inb(TS_DATA);
432 newbyte = inb(TS_DATA);
433 outb(addr_6845, 0x27);
434 byte = inb(addr_6845 + 1);
436 outb(TS_DATA, oldbyte);
437 if (newbyte == 0x12) {
438 vga_family = VGA_F_CIR;
440 switch ((byte & 0xfc) >> 2) {
444 return VGA_CL_GD5402;
446 return VGA_CL_GD5402r1;
448 return VGA_CL_GD5420;
450 return VGA_CL_GD5420r1;
454 return VGA_CL_GD5422;
456 return VGA_CL_GD5424;
458 return VGA_CL_GD5426;
460 return VGA_CL_GD5428;
467 /*---------------------------------------------------------------------------
468 * test if index 35 lower nibble is writable (taken from SuperProbe 1.0)
469 *---------------------------------------------------------------------------*/
473 u_char old, new1, new2;
475 outb(addr_6845, 0x35);
476 old = inb(addr_6845+1); /* save */
478 outb(addr_6845, 0x35);
479 outb(addr_6845+1, (old & 0xf0)); /* write 0 */
481 outb(addr_6845, 0x35);
482 new1 = (inb(addr_6845+1)) & 0x0f; /* must read 0 */
484 outb(addr_6845, 0x35);
485 outb(addr_6845+1, (old | 0x0f)); /* write 1 */
487 outb(addr_6845, 0x35);
488 new2 = (inb(addr_6845+1)) & 0x0f; /* must read 1 */
490 outb(addr_6845, 0x35);
491 outb(addr_6845+1, old); /* restore */
493 return((new1==0) && (new2==0x0f));
496 /*---------------------------------------------------------------------------*
497 * return ptr to string describing vga type
498 *---------------------------------------------------------------------------*/
500 vga_string(int number)
502 static char *vga_tab[] = {
538 return(vga_tab[number]);
541 /*---------------------------------------------------------------------------*
542 * toggle vga 80/132 column operation
543 *---------------------------------------------------------------------------*/
545 vga_col(struct video_state *svsp, int cols)
549 if(adaptor_type != VGA_ADAPTOR)
555 ret = et4000_col(cols);
559 ret = wd90c11_col(cols);
566 ret = tri9000_col(cols);
570 ret = v7_1024i_col(cols);
574 ret = s3_928_col(cols);
578 case VGA_CL_GD5402r1:
580 case VGA_CL_GD5420r1:
585 ret = cl_gd542x_col(cols);
591 ret = generic_col(cols);
592 #endif /* PCVT_132GENERIC */
598 return(0); /* failed */
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 *---------------------------------------------------------------------------*/
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.)
629 * The actual numbers result in 23 kHz line scan and 54 Hz vertical
632 #endif /* PCVT_EXP_132COL */
635 generic_col(int cols)
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;
649 #else /* PCVT_EXP_132COL */
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;
658 #endif /* PCVT_EXP_132COL */
662 /* enable access to first 7 CRTC registers */
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);
669 if(cols == SCR_COL132) /* switch 80 -> 132 */
671 /* save state of board for 80 columns */
677 sp = savearea.generic;
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);
692 outb(addr_6845, 0x13); /* Row Offset Register */
693 *sp++ = inb(addr_6845+1);
695 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
696 *sp++ = inb(TS_DATA);
702 /* ATC Mode control */
703 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
704 *sp++ = inb(ATC_DATAR);
710 /* ATC Horizontal Pixel Panning */
711 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
712 *sp++ = inb(ATC_DATAR);
714 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
717 /* setup chipset for 132 column operation */
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 */
732 (((syncend / 8) & 0x20) * 4)
733 | ((syncend / 8) & 0x1f));
735 outb(addr_6845, 0x13); /* Row Offset Register */
736 outb(addr_6845+1, 0x42);
738 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
739 outb(TS_DATA, 0x01); /* 8 dot char clock */
745 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
746 outb(ATC_DATAW, 0x08); /* Line graphics disable */
752 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
753 outb(ATC_DATAW, 0x00);
755 /* Misc output register */
756 /* use the 28.322 MHz clock */
757 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | 4);
759 else /* switch 132 -> 80 */
761 if(!regsaved) /* failsafe */
763 /* disable access to first 7 CRTC registers */
764 outb(addr_6845, CRTC_VSYNCE);
765 outb(addr_6845+1, byte);
770 sp = savearea.generic;
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++);
785 outb(addr_6845, 0x13); /* Row Offset Register */
786 outb(addr_6845+1, *sp++);
788 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
789 outb(TS_DATA, *sp++);
795 /* ATC Mode control */
796 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
797 outb(ATC_DATAW, *sp++);
803 /* ATC Horizontal Pixel Panning */
804 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
805 outb(ATC_DATAW, *sp++);
807 outb(GN_MISCOUTW, *sp++); /* Misc output register */
810 /* disable access to first 7 CRTC registers */
812 outb(addr_6845, CRTC_VSYNCE);
813 outb(addr_6845+1, byte);
819 #endif /* PCVT_132GENERIC */
821 /*---------------------------------------------------------------------------*
822 * toggle 80/132 column operation for ET4000 based boards
823 *---------------------------------------------------------------------------*/
832 /* enable access to first 7 CRTC registers */
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);
839 if(cols == SCR_COL132) /* switch 80 -> 132 */
841 /* save state of board for 80 columns */
847 sp = savearea.et4000;
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);
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);
861 outb(addr_6845, 0x13); /* Row Offset Register */
862 *sp++ = inb(addr_6845+1);
864 outb(addr_6845, 0x34); /* 6845 Compatibility */
865 *sp++ = inb(addr_6845+1);
867 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
868 *sp++ = inb(TS_DATA);
874 /* ATC Mode control */
875 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
876 *sp++ = inb(ATC_DATAR);
882 /* ATC Horizontal Pixel Panning */
883 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
884 *sp++ = inb(ATC_DATAR);
886 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
889 /* setup chipset for 132 column operation */
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);
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);
903 outb(addr_6845, 0x13); /* Row Offset Register */
904 outb(addr_6845+1, 0x42);
906 outb(addr_6845, 0x34); /* 6845 Compatibility */
907 outb(addr_6845+1, 0x0a);
909 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
910 outb(TS_DATA, 0x01); /* 8 dot char clock */
916 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
917 outb(ATC_DATAW, 0x08); /* Line graphics disable */
923 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
924 outb(ATC_DATAW, 0x00);
926 /* Misc output register */
928 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c));
930 else /* switch 132 -> 80 */
932 if(!regsaved) /* failsafe */
934 /* disable access to first 7 CRTC registers */
935 outb(addr_6845, CRTC_VSYNCE);
936 outb(addr_6845+1, byte);
941 sp = savearea.et4000;
943 outb(addr_6845, 0x00); /* Horizontal Total */
944 outb(addr_6845+1, *sp++);
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++);
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++);
957 outb(addr_6845, 0x13); /* Row Offset Register */
958 outb(addr_6845+1, *sp++);
960 outb(addr_6845, 0x34); /* 6845 Compatibility */
961 outb(addr_6845+1, *sp++);
963 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
964 outb(TS_DATA, *sp++);
970 /* ATC Mode control */
971 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
972 outb(ATC_DATAW, *sp++);
978 /* ATC Horizontal Pixel Panning */
979 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
980 outb(ATC_DATAW, *sp++);
982 outb(GN_MISCOUTW, *sp++); /* Misc output register */
985 /* disable access to first 7 CRTC registers */
987 outb(addr_6845, CRTC_VSYNCE);
988 outb(addr_6845+1, byte);
995 /*---------------------------------------------------------------------------*
996 * toggle 80/132 column operation for WD/Paradise based boards
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 .......
1002 *---------------------------------------------------------------------------*/
1004 wd90c11_col(int cols)
1012 /* enable access to first 7 CRTC registers */
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);
1019 /* enable access to WD/Paradise "control extensions" */
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);
1028 if(cols == SCR_COL132) /* switch 80 -> 132 */
1030 /* save state of board for 80 columns */
1036 /* save current fonts */
1038 sp = savearea.wd90c11;
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);
1053 outb(addr_6845, 0x13); /* Row Offset Register */
1054 *sp++ = inb(addr_6845+1);
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);
1061 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1062 *sp++ = inb(TS_DATA);
1063 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1064 *sp++ = inb(TS_DATA);
1066 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1069 /* setup chipset for 132 column operation */
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);
1084 outb(addr_6845, 0x13); /* Row Offset Register */
1085 outb(addr_6845+1, 0x42);
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);
1092 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1093 outb(TS_DATA, 0x21);
1094 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1095 outb(TS_DATA, 0x14);
1097 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x08)); /* Misc output register */
1101 else /* switch 132 -> 80 */
1103 if(!regsaved) /* failsafe */
1105 /* disable access to first 7 CRTC registers */
1107 outb(addr_6845, CRTC_VSYNCE);
1108 outb(addr_6845+1, byte);
1110 /* disable access to WD/Paradise "control extensions" */
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);
1124 sp = savearea.wd90c11;
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++);
1139 outb(addr_6845, 0x13); /* Row Offset Register */
1140 outb(addr_6845+1, *sp++);
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++);
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++);
1152 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1159 for(i = 0; i < totalfonts; i++)
1160 if(saved_charsets[i])
1161 vga_move_charset(i, 0, 0);
1163 select_vga_charset(vsp->vga_charset);
1165 /* disable access to first 7 CRTC registers */
1167 outb(addr_6845, CRTC_VSYNCE);
1168 outb(addr_6845+1, byte);
1170 /* disable access to WD/Paradise "control extensions" */
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);
1184 /*---------------------------------------------------------------------------*
1185 * toggle 80/132 column operation for TRIDENT 9000 based boards
1186 *---------------------------------------------------------------------------*/
1188 tri9000_col(int cols)
1195 /* sync reset is necessary to preserve memory contents ... */
1197 outb(TS_INDEX, TS_SYNCRESET);
1198 outb(TS_DATA, 0x01); /* synchronous reset */
1200 /* disable protection of misc out and other regs */
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);
1207 /* enable access to first 7 CRTC registers */
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);
1214 if(cols == SCR_COL132) /* switch 80 -> 132 */
1216 /* save state of board for 80 columns */
1222 sp = savearea.tri9000;
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);
1237 outb(addr_6845, 0x13);
1238 *sp++ = inb(addr_6845+1);
1240 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1241 *sp++ = inb(TS_DATA);
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);
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);
1257 /* ATC Mode control */
1258 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1259 *sp++ = inb(ATC_DATAR);
1265 /* ATC Horizontal Pixel Panning */
1266 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1267 *sp++ = inb(ATC_DATAR);
1269 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1272 /* setup chipset for 132 column operation */
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);
1287 outb(addr_6845, 0x13); /* Row Offset Register */
1288 outb(addr_6845+1, 0x42);
1290 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1291 outb(TS_DATA, 0x01); /* 8 dot char clock */
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);
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);
1307 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1308 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1314 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1315 outb(ATC_DATAW, 0x00);
1317 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c)); /* Misc output register */
1319 else /* switch 132 -> 80 */
1321 if(!regsaved) /* failsafe */
1323 /* disable access to first 7 CRTC registers */
1324 outb(addr_6845, CRTC_VSYNCE);
1325 outb(addr_6845+1, byte);
1327 outb(TS_INDEX, TS_SYNCRESET);
1328 outb(TS_DATA, 0x03); /* clear synchronous reset */
1335 sp = savearea.tri9000;
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++);
1350 outb(addr_6845, 0x13); /* Row Offset Register */
1351 outb(addr_6845+1, *sp++);
1353 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1354 outb(TS_DATA, *sp++);
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++);
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++);
1370 /* ATC Mode control */
1371 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1372 outb(ATC_DATAW, *sp++);
1378 /* ATC Horizontal Pixel Panning */
1379 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1380 outb(ATC_DATAW, *sp++);
1382 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1385 /* disable access to first 7 CRTC registers */
1387 outb(addr_6845, CRTC_VSYNCE);
1388 outb(addr_6845+1, byte);
1390 outb(TS_INDEX, TS_SYNCRESET);
1391 outb(TS_DATA, 0x03); /* clear synchronous reset */
1398 /*---------------------------------------------------------------------------*
1399 * toggle 80/132 column operation for Video7 VGA 1024i
1400 *---------------------------------------------------------------------------*/
1402 v7_1024i_col(int cols)
1410 /* enable access to first 7 CRTC registers */
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));
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);
1426 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
1427 outb(TS_DATA, 0xea);
1430 if(cols == SCR_COL132) /* switch 80 -> 132 */
1432 /* save state of board for 80 columns */
1438 sp = savearea.v7_1024i;
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);
1453 outb(addr_6845, 0x13); /* Row Offset Register */
1454 *sp++ = inb(addr_6845+1);
1456 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1457 *sp++ = inb(TS_DATA);
1463 /* ATC Mode control */
1464 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1465 *sp++ = inb(ATC_DATAR);
1471 /* ATC Horizontal Pixel Panning */
1472 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1473 *sp++ = inb(ATC_DATAR);
1475 outb(TS_INDEX, 0x83);
1476 *sp++ = inb(TS_DATA);
1478 outb(TS_INDEX, 0xa4);
1479 *sp++ = inb(TS_DATA);
1481 outb(TS_INDEX, 0xe0);
1482 *sp++ = inb(TS_DATA);
1484 outb(TS_INDEX, 0xe4);
1485 *sp++ = inb(TS_DATA);
1487 outb(TS_INDEX, 0xf8);
1488 *sp++ = inb(TS_DATA);
1490 outb(TS_INDEX, 0xfd);
1491 *sp++ = inb(TS_DATA);
1493 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1496 /* setup chipset for 132 column operation */
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);
1511 outb(addr_6845, 0x13); /* Row Offset Register */
1512 outb(addr_6845+1, 0x42);
1514 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1515 outb(TS_DATA, 0x01); /* 8 dot char clock */
1521 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1522 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1528 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1529 outb(ATC_DATAW, 0x00);
1531 outb(TS_INDEX, TS_SYNCRESET);
1532 outb(TS_DATA, 0x01); /* synchronous reset */
1534 outb(TS_INDEX, 0x83);
1535 outb(TS_DATA, 0xa0);
1537 outb(TS_INDEX, 0xa4);
1538 outb(TS_DATA, 0x1c);
1540 outb(TS_INDEX, 0xe0);
1541 outb(TS_DATA, 0x00);
1543 outb(TS_INDEX, 0xe4);
1544 outb(TS_DATA, 0xfe);
1546 outb(TS_INDEX, 0xf8);
1547 outb(TS_DATA, 0x1b);
1549 outb(TS_INDEX, 0xfd);
1550 outb(TS_DATA, 0x33);
1552 byte = inb(GN_MISCOUTR);
1554 outb(GN_MISCOUTW, byte); /* Misc output register */
1556 outb(TS_INDEX, TS_SYNCRESET);
1557 outb(TS_DATA, 0x03); /* clear synchronous reset */
1559 else /* switch 132 -> 80 */
1561 if(!regsaved) /* failsafe */
1563 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1564 outb(TS_DATA, 0xae);
1566 /* disable access to first 7 CRTC registers */
1567 outb(addr_6845, CRTC_VSYNCE);
1568 outb(addr_6845+1, byte);
1573 sp = savearea.v7_1024i;
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++);
1588 outb(addr_6845, 0x13); /* Row Offset Register */
1589 outb(addr_6845+1, *sp++);
1591 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1592 outb(TS_DATA, *sp++);
1598 /* ATC Mode control */
1599 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1600 outb(ATC_DATAW, *sp++);
1606 /* ATC Horizontal Pixel Panning */
1607 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1608 outb(ATC_DATAW, *sp++);
1610 outb(TS_INDEX, TS_SYNCRESET);
1611 outb(TS_DATA, 0x01); /* synchronous reset */
1613 outb(TS_INDEX, 0x83);
1614 outb(TS_DATA, *sp++);
1616 outb(TS_INDEX, 0xa4);
1617 outb(TS_DATA, *sp++);
1619 outb(TS_INDEX, 0xe0);
1620 outb(TS_DATA, *sp++);
1622 outb(TS_INDEX, 0xe4);
1623 outb(TS_DATA, *sp++);
1625 outb(TS_INDEX, 0xf8);
1626 outb(TS_DATA, *sp++);
1628 outb(TS_INDEX, 0xfd);
1629 outb(TS_DATA, *sp++);
1631 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1633 outb(TS_INDEX, TS_SYNCRESET);
1634 outb(TS_DATA, 0x03); /* clear synchronous reset */
1637 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1638 outb(TS_DATA, 0xae);
1640 /* disable access to first 7 CRTC registers */
1642 outb(addr_6845, CRTC_VSYNCE);
1643 outb(addr_6845+1, save__byte);
1650 /*---------------------------------------------------------------------------*
1651 * toggle 80/132 column operation for S3 86C928 based boards
1652 *---------------------------------------------------------------------------*/
1654 s3_928_col(int cols)
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 */
1666 /* enable access to first 7 CRTC registers */
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);
1673 if(cols == SCR_COL132) /* switch 80 -> 132 */
1675 /* save state of board for 80 columns */
1681 sp = savearea.s3_928;
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);
1696 outb(addr_6845, 0x13); /* Row Offset Register */
1697 *sp++ = inb(addr_6845+1);
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);
1704 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1705 *sp++ = inb(addr_6845+1);
1707 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1708 *sp++ = inb(TS_DATA);
1714 /* ATC Mode control */
1715 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1716 *sp++ = inb(ATC_DATAR);
1722 /* ATC Horizontal Pixel Panning */
1723 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1724 *sp++ = inb(ATC_DATAR);
1726 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1729 /* setup chipset for 132 column operation */
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);
1744 outb(addr_6845, 0x13); /* Row Offset Register */
1745 outb(addr_6845+1, 0x42);
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 */
1752 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1753 outb(addr_6845+1, 0x02);/* Select 40MHz Clock */
1755 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1756 outb(TS_DATA, 0x01); /* 8 dot char clock */
1762 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1763 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1769 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1770 outb(ATC_DATAW, 0x00);
1772 /* Misc output register */
1774 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c));
1776 else /* switch 132 -> 80 */
1778 if(!regsaved) /* failsafe */
1780 /* disable access to first 7 CRTC registers */
1781 outb(addr_6845, CRTC_VSYNCE);
1782 outb(addr_6845+1, byte);
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 */
1793 sp = savearea.s3_928;
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++);
1808 outb(addr_6845, 0x13); /* Row Offset Register */
1809 outb(addr_6845+1, *sp++);
1811 outb(addr_6845, 0x34);
1812 outb(addr_6845+1, *sp++);
1813 outb(addr_6845, 0x3b);
1814 outb(addr_6845+1, *sp++);
1816 outb(addr_6845, 0x42); /* Mode control */
1817 outb(addr_6845+1, *sp++);
1819 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1820 outb(TS_DATA, *sp++);
1826 /* ATC Mode control */
1827 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1828 outb(ATC_DATAW, *sp++);
1834 /* ATC Horizontal Pixel Panning */
1835 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1836 outb(ATC_DATAW, *sp++);
1838 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1841 /* disable access to first 7 CRTC registers */
1843 outb(addr_6845, CRTC_VSYNCE);
1844 outb(addr_6845+1, byte);
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 */
1856 /*---------------------------------------------------------------------------*
1857 * toggle 80/132 column operation for Cirrus Logic 542x based boards
1858 *---------------------------------------------------------------------------*/
1860 cl_gd542x_col(int cols)
1867 /* enable access to first 7 CRTC registers */
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);
1874 /* enable access to cirrus extension registers */
1876 outb(TS_DATA, 0x12);
1878 if(cols == SCR_COL132) /* switch 80 -> 132 */
1880 /* save state of board for 80 columns */
1886 sp = savearea.cirrus;
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);
1901 outb(addr_6845, 0x13); /* Row Offset Register */
1902 *sp++ = inb(addr_6845+1);
1904 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1905 *sp++ = inb(TS_DATA);
1912 /* ATC Mode control */
1913 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1914 *sp++ = inb(ATC_DATAR);
1920 /* ATC Horizontal Pixel Panning */
1921 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1922 *sp++ = inb(ATC_DATAR);
1924 /* VCLK2 Numerator Register */
1925 outb(TS_INDEX, 0xd);
1926 *sp++ = inb(TS_DATA);
1928 /* VCLK2 Denominator and Post-Scalar Value Register */
1929 outb(TS_INDEX, 0x1d);
1930 *sp++ = inb(TS_DATA);
1932 /* Misc output register */
1933 *sp++ = inb(GN_MISCOUTR);
1936 /* setup chipset for 132 column operation */
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);
1951 outb(addr_6845, 0x13); /* Row Offset Register */
1952 outb(addr_6845+1, 0x42);
1954 /* set VCLK2 to 41.164 MHz ..... */
1955 outb(TS_INDEX, 0xd); /* VCLK2 Numerator Register */
1956 outb(TS_DATA, 0x45);
1958 outb(TS_INDEX, 0x1d); /* VCLK2 Denominator and */
1959 outb(TS_DATA, 0x30); /* Post-Scalar Value Register */
1962 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | (2 << 2));
1964 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1965 outb(TS_DATA, 0x01); /* 8 dot char clock */
1971 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1972 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1978 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1979 outb(ATC_DATAW, 0x00);
1981 else /* switch 132 -> 80 */
1983 if(!regsaved) /* failsafe */
1985 /* disable access to first 7 CRTC registers */
1986 outb(addr_6845, CRTC_VSYNCE);
1987 outb(addr_6845+1, byte);
1989 /* disable access to cirrus extension registers */
1997 sp = savearea.cirrus;
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++);
2012 outb(addr_6845, 0x13); /* Row Offset Register */
2013 outb(addr_6845+1, *sp++);
2015 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2016 outb(TS_DATA, *sp++);
2022 /* ATC Mode control */
2023 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
2024 outb(ATC_DATAW, *sp++);
2030 /* ATC Horizontal Pixel Panning */
2031 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
2032 outb(ATC_DATAW, *sp++);
2034 /* VCLK2 Numerator Register */
2035 outb(TS_INDEX, 0xd);
2036 outb(TS_DATA, *sp++);
2038 /* VCLK2 Denominator and Post-Scalar Value Register */
2039 outb(TS_INDEX, 0x1d);
2040 outb(TS_DATA, *sp++);
2042 outb(GN_MISCOUTW, *sp++); /* Misc output register */
2045 /* disable access to cirrus extension registers */
2049 /* disable access to first 7 CRTC registers */
2051 outb(addr_6845, CRTC_VSYNCE);
2052 outb(addr_6845+1, byte);
2060 /*---------------------------------------------------------------------------*
2061 * switch screen from text mode to X-mode and vice versa
2062 *---------------------------------------------------------------------------*/
2064 switch_screen(int n, int oldgrafx, int newgrafx)
2066 #if PCVT_SCREENSAVER
2067 static unsigned saved_scrnsv_tmo = 0;
2068 #endif /* PCVT_SCREENSAVER */
2070 int cols = vsp->maxcol; /* get current col val */
2072 if(n < 0 || n >= totalscreens)
2075 if(!oldgrafx && newgrafx)
2077 /* switch from text to graphics */
2079 #if PCVT_SCREENSAVER
2080 if((saved_scrnsv_tmo = scrnsv_timeout))
2081 pcvt_set_scrnsv_tmo(0); /* screensaver off */
2082 #endif /* PCVT_SCREENSAVER */
2084 async_update(UPDATE_STOP); /* status display off */
2089 /* switch from text mode */
2091 /* video board memory -> kernel memory */
2092 bcopy(vsp->Crtat, vsp->Memory,
2093 vsp->screen_rows * vsp->maxcol * CHR);
2095 vsp->Crtat = vsp->Memory; /* operate in memory now */
2098 /* update global screen pointers/variables */
2099 current_video_screen = n; /* current screen no */
2101 vsp = &vs[n]; /* current video state ptr */
2103 if(oldgrafx && !newgrafx)
2105 /* switch from graphics to text mode */
2109 for(i = 0; i < totalfonts; i++)
2110 if(saved_charsets[i])
2111 vga_move_charset(i, 0, 0);
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 */
2119 /* re-initialize lost MDA information */
2120 if(adaptor_type == MDA_ADAPTOR)
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.
2129 outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
2130 outb(addr_6845, CRTC_CURSORH); /* select high register */
2132 ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
2133 outb(addr_6845, CRTC_CURSORL); /* select low register */
2135 ((vsp->Crtat + vsp->cur_offset) - Crtat));
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);
2143 /* make status display happy */
2144 async_update(UPDATE_START);
2151 /* kernel memory -> video board memory */
2152 bcopy(vsp->Crtat, Crtat,
2153 vsp->screen_rows * vsp->maxcol * CHR);
2155 vsp->Crtat = Crtat; /* operate on screen now */
2157 outb(addr_6845, CRTC_STARTADRH);
2158 outb(addr_6845+1, 0);
2159 outb(addr_6845, CRTC_STARTADRL);
2160 outb(addr_6845+1, 0);
2163 select_vga_charset(vsp->vga_charset);
2165 if(vsp->maxcol != cols)
2166 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
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);
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);
2185 if(adaptor_type == VGA_ADAPTOR)
2189 /* switch VGA DAC palette entries */
2190 for(i = 0; i < NVGAPEL; i++)
2191 vgapaletteio(i, &vsp->palette[i], 1);
2196 update_led(); /* update led's */
2197 update_hp(vsp); /* update fkey labels, if present */
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 ... */
2203 if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) &&
2204 (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS))
2206 fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol,
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 *---------------------------------------------------------------------------*/
2218 set_auto_mode (struct video_state *vsx)
2220 unsigned ostatus = vsx->vt_status;
2221 vsx->smode.mode = VT_AUTO;
2224 vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK);
2226 if (ostatus & VT_WAIT_ACK)
2228 if(vsp == vsx && vt_switch_pending == current_video_screen + 1)
2229 vt_switch_pending = 0;
2231 if (ostatus & VT_WAIT_REL)
2233 int new_screen = vt_switch_pending - 1;
2234 if (vsp == vsx && vt_switch_pending)
2236 vt_switch_pending = 0;
2237 vgapage (new_screen);
2242 /*---------------------------------------------------------------------------*
2243 * Exported function; to be called when a vt is closed down.
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 *---------------------------------------------------------------------------*/
2251 reset_usl_modes (struct video_state *vsx)
2253 /* Clear graphics mode */
2254 if (vsx->vt_status & VT_GRAFX) {
2255 vsx->vt_status &= ~VT_GRAFX;
2257 switch_screen(current_video_screen, 1, 0);
2260 /* Take kbd out of raw mode */
2261 if (pcvt_kbd_raw && vsp == vsx) {
2262 #if PCVT_SCANSET > 1
2264 #endif /* PCVT_SCANSET > 1 */
2268 /* Clear process controlled mode */
2269 set_auto_mode (vsx);
2273 * Fallback to VT_AUTO if controlling process died.
2276 fallback_to_auto(struct video_state *vsx)
2281 p = pfind(vsx->pid);
2290 /*---------------------------------------------------------------------------*
2291 * switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version
2292 * (the name vgapage() stands for historical reasons)
2293 *---------------------------------------------------------------------------*/
2295 vgapage(int new_screen)
2299 if(new_screen < 0 || new_screen >= totalscreens)
2302 /* fallback to VT_AUTO if controlling processes died */
2303 fallback_to_auto(vsp);
2304 fallback_to_auto(&vs[new_screen]);
2306 if (!vt_switch_pending && new_screen == current_video_screen)
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);
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);
2329 vt_switch_pending = new_screen + 1;
2331 if(vsp->smode.mode == VT_PROCESS)
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);
2343 struct video_state *old_vsp = vsp;
2345 switch_screen(new_screen,
2346 vsp->vt_status & VT_GRAFX,
2347 vs[new_screen].vt_status & VT_GRAFX);
2351 if(old_vsp->vt_status & VT_WAIT_ACT)
2353 old_vsp->vt_status &= ~VT_WAIT_ACT;
2354 wakeup(&old_vsp->smode);
2357 if(vsp->vt_status & VT_WAIT_ACT)
2359 vsp->vt_status &= ~VT_WAIT_ACT;
2360 wakeup(&vsp->smode);
2365 if(vsp->smode.mode == VT_PROCESS)
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);
2377 /* we are committed */
2378 vt_switch_pending = 0;
2381 * XXX: If pcvt is acting as the systems console,
2382 * avoid panics going to the debugger while we are in
2386 cnavailable(pcvt_consptr, TRUE);
2392 /*---------------------------------------------------------------------------*
2393 * ioctl handling for VT_USL mode
2394 *---------------------------------------------------------------------------*/
2396 usl_vt_ioctl(struct cdev *dev, int cmd, caddr_t data, int flag, struct thread *td)
2399 int i, j, error, opri;
2400 struct vt_mode newmode;
2406 newmode = *(struct vt_mode *)data;
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) {
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.
2439 if (minor(dev) != current_video_screen) {
2444 /* Check for server died */
2445 fallback_to_auto(vsp);
2447 /* Check for server already running */
2448 if (vsp->smode.mode == VT_PROCESS && vsp->proc != p)
2451 return EBUSY; /* already in use on this VT */
2454 if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig)
2455 || !ISSIGVALID(newmode.frsig))
2461 vsp->smode = newmode;
2463 vsp->pid = p->p_pid;
2466 * XXX: If pcvt is acting as the systems console,
2467 * avoid panics going to the debugger while we are in
2471 cnavailable(pcvt_consptr, (newmode.mode != VT_PROCESS));
2477 *(struct vt_mode *)data = vsp->smode;
2483 if (minor(dev) != current_video_screen)
2485 if (vsp->smode.mode != VT_PROCESS)
2489 switch(*(int *)data) {
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;
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;
2507 vsp->vt_status &= ~VT_WAIT_REL;
2509 switch_screen(new_screen,
2510 vsp->vt_status & VT_GRAFX,
2511 vs[new_screen].vt_status
2515 if(old_vsp->vt_status & VT_WAIT_ACT)
2517 old_vsp->vt_status &= ~VT_WAIT_ACT;
2518 wakeup(&old_vsp->smode);
2520 if(vsp->vt_status & VT_WAIT_ACT)
2522 vsp->vt_status &= ~VT_WAIT_ACT;
2523 wakeup(&vsp->smode);
2527 if(vsp->smode.mode == VT_PROCESS) {
2529 * if the new vt is also in process
2530 * mode, we have to wait until its
2531 * controlling process acknowledged
2536 if(vsp->smode.acqsig) {
2537 PROC_LOCK(vsp->proc);
2540 PROC_UNLOCK(vsp->proc);
2545 /* we are committed */
2546 vt_switch_pending = 0;
2550 cnavailable(pcvt_consptr, TRUE);
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;
2564 cnavailable(pcvt_consptr, FALSE);
2570 return EINVAL; /* end case VT_RELDISP */
2574 /* return free vt */
2575 for(i = 0; i < PCVT_NSCREENS; i++)
2577 *(int *)data = i + 1;
2583 *(int *)data = current_video_screen + 1;
2587 return vgapage(*(int *)data - 1);
2590 /* sleep until vt switch happened */
2591 i = *(int *)data - 1;
2596 if(i < 0 || i >= PCVT_NSCREENS)
2599 if(current_video_screen == i)
2604 vs[i].vt_status |= VT_WAIT_ACT;
2605 error = tsleep(&vs[i].smode,
2606 PZERO | PCATCH, "waitvt", 0);
2612 /* grant the process IO access; only allowed if euid == 0 */
2615 struct trapframe *fp = td->td_frame;
2620 error = securelevel_gt(td->td_ucred, 0);
2624 fp->tf_eflags |= PSL_IOPL;
2630 /* abandon IO access permission */
2632 struct trapframe *fp = td->td_frame;
2633 fp->tf_eflags &= ~PSL_IOPL;
2639 struct video_state *vsx = &vs[minor(dev)];
2642 if(adaptor_type != VGA_ADAPTOR
2643 && adaptor_type != MDA_ADAPTOR)
2644 /* X will only run on those adaptors */
2647 /* set text/graphics mode of current vt */
2648 switch(*(int *)data)
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);
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);
2668 return EINVAL; /* end case KDSETMODE */
2672 /* set keyboard repeat and delay */
2673 return kbdioctl(dev, KBDSTPMAT, data, flag);
2676 switch(*(int *)data)
2680 #if PCVT_SCANSET > 1
2681 /* put keyboard to return ancient PC scan codes */
2683 #endif /* PCVT_SCANSET > 1 */
2686 shift_down = meta_down = altgr_down = ctrl_down = 0;
2691 #if PCVT_SCANSET > 1
2693 #endif /* PCVT_SCANSET > 1 */
2698 return EINVAL; /* end KDSKBMODE */
2701 /* ring the speaker */
2704 int duration = *(int *)data >> 16;
2705 int pitch = *(int *)data & 0xffff;
2707 sysbeep(pitch, duration * hz / 3000);
2711 sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
2716 /* set kbd LED status */
2717 /* unfortunately, the LED definitions between pcvt and */
2718 /* USL differ some way :-( */
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);
2726 /* get kbd LED status */
2727 if((error = kbdioctl(dev, KBDGLOCK, (caddr_t)&j, flag)))
2729 i = (j & KBD_CAPSLOCK? LED_CAP: 0)
2730 + (j & KBD_NUMLOCK? LED_NUM: 0)
2731 + (j & KBD_SCROLLLOCK? LED_SCR: 0);
2736 get_usl_keymap((keymap_t *)data);
2738 } /* end case cmd */
2740 return -1; /* inappropriate usl_vt_compat ioctl */
2742 #endif /* XSERVER */
2744 /* ------------------------- E O F ------------------------------------------*/