2 * Copyright (c) 1999 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: [Mon Dec 27 14:05:16 1999]
47 * $FreeBSD: src/sys/i386/isa/pcvt/pcvt_ext.c,v 1.17 1999/12/30 16:17:09 hm Exp $
48 * $DragonFly: src/sys/dev/video/pcvt/i386/Attic/pcvt_ext.c,v 1.5 2003/07/21 07:57:45 dillon Exp $
50 *---------------------------------------------------------------------------*/
55 #include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
57 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
59 static int s3testwritable( void );
60 static int et4000_col( int );
61 static int wd90c11_col( int );
62 static int tri9000_col( int );
63 static int v7_1024i_col( int );
64 static int s3_928_col( int );
65 static int cl_gd542x_col( int );
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)
1007 #if !PCVT_BACKUP_FONTS
1008 static unsigned char *sv_fontwd[NVGAFONTS];
1009 #endif /* !PCVT_BACKUP_FONTS */
1017 /* enable access to first 7 CRTC registers */
1019 outb(addr_6845, CRTC_VSYNCE);
1020 byte = inb(addr_6845+1);
1021 outb(addr_6845, CRTC_VSYNCE);
1022 outb(addr_6845+1, byte & 0x7f);
1024 /* enable access to WD/Paradise "control extensions" */
1026 outb(GDC_INDEX, GDC_PR5GPLOCK);
1027 outb(GDC_INDEX, 0x05);
1028 outb(addr_6845, CRTC_PR10);
1029 outb(addr_6845, 0x85);
1030 outb(TS_INDEX, TS_UNLOCKSEQ);
1031 outb(TS_DATA, 0x48);
1033 if(cols == SCR_COL132) /* switch 80 -> 132 */
1035 /* save state of board for 80 columns */
1041 /* save current fonts */
1043 #if !PCVT_BACKUP_FONTS
1044 for(i = 0; i < totalfonts; i++)
1049 (u_char *)malloc(32 * 256,
1053 printf("pcvt: no font buffer\n");
1065 #endif /* !PCVT_BACKUP_FONTS */
1067 sp = savearea.wd90c11;
1069 outb(addr_6845, 0x00); /* Horizontal Total */
1070 *sp++ = inb(addr_6845+1);
1071 outb(addr_6845, 0x01); /* Horizontal Display End */
1072 *sp++ = inb(addr_6845+1);
1073 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1074 *sp++ = inb(addr_6845+1);
1075 outb(addr_6845, 0x03); /* Horizontal Blank End */
1076 *sp++ = inb(addr_6845+1);
1077 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1078 *sp++ = inb(addr_6845+1);
1079 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1080 *sp++ = inb(addr_6845+1);
1082 outb(addr_6845, 0x13); /* Row Offset Register */
1083 *sp++ = inb(addr_6845+1);
1085 outb(addr_6845, 0x2e); /* misc 1 */
1086 *sp++ = inb(addr_6845+1);
1087 outb(addr_6845, 0x2f); /* misc 2 */
1088 *sp++ = inb(addr_6845+1);
1090 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1091 *sp++ = inb(TS_DATA);
1092 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1093 *sp++ = inb(TS_DATA);
1095 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1098 /* setup chipset for 132 column operation */
1100 outb(addr_6845, 0x00); /* Horizontal Total */
1101 outb(addr_6845+1, 0x9c);
1102 outb(addr_6845, 0x01); /* Horizontal Display End */
1103 outb(addr_6845+1, 0x83);
1104 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1105 outb(addr_6845+1, 0x84);
1106 outb(addr_6845, 0x03); /* Horizontal Blank End */
1107 outb(addr_6845+1, 0x9f);
1108 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1109 outb(addr_6845+1, 0x8a);
1110 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1111 outb(addr_6845+1, 0x1c);
1113 outb(addr_6845, 0x13); /* Row Offset Register */
1114 outb(addr_6845+1, 0x42);
1116 outb(addr_6845, 0x2e); /* misc 1 */
1117 outb(addr_6845+1, 0x04);
1118 outb(addr_6845, 0x2f); /* misc 2 */
1119 outb(addr_6845+1, 0x00);
1121 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1122 outb(TS_DATA, 0x21);
1123 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1124 outb(TS_DATA, 0x14);
1126 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x08)); /* Misc output register */
1130 else /* switch 132 -> 80 */
1132 if(!regsaved) /* failsafe */
1134 /* disable access to first 7 CRTC registers */
1136 outb(addr_6845, CRTC_VSYNCE);
1137 outb(addr_6845+1, byte);
1139 /* disable access to WD/Paradise "control extensions" */
1141 outb(GDC_INDEX, GDC_PR5GPLOCK);
1142 outb(GDC_INDEX, 0x00);
1143 outb(addr_6845, CRTC_PR10);
1144 outb(addr_6845, 0x00);
1145 outb(TS_INDEX, TS_UNLOCKSEQ);
1146 outb(TS_DATA, 0x00);
1153 sp = savearea.wd90c11;
1155 outb(addr_6845, 0x00); /* Horizontal Total */
1156 outb(addr_6845+1, *sp++);
1157 outb(addr_6845, 0x01); /* Horizontal Display End */
1158 outb(addr_6845+1, *sp++);
1159 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1160 outb(addr_6845+1, *sp++);
1161 outb(addr_6845, 0x03); /* Horizontal Blank End */
1162 outb(addr_6845+1, *sp++);
1163 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1164 outb(addr_6845+1, *sp++);
1165 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1166 outb(addr_6845+1, *sp++);
1168 outb(addr_6845, 0x13); /* Row Offset Register */
1169 outb(addr_6845+1, *sp++);
1171 outb(addr_6845, 0x2e); /* misc 1 */
1172 outb(addr_6845+1, *sp++);
1173 outb(addr_6845, 0x2f); /* misc 2 */
1174 outb(addr_6845+1, *sp++);
1176 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1177 outb(addr_6845+1, *sp++);
1178 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1179 outb(addr_6845+1, *sp++);
1181 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1188 #if !PCVT_BACKUP_FONTS
1189 for(i = 0; i < totalfonts; i++)
1192 vga_move_charset(i, sv_fontwd[i], 0);
1195 for(i = 0; i < totalfonts; i++)
1196 if(saved_charsets[i])
1197 vga_move_charset(i, 0, 0);
1198 #endif /* !PCVT_BACKUP_FONTS */
1200 select_vga_charset(vsp->vga_charset);
1202 /* disable access to first 7 CRTC registers */
1204 outb(addr_6845, CRTC_VSYNCE);
1205 outb(addr_6845+1, byte);
1207 /* disable access to WD/Paradise "control extensions" */
1209 outb(GDC_INDEX, GDC_PR5GPLOCK);
1210 outb(GDC_INDEX, 0x00);
1211 outb(addr_6845, CRTC_PR10);
1212 outb(addr_6845, 0x00);
1213 outb(TS_INDEX, TS_UNLOCKSEQ);
1214 outb(TS_DATA, 0x00);
1221 /*---------------------------------------------------------------------------*
1222 * toggle 80/132 column operation for TRIDENT 9000 based boards
1223 *---------------------------------------------------------------------------*/
1225 tri9000_col(int cols)
1232 /* sync reset is necessary to preserve memory contents ... */
1234 outb(TS_INDEX, TS_SYNCRESET);
1235 outb(TS_DATA, 0x01); /* synchronous reset */
1237 /* disable protection of misc out and other regs */
1239 outb(addr_6845, CRTC_MTEST);
1240 byte = inb(addr_6845+1);
1241 outb(addr_6845, CRTC_MTEST);
1242 outb(addr_6845+1, byte & ~0x50);
1244 /* enable access to first 7 CRTC registers */
1246 outb(addr_6845, CRTC_VSYNCE);
1247 byte = inb(addr_6845+1);
1248 outb(addr_6845, CRTC_VSYNCE);
1249 outb(addr_6845+1, byte & 0x7f);
1251 if(cols == SCR_COL132) /* switch 80 -> 132 */
1253 /* save state of board for 80 columns */
1259 sp = savearea.tri9000;
1261 outb(addr_6845, 0x00); /* Horizontal Total */
1262 *sp++ = inb(addr_6845+1);
1263 outb(addr_6845, 0x01); /* Horizontal Display End */
1264 *sp++ = inb(addr_6845+1);
1265 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1266 *sp++ = inb(addr_6845+1);
1267 outb(addr_6845, 0x03); /* Horizontal Blank End */
1268 *sp++ = inb(addr_6845+1);
1269 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1270 *sp++ = inb(addr_6845+1);
1271 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1272 *sp++ = inb(addr_6845+1);
1274 outb(addr_6845, 0x13);
1275 *sp++ = inb(addr_6845+1);
1277 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1278 *sp++ = inb(TS_DATA);
1280 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1281 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1282 outb(TS_INDEX, TS_MODEC2);
1283 *sp++ = inb(TS_DATA);
1285 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1286 inb(TS_DATA); /* read switches to NEW */
1287 outb(TS_INDEX, TS_MODEC2);
1288 *sp++ = inb(TS_DATA);
1294 /* ATC Mode control */
1295 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1296 *sp++ = inb(ATC_DATAR);
1302 /* ATC Horizontal Pixel Panning */
1303 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1304 *sp++ = inb(ATC_DATAR);
1306 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1309 /* setup chipset for 132 column operation */
1311 outb(addr_6845, 0x00); /* Horizontal Total */
1312 outb(addr_6845+1, 0x9b);
1313 outb(addr_6845, 0x01); /* Horizontal Display End */
1314 outb(addr_6845+1, 0x83);
1315 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1316 outb(addr_6845+1, 0x84);
1317 outb(addr_6845, 0x03); /* Horizontal Blank End */
1318 outb(addr_6845+1, 0x1e);
1319 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1320 outb(addr_6845+1, 0x87);
1321 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1322 outb(addr_6845+1, 0x1a);
1324 outb(addr_6845, 0x13); /* Row Offset Register */
1325 outb(addr_6845+1, 0x42);
1327 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1328 outb(TS_DATA, 0x01); /* 8 dot char clock */
1330 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1331 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1332 outb(TS_INDEX, TS_MODEC2);
1333 outb(TS_DATA, 0x00);
1335 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1336 inb(TS_DATA); /* read switches to NEW */
1337 outb(TS_INDEX, TS_MODEC2);
1338 outb(TS_DATA, 0x01);
1344 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1345 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1351 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1352 outb(ATC_DATAW, 0x00);
1354 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c)); /* Misc output register */
1356 else /* switch 132 -> 80 */
1358 if(!regsaved) /* failsafe */
1360 /* disable access to first 7 CRTC registers */
1361 outb(addr_6845, CRTC_VSYNCE);
1362 outb(addr_6845+1, byte);
1364 outb(TS_INDEX, TS_SYNCRESET);
1365 outb(TS_DATA, 0x03); /* clear synchronous reset */
1372 sp = savearea.tri9000;
1374 outb(addr_6845, 0x00); /* Horizontal Total */
1375 outb(addr_6845+1, *sp++);
1376 outb(addr_6845, 0x01); /* Horizontal Display End */
1377 outb(addr_6845+1, *sp++);
1378 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1379 outb(addr_6845+1, *sp++);
1380 outb(addr_6845, 0x03); /* Horizontal Blank End */
1381 outb(addr_6845+1, *sp++);
1382 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1383 outb(addr_6845+1, *sp++);
1384 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1385 outb(addr_6845+1, *sp++);
1387 outb(addr_6845, 0x13); /* Row Offset Register */
1388 outb(addr_6845+1, *sp++);
1390 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1391 outb(TS_DATA, *sp++);
1393 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1394 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1395 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1396 outb(TS_DATA, *sp++);
1398 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1399 inb(TS_DATA); /* read switches to NEW */
1400 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1401 outb(TS_DATA, *sp++);
1407 /* ATC Mode control */
1408 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1409 outb(ATC_DATAW, *sp++);
1415 /* ATC Horizontal Pixel Panning */
1416 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1417 outb(ATC_DATAW, *sp++);
1419 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1422 /* disable access to first 7 CRTC registers */
1424 outb(addr_6845, CRTC_VSYNCE);
1425 outb(addr_6845+1, byte);
1427 outb(TS_INDEX, TS_SYNCRESET);
1428 outb(TS_DATA, 0x03); /* clear synchronous reset */
1435 /*---------------------------------------------------------------------------*
1436 * toggle 80/132 column operation for Video7 VGA 1024i
1437 *---------------------------------------------------------------------------*/
1439 v7_1024i_col(int cols)
1447 /* enable access to first 7 CRTC registers */
1449 /* first, enable read access to vertical retrace start/end */
1450 outb(addr_6845, CRTC_HBLANKE);
1451 byte = inb(addr_6845+1);
1452 outb(addr_6845, CRTC_HBLANKE);
1453 outb(addr_6845+1, (byte | 0x80));
1455 /* second, enable access to protected registers */
1456 outb(addr_6845, CRTC_VSYNCE);
1457 save__byte = byte = inb(addr_6845+1);
1458 byte |= 0x20; /* no irq 2 */
1459 byte &= 0x6f; /* wr enable, clr irq flag */
1460 outb(addr_6845, CRTC_VSYNCE);
1461 outb(addr_6845+1, byte);
1463 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
1464 outb(TS_DATA, 0xea);
1467 if(cols == SCR_COL132) /* switch 80 -> 132 */
1469 /* save state of board for 80 columns */
1475 sp = savearea.v7_1024i;
1477 outb(addr_6845, 0x00); /* Horizontal Total */
1478 *sp++ = inb(addr_6845+1);
1479 outb(addr_6845, 0x01); /* Horizontal Display End */
1480 *sp++ = inb(addr_6845+1);
1481 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1482 *sp++ = inb(addr_6845+1);
1483 outb(addr_6845, 0x03); /* Horizontal Blank End */
1484 *sp++ = inb(addr_6845+1);
1485 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1486 *sp++ = inb(addr_6845+1);
1487 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1488 *sp++ = inb(addr_6845+1);
1490 outb(addr_6845, 0x13); /* Row Offset Register */
1491 *sp++ = inb(addr_6845+1);
1493 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1494 *sp++ = inb(TS_DATA);
1500 /* ATC Mode control */
1501 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1502 *sp++ = inb(ATC_DATAR);
1508 /* ATC Horizontal Pixel Panning */
1509 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1510 *sp++ = inb(ATC_DATAR);
1512 outb(TS_INDEX, 0x83);
1513 *sp++ = inb(TS_DATA);
1515 outb(TS_INDEX, 0xa4);
1516 *sp++ = inb(TS_DATA);
1518 outb(TS_INDEX, 0xe0);
1519 *sp++ = inb(TS_DATA);
1521 outb(TS_INDEX, 0xe4);
1522 *sp++ = inb(TS_DATA);
1524 outb(TS_INDEX, 0xf8);
1525 *sp++ = inb(TS_DATA);
1527 outb(TS_INDEX, 0xfd);
1528 *sp++ = inb(TS_DATA);
1530 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1533 /* setup chipset for 132 column operation */
1535 outb(addr_6845, 0x00); /* Horizontal Total */
1536 outb(addr_6845+1, 0x9c);
1537 outb(addr_6845, 0x01); /* Horizontal Display End */
1538 outb(addr_6845+1, 0x83);
1539 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1540 outb(addr_6845+1, 0x86);
1541 outb(addr_6845, 0x03); /* Horizontal Blank End */
1542 outb(addr_6845+1, 0x9e);
1543 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1544 outb(addr_6845+1, 0x89);
1545 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1546 outb(addr_6845+1, 0x1c);
1548 outb(addr_6845, 0x13); /* Row Offset Register */
1549 outb(addr_6845+1, 0x42);
1551 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1552 outb(TS_DATA, 0x01); /* 8 dot char clock */
1558 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1559 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1565 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1566 outb(ATC_DATAW, 0x00);
1568 outb(TS_INDEX, TS_SYNCRESET);
1569 outb(TS_DATA, 0x01); /* synchronous reset */
1571 outb(TS_INDEX, 0x83);
1572 outb(TS_DATA, 0xa0);
1574 outb(TS_INDEX, 0xa4);
1575 outb(TS_DATA, 0x1c);
1577 outb(TS_INDEX, 0xe0);
1578 outb(TS_DATA, 0x00);
1580 outb(TS_INDEX, 0xe4);
1581 outb(TS_DATA, 0xfe);
1583 outb(TS_INDEX, 0xf8);
1584 outb(TS_DATA, 0x1b);
1586 outb(TS_INDEX, 0xfd);
1587 outb(TS_DATA, 0x33);
1589 byte = inb(GN_MISCOUTR);
1591 outb(GN_MISCOUTW, byte); /* Misc output register */
1593 outb(TS_INDEX, TS_SYNCRESET);
1594 outb(TS_DATA, 0x03); /* clear synchronous reset */
1596 else /* switch 132 -> 80 */
1598 if(!regsaved) /* failsafe */
1600 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1601 outb(TS_DATA, 0xae);
1603 /* disable access to first 7 CRTC registers */
1604 outb(addr_6845, CRTC_VSYNCE);
1605 outb(addr_6845+1, byte);
1610 sp = savearea.v7_1024i;
1612 outb(addr_6845, 0x00); /* Horizontal Total */
1613 outb(addr_6845+1, *sp++);
1614 outb(addr_6845, 0x01); /* Horizontal Display End */
1615 outb(addr_6845+1, *sp++);
1616 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1617 outb(addr_6845+1, *sp++);
1618 outb(addr_6845, 0x03); /* Horizontal Blank End */
1619 outb(addr_6845+1, *sp++);
1620 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1621 outb(addr_6845+1, *sp++);
1622 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1623 outb(addr_6845+1, *sp++);
1625 outb(addr_6845, 0x13); /* Row Offset Register */
1626 outb(addr_6845+1, *sp++);
1628 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1629 outb(TS_DATA, *sp++);
1635 /* ATC Mode control */
1636 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1637 outb(ATC_DATAW, *sp++);
1643 /* ATC Horizontal Pixel Panning */
1644 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1645 outb(ATC_DATAW, *sp++);
1647 outb(TS_INDEX, TS_SYNCRESET);
1648 outb(TS_DATA, 0x01); /* synchronous reset */
1650 outb(TS_INDEX, 0x83);
1651 outb(TS_DATA, *sp++);
1653 outb(TS_INDEX, 0xa4);
1654 outb(TS_DATA, *sp++);
1656 outb(TS_INDEX, 0xe0);
1657 outb(TS_DATA, *sp++);
1659 outb(TS_INDEX, 0xe4);
1660 outb(TS_DATA, *sp++);
1662 outb(TS_INDEX, 0xf8);
1663 outb(TS_DATA, *sp++);
1665 outb(TS_INDEX, 0xfd);
1666 outb(TS_DATA, *sp++);
1668 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1670 outb(TS_INDEX, TS_SYNCRESET);
1671 outb(TS_DATA, 0x03); /* clear synchronous reset */
1674 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1675 outb(TS_DATA, 0xae);
1677 /* disable access to first 7 CRTC registers */
1679 outb(addr_6845, CRTC_VSYNCE);
1680 outb(addr_6845+1, save__byte);
1687 /*---------------------------------------------------------------------------*
1688 * toggle 80/132 column operation for S3 86C928 based boards
1689 *---------------------------------------------------------------------------*/
1691 s3_928_col(int cols)
1698 outb(addr_6845, 0x38);
1699 outb(addr_6845+1, 0x48); /* unlock registers */
1700 outb(addr_6845, 0x39);
1701 outb(addr_6845+1, 0xa0); /* unlock registers */
1703 /* enable access to first 7 CRTC registers */
1705 outb(addr_6845, CRTC_VSYNCE);
1706 byte = inb(addr_6845+1);
1707 outb(addr_6845, CRTC_VSYNCE);
1708 outb(addr_6845+1, byte & 0x7f);
1710 if(cols == SCR_COL132) /* switch 80 -> 132 */
1712 /* save state of board for 80 columns */
1718 sp = savearea.s3_928;
1720 outb(addr_6845, 0x00); /* Horizontal Total */
1721 *sp++ = inb(addr_6845+1);
1722 outb(addr_6845, 0x01); /* Horizontal Display End */
1723 *sp++ = inb(addr_6845+1);
1724 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1725 *sp++ = inb(addr_6845+1);
1726 outb(addr_6845, 0x03); /* Horizontal Blank End */
1727 *sp++ = inb(addr_6845+1);
1728 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1729 *sp++ = inb(addr_6845+1);
1730 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1731 *sp++ = inb(addr_6845+1);
1733 outb(addr_6845, 0x13); /* Row Offset Register */
1734 *sp++ = inb(addr_6845+1);
1736 outb(addr_6845, 0x34); /* Backward Compat 3 Reg */
1737 *sp++ = inb(addr_6845+1);
1738 outb(addr_6845, 0x3b); /* Data Xfer Exec Position */
1739 *sp++ = inb(addr_6845+1);
1741 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1742 *sp++ = inb(addr_6845+1);
1744 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1745 *sp++ = inb(TS_DATA);
1751 /* ATC Mode control */
1752 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1753 *sp++ = inb(ATC_DATAR);
1759 /* ATC Horizontal Pixel Panning */
1760 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1761 *sp++ = inb(ATC_DATAR);
1763 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1766 /* setup chipset for 132 column operation */
1768 outb(addr_6845, 0x00); /* Horizontal Total */
1769 outb(addr_6845+1, 0x9a);
1770 outb(addr_6845, 0x01); /* Horizontal Display End */
1771 outb(addr_6845+1, 0x83);
1772 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1773 outb(addr_6845+1, 0x86);
1774 outb(addr_6845, 0x03); /* Horizontal Blank End */
1775 outb(addr_6845+1, 0x9d);
1776 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1777 outb(addr_6845+1, 0x87);
1778 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1779 outb(addr_6845+1, 0x1b);
1781 outb(addr_6845, 0x13); /* Row Offset Register */
1782 outb(addr_6845+1, 0x42);
1784 outb(addr_6845, 0x34);
1785 outb(addr_6845+1, 0x10);/* enable data xfer pos control */
1786 outb(addr_6845, 0x3b);
1787 outb(addr_6845+1, 0x90);/* set data xfer pos value */
1789 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1790 outb(addr_6845+1, 0x02);/* Select 40MHz Clock */
1792 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1793 outb(TS_DATA, 0x01); /* 8 dot char clock */
1799 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1800 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1806 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1807 outb(ATC_DATAW, 0x00);
1809 /* Misc output register */
1811 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c));
1813 else /* switch 132 -> 80 */
1815 if(!regsaved) /* failsafe */
1817 /* disable access to first 7 CRTC registers */
1818 outb(addr_6845, CRTC_VSYNCE);
1819 outb(addr_6845+1, byte);
1821 outb(addr_6845, 0x38);
1822 outb(addr_6845+1, 0x00); /* lock registers */
1823 outb(addr_6845, 0x39);
1824 outb(addr_6845+1, 0x00); /* lock registers */
1830 sp = savearea.s3_928;
1832 outb(addr_6845, 0x00); /* Horizontal Total */
1833 outb(addr_6845+1, *sp++);
1834 outb(addr_6845, 0x01); /* Horizontal Display End */
1835 outb(addr_6845+1, *sp++);
1836 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1837 outb(addr_6845+1, *sp++);
1838 outb(addr_6845, 0x03); /* Horizontal Blank End */
1839 outb(addr_6845+1, *sp++);
1840 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1841 outb(addr_6845+1, *sp++);
1842 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1843 outb(addr_6845+1, *sp++);
1845 outb(addr_6845, 0x13); /* Row Offset Register */
1846 outb(addr_6845+1, *sp++);
1848 outb(addr_6845, 0x34);
1849 outb(addr_6845+1, *sp++);
1850 outb(addr_6845, 0x3b);
1851 outb(addr_6845+1, *sp++);
1853 outb(addr_6845, 0x42); /* Mode control */
1854 outb(addr_6845+1, *sp++);
1856 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1857 outb(TS_DATA, *sp++);
1863 /* ATC Mode control */
1864 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1865 outb(ATC_DATAW, *sp++);
1871 /* ATC Horizontal Pixel Panning */
1872 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1873 outb(ATC_DATAW, *sp++);
1875 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1878 /* disable access to first 7 CRTC registers */
1880 outb(addr_6845, CRTC_VSYNCE);
1881 outb(addr_6845+1, byte);
1883 outb(addr_6845, 0x38);
1884 outb(addr_6845+1, 0x00); /* lock registers */
1885 outb(addr_6845, 0x39);
1886 outb(addr_6845+1, 0x00); /* lock registers */
1893 /*---------------------------------------------------------------------------*
1894 * toggle 80/132 column operation for Cirrus Logic 542x based boards
1895 *---------------------------------------------------------------------------*/
1897 cl_gd542x_col(int cols)
1904 /* enable access to first 7 CRTC registers */
1906 outb(addr_6845, CRTC_VSYNCE);
1907 byte = inb(addr_6845+1);
1908 outb(addr_6845, CRTC_VSYNCE);
1909 outb(addr_6845+1, byte & 0x7f);
1911 /* enable access to cirrus extension registers */
1913 outb(TS_DATA, 0x12);
1915 if(cols == SCR_COL132) /* switch 80 -> 132 */
1917 /* save state of board for 80 columns */
1923 sp = savearea.cirrus;
1925 outb(addr_6845, 0x00); /* Horizontal Total */
1926 *sp++ = inb(addr_6845+1);
1927 outb(addr_6845, 0x01); /* Horizontal Display End */
1928 *sp++ = inb(addr_6845+1);
1929 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1930 *sp++ = inb(addr_6845+1);
1931 outb(addr_6845, 0x03); /* Horizontal Blank End */
1932 *sp++ = inb(addr_6845+1);
1933 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1934 *sp++ = inb(addr_6845+1);
1935 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1936 *sp++ = inb(addr_6845+1);
1938 outb(addr_6845, 0x13); /* Row Offset Register */
1939 *sp++ = inb(addr_6845+1);
1941 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1942 *sp++ = inb(TS_DATA);
1949 /* ATC Mode control */
1950 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1951 *sp++ = inb(ATC_DATAR);
1957 /* ATC Horizontal Pixel Panning */
1958 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1959 *sp++ = inb(ATC_DATAR);
1961 /* VCLK2 Numerator Register */
1962 outb(TS_INDEX, 0xd);
1963 *sp++ = inb(TS_DATA);
1965 /* VCLK2 Denominator and Post-Scalar Value Register */
1966 outb(TS_INDEX, 0x1d);
1967 *sp++ = inb(TS_DATA);
1969 /* Misc output register */
1970 *sp++ = inb(GN_MISCOUTR);
1973 /* setup chipset for 132 column operation */
1975 outb(addr_6845, 0x00); /* Horizontal Total */
1976 outb(addr_6845+1, 0x9f);
1977 outb(addr_6845, 0x01); /* Horizontal Display End */
1978 outb(addr_6845+1, 0x83);
1979 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1980 outb(addr_6845+1, 0x84);
1981 outb(addr_6845, 0x03); /* Horizontal Blank End */
1982 outb(addr_6845+1, 0x82);
1983 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1984 outb(addr_6845+1, 0x8a);
1985 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1986 outb(addr_6845+1, 0x9e);
1988 outb(addr_6845, 0x13); /* Row Offset Register */
1989 outb(addr_6845+1, 0x42);
1991 /* set VCLK2 to 41.164 MHz ..... */
1992 outb(TS_INDEX, 0xd); /* VCLK2 Numerator Register */
1993 outb(TS_DATA, 0x45);
1995 outb(TS_INDEX, 0x1d); /* VCLK2 Denominator and */
1996 outb(TS_DATA, 0x30); /* Post-Scalar Value Register */
1999 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | (2 << 2));
2001 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2002 outb(TS_DATA, 0x01); /* 8 dot char clock */
2008 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
2009 outb(ATC_DATAW, 0x08); /* Line graphics disable */
2015 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
2016 outb(ATC_DATAW, 0x00);
2018 else /* switch 132 -> 80 */
2020 if(!regsaved) /* failsafe */
2022 /* disable access to first 7 CRTC registers */
2023 outb(addr_6845, CRTC_VSYNCE);
2024 outb(addr_6845+1, byte);
2026 /* disable access to cirrus extension registers */
2034 sp = savearea.cirrus;
2036 outb(addr_6845, 0x00); /* Horizontal Total */
2037 outb(addr_6845+1, *sp++);
2038 outb(addr_6845, 0x01); /* Horizontal Display End */
2039 outb(addr_6845+1, *sp++);
2040 outb(addr_6845, 0x02); /* Horizontal Blank Start */
2041 outb(addr_6845+1, *sp++);
2042 outb(addr_6845, 0x03); /* Horizontal Blank End */
2043 outb(addr_6845+1, *sp++);
2044 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
2045 outb(addr_6845+1, *sp++);
2046 outb(addr_6845, 0x05); /* Horizontal Retrace End */
2047 outb(addr_6845+1, *sp++);
2049 outb(addr_6845, 0x13); /* Row Offset Register */
2050 outb(addr_6845+1, *sp++);
2052 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2053 outb(TS_DATA, *sp++);
2059 /* ATC Mode control */
2060 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
2061 outb(ATC_DATAW, *sp++);
2067 /* ATC Horizontal Pixel Panning */
2068 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
2069 outb(ATC_DATAW, *sp++);
2071 /* VCLK2 Numerator Register */
2072 outb(TS_INDEX, 0xd);
2073 outb(TS_DATA, *sp++);
2075 /* VCLK2 Denominator and Post-Scalar Value Register */
2076 outb(TS_INDEX, 0x1d);
2077 outb(TS_DATA, *sp++);
2079 outb(GN_MISCOUTW, *sp++); /* Misc output register */
2082 /* disable access to cirrus extension registers */
2086 /* disable access to first 7 CRTC registers */
2088 outb(addr_6845, CRTC_VSYNCE);
2089 outb(addr_6845+1, byte);
2096 #if PCVT_USL_VT_COMPAT
2097 /*---------------------------------------------------------------------------*
2098 * switch screen from text mode to X-mode and vice versa
2099 *---------------------------------------------------------------------------*/
2101 switch_screen(int n, int oldgrafx, int newgrafx)
2104 #if PCVT_SCREENSAVER
2105 static unsigned saved_scrnsv_tmo = 0;
2106 #endif /* PCVT_SCREENSAVER */
2110 #endif /* !PCVT_KBD_FIFO */
2112 int cols = vsp->maxcol; /* get current col val */
2114 if(n < 0 || n >= totalscreens)
2118 x = spltty(); /* protect us */
2119 #endif /* !PCVT_KBD_FIFO */
2121 if(!oldgrafx && newgrafx)
2123 /* switch from text to graphics */
2125 #if PCVT_SCREENSAVER
2126 if((saved_scrnsv_tmo = scrnsv_timeout))
2127 pcvt_set_scrnsv_tmo(0); /* screensaver off */
2128 #endif /* PCVT_SCREENSAVER */
2130 async_update(UPDATE_STOP); /* status display off */
2135 /* switch from text mode */
2137 /* video board memory -> kernel memory */
2138 bcopy(vsp->Crtat, vsp->Memory,
2139 vsp->screen_rows * vsp->maxcol * CHR);
2141 vsp->Crtat = vsp->Memory; /* operate in memory now */
2144 /* update global screen pointers/variables */
2145 current_video_screen = n; /* current screen no */
2147 #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
2148 pcconsp = &pccons[n]; /* current tty */
2149 #elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200
2150 pcconsp = pccons[n]; /* current tty */
2152 pcconsp = pc_tty[n]; /* current tty */
2155 vsp = &vs[n]; /* current video state ptr */
2157 if(oldgrafx && !newgrafx)
2159 /* switch from graphics to text mode */
2163 for(i = 0; i < totalfonts; i++)
2164 if(saved_charsets[i])
2165 vga_move_charset(i, 0, 0);
2167 #if PCVT_SCREENSAVER
2168 /* activate screen saver */
2169 if(saved_scrnsv_tmo)
2170 pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
2171 #endif /* PCVT_SCREENSAVER */
2173 /* re-initialize lost MDA information */
2174 if(adaptor_type == MDA_ADAPTOR)
2177 * Due to the fact that HGC registers are write-only,
2178 * the Xserver can only make guesses about the state
2179 * the HGC adaptor has been before turning on X mode.
2180 * Thus, the display must be re-enabled now, and the
2181 * cursor shape and location restored.
2183 outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
2184 outb(addr_6845, CRTC_CURSORH); /* select high register */
2186 ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
2187 outb(addr_6845, CRTC_CURSORL); /* select low register */
2189 ((vsp->Crtat + vsp->cur_offset) - Crtat));
2191 outb(addr_6845, CRTC_CURSTART); /* select high register */
2192 outb(addr_6845+1, vsp->cursor_start);
2193 outb(addr_6845, CRTC_CUREND); /* select low register */
2194 outb(addr_6845+1, vsp->cursor_end);
2197 /* make status display happy */
2198 async_update(UPDATE_START);
2205 /* kernel memory -> video board memory */
2206 bcopy(vsp->Crtat, Crtat,
2207 vsp->screen_rows * vsp->maxcol * CHR);
2209 vsp->Crtat = Crtat; /* operate on screen now */
2211 outb(addr_6845, CRTC_STARTADRH);
2212 outb(addr_6845+1, 0);
2213 outb(addr_6845, CRTC_STARTADRL);
2214 outb(addr_6845+1, 0);
2219 #endif /* !PCVT_KBD_FIFO */
2221 select_vga_charset(vsp->vga_charset);
2223 if(vsp->maxcol != cols)
2224 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
2226 outb(addr_6845, CRTC_CURSORH); /* select high register */
2227 outb(addr_6845+1, vsp->cur_offset >> 8);
2228 outb(addr_6845, CRTC_CURSORL); /* select low register */
2229 outb(addr_6845+1, vsp->cur_offset);
2233 outb(addr_6845, CRTC_CURSTART); /* select high register */
2234 outb(addr_6845+1, vsp->cursor_start);
2235 outb(addr_6845, CRTC_CUREND); /* select low register */
2236 outb(addr_6845+1, vsp->cursor_end);
2243 if(adaptor_type == VGA_ADAPTOR)
2247 /* switch VGA DAC palette entries */
2248 for(i = 0; i < NVGAPEL; i++)
2249 vgapaletteio(i, &vsp->palette[i], 1);
2254 update_led(); /* update led's */
2255 update_hp(vsp); /* update fkey labels, if present */
2257 /* if we switch to a vt with force 24 lines mode and */
2258 /* pure VT emulation and 25 rows charset, then we have */
2259 /* to clear the last line on display ... */
2261 if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) &&
2262 (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS))
2264 fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol,
2270 /*---------------------------------------------------------------------------*
2271 * Change specified vt to VT_AUTO mode
2272 * xxx Maybe this should also reset VT_GRAFX mode; since switching and
2273 * graphics modes are not going to work without VT_PROCESS mode.
2274 *---------------------------------------------------------------------------*/
2276 set_auto_mode (struct video_state *vsx)
2278 unsigned ostatus = vsx->vt_status;
2279 vsx->smode.mode = VT_AUTO;
2282 vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK);
2283 if (ostatus & VT_WAIT_ACK) {
2285 assert (!(ostatus&VT_WAIT_REL));
2286 assert (vsp == vsx &&
2287 vt_switch_pending == current_video_screen + 1);
2288 vt_switch_pending = 0;
2291 vt_switch_pending == current_video_screen + 1)
2292 vt_switch_pending = 0;
2295 if (ostatus&VT_WAIT_REL) {
2296 int new_screen = vt_switch_pending - 1;
2298 assert(vsp == vsx && vt_switch_pending);
2299 vt_switch_pending = 0;
2300 vgapage (new_screen);
2302 if (vsp == vsx && vt_switch_pending) {
2303 vt_switch_pending = 0;
2304 vgapage (new_screen);
2310 /*---------------------------------------------------------------------------*
2311 * Exported function; to be called when a vt is closed down.
2313 * Ideally, we would like to be able to recover from an X server crash;
2314 * but in reality, if the server crashes hard while in control of the
2315 * vga board, then you're not likely to be able to use pcvt ttys
2316 * without rebooting.
2317 *---------------------------------------------------------------------------*/
2319 reset_usl_modes (struct video_state *vsx)
2321 /* Clear graphics mode */
2322 if (vsx->vt_status & VT_GRAFX) {
2323 vsx->vt_status &= ~VT_GRAFX;
2325 switch_screen(current_video_screen, 1, 0);
2328 /* Take kbd out of raw mode */
2329 if (pcvt_kbd_raw && vsp == vsx) {
2330 #if PCVT_SCANSET > 1
2332 #endif /* PCVT_SCANSET > 1 */
2336 /* Clear process controlled mode */
2337 set_auto_mode (vsx);
2340 /*---------------------------------------------------------------------------*
2341 * switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version
2342 * (the name vgapage() stands for historical reasons)
2343 *---------------------------------------------------------------------------*/
2345 vgapage(int new_screen)
2349 if(new_screen < 0 || new_screen >= totalscreens)
2352 /* fallback to VT_AUTO if controlling processes died */
2353 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2356 if(vs[new_screen].proc
2357 && vs[new_screen].proc != pfind(vs[new_screen].pid))
2358 set_auto_mode(&vs[new_screen]);
2360 if (!vt_switch_pending && new_screen == current_video_screen)
2363 if(vt_switch_pending && vt_switch_pending != new_screen + 1) {
2364 /* Try resignaling uncooperative X-window servers */
2365 if (vsp->smode.mode == VT_PROCESS) {
2366 if (vsp->vt_status & VT_WAIT_REL) {
2367 if(vsp->smode.relsig)
2368 psignal(vsp->proc, vsp->smode.relsig);
2369 } else if (vsp->vt_status & VT_WAIT_ACK) {
2370 if(vsp->smode.acqsig)
2371 psignal(vsp->proc, vsp->smode.acqsig);
2377 vt_switch_pending = new_screen + 1;
2379 if(vsp->smode.mode == VT_PROCESS)
2381 /* we cannot switch immediately here */
2382 vsp->vt_status |= VT_WAIT_REL;
2383 if(vsp->smode.relsig)
2384 psignal(vsp->proc, vsp->smode.relsig);
2388 struct video_state *old_vsp = vsp;
2390 switch_screen(new_screen,
2391 vsp->vt_status & VT_GRAFX,
2392 vs[new_screen].vt_status & VT_GRAFX);
2396 if(old_vsp->vt_status & VT_WAIT_ACT)
2398 old_vsp->vt_status &= ~VT_WAIT_ACT;
2399 wakeup((caddr_t)&old_vsp->smode);
2402 if(vsp->vt_status & VT_WAIT_ACT)
2404 vsp->vt_status &= ~VT_WAIT_ACT;
2405 wakeup((caddr_t)&vsp->smode);
2410 if(vsp->smode.mode == VT_PROCESS)
2412 /* if _new_ vt is under process control... */
2413 vsp->vt_status |= VT_WAIT_ACK;
2414 if(vsp->smode.acqsig)
2415 psignal(vsp->proc, vsp->smode.acqsig);
2419 /* we are committed */
2420 vt_switch_pending = 0;
2422 #if PCVT_FREEBSD > 206
2424 * XXX: If pcvt is acting as the systems console,
2425 * avoid panics going to the debugger while we are in
2436 /*---------------------------------------------------------------------------*
2437 * ioctl handling for VT_USL mode
2438 *---------------------------------------------------------------------------*/
2440 usl_vt_ioctl(Dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
2442 int i, j, error, opri;
2443 struct vt_mode newmode;
2449 newmode = *(struct vt_mode *)data;
2453 if (newmode.mode != VT_PROCESS) {
2454 struct video_state *vsx = &vs[minor(dev)];
2455 if (vsx->smode.mode == VT_PROCESS) {
2456 if (vsx->proc != p) {
2467 * NB: XFree86-3.1.1 does the following:
2468 * VT_ACTIVATE (vtnum)
2469 * VT_WAITACTIVE (vtnum)
2470 * VT_SETMODE (VT_PROCESS)
2471 * So it is possible that the screen was switched
2472 * between the WAITACTIVE and the SETMODE (here). This
2473 * can actually happen quite frequently, and it was
2474 * leading to dire consequences. Now it is detected by
2475 * requiring that minor(dev) match current_video_screen.
2476 * An alternative would be to operate on vs[minor(dev)]
2477 * instead of *vsp, but that would leave the server
2478 * confused, because it would believe that its vt was
2479 * currently activated.
2481 if (minor(dev) != current_video_screen) {
2486 /* Check for server died */
2487 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2490 /* Check for server already running */
2491 if (vsp->smode.mode == VT_PROCESS && vsp->proc != p)
2494 return EBUSY; /* already in use on this VT */
2497 if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig)
2498 || !ISSIGVALID(newmode.frsig))
2504 vsp->smode = newmode;
2506 vsp->pid = p->p_pid;
2508 #if PCVT_FREEBSD > 206
2510 * XXX: If pcvt is acting as the systems console,
2511 * avoid panics going to the debugger while we are in
2515 cons_unavail = (newmode.mode == VT_PROCESS);
2521 *(struct vt_mode *)data = vsp->smode;
2525 if (minor(dev) != current_video_screen)
2527 if (vsp->smode.mode != VT_PROCESS)
2531 switch(*(int *)data) {
2533 /* process refuses to release screen; abort */
2534 if(vt_switch_pending
2535 && (vsp->vt_status & VT_WAIT_REL)) {
2536 vsp->vt_status &= ~VT_WAIT_REL;
2537 vt_switch_pending = 0;
2543 /* process releases its VT */
2544 if(vt_switch_pending
2545 && (vsp->vt_status & VT_WAIT_REL)) {
2546 int new_screen = vt_switch_pending - 1;
2547 struct video_state *old_vsp = vsp;
2549 vsp->vt_status &= ~VT_WAIT_REL;
2551 switch_screen(new_screen,
2552 vsp->vt_status & VT_GRAFX,
2553 vs[new_screen].vt_status
2557 if(old_vsp->vt_status & VT_WAIT_ACT)
2559 old_vsp->vt_status &= ~VT_WAIT_ACT;
2560 wakeup((caddr_t)&old_vsp->smode);
2562 if(vsp->vt_status & VT_WAIT_ACT)
2564 vsp->vt_status &= ~VT_WAIT_ACT;
2565 wakeup((caddr_t)&vsp->smode);
2569 if(vsp->smode.mode == VT_PROCESS) {
2571 * if the new vt is also in process
2572 * mode, we have to wait until its
2573 * controlling process acknowledged
2578 if(vsp->smode.acqsig)
2584 /* we are committed */
2585 vt_switch_pending = 0;
2586 #if PCVT_FREEBSD > 206
2597 /* new vts controlling process acknowledged */
2598 if(vsp->vt_status & VT_WAIT_ACK) {
2599 vt_switch_pending = 0;
2600 vsp->vt_status &= ~VT_WAIT_ACK;
2601 #if PCVT_FREEBSD > 206
2610 return EINVAL; /* end case VT_RELDISP */
2614 /* return free vt */
2615 for(i = 0; i < PCVT_NSCREENS; i++)
2617 *(int *)data = i + 1;
2623 *(int *)data = current_video_screen + 1;
2627 return vgapage(*(int *)data - 1);
2630 /* sleep until vt switch happened */
2631 i = *(int *)data - 1;
2634 && (i < 0 || i >= PCVT_NSCREENS))
2637 if(i != -1 && current_video_screen == i)
2646 while (current_video_screen != i &&
2647 (error == 0 || error == ERESTART))
2649 vs[i].vt_status |= VT_WAIT_ACT;
2650 error = tsleep((caddr_t)&vs[i].smode,
2651 PCATCH, "waitvt", 0);
2658 /* grant the process IO access; only allowed if euid == 0 */
2662 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2663 struct trapframe *fp = p->p_md.md_regs;
2664 #elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2665 struct trapframe *fp = (struct trapframe *)p->p_regs;
2667 struct syscframe *fp = (struct syscframe *)p->p_regs;
2670 error = suser(p->p_thread);
2673 if (securelevel > 0)
2676 #if PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2677 fp->tf_eflags |= PSL_IOPL;
2679 fp->sf_eflags |= PSL_IOPL;
2686 /* abandon IO access permission */
2689 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2690 struct trapframe *fp = p->p_md.md_regs;
2691 fp->tf_eflags &= ~PSL_IOPL;
2692 #elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2693 struct trapframe *fp = (struct trapframe *)p->p_regs;
2694 fp->tf_eflags &= ~PSL_IOPL;
2696 struct syscframe *fp = (struct syscframe *)p->p_regs;
2697 fp->sf_eflags &= ~PSL_IOPL;
2705 struct video_state *vsx = &vs[minor(dev)];
2708 if(adaptor_type != VGA_ADAPTOR
2709 && adaptor_type != MDA_ADAPTOR)
2710 /* X will only run on those adaptors */
2713 /* set text/graphics mode of current vt */
2714 switch(*(int *)data)
2717 haschanged = (vsx->vt_status & VT_GRAFX) != 0;
2718 vsx->vt_status &= ~VT_GRAFX;
2719 if(haschanged && vsx == vsp)
2720 switch_screen(current_video_screen, 1, 0);
2724 /* xxx It might be a good idea to require that
2725 the vt be in process controlled mode here,
2726 and that the calling process is the owner */
2727 haschanged = (vsx->vt_status & VT_GRAFX) == 0;
2728 vsx->vt_status |= VT_GRAFX;
2729 if(haschanged && vsx == vsp)
2730 switch_screen(current_video_screen, 0, 1);
2734 return EINVAL; /* end case KDSETMODE */
2738 /* set keyboard repeat and delay */
2739 return kbdioctl(dev, KBDSTPMAT, data, flag);
2742 switch(*(int *)data)
2746 #if PCVT_SCANSET > 1
2747 /* put keyboard to return ancient PC scan codes */
2749 #endif /* PCVT_SCANSET > 1 */
2752 shift_down = meta_down = altgr_down = ctrl_down = 0;
2757 #if PCVT_SCANSET > 1
2759 #endif /* PCVT_SCANSET > 1 */
2764 return EINVAL; /* end KDSKBMODE */
2767 /* ring the speaker */
2770 int duration = *(int *)data >> 16;
2771 int pitch = *(int *)data & 0xffff;
2776 sysbeep(PCVT_SYSBEEPF / pitch,
2777 duration * hz / 1000);
2779 #else /* PCVT_NETBSD */
2780 sysbeep(pitch, duration * hz / 3000);
2781 #endif /* PCVT_NETBSD */
2786 sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
2791 /* set kbd LED status */
2792 /* unfortunately, the LED definitions between pcvt and */
2793 /* USL differ some way :-( */
2795 j = (i & LED_CAP? KBD_CAPSLOCK: 0)
2796 + (i & LED_NUM? KBD_NUMLOCK: 0)
2797 + (i & LED_SCR? KBD_SCROLLLOCK: 0);
2798 return kbdioctl(dev, KBDSLOCK, (caddr_t)&j, flag);
2801 /* get kbd LED status */
2802 if((error = kbdioctl(dev, KBDGLOCK, (caddr_t)&j, flag)))
2804 i = (j & KBD_CAPSLOCK? LED_CAP: 0)
2805 + (j & KBD_NUMLOCK? LED_NUM: 0)
2806 + (j & KBD_SCROLLLOCK? LED_SCR: 0);
2811 get_usl_keymap((keymap_t *)data);
2813 } /* end case cmd */
2815 return -1; /* inappropriate usl_vt_compat ioctl */
2817 #endif /* PCVT_USL_VT_COMPAT */
2819 #endif /* NVT > 0 */
2821 /* ------------------------- E O F ------------------------------------------*/