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 $
49 *---------------------------------------------------------------------------*/
54 #include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
56 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
58 static int s3testwritable( void );
59 static int et4000_col( int );
60 static int wd90c11_col( int );
61 static int tri9000_col( int );
62 static int v7_1024i_col( int );
63 static int s3_928_col( int );
64 static int cl_gd542x_col( int );
66 /* storage to save video timing values of 80 columns text mode */
78 static int regsaved = 0; /* registers are saved to savearea */
80 /*---------------------------------------------------------------------------*
82 * Find out which video board we are running on, taken from:
83 * Richard Ferraro: Programmers Guide to the EGA and VGA Cards
84 * and from David E. Wexelblat's SuperProbe Version 1.0.
85 * When a board is found, for which 132 column switching is
86 * provided, the global variable "can_do_132col" is set to 1,
87 * also the global variable vga_family is set to what we found.
89 * ###############################################################
90 * ## THIS IS GETTING MORE AND MORE A LARGE SPAGHETTI HACK !!!! ##
91 * ###############################################################
93 *---------------------------------------------------------------------------*/
98 u_char byte, oldbyte, old1byte, newbyte;
101 can_do_132col = 1; /* assumes everyone can do 132 col */
103 can_do_132col = 0; /* assumes noone can do 132 col */
104 #endif /* PCVT_132GENERIC */
106 vga_family = VGA_F_NONE;
108 /*---------------------------------------------------------------------------*
109 * check for Western Digital / Paradise chipsets
110 *---------------------------------------------------------------------------*/
112 ptr = (u_char *)Crtat;
115 ptr += (0xc007d - 0xb8000);
117 ptr += (0xc007d - 0xb0000);
119 if((*ptr++ == 'V') && (*ptr++ == 'G') &&
120 (*ptr++ == 'A') && (*ptr++ == '='))
124 vga_family = VGA_F_WD;
126 outb(addr_6845, 0x2b);
127 oldbyte = inb(addr_6845+1);
128 outb(addr_6845+1, 0xaa);
129 newbyte = inb(addr_6845+1);
130 outb(addr_6845+1, oldbyte);
132 return(VGA_PVGA); /* PVGA1A chip */
134 outb(TS_INDEX, 0x12);
135 oldbyte = inb(TS_DATA);
136 outb(TS_DATA, oldbyte & 0xbf);
137 newbyte = inb(TS_DATA) & 0x40;
139 return(VGA_WD90C00); /* WD90C00 chip */
141 outb(TS_DATA, oldbyte | 0x40);
142 newbyte = inb(TS_DATA) & 0x40;
144 return(VGA_WD90C00); /* WD90C00 chip */
146 outb(TS_DATA, oldbyte);
149 outb(TS_INDEX, 0x10);
150 oldbyte = inb(TS_DATA);
152 outb(TS_DATA, oldbyte & 0xfb);
153 newbyte = inb(TS_DATA) & 0x04;
157 outb(TS_DATA, oldbyte | 0x04);
158 newbyte = inb(TS_DATA) & 0x04;
162 outb(TS_DATA, oldbyte);
173 /*---------------------------------------------------------------------------*
174 * check for Trident chipsets
175 *---------------------------------------------------------------------------*/
177 outb(TS_INDEX, 0x0b);
178 oldbyte = inb(TS_DATA);
181 outb(TS_INDEX, 0x0b);
184 byte = inb(TS_DATA); /* chipset type */
187 outb(TS_INDEX, 0x0e);
188 old1byte = inb(TS_DATA);
191 newbyte = inb(TS_DATA);
193 outb(TS_DATA, (old1byte ^ 0x02));
195 outb(TS_INDEX, 0x0b);
196 outb(TS_DATA, oldbyte);
198 if((newbyte & 0x0f) == 0x02)
200 /* is a trident chip */
202 vga_family = VGA_F_TRI;
207 return(VGA_TR8800BR);
210 return(VGA_TR8800CS);
218 /* Haven't tried, but should work */
228 return(VGA_TR8900CL);
237 return(VGA_TRUNKNOWN);
241 /*---------------------------------------------------------------------------*
242 * check for Tseng Labs ET3000/4000 chipsets
243 *---------------------------------------------------------------------------*/
245 outb(GN_HERCOMPAT, 0x06);
247 outb(GN_DMCNTLC, 0xa0);
249 outb(GN_DMCNTLM, 0xa0);
257 outb(ATC_INDEX, ATC_MISC);
258 oldbyte = inb(ATC_DATAR);
260 /* write new value */
266 outb(ATC_INDEX, ATC_MISC);
267 newbyte = oldbyte ^ 0x10;
268 outb(ATC_DATAW, newbyte);
270 /* read back new value */
275 outb(ATC_INDEX, ATC_MISC);
276 byte = inb(ATC_DATAR);
278 /* write back old value */
283 outb(ATC_INDEX, ATC_MISC);
284 outb(ATC_DATAW, oldbyte);
286 if(byte == newbyte) /* ET3000 or ET4000 */
288 vga_family = VGA_F_TSENG;
290 outb(addr_6845, CRTC_EXTSTART);
291 oldbyte = inb(addr_6845+1);
292 newbyte = oldbyte ^ 0x0f;
293 outb(addr_6845+1, newbyte);
294 byte = inb(addr_6845+1);
295 outb(addr_6845+1, oldbyte);
308 /*---------------------------------------------------------------------------*
309 * check for Video7 VGA chipsets
310 *---------------------------------------------------------------------------*/
312 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
315 outb(addr_6845, CRTC_STARTADRH);
316 oldbyte = inb(addr_6845+1);
318 outb(addr_6845+1, 0x55);
319 newbyte = inb(addr_6845+1);
321 outb(addr_6845, CRTC_V7ID); /* id register */
322 byte = inb(addr_6845+1); /* read id */
324 outb(addr_6845, CRTC_STARTADRH);
325 outb(addr_6845+1, oldbyte);
327 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
330 if(byte == (0x55 ^ 0xea))
333 vga_family = VGA_F_V7;
335 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
338 outb(TS_INDEX, TS_V7CHIPREV);
341 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
344 if(byte < 0xff && byte >= 0x80)
346 if(byte < 0x7f && byte >= 0x70)
348 if(byte < 0x5a && byte >= 0x50)
350 if(byte < 0x4a && byte > 0x40)
355 return(VGA_V7UNKNOWN);
358 /*---------------------------------------------------------------------------*
359 * check for S3 chipsets
360 *---------------------------------------------------------------------------*/
362 outb(addr_6845, 0x38); /* reg 1 lock register */
363 old1byte = inb(addr_6845+1); /* get old value */
365 outb(addr_6845, 0x38);
366 outb(addr_6845+1, 0x00); /* lock registers */
368 if(s3testwritable() == 0) /* check if locked */
370 outb(addr_6845, 0x38);
371 outb(addr_6845+1, 0x48); /* unlock registers */
373 if(s3testwritable() == 1 ) /* check if unlocked */
375 vga_family = VGA_F_S3; /* FAMILY S3 */
377 outb(addr_6845, 0x30); /* chip id/rev reg */
378 byte = inb(addr_6845+1);
386 outb(addr_6845, 0x38);
387 outb(addr_6845+1, old1byte);
391 outb(addr_6845, 0x38);
392 outb(addr_6845+1, old1byte);
396 outb(addr_6845, 0x38);
397 outb(addr_6845+1, old1byte);
398 return VGA_S3_UNKNOWN;
403 outb(addr_6845, 0x38);
404 outb(addr_6845+1, old1byte);
409 outb(addr_6845, 0x38);
410 outb(addr_6845+1, old1byte);
415 outb(addr_6845, 0x38);
416 outb(addr_6845+1, old1byte);
417 return VGA_S3_UNKNOWN;
422 /*---------------------------------------------------------------------------*
423 * check for Cirrus chipsets
424 *---------------------------------------------------------------------------*/
427 oldbyte = inb(TS_DATA);
431 newbyte = inb(TS_DATA);
432 outb(addr_6845, 0x27);
433 byte = inb(addr_6845 + 1);
435 outb(TS_DATA, oldbyte);
436 if (newbyte == 0x12) {
437 vga_family = VGA_F_CIR;
439 switch ((byte & 0xfc) >> 2) {
443 return VGA_CL_GD5402;
445 return VGA_CL_GD5402r1;
447 return VGA_CL_GD5420;
449 return VGA_CL_GD5420r1;
453 return VGA_CL_GD5422;
455 return VGA_CL_GD5424;
457 return VGA_CL_GD5426;
459 return VGA_CL_GD5428;
466 /*---------------------------------------------------------------------------
467 * test if index 35 lower nibble is writable (taken from SuperProbe 1.0)
468 *---------------------------------------------------------------------------*/
472 u_char old, new1, new2;
474 outb(addr_6845, 0x35);
475 old = inb(addr_6845+1); /* save */
477 outb(addr_6845, 0x35);
478 outb(addr_6845+1, (old & 0xf0)); /* write 0 */
480 outb(addr_6845, 0x35);
481 new1 = (inb(addr_6845+1)) & 0x0f; /* must read 0 */
483 outb(addr_6845, 0x35);
484 outb(addr_6845+1, (old | 0x0f)); /* write 1 */
486 outb(addr_6845, 0x35);
487 new2 = (inb(addr_6845+1)) & 0x0f; /* must read 1 */
489 outb(addr_6845, 0x35);
490 outb(addr_6845+1, old); /* restore */
492 return((new1==0) && (new2==0x0f));
495 /*---------------------------------------------------------------------------*
496 * return ptr to string describing vga type
497 *---------------------------------------------------------------------------*/
499 vga_string(int number)
501 static char *vga_tab[] = {
537 return(vga_tab[number]);
540 /*---------------------------------------------------------------------------*
541 * toggle vga 80/132 column operation
542 *---------------------------------------------------------------------------*/
544 vga_col(struct video_state *svsp, int cols)
548 if(adaptor_type != VGA_ADAPTOR)
554 ret = et4000_col(cols);
558 ret = wd90c11_col(cols);
565 ret = tri9000_col(cols);
569 ret = v7_1024i_col(cols);
573 ret = s3_928_col(cols);
577 case VGA_CL_GD5402r1:
579 case VGA_CL_GD5420r1:
584 ret = cl_gd542x_col(cols);
590 ret = generic_col(cols);
591 #endif /* PCVT_132GENERIC */
597 return(0); /* failed */
605 /*---------------------------------------------------------------------------*
606 * toggle 80/132 column operation for "generic" SVGAs
607 * NB: this is supposed to work on any (S)VGA as long as the monitor
608 * is able to sync down to 21.5 kHz horizontally. The resulting
609 * vertical frequency is only 50 Hz, so if there is some better board
610 * specific algorithm, we avoid using this generic one.
611 * REPORT ANY FAILURES SO WE CAN IMPROVE THIS
612 *---------------------------------------------------------------------------*/
616 * Some improved (i.e. higher scan rates) figures for the horizontal
617 * timing. USE AT YOUR OWN RISK, THIS MIGHT DAMAGE YOUR MONITOR DUE
618 * TO A LOSS OF HORIZONTAL SYNC!
619 * The figures have been tested with an ET3000 board along with a
620 * NEC MultiSync 3D monitor. If you are playing here, consider
621 * testing with several screen pictures (dark background vs. light
622 * background, even enlightening the border color may impact the
623 * result - you can do this e.g. by "scon -p black,42,42,42")
624 * Remember that all horizontal timing values must be dividable
625 * by 8! (The scheme below is taken so that nifty kernel hackers
626 * are able to patch the figures at run-time.)
628 * The actual numbers result in 23 kHz line scan and 54 Hz vertical
631 #endif /* PCVT_EXP_132COL */
634 generic_col(int cols)
641 /* stable figures for any multisync monitor that syncs down to 22 kHz*/
642 static volatile u_short htotal = 1312;
643 static volatile u_short displayend = 1056;
644 static volatile u_short blankstart = 1072;
645 static volatile u_short syncstart = 1112;
646 static volatile u_short syncend = 1280;
648 #else /* PCVT_EXP_132COL */
650 /* reduced sync-pulse width and sync delays */
651 static volatile u_short htotal = 1232;
652 static volatile u_short displayend = 1056;
653 static volatile u_short blankstart = 1056;
654 static volatile u_short syncstart = 1104;
655 static volatile u_short syncend = 1168;
657 #endif /* PCVT_EXP_132COL */
661 /* enable access to first 7 CRTC registers */
663 outb(addr_6845, CRTC_VSYNCE);
664 byte = inb(addr_6845+1);
665 outb(addr_6845, CRTC_VSYNCE);
666 outb(addr_6845+1, byte & 0x7f);
668 if(cols == SCR_COL132) /* switch 80 -> 132 */
670 /* save state of board for 80 columns */
676 sp = savearea.generic;
678 outb(addr_6845, 0x00); /* Horizontal Total */
679 *sp++ = inb(addr_6845+1);
680 outb(addr_6845, 0x01); /* Horizontal Display End */
681 *sp++ = inb(addr_6845+1);
682 outb(addr_6845, 0x02); /* Horizontal Blank Start */
683 *sp++ = inb(addr_6845+1);
684 outb(addr_6845, 0x03); /* Horizontal Blank End */
685 *sp++ = inb(addr_6845+1);
686 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
687 *sp++ = inb(addr_6845+1);
688 outb(addr_6845, 0x05); /* Horizontal Retrace End */
689 *sp++ = inb(addr_6845+1);
691 outb(addr_6845, 0x13); /* Row Offset Register */
692 *sp++ = inb(addr_6845+1);
694 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
695 *sp++ = inb(TS_DATA);
701 /* ATC Mode control */
702 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
703 *sp++ = inb(ATC_DATAR);
709 /* ATC Horizontal Pixel Panning */
710 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
711 *sp++ = inb(ATC_DATAR);
713 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
716 /* setup chipset for 132 column operation */
719 outb(addr_6845, 0x00); /* Horizontal Total */
720 outb(addr_6845+1, (htotal / 8) - 5);
721 outb(addr_6845, 0x01); /* Horizontal Display End */
722 outb(addr_6845+1, (displayend / 8) - 1);
723 outb(addr_6845, 0x02); /* Horizontal Blank Start */
724 outb(addr_6845+1, blankstart / 8);
725 outb(addr_6845, 0x03); /* Horizontal Blank End */
726 outb(addr_6845+1, ((syncend / 8) & 0x1f) | 0x80);
727 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
728 outb(addr_6845+1, syncstart / 8);
729 outb(addr_6845, 0x05); /* Horizontal Retrace End */
731 (((syncend / 8) & 0x20) * 4)
732 | ((syncend / 8) & 0x1f));
734 outb(addr_6845, 0x13); /* Row Offset Register */
735 outb(addr_6845+1, 0x42);
737 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
738 outb(TS_DATA, 0x01); /* 8 dot char clock */
744 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
745 outb(ATC_DATAW, 0x08); /* Line graphics disable */
751 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
752 outb(ATC_DATAW, 0x00);
754 /* Misc output register */
755 /* use the 28.322 MHz clock */
756 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | 4);
758 else /* switch 132 -> 80 */
760 if(!regsaved) /* failsafe */
762 /* disable access to first 7 CRTC registers */
763 outb(addr_6845, CRTC_VSYNCE);
764 outb(addr_6845+1, byte);
769 sp = savearea.generic;
771 outb(addr_6845, 0x00); /* Horizontal Total */
772 outb(addr_6845+1, *sp++);
773 outb(addr_6845, 0x01); /* Horizontal Display End */
774 outb(addr_6845+1, *sp++);
775 outb(addr_6845, 0x02); /* Horizontal Blank Start */
776 outb(addr_6845+1, *sp++);
777 outb(addr_6845, 0x03); /* Horizontal Blank End */
778 outb(addr_6845+1, *sp++);
779 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
780 outb(addr_6845+1, *sp++);
781 outb(addr_6845, 0x05); /* Horizontal Retrace End */
782 outb(addr_6845+1, *sp++);
784 outb(addr_6845, 0x13); /* Row Offset Register */
785 outb(addr_6845+1, *sp++);
787 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
788 outb(TS_DATA, *sp++);
794 /* ATC Mode control */
795 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
796 outb(ATC_DATAW, *sp++);
802 /* ATC Horizontal Pixel Panning */
803 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
804 outb(ATC_DATAW, *sp++);
806 outb(GN_MISCOUTW, *sp++); /* Misc output register */
809 /* disable access to first 7 CRTC registers */
811 outb(addr_6845, CRTC_VSYNCE);
812 outb(addr_6845+1, byte);
818 #endif /* PCVT_132GENERIC */
820 /*---------------------------------------------------------------------------*
821 * toggle 80/132 column operation for ET4000 based boards
822 *---------------------------------------------------------------------------*/
831 /* enable access to first 7 CRTC registers */
833 outb(addr_6845, CRTC_VSYNCE);
834 byte = inb(addr_6845+1);
835 outb(addr_6845, CRTC_VSYNCE);
836 outb(addr_6845+1, byte & 0x7f);
838 if(cols == SCR_COL132) /* switch 80 -> 132 */
840 /* save state of board for 80 columns */
846 sp = savearea.et4000;
848 outb(addr_6845, 0x00); /* Horizontal Total */
849 *sp++ = inb(addr_6845+1);
850 outb(addr_6845, 0x01); /* Horizontal Display End */
851 *sp++ = inb(addr_6845+1);
852 outb(addr_6845, 0x02); /* Horizontal Blank Start */
853 *sp++ = inb(addr_6845+1);
855 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
856 *sp++ = inb(addr_6845+1);
857 outb(addr_6845, 0x05); /* Horizontal Retrace End */
858 *sp++ = inb(addr_6845+1);
860 outb(addr_6845, 0x13); /* Row Offset Register */
861 *sp++ = inb(addr_6845+1);
863 outb(addr_6845, 0x34); /* 6845 Compatibility */
864 *sp++ = inb(addr_6845+1);
866 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
867 *sp++ = inb(TS_DATA);
873 /* ATC Mode control */
874 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
875 *sp++ = inb(ATC_DATAR);
881 /* ATC Horizontal Pixel Panning */
882 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
883 *sp++ = inb(ATC_DATAR);
885 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
888 /* setup chipset for 132 column operation */
890 outb(addr_6845, 0x00); /* Horizontal Total */
891 outb(addr_6845+1, 0x9f);
892 outb(addr_6845, 0x01); /* Horizontal Display End */
893 outb(addr_6845+1, 0x83);
894 outb(addr_6845, 0x02); /* Horizontal Blank Start */
895 outb(addr_6845+1, 0x84);
897 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
898 outb(addr_6845+1, 0x8b);
899 outb(addr_6845, 0x05); /* Horizontal Retrace End */
900 outb(addr_6845+1, 0x80);
902 outb(addr_6845, 0x13); /* Row Offset Register */
903 outb(addr_6845+1, 0x42);
905 outb(addr_6845, 0x34); /* 6845 Compatibility */
906 outb(addr_6845+1, 0x0a);
908 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
909 outb(TS_DATA, 0x01); /* 8 dot char clock */
915 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
916 outb(ATC_DATAW, 0x08); /* Line graphics disable */
922 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
923 outb(ATC_DATAW, 0x00);
925 /* Misc output register */
927 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c));
929 else /* switch 132 -> 80 */
931 if(!regsaved) /* failsafe */
933 /* disable access to first 7 CRTC registers */
934 outb(addr_6845, CRTC_VSYNCE);
935 outb(addr_6845+1, byte);
940 sp = savearea.et4000;
942 outb(addr_6845, 0x00); /* Horizontal Total */
943 outb(addr_6845+1, *sp++);
945 outb(addr_6845, 0x01); /* Horizontal Display End */
946 outb(addr_6845+1, *sp++);
947 outb(addr_6845, 0x02); /* Horizontal Blank Start */
948 outb(addr_6845+1, *sp++);
951 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
952 outb(addr_6845+1, *sp++);
953 outb(addr_6845, 0x05); /* Horizontal Retrace End */
954 outb(addr_6845+1, *sp++);
956 outb(addr_6845, 0x13); /* Row Offset Register */
957 outb(addr_6845+1, *sp++);
959 outb(addr_6845, 0x34); /* 6845 Compatibility */
960 outb(addr_6845+1, *sp++);
962 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
963 outb(TS_DATA, *sp++);
969 /* ATC Mode control */
970 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
971 outb(ATC_DATAW, *sp++);
977 /* ATC Horizontal Pixel Panning */
978 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
979 outb(ATC_DATAW, *sp++);
981 outb(GN_MISCOUTW, *sp++); /* Misc output register */
984 /* disable access to first 7 CRTC registers */
986 outb(addr_6845, CRTC_VSYNCE);
987 outb(addr_6845+1, byte);
994 /*---------------------------------------------------------------------------*
995 * toggle 80/132 column operation for WD/Paradise based boards
997 * when this card does 132 cols, the char map select register (TS_INDEX,
998 * TS_FONTSEL) function bits get REDEFINED. whoever did design this,
999 * please don't cross my way ever .......
1001 *---------------------------------------------------------------------------*/
1003 wd90c11_col(int cols)
1006 #if !PCVT_BACKUP_FONTS
1007 static unsigned char *sv_fontwd[NVGAFONTS];
1008 #endif /* !PCVT_BACKUP_FONTS */
1016 /* enable access to first 7 CRTC registers */
1018 outb(addr_6845, CRTC_VSYNCE);
1019 byte = inb(addr_6845+1);
1020 outb(addr_6845, CRTC_VSYNCE);
1021 outb(addr_6845+1, byte & 0x7f);
1023 /* enable access to WD/Paradise "control extensions" */
1025 outb(GDC_INDEX, GDC_PR5GPLOCK);
1026 outb(GDC_INDEX, 0x05);
1027 outb(addr_6845, CRTC_PR10);
1028 outb(addr_6845, 0x85);
1029 outb(TS_INDEX, TS_UNLOCKSEQ);
1030 outb(TS_DATA, 0x48);
1032 if(cols == SCR_COL132) /* switch 80 -> 132 */
1034 /* save state of board for 80 columns */
1040 /* save current fonts */
1042 #if !PCVT_BACKUP_FONTS
1043 for(i = 0; i < totalfonts; i++)
1048 (u_char *)malloc(32 * 256,
1052 printf("pcvt: no font buffer\n");
1064 #endif /* !PCVT_BACKUP_FONTS */
1066 sp = savearea.wd90c11;
1068 outb(addr_6845, 0x00); /* Horizontal Total */
1069 *sp++ = inb(addr_6845+1);
1070 outb(addr_6845, 0x01); /* Horizontal Display End */
1071 *sp++ = inb(addr_6845+1);
1072 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1073 *sp++ = inb(addr_6845+1);
1074 outb(addr_6845, 0x03); /* Horizontal Blank End */
1075 *sp++ = inb(addr_6845+1);
1076 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1077 *sp++ = inb(addr_6845+1);
1078 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1079 *sp++ = inb(addr_6845+1);
1081 outb(addr_6845, 0x13); /* Row Offset Register */
1082 *sp++ = inb(addr_6845+1);
1084 outb(addr_6845, 0x2e); /* misc 1 */
1085 *sp++ = inb(addr_6845+1);
1086 outb(addr_6845, 0x2f); /* misc 2 */
1087 *sp++ = inb(addr_6845+1);
1089 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1090 *sp++ = inb(TS_DATA);
1091 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1092 *sp++ = inb(TS_DATA);
1094 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1097 /* setup chipset for 132 column operation */
1099 outb(addr_6845, 0x00); /* Horizontal Total */
1100 outb(addr_6845+1, 0x9c);
1101 outb(addr_6845, 0x01); /* Horizontal Display End */
1102 outb(addr_6845+1, 0x83);
1103 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1104 outb(addr_6845+1, 0x84);
1105 outb(addr_6845, 0x03); /* Horizontal Blank End */
1106 outb(addr_6845+1, 0x9f);
1107 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1108 outb(addr_6845+1, 0x8a);
1109 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1110 outb(addr_6845+1, 0x1c);
1112 outb(addr_6845, 0x13); /* Row Offset Register */
1113 outb(addr_6845+1, 0x42);
1115 outb(addr_6845, 0x2e); /* misc 1 */
1116 outb(addr_6845+1, 0x04);
1117 outb(addr_6845, 0x2f); /* misc 2 */
1118 outb(addr_6845+1, 0x00);
1120 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1121 outb(TS_DATA, 0x21);
1122 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1123 outb(TS_DATA, 0x14);
1125 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x08)); /* Misc output register */
1129 else /* switch 132 -> 80 */
1131 if(!regsaved) /* failsafe */
1133 /* disable access to first 7 CRTC registers */
1135 outb(addr_6845, CRTC_VSYNCE);
1136 outb(addr_6845+1, byte);
1138 /* disable access to WD/Paradise "control extensions" */
1140 outb(GDC_INDEX, GDC_PR5GPLOCK);
1141 outb(GDC_INDEX, 0x00);
1142 outb(addr_6845, CRTC_PR10);
1143 outb(addr_6845, 0x00);
1144 outb(TS_INDEX, TS_UNLOCKSEQ);
1145 outb(TS_DATA, 0x00);
1152 sp = savearea.wd90c11;
1154 outb(addr_6845, 0x00); /* Horizontal Total */
1155 outb(addr_6845+1, *sp++);
1156 outb(addr_6845, 0x01); /* Horizontal Display End */
1157 outb(addr_6845+1, *sp++);
1158 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1159 outb(addr_6845+1, *sp++);
1160 outb(addr_6845, 0x03); /* Horizontal Blank End */
1161 outb(addr_6845+1, *sp++);
1162 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1163 outb(addr_6845+1, *sp++);
1164 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1165 outb(addr_6845+1, *sp++);
1167 outb(addr_6845, 0x13); /* Row Offset Register */
1168 outb(addr_6845+1, *sp++);
1170 outb(addr_6845, 0x2e); /* misc 1 */
1171 outb(addr_6845+1, *sp++);
1172 outb(addr_6845, 0x2f); /* misc 2 */
1173 outb(addr_6845+1, *sp++);
1175 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1176 outb(addr_6845+1, *sp++);
1177 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1178 outb(addr_6845+1, *sp++);
1180 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1187 #if !PCVT_BACKUP_FONTS
1188 for(i = 0; i < totalfonts; i++)
1191 vga_move_charset(i, sv_fontwd[i], 0);
1194 for(i = 0; i < totalfonts; i++)
1195 if(saved_charsets[i])
1196 vga_move_charset(i, 0, 0);
1197 #endif /* !PCVT_BACKUP_FONTS */
1199 select_vga_charset(vsp->vga_charset);
1201 /* disable access to first 7 CRTC registers */
1203 outb(addr_6845, CRTC_VSYNCE);
1204 outb(addr_6845+1, byte);
1206 /* disable access to WD/Paradise "control extensions" */
1208 outb(GDC_INDEX, GDC_PR5GPLOCK);
1209 outb(GDC_INDEX, 0x00);
1210 outb(addr_6845, CRTC_PR10);
1211 outb(addr_6845, 0x00);
1212 outb(TS_INDEX, TS_UNLOCKSEQ);
1213 outb(TS_DATA, 0x00);
1220 /*---------------------------------------------------------------------------*
1221 * toggle 80/132 column operation for TRIDENT 9000 based boards
1222 *---------------------------------------------------------------------------*/
1224 tri9000_col(int cols)
1231 /* sync reset is necessary to preserve memory contents ... */
1233 outb(TS_INDEX, TS_SYNCRESET);
1234 outb(TS_DATA, 0x01); /* synchronous reset */
1236 /* disable protection of misc out and other regs */
1238 outb(addr_6845, CRTC_MTEST);
1239 byte = inb(addr_6845+1);
1240 outb(addr_6845, CRTC_MTEST);
1241 outb(addr_6845+1, byte & ~0x50);
1243 /* enable access to first 7 CRTC registers */
1245 outb(addr_6845, CRTC_VSYNCE);
1246 byte = inb(addr_6845+1);
1247 outb(addr_6845, CRTC_VSYNCE);
1248 outb(addr_6845+1, byte & 0x7f);
1250 if(cols == SCR_COL132) /* switch 80 -> 132 */
1252 /* save state of board for 80 columns */
1258 sp = savearea.tri9000;
1260 outb(addr_6845, 0x00); /* Horizontal Total */
1261 *sp++ = inb(addr_6845+1);
1262 outb(addr_6845, 0x01); /* Horizontal Display End */
1263 *sp++ = inb(addr_6845+1);
1264 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1265 *sp++ = inb(addr_6845+1);
1266 outb(addr_6845, 0x03); /* Horizontal Blank End */
1267 *sp++ = inb(addr_6845+1);
1268 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1269 *sp++ = inb(addr_6845+1);
1270 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1271 *sp++ = inb(addr_6845+1);
1273 outb(addr_6845, 0x13);
1274 *sp++ = inb(addr_6845+1);
1276 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1277 *sp++ = inb(TS_DATA);
1279 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1280 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1281 outb(TS_INDEX, TS_MODEC2);
1282 *sp++ = inb(TS_DATA);
1284 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1285 inb(TS_DATA); /* read switches to NEW */
1286 outb(TS_INDEX, TS_MODEC2);
1287 *sp++ = inb(TS_DATA);
1293 /* ATC Mode control */
1294 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1295 *sp++ = inb(ATC_DATAR);
1301 /* ATC Horizontal Pixel Panning */
1302 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1303 *sp++ = inb(ATC_DATAR);
1305 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1308 /* setup chipset for 132 column operation */
1310 outb(addr_6845, 0x00); /* Horizontal Total */
1311 outb(addr_6845+1, 0x9b);
1312 outb(addr_6845, 0x01); /* Horizontal Display End */
1313 outb(addr_6845+1, 0x83);
1314 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1315 outb(addr_6845+1, 0x84);
1316 outb(addr_6845, 0x03); /* Horizontal Blank End */
1317 outb(addr_6845+1, 0x1e);
1318 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1319 outb(addr_6845+1, 0x87);
1320 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1321 outb(addr_6845+1, 0x1a);
1323 outb(addr_6845, 0x13); /* Row Offset Register */
1324 outb(addr_6845+1, 0x42);
1326 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1327 outb(TS_DATA, 0x01); /* 8 dot char clock */
1329 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1330 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1331 outb(TS_INDEX, TS_MODEC2);
1332 outb(TS_DATA, 0x00);
1334 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1335 inb(TS_DATA); /* read switches to NEW */
1336 outb(TS_INDEX, TS_MODEC2);
1337 outb(TS_DATA, 0x01);
1343 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1344 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1350 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1351 outb(ATC_DATAW, 0x00);
1353 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c)); /* Misc output register */
1355 else /* switch 132 -> 80 */
1357 if(!regsaved) /* failsafe */
1359 /* disable access to first 7 CRTC registers */
1360 outb(addr_6845, CRTC_VSYNCE);
1361 outb(addr_6845+1, byte);
1363 outb(TS_INDEX, TS_SYNCRESET);
1364 outb(TS_DATA, 0x03); /* clear synchronous reset */
1371 sp = savearea.tri9000;
1373 outb(addr_6845, 0x00); /* Horizontal Total */
1374 outb(addr_6845+1, *sp++);
1375 outb(addr_6845, 0x01); /* Horizontal Display End */
1376 outb(addr_6845+1, *sp++);
1377 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1378 outb(addr_6845+1, *sp++);
1379 outb(addr_6845, 0x03); /* Horizontal Blank End */
1380 outb(addr_6845+1, *sp++);
1381 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1382 outb(addr_6845+1, *sp++);
1383 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1384 outb(addr_6845+1, *sp++);
1386 outb(addr_6845, 0x13); /* Row Offset Register */
1387 outb(addr_6845+1, *sp++);
1389 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1390 outb(TS_DATA, *sp++);
1392 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1393 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1394 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1395 outb(TS_DATA, *sp++);
1397 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1398 inb(TS_DATA); /* read switches to NEW */
1399 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1400 outb(TS_DATA, *sp++);
1406 /* ATC Mode control */
1407 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1408 outb(ATC_DATAW, *sp++);
1414 /* ATC Horizontal Pixel Panning */
1415 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1416 outb(ATC_DATAW, *sp++);
1418 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1421 /* disable access to first 7 CRTC registers */
1423 outb(addr_6845, CRTC_VSYNCE);
1424 outb(addr_6845+1, byte);
1426 outb(TS_INDEX, TS_SYNCRESET);
1427 outb(TS_DATA, 0x03); /* clear synchronous reset */
1434 /*---------------------------------------------------------------------------*
1435 * toggle 80/132 column operation for Video7 VGA 1024i
1436 *---------------------------------------------------------------------------*/
1438 v7_1024i_col(int cols)
1446 /* enable access to first 7 CRTC registers */
1448 /* first, enable read access to vertical retrace start/end */
1449 outb(addr_6845, CRTC_HBLANKE);
1450 byte = inb(addr_6845+1);
1451 outb(addr_6845, CRTC_HBLANKE);
1452 outb(addr_6845+1, (byte | 0x80));
1454 /* second, enable access to protected registers */
1455 outb(addr_6845, CRTC_VSYNCE);
1456 save__byte = byte = inb(addr_6845+1);
1457 byte |= 0x20; /* no irq 2 */
1458 byte &= 0x6f; /* wr enable, clr irq flag */
1459 outb(addr_6845, CRTC_VSYNCE);
1460 outb(addr_6845+1, byte);
1462 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
1463 outb(TS_DATA, 0xea);
1466 if(cols == SCR_COL132) /* switch 80 -> 132 */
1468 /* save state of board for 80 columns */
1474 sp = savearea.v7_1024i;
1476 outb(addr_6845, 0x00); /* Horizontal Total */
1477 *sp++ = inb(addr_6845+1);
1478 outb(addr_6845, 0x01); /* Horizontal Display End */
1479 *sp++ = inb(addr_6845+1);
1480 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1481 *sp++ = inb(addr_6845+1);
1482 outb(addr_6845, 0x03); /* Horizontal Blank End */
1483 *sp++ = inb(addr_6845+1);
1484 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1485 *sp++ = inb(addr_6845+1);
1486 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1487 *sp++ = inb(addr_6845+1);
1489 outb(addr_6845, 0x13); /* Row Offset Register */
1490 *sp++ = inb(addr_6845+1);
1492 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1493 *sp++ = inb(TS_DATA);
1499 /* ATC Mode control */
1500 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1501 *sp++ = inb(ATC_DATAR);
1507 /* ATC Horizontal Pixel Panning */
1508 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1509 *sp++ = inb(ATC_DATAR);
1511 outb(TS_INDEX, 0x83);
1512 *sp++ = inb(TS_DATA);
1514 outb(TS_INDEX, 0xa4);
1515 *sp++ = inb(TS_DATA);
1517 outb(TS_INDEX, 0xe0);
1518 *sp++ = inb(TS_DATA);
1520 outb(TS_INDEX, 0xe4);
1521 *sp++ = inb(TS_DATA);
1523 outb(TS_INDEX, 0xf8);
1524 *sp++ = inb(TS_DATA);
1526 outb(TS_INDEX, 0xfd);
1527 *sp++ = inb(TS_DATA);
1529 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1532 /* setup chipset for 132 column operation */
1534 outb(addr_6845, 0x00); /* Horizontal Total */
1535 outb(addr_6845+1, 0x9c);
1536 outb(addr_6845, 0x01); /* Horizontal Display End */
1537 outb(addr_6845+1, 0x83);
1538 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1539 outb(addr_6845+1, 0x86);
1540 outb(addr_6845, 0x03); /* Horizontal Blank End */
1541 outb(addr_6845+1, 0x9e);
1542 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1543 outb(addr_6845+1, 0x89);
1544 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1545 outb(addr_6845+1, 0x1c);
1547 outb(addr_6845, 0x13); /* Row Offset Register */
1548 outb(addr_6845+1, 0x42);
1550 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1551 outb(TS_DATA, 0x01); /* 8 dot char clock */
1557 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1558 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1564 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1565 outb(ATC_DATAW, 0x00);
1567 outb(TS_INDEX, TS_SYNCRESET);
1568 outb(TS_DATA, 0x01); /* synchronous reset */
1570 outb(TS_INDEX, 0x83);
1571 outb(TS_DATA, 0xa0);
1573 outb(TS_INDEX, 0xa4);
1574 outb(TS_DATA, 0x1c);
1576 outb(TS_INDEX, 0xe0);
1577 outb(TS_DATA, 0x00);
1579 outb(TS_INDEX, 0xe4);
1580 outb(TS_DATA, 0xfe);
1582 outb(TS_INDEX, 0xf8);
1583 outb(TS_DATA, 0x1b);
1585 outb(TS_INDEX, 0xfd);
1586 outb(TS_DATA, 0x33);
1588 byte = inb(GN_MISCOUTR);
1590 outb(GN_MISCOUTW, byte); /* Misc output register */
1592 outb(TS_INDEX, TS_SYNCRESET);
1593 outb(TS_DATA, 0x03); /* clear synchronous reset */
1595 else /* switch 132 -> 80 */
1597 if(!regsaved) /* failsafe */
1599 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1600 outb(TS_DATA, 0xae);
1602 /* disable access to first 7 CRTC registers */
1603 outb(addr_6845, CRTC_VSYNCE);
1604 outb(addr_6845+1, byte);
1609 sp = savearea.v7_1024i;
1611 outb(addr_6845, 0x00); /* Horizontal Total */
1612 outb(addr_6845+1, *sp++);
1613 outb(addr_6845, 0x01); /* Horizontal Display End */
1614 outb(addr_6845+1, *sp++);
1615 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1616 outb(addr_6845+1, *sp++);
1617 outb(addr_6845, 0x03); /* Horizontal Blank End */
1618 outb(addr_6845+1, *sp++);
1619 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1620 outb(addr_6845+1, *sp++);
1621 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1622 outb(addr_6845+1, *sp++);
1624 outb(addr_6845, 0x13); /* Row Offset Register */
1625 outb(addr_6845+1, *sp++);
1627 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1628 outb(TS_DATA, *sp++);
1634 /* ATC Mode control */
1635 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1636 outb(ATC_DATAW, *sp++);
1642 /* ATC Horizontal Pixel Panning */
1643 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1644 outb(ATC_DATAW, *sp++);
1646 outb(TS_INDEX, TS_SYNCRESET);
1647 outb(TS_DATA, 0x01); /* synchronous reset */
1649 outb(TS_INDEX, 0x83);
1650 outb(TS_DATA, *sp++);
1652 outb(TS_INDEX, 0xa4);
1653 outb(TS_DATA, *sp++);
1655 outb(TS_INDEX, 0xe0);
1656 outb(TS_DATA, *sp++);
1658 outb(TS_INDEX, 0xe4);
1659 outb(TS_DATA, *sp++);
1661 outb(TS_INDEX, 0xf8);
1662 outb(TS_DATA, *sp++);
1664 outb(TS_INDEX, 0xfd);
1665 outb(TS_DATA, *sp++);
1667 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1669 outb(TS_INDEX, TS_SYNCRESET);
1670 outb(TS_DATA, 0x03); /* clear synchronous reset */
1673 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1674 outb(TS_DATA, 0xae);
1676 /* disable access to first 7 CRTC registers */
1678 outb(addr_6845, CRTC_VSYNCE);
1679 outb(addr_6845+1, save__byte);
1686 /*---------------------------------------------------------------------------*
1687 * toggle 80/132 column operation for S3 86C928 based boards
1688 *---------------------------------------------------------------------------*/
1690 s3_928_col(int cols)
1697 outb(addr_6845, 0x38);
1698 outb(addr_6845+1, 0x48); /* unlock registers */
1699 outb(addr_6845, 0x39);
1700 outb(addr_6845+1, 0xa0); /* unlock registers */
1702 /* enable access to first 7 CRTC registers */
1704 outb(addr_6845, CRTC_VSYNCE);
1705 byte = inb(addr_6845+1);
1706 outb(addr_6845, CRTC_VSYNCE);
1707 outb(addr_6845+1, byte & 0x7f);
1709 if(cols == SCR_COL132) /* switch 80 -> 132 */
1711 /* save state of board for 80 columns */
1717 sp = savearea.s3_928;
1719 outb(addr_6845, 0x00); /* Horizontal Total */
1720 *sp++ = inb(addr_6845+1);
1721 outb(addr_6845, 0x01); /* Horizontal Display End */
1722 *sp++ = inb(addr_6845+1);
1723 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1724 *sp++ = inb(addr_6845+1);
1725 outb(addr_6845, 0x03); /* Horizontal Blank End */
1726 *sp++ = inb(addr_6845+1);
1727 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1728 *sp++ = inb(addr_6845+1);
1729 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1730 *sp++ = inb(addr_6845+1);
1732 outb(addr_6845, 0x13); /* Row Offset Register */
1733 *sp++ = inb(addr_6845+1);
1735 outb(addr_6845, 0x34); /* Backward Compat 3 Reg */
1736 *sp++ = inb(addr_6845+1);
1737 outb(addr_6845, 0x3b); /* Data Xfer Exec Position */
1738 *sp++ = inb(addr_6845+1);
1740 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1741 *sp++ = inb(addr_6845+1);
1743 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1744 *sp++ = inb(TS_DATA);
1750 /* ATC Mode control */
1751 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1752 *sp++ = inb(ATC_DATAR);
1758 /* ATC Horizontal Pixel Panning */
1759 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1760 *sp++ = inb(ATC_DATAR);
1762 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1765 /* setup chipset for 132 column operation */
1767 outb(addr_6845, 0x00); /* Horizontal Total */
1768 outb(addr_6845+1, 0x9a);
1769 outb(addr_6845, 0x01); /* Horizontal Display End */
1770 outb(addr_6845+1, 0x83);
1771 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1772 outb(addr_6845+1, 0x86);
1773 outb(addr_6845, 0x03); /* Horizontal Blank End */
1774 outb(addr_6845+1, 0x9d);
1775 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1776 outb(addr_6845+1, 0x87);
1777 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1778 outb(addr_6845+1, 0x1b);
1780 outb(addr_6845, 0x13); /* Row Offset Register */
1781 outb(addr_6845+1, 0x42);
1783 outb(addr_6845, 0x34);
1784 outb(addr_6845+1, 0x10);/* enable data xfer pos control */
1785 outb(addr_6845, 0x3b);
1786 outb(addr_6845+1, 0x90);/* set data xfer pos value */
1788 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1789 outb(addr_6845+1, 0x02);/* Select 40MHz Clock */
1791 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1792 outb(TS_DATA, 0x01); /* 8 dot char clock */
1798 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1799 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1805 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1806 outb(ATC_DATAW, 0x00);
1808 /* Misc output register */
1810 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c));
1812 else /* switch 132 -> 80 */
1814 if(!regsaved) /* failsafe */
1816 /* disable access to first 7 CRTC registers */
1817 outb(addr_6845, CRTC_VSYNCE);
1818 outb(addr_6845+1, byte);
1820 outb(addr_6845, 0x38);
1821 outb(addr_6845+1, 0x00); /* lock registers */
1822 outb(addr_6845, 0x39);
1823 outb(addr_6845+1, 0x00); /* lock registers */
1829 sp = savearea.s3_928;
1831 outb(addr_6845, 0x00); /* Horizontal Total */
1832 outb(addr_6845+1, *sp++);
1833 outb(addr_6845, 0x01); /* Horizontal Display End */
1834 outb(addr_6845+1, *sp++);
1835 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1836 outb(addr_6845+1, *sp++);
1837 outb(addr_6845, 0x03); /* Horizontal Blank End */
1838 outb(addr_6845+1, *sp++);
1839 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1840 outb(addr_6845+1, *sp++);
1841 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1842 outb(addr_6845+1, *sp++);
1844 outb(addr_6845, 0x13); /* Row Offset Register */
1845 outb(addr_6845+1, *sp++);
1847 outb(addr_6845, 0x34);
1848 outb(addr_6845+1, *sp++);
1849 outb(addr_6845, 0x3b);
1850 outb(addr_6845+1, *sp++);
1852 outb(addr_6845, 0x42); /* Mode control */
1853 outb(addr_6845+1, *sp++);
1855 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1856 outb(TS_DATA, *sp++);
1862 /* ATC Mode control */
1863 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1864 outb(ATC_DATAW, *sp++);
1870 /* ATC Horizontal Pixel Panning */
1871 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1872 outb(ATC_DATAW, *sp++);
1874 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1877 /* disable access to first 7 CRTC registers */
1879 outb(addr_6845, CRTC_VSYNCE);
1880 outb(addr_6845+1, byte);
1882 outb(addr_6845, 0x38);
1883 outb(addr_6845+1, 0x00); /* lock registers */
1884 outb(addr_6845, 0x39);
1885 outb(addr_6845+1, 0x00); /* lock registers */
1892 /*---------------------------------------------------------------------------*
1893 * toggle 80/132 column operation for Cirrus Logic 542x based boards
1894 *---------------------------------------------------------------------------*/
1896 cl_gd542x_col(int cols)
1903 /* enable access to first 7 CRTC registers */
1905 outb(addr_6845, CRTC_VSYNCE);
1906 byte = inb(addr_6845+1);
1907 outb(addr_6845, CRTC_VSYNCE);
1908 outb(addr_6845+1, byte & 0x7f);
1910 /* enable access to cirrus extension registers */
1912 outb(TS_DATA, 0x12);
1914 if(cols == SCR_COL132) /* switch 80 -> 132 */
1916 /* save state of board for 80 columns */
1922 sp = savearea.cirrus;
1924 outb(addr_6845, 0x00); /* Horizontal Total */
1925 *sp++ = inb(addr_6845+1);
1926 outb(addr_6845, 0x01); /* Horizontal Display End */
1927 *sp++ = inb(addr_6845+1);
1928 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1929 *sp++ = inb(addr_6845+1);
1930 outb(addr_6845, 0x03); /* Horizontal Blank End */
1931 *sp++ = inb(addr_6845+1);
1932 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1933 *sp++ = inb(addr_6845+1);
1934 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1935 *sp++ = inb(addr_6845+1);
1937 outb(addr_6845, 0x13); /* Row Offset Register */
1938 *sp++ = inb(addr_6845+1);
1940 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1941 *sp++ = inb(TS_DATA);
1948 /* ATC Mode control */
1949 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1950 *sp++ = inb(ATC_DATAR);
1956 /* ATC Horizontal Pixel Panning */
1957 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1958 *sp++ = inb(ATC_DATAR);
1960 /* VCLK2 Numerator Register */
1961 outb(TS_INDEX, 0xd);
1962 *sp++ = inb(TS_DATA);
1964 /* VCLK2 Denominator and Post-Scalar Value Register */
1965 outb(TS_INDEX, 0x1d);
1966 *sp++ = inb(TS_DATA);
1968 /* Misc output register */
1969 *sp++ = inb(GN_MISCOUTR);
1972 /* setup chipset for 132 column operation */
1974 outb(addr_6845, 0x00); /* Horizontal Total */
1975 outb(addr_6845+1, 0x9f);
1976 outb(addr_6845, 0x01); /* Horizontal Display End */
1977 outb(addr_6845+1, 0x83);
1978 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1979 outb(addr_6845+1, 0x84);
1980 outb(addr_6845, 0x03); /* Horizontal Blank End */
1981 outb(addr_6845+1, 0x82);
1982 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1983 outb(addr_6845+1, 0x8a);
1984 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1985 outb(addr_6845+1, 0x9e);
1987 outb(addr_6845, 0x13); /* Row Offset Register */
1988 outb(addr_6845+1, 0x42);
1990 /* set VCLK2 to 41.164 MHz ..... */
1991 outb(TS_INDEX, 0xd); /* VCLK2 Numerator Register */
1992 outb(TS_DATA, 0x45);
1994 outb(TS_INDEX, 0x1d); /* VCLK2 Denominator and */
1995 outb(TS_DATA, 0x30); /* Post-Scalar Value Register */
1998 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | (2 << 2));
2000 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2001 outb(TS_DATA, 0x01); /* 8 dot char clock */
2007 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
2008 outb(ATC_DATAW, 0x08); /* Line graphics disable */
2014 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
2015 outb(ATC_DATAW, 0x00);
2017 else /* switch 132 -> 80 */
2019 if(!regsaved) /* failsafe */
2021 /* disable access to first 7 CRTC registers */
2022 outb(addr_6845, CRTC_VSYNCE);
2023 outb(addr_6845+1, byte);
2025 /* disable access to cirrus extension registers */
2033 sp = savearea.cirrus;
2035 outb(addr_6845, 0x00); /* Horizontal Total */
2036 outb(addr_6845+1, *sp++);
2037 outb(addr_6845, 0x01); /* Horizontal Display End */
2038 outb(addr_6845+1, *sp++);
2039 outb(addr_6845, 0x02); /* Horizontal Blank Start */
2040 outb(addr_6845+1, *sp++);
2041 outb(addr_6845, 0x03); /* Horizontal Blank End */
2042 outb(addr_6845+1, *sp++);
2043 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
2044 outb(addr_6845+1, *sp++);
2045 outb(addr_6845, 0x05); /* Horizontal Retrace End */
2046 outb(addr_6845+1, *sp++);
2048 outb(addr_6845, 0x13); /* Row Offset Register */
2049 outb(addr_6845+1, *sp++);
2051 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2052 outb(TS_DATA, *sp++);
2058 /* ATC Mode control */
2059 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
2060 outb(ATC_DATAW, *sp++);
2066 /* ATC Horizontal Pixel Panning */
2067 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
2068 outb(ATC_DATAW, *sp++);
2070 /* VCLK2 Numerator Register */
2071 outb(TS_INDEX, 0xd);
2072 outb(TS_DATA, *sp++);
2074 /* VCLK2 Denominator and Post-Scalar Value Register */
2075 outb(TS_INDEX, 0x1d);
2076 outb(TS_DATA, *sp++);
2078 outb(GN_MISCOUTW, *sp++); /* Misc output register */
2081 /* disable access to cirrus extension registers */
2085 /* disable access to first 7 CRTC registers */
2087 outb(addr_6845, CRTC_VSYNCE);
2088 outb(addr_6845+1, byte);
2095 #if PCVT_USL_VT_COMPAT
2096 /*---------------------------------------------------------------------------*
2097 * switch screen from text mode to X-mode and vice versa
2098 *---------------------------------------------------------------------------*/
2100 switch_screen(int n, int oldgrafx, int newgrafx)
2103 #if PCVT_SCREENSAVER
2104 static unsigned saved_scrnsv_tmo = 0;
2105 #endif /* PCVT_SCREENSAVER */
2109 #endif /* !PCVT_KBD_FIFO */
2111 int cols = vsp->maxcol; /* get current col val */
2113 if(n < 0 || n >= totalscreens)
2117 x = spltty(); /* protect us */
2118 #endif /* !PCVT_KBD_FIFO */
2120 if(!oldgrafx && newgrafx)
2122 /* switch from text to graphics */
2124 #if PCVT_SCREENSAVER
2125 if((saved_scrnsv_tmo = scrnsv_timeout))
2126 pcvt_set_scrnsv_tmo(0); /* screensaver off */
2127 #endif /* PCVT_SCREENSAVER */
2129 async_update(UPDATE_STOP); /* status display off */
2134 /* switch from text mode */
2136 /* video board memory -> kernel memory */
2137 bcopy(vsp->Crtat, vsp->Memory,
2138 vsp->screen_rows * vsp->maxcol * CHR);
2140 vsp->Crtat = vsp->Memory; /* operate in memory now */
2143 /* update global screen pointers/variables */
2144 current_video_screen = n; /* current screen no */
2146 #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
2147 pcconsp = &pccons[n]; /* current tty */
2148 #elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200
2149 pcconsp = pccons[n]; /* current tty */
2151 pcconsp = pc_tty[n]; /* current tty */
2154 vsp = &vs[n]; /* current video state ptr */
2156 if(oldgrafx && !newgrafx)
2158 /* switch from graphics to text mode */
2162 for(i = 0; i < totalfonts; i++)
2163 if(saved_charsets[i])
2164 vga_move_charset(i, 0, 0);
2166 #if PCVT_SCREENSAVER
2167 /* activate screen saver */
2168 if(saved_scrnsv_tmo)
2169 pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
2170 #endif /* PCVT_SCREENSAVER */
2172 /* re-initialize lost MDA information */
2173 if(adaptor_type == MDA_ADAPTOR)
2176 * Due to the fact that HGC registers are write-only,
2177 * the Xserver can only make guesses about the state
2178 * the HGC adaptor has been before turning on X mode.
2179 * Thus, the display must be re-enabled now, and the
2180 * cursor shape and location restored.
2182 outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
2183 outb(addr_6845, CRTC_CURSORH); /* select high register */
2185 ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
2186 outb(addr_6845, CRTC_CURSORL); /* select low register */
2188 ((vsp->Crtat + vsp->cur_offset) - Crtat));
2190 outb(addr_6845, CRTC_CURSTART); /* select high register */
2191 outb(addr_6845+1, vsp->cursor_start);
2192 outb(addr_6845, CRTC_CUREND); /* select low register */
2193 outb(addr_6845+1, vsp->cursor_end);
2196 /* make status display happy */
2197 async_update(UPDATE_START);
2204 /* kernel memory -> video board memory */
2205 bcopy(vsp->Crtat, Crtat,
2206 vsp->screen_rows * vsp->maxcol * CHR);
2208 vsp->Crtat = Crtat; /* operate on screen now */
2210 outb(addr_6845, CRTC_STARTADRH);
2211 outb(addr_6845+1, 0);
2212 outb(addr_6845, CRTC_STARTADRL);
2213 outb(addr_6845+1, 0);
2218 #endif /* !PCVT_KBD_FIFO */
2220 select_vga_charset(vsp->vga_charset);
2222 if(vsp->maxcol != cols)
2223 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
2225 outb(addr_6845, CRTC_CURSORH); /* select high register */
2226 outb(addr_6845+1, vsp->cur_offset >> 8);
2227 outb(addr_6845, CRTC_CURSORL); /* select low register */
2228 outb(addr_6845+1, vsp->cur_offset);
2232 outb(addr_6845, CRTC_CURSTART); /* select high register */
2233 outb(addr_6845+1, vsp->cursor_start);
2234 outb(addr_6845, CRTC_CUREND); /* select low register */
2235 outb(addr_6845+1, vsp->cursor_end);
2242 if(adaptor_type == VGA_ADAPTOR)
2246 /* switch VGA DAC palette entries */
2247 for(i = 0; i < NVGAPEL; i++)
2248 vgapaletteio(i, &vsp->palette[i], 1);
2253 update_led(); /* update led's */
2254 update_hp(vsp); /* update fkey labels, if present */
2256 /* if we switch to a vt with force 24 lines mode and */
2257 /* pure VT emulation and 25 rows charset, then we have */
2258 /* to clear the last line on display ... */
2260 if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) &&
2261 (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS))
2263 fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol,
2269 /*---------------------------------------------------------------------------*
2270 * Change specified vt to VT_AUTO mode
2271 * xxx Maybe this should also reset VT_GRAFX mode; since switching and
2272 * graphics modes are not going to work without VT_PROCESS mode.
2273 *---------------------------------------------------------------------------*/
2275 set_auto_mode (struct video_state *vsx)
2277 unsigned ostatus = vsx->vt_status;
2278 vsx->smode.mode = VT_AUTO;
2281 vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK);
2282 if (ostatus & VT_WAIT_ACK) {
2284 assert (!(ostatus&VT_WAIT_REL));
2285 assert (vsp == vsx &&
2286 vt_switch_pending == current_video_screen + 1);
2287 vt_switch_pending = 0;
2290 vt_switch_pending == current_video_screen + 1)
2291 vt_switch_pending = 0;
2294 if (ostatus&VT_WAIT_REL) {
2295 int new_screen = vt_switch_pending - 1;
2297 assert(vsp == vsx && vt_switch_pending);
2298 vt_switch_pending = 0;
2299 vgapage (new_screen);
2301 if (vsp == vsx && vt_switch_pending) {
2302 vt_switch_pending = 0;
2303 vgapage (new_screen);
2309 /*---------------------------------------------------------------------------*
2310 * Exported function; to be called when a vt is closed down.
2312 * Ideally, we would like to be able to recover from an X server crash;
2313 * but in reality, if the server crashes hard while in control of the
2314 * vga board, then you're not likely to be able to use pcvt ttys
2315 * without rebooting.
2316 *---------------------------------------------------------------------------*/
2318 reset_usl_modes (struct video_state *vsx)
2320 /* Clear graphics mode */
2321 if (vsx->vt_status & VT_GRAFX) {
2322 vsx->vt_status &= ~VT_GRAFX;
2324 switch_screen(current_video_screen, 1, 0);
2327 /* Take kbd out of raw mode */
2328 if (pcvt_kbd_raw && vsp == vsx) {
2329 #if PCVT_SCANSET > 1
2331 #endif /* PCVT_SCANSET > 1 */
2335 /* Clear process controlled mode */
2336 set_auto_mode (vsx);
2339 /*---------------------------------------------------------------------------*
2340 * switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version
2341 * (the name vgapage() stands for historical reasons)
2342 *---------------------------------------------------------------------------*/
2344 vgapage(int new_screen)
2348 if(new_screen < 0 || new_screen >= totalscreens)
2351 /* fallback to VT_AUTO if controlling processes died */
2352 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2355 if(vs[new_screen].proc
2356 && vs[new_screen].proc != pfind(vs[new_screen].pid))
2357 set_auto_mode(&vs[new_screen]);
2359 if (!vt_switch_pending && new_screen == current_video_screen)
2362 if(vt_switch_pending && vt_switch_pending != new_screen + 1) {
2363 /* Try resignaling uncooperative X-window servers */
2364 if (vsp->smode.mode == VT_PROCESS) {
2365 if (vsp->vt_status & VT_WAIT_REL) {
2366 if(vsp->smode.relsig)
2367 psignal(vsp->proc, vsp->smode.relsig);
2368 } else if (vsp->vt_status & VT_WAIT_ACK) {
2369 if(vsp->smode.acqsig)
2370 psignal(vsp->proc, vsp->smode.acqsig);
2376 vt_switch_pending = new_screen + 1;
2378 if(vsp->smode.mode == VT_PROCESS)
2380 /* we cannot switch immediately here */
2381 vsp->vt_status |= VT_WAIT_REL;
2382 if(vsp->smode.relsig)
2383 psignal(vsp->proc, vsp->smode.relsig);
2387 struct video_state *old_vsp = vsp;
2389 switch_screen(new_screen,
2390 vsp->vt_status & VT_GRAFX,
2391 vs[new_screen].vt_status & VT_GRAFX);
2395 if(old_vsp->vt_status & VT_WAIT_ACT)
2397 old_vsp->vt_status &= ~VT_WAIT_ACT;
2398 wakeup((caddr_t)&old_vsp->smode);
2401 if(vsp->vt_status & VT_WAIT_ACT)
2403 vsp->vt_status &= ~VT_WAIT_ACT;
2404 wakeup((caddr_t)&vsp->smode);
2409 if(vsp->smode.mode == VT_PROCESS)
2411 /* if _new_ vt is under process control... */
2412 vsp->vt_status |= VT_WAIT_ACK;
2413 if(vsp->smode.acqsig)
2414 psignal(vsp->proc, vsp->smode.acqsig);
2418 /* we are committed */
2419 vt_switch_pending = 0;
2421 #if PCVT_FREEBSD > 206
2423 * XXX: If pcvt is acting as the systems console,
2424 * avoid panics going to the debugger while we are in
2435 /*---------------------------------------------------------------------------*
2436 * ioctl handling for VT_USL mode
2437 *---------------------------------------------------------------------------*/
2439 usl_vt_ioctl(Dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
2441 int i, j, error, opri;
2442 struct vt_mode newmode;
2448 newmode = *(struct vt_mode *)data;
2452 if (newmode.mode != VT_PROCESS) {
2453 struct video_state *vsx = &vs[minor(dev)];
2454 if (vsx->smode.mode == VT_PROCESS) {
2455 if (vsx->proc != p) {
2466 * NB: XFree86-3.1.1 does the following:
2467 * VT_ACTIVATE (vtnum)
2468 * VT_WAITACTIVE (vtnum)
2469 * VT_SETMODE (VT_PROCESS)
2470 * So it is possible that the screen was switched
2471 * between the WAITACTIVE and the SETMODE (here). This
2472 * can actually happen quite frequently, and it was
2473 * leading to dire consequences. Now it is detected by
2474 * requiring that minor(dev) match current_video_screen.
2475 * An alternative would be to operate on vs[minor(dev)]
2476 * instead of *vsp, but that would leave the server
2477 * confused, because it would believe that its vt was
2478 * currently activated.
2480 if (minor(dev) != current_video_screen) {
2485 /* Check for server died */
2486 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2489 /* Check for server already running */
2490 if (vsp->smode.mode == VT_PROCESS && vsp->proc != p)
2493 return EBUSY; /* already in use on this VT */
2496 if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig)
2497 || !ISSIGVALID(newmode.frsig))
2503 vsp->smode = newmode;
2505 vsp->pid = p->p_pid;
2507 #if PCVT_FREEBSD > 206
2509 * XXX: If pcvt is acting as the systems console,
2510 * avoid panics going to the debugger while we are in
2514 cons_unavail = (newmode.mode == VT_PROCESS);
2520 *(struct vt_mode *)data = vsp->smode;
2524 if (minor(dev) != current_video_screen)
2526 if (vsp->smode.mode != VT_PROCESS)
2530 switch(*(int *)data) {
2532 /* process refuses to release screen; abort */
2533 if(vt_switch_pending
2534 && (vsp->vt_status & VT_WAIT_REL)) {
2535 vsp->vt_status &= ~VT_WAIT_REL;
2536 vt_switch_pending = 0;
2542 /* process releases its VT */
2543 if(vt_switch_pending
2544 && (vsp->vt_status & VT_WAIT_REL)) {
2545 int new_screen = vt_switch_pending - 1;
2546 struct video_state *old_vsp = vsp;
2548 vsp->vt_status &= ~VT_WAIT_REL;
2550 switch_screen(new_screen,
2551 vsp->vt_status & VT_GRAFX,
2552 vs[new_screen].vt_status
2556 if(old_vsp->vt_status & VT_WAIT_ACT)
2558 old_vsp->vt_status &= ~VT_WAIT_ACT;
2559 wakeup((caddr_t)&old_vsp->smode);
2561 if(vsp->vt_status & VT_WAIT_ACT)
2563 vsp->vt_status &= ~VT_WAIT_ACT;
2564 wakeup((caddr_t)&vsp->smode);
2568 if(vsp->smode.mode == VT_PROCESS) {
2570 * if the new vt is also in process
2571 * mode, we have to wait until its
2572 * controlling process acknowledged
2577 if(vsp->smode.acqsig)
2583 /* we are committed */
2584 vt_switch_pending = 0;
2585 #if PCVT_FREEBSD > 206
2596 /* new vts controlling process acknowledged */
2597 if(vsp->vt_status & VT_WAIT_ACK) {
2598 vt_switch_pending = 0;
2599 vsp->vt_status &= ~VT_WAIT_ACK;
2600 #if PCVT_FREEBSD > 206
2609 return EINVAL; /* end case VT_RELDISP */
2613 /* return free vt */
2614 for(i = 0; i < PCVT_NSCREENS; i++)
2616 *(int *)data = i + 1;
2622 *(int *)data = current_video_screen + 1;
2626 return vgapage(*(int *)data - 1);
2629 /* sleep until vt switch happened */
2630 i = *(int *)data - 1;
2633 && (i < 0 || i >= PCVT_NSCREENS))
2636 if(i != -1 && current_video_screen == i)
2645 while (current_video_screen != i &&
2646 (error == 0 || error == ERESTART))
2648 vs[i].vt_status |= VT_WAIT_ACT;
2649 error = tsleep((caddr_t)&vs[i].smode,
2650 PZERO | PCATCH, "waitvt", 0);
2657 /* grant the process IO access; only allowed if euid == 0 */
2661 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2662 struct trapframe *fp = p->p_md.md_regs;
2663 #elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2664 struct trapframe *fp = (struct trapframe *)p->p_regs;
2666 struct syscframe *fp = (struct syscframe *)p->p_regs;
2672 if (securelevel > 0)
2675 #if PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2676 fp->tf_eflags |= PSL_IOPL;
2678 fp->sf_eflags |= PSL_IOPL;
2685 /* abandon IO access permission */
2688 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2689 struct trapframe *fp = p->p_md.md_regs;
2690 fp->tf_eflags &= ~PSL_IOPL;
2691 #elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2692 struct trapframe *fp = (struct trapframe *)p->p_regs;
2693 fp->tf_eflags &= ~PSL_IOPL;
2695 struct syscframe *fp = (struct syscframe *)p->p_regs;
2696 fp->sf_eflags &= ~PSL_IOPL;
2704 struct video_state *vsx = &vs[minor(dev)];
2707 if(adaptor_type != VGA_ADAPTOR
2708 && adaptor_type != MDA_ADAPTOR)
2709 /* X will only run on those adaptors */
2712 /* set text/graphics mode of current vt */
2713 switch(*(int *)data)
2716 haschanged = (vsx->vt_status & VT_GRAFX) != 0;
2717 vsx->vt_status &= ~VT_GRAFX;
2718 if(haschanged && vsx == vsp)
2719 switch_screen(current_video_screen, 1, 0);
2723 /* xxx It might be a good idea to require that
2724 the vt be in process controlled mode here,
2725 and that the calling process is the owner */
2726 haschanged = (vsx->vt_status & VT_GRAFX) == 0;
2727 vsx->vt_status |= VT_GRAFX;
2728 if(haschanged && vsx == vsp)
2729 switch_screen(current_video_screen, 0, 1);
2733 return EINVAL; /* end case KDSETMODE */
2737 /* set keyboard repeat and delay */
2738 return kbdioctl(dev, KBDSTPMAT, data, flag);
2741 switch(*(int *)data)
2745 #if PCVT_SCANSET > 1
2746 /* put keyboard to return ancient PC scan codes */
2748 #endif /* PCVT_SCANSET > 1 */
2751 shift_down = meta_down = altgr_down = ctrl_down = 0;
2756 #if PCVT_SCANSET > 1
2758 #endif /* PCVT_SCANSET > 1 */
2763 return EINVAL; /* end KDSKBMODE */
2766 /* ring the speaker */
2769 int duration = *(int *)data >> 16;
2770 int pitch = *(int *)data & 0xffff;
2775 sysbeep(PCVT_SYSBEEPF / pitch,
2776 duration * hz / 1000);
2778 #else /* PCVT_NETBSD */
2779 sysbeep(pitch, duration * hz / 3000);
2780 #endif /* PCVT_NETBSD */
2785 sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
2790 /* set kbd LED status */
2791 /* unfortunately, the LED definitions between pcvt and */
2792 /* USL differ some way :-( */
2794 j = (i & LED_CAP? KBD_CAPSLOCK: 0)
2795 + (i & LED_NUM? KBD_NUMLOCK: 0)
2796 + (i & LED_SCR? KBD_SCROLLLOCK: 0);
2797 return kbdioctl(dev, KBDSLOCK, (caddr_t)&j, flag);
2800 /* get kbd LED status */
2801 if((error = kbdioctl(dev, KBDGLOCK, (caddr_t)&j, flag)))
2803 i = (j & KBD_CAPSLOCK? LED_CAP: 0)
2804 + (j & KBD_NUMLOCK? LED_NUM: 0)
2805 + (j & KBD_SCROLLLOCK? LED_SCR: 0);
2810 get_usl_keymap((keymap_t *)data);
2812 } /* end case cmd */
2814 return -1; /* inappropriate usl_vt_compat ioctl */
2816 #endif /* PCVT_USL_VT_COMPAT */
2818 #endif /* NVT > 0 */
2820 /* ------------------------- E O F ------------------------------------------*/