2 * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
4 * Copyright (C) 1992, 1993 Soeren Schmidt.
8 * For the sake of compatibility, portions of this code regarding the
9 * X server interface are taken from Soeren Schmidt's syscons driver.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by
22 * Hellmuth Michaelis, Joerg Wunsch and Soeren Schmidt.
23 * 4. The name authors may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * @(#)pcvt_ext.c, 3.20, Last Edit-Date: [Thu Apr 6 10:07:45 1995]
42 /*---------------------------------------------------------------------------*
44 * pcvt_ext.c VT220 Driver Extended Support Routines
45 * ------------------------------------------------------
47 * -hm ------------ Release 3.00 --------------
48 * -hm integrating NetBSD-current patches
49 * -hm applied Onno van der Linden's patch for Cirrus BIOS upgrade
50 * -hm pcvt_x_hook has to care about fkey labels now
51 * -hm changed some bcopyb's to bcopy's
52 * -hm TS_INDEX -> TS_DATA for cirrus (mail from Onno/Charles)
53 * -jw removed kbc_8042(), and replaced by kbd_emulate_pc()
54 * -hm X server patch from John Kohl <jtk@kolvir.blrc.ma.us>
55 * -hm applying Joerg's patch for FreeBSD 2.0
56 * -hm enable 132 col support for Trident TVGA8900CL
57 * -hm applying patch from Joerg fixing Crtat bug
58 * -hm removed PCVT_FAKE_SYSCONS10
59 * -hm fastscroll/Crtat bugfix from Lon Willett
60 * -hm bell patch from Thomas Eberhardt for NetBSD
61 * -hm multiple X server bugfixes from Lon Willett
62 * -hm patch from John Kohl fixing tsleep bug in usl_vt_ioctl()
63 * -hm bugfix: clear 25th line when switching to a force 24 lines vt
64 * -jw add some forward declarations
65 * -hm fixing MDA re-init when leaving X
66 * -hm patch from John Kohl fixing potential divide by 0 problem
68 *---------------------------------------------------------------------------*/
73 #include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
75 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
77 static int s3testwritable( void );
78 static int et4000_col( int );
79 static int wd90c11_col( int );
80 static int tri9000_col( int );
81 static int v7_1024i_col( int );
82 static int s3_928_col( int );
83 static int cl_gd542x_col( int );
85 /* storage to save video timing values of 80 columns text mode */
97 static int regsaved = 0; /* registers are saved to savearea */
99 /*---------------------------------------------------------------------------*
101 * Find out which video board we are running on, taken from:
102 * Richard Ferraro: Programmers Guide to the EGA and VGA Cards
103 * and from David E. Wexelblat's SuperProbe Version 1.0.
104 * When a board is found, for which 132 column switching is
105 * provided, the global variable "can_do_132col" is set to 1,
106 * also the global variable vga_family is set to what we found.
108 * ###############################################################
109 * ## THIS IS GETTING MORE AND MORE A LARGE SPAGHETTI HACK !!!! ##
110 * ###############################################################
112 *---------------------------------------------------------------------------*/
117 u_char byte, oldbyte, old1byte, newbyte;
120 can_do_132col = 1; /* assumes everyone can do 132 col */
122 can_do_132col = 0; /* assumes noone can do 132 col */
123 #endif /* PCVT_132GENERIC */
125 vga_family = VGA_F_NONE;
127 /*---------------------------------------------------------------------------*
128 * check for Western Digital / Paradise chipsets
129 *---------------------------------------------------------------------------*/
131 ptr = (u_char *)Crtat;
134 ptr += (0xc007d - 0xb8000);
136 ptr += (0xc007d - 0xb0000);
138 if((*ptr++ == 'V') && (*ptr++ == 'G') &&
139 (*ptr++ == 'A') && (*ptr++ == '='))
143 vga_family = VGA_F_WD;
145 outb(addr_6845, 0x2b);
146 oldbyte = inb(addr_6845+1);
147 outb(addr_6845+1, 0xaa);
148 newbyte = inb(addr_6845+1);
149 outb(addr_6845+1, oldbyte);
151 return(VGA_PVGA); /* PVGA1A chip */
153 outb(TS_INDEX, 0x12);
154 oldbyte = inb(TS_DATA);
155 outb(TS_DATA, oldbyte & 0xbf);
156 newbyte = inb(TS_DATA) & 0x40;
158 return(VGA_WD90C00); /* WD90C00 chip */
160 outb(TS_DATA, oldbyte | 0x40);
161 newbyte = inb(TS_DATA) & 0x40;
163 return(VGA_WD90C00); /* WD90C00 chip */
165 outb(TS_DATA, oldbyte);
168 outb(TS_INDEX, 0x10);
169 oldbyte = inb(TS_DATA);
171 outb(TS_DATA, oldbyte & 0xfb);
172 newbyte = inb(TS_DATA) & 0x04;
176 outb(TS_DATA, oldbyte | 0x04);
177 newbyte = inb(TS_DATA) & 0x04;
181 outb(TS_DATA, oldbyte);
192 /*---------------------------------------------------------------------------*
193 * check for Trident chipsets
194 *---------------------------------------------------------------------------*/
196 outb(TS_INDEX, 0x0b);
197 oldbyte = inb(TS_DATA);
200 outb(TS_INDEX, 0x0b);
203 byte = inb(TS_DATA); /* chipset type */
206 outb(TS_INDEX, 0x0e);
207 old1byte = inb(TS_DATA);
210 newbyte = inb(TS_DATA);
212 outb(TS_DATA, (old1byte ^ 0x02));
214 outb(TS_INDEX, 0x0b);
215 outb(TS_DATA, oldbyte);
217 if((newbyte & 0x0f) == 0x02)
219 /* is a trident chip */
221 vga_family = VGA_F_TRI;
226 return(VGA_TR8800BR);
229 return(VGA_TR8800CS);
237 /* Haven't tried, but should work */
247 return(VGA_TR8900CL);
256 return(VGA_TRUNKNOWN);
260 /*---------------------------------------------------------------------------*
261 * check for Tseng Labs ET3000/4000 chipsets
262 *---------------------------------------------------------------------------*/
264 outb(GN_HERCOMPAT, 0x06);
266 outb(GN_DMCNTLC, 0xa0);
268 outb(GN_DMCNTLM, 0xa0);
276 outb(ATC_INDEX, ATC_MISC);
277 oldbyte = inb(ATC_DATAR);
279 /* write new value */
285 outb(ATC_INDEX, ATC_MISC);
286 newbyte = oldbyte ^ 0x10;
287 outb(ATC_DATAW, newbyte);
289 /* read back new value */
294 outb(ATC_INDEX, ATC_MISC);
295 byte = inb(ATC_DATAR);
297 /* write back old value */
302 outb(ATC_INDEX, ATC_MISC);
303 outb(ATC_DATAW, oldbyte);
305 if(byte == newbyte) /* ET3000 or ET4000 */
307 vga_family = VGA_F_TSENG;
309 outb(addr_6845, CRTC_EXTSTART);
310 oldbyte = inb(addr_6845+1);
311 newbyte = oldbyte ^ 0x0f;
312 outb(addr_6845+1, newbyte);
313 byte = inb(addr_6845+1);
314 outb(addr_6845+1, oldbyte);
327 /*---------------------------------------------------------------------------*
328 * check for Video7 VGA chipsets
329 *---------------------------------------------------------------------------*/
331 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
334 outb(addr_6845, CRTC_STARTADRH);
335 oldbyte = inb(addr_6845+1);
337 outb(addr_6845+1, 0x55);
338 newbyte = inb(addr_6845+1);
340 outb(addr_6845, CRTC_V7ID); /* id register */
341 byte = inb(addr_6845+1); /* read id */
343 outb(addr_6845, CRTC_STARTADRH);
344 outb(addr_6845+1, oldbyte);
346 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
349 if(byte == (0x55 ^ 0xea))
352 vga_family = VGA_F_V7;
354 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
357 outb(TS_INDEX, TS_V7CHIPREV);
360 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
363 if(byte < 0xff && byte >= 0x80)
365 if(byte < 0x7f && byte >= 0x70)
367 if(byte < 0x5a && byte >= 0x50)
369 if(byte < 0x4a && byte > 0x40)
374 return(VGA_V7UNKNOWN);
377 /*---------------------------------------------------------------------------*
378 * check for S3 chipsets
379 *---------------------------------------------------------------------------*/
381 outb(addr_6845, 0x38); /* reg 1 lock register */
382 old1byte = inb(addr_6845+1); /* get old value */
384 outb(addr_6845, 0x38);
385 outb(addr_6845+1, 0x00); /* lock registers */
387 if(s3testwritable() == 0) /* check if locked */
389 outb(addr_6845, 0x38);
390 outb(addr_6845+1, 0x48); /* unlock registers */
392 if(s3testwritable() == 1 ) /* check if unlocked */
394 vga_family = VGA_F_S3; /* FAMILY S3 */
396 outb(addr_6845, 0x30); /* chip id/rev reg */
397 byte = inb(addr_6845+1);
405 outb(addr_6845, 0x38);
406 outb(addr_6845+1, old1byte);
410 outb(addr_6845, 0x38);
411 outb(addr_6845+1, old1byte);
415 outb(addr_6845, 0x38);
416 outb(addr_6845+1, old1byte);
417 return VGA_S3_UNKNOWN;
422 outb(addr_6845, 0x38);
423 outb(addr_6845+1, old1byte);
428 outb(addr_6845, 0x38);
429 outb(addr_6845+1, old1byte);
434 outb(addr_6845, 0x38);
435 outb(addr_6845+1, old1byte);
436 return VGA_S3_UNKNOWN;
441 /*---------------------------------------------------------------------------*
442 * check for Cirrus chipsets
443 *---------------------------------------------------------------------------*/
446 oldbyte = inb(TS_DATA);
450 newbyte = inb(TS_DATA);
451 outb(addr_6845, 0x27);
452 byte = inb(addr_6845 + 1);
454 outb(TS_DATA, oldbyte);
455 if (newbyte == 0x12) {
456 vga_family = VGA_F_CIR;
458 switch ((byte & 0xfc) >> 2) {
462 return VGA_CL_GD5402;
464 return VGA_CL_GD5402r1;
466 return VGA_CL_GD5420;
468 return VGA_CL_GD5420r1;
472 return VGA_CL_GD5422;
474 return VGA_CL_GD5424;
476 return VGA_CL_GD5426;
478 return VGA_CL_GD5428;
485 /*---------------------------------------------------------------------------
486 * test if index 35 lower nibble is writable (taken from SuperProbe 1.0)
487 *---------------------------------------------------------------------------*/
491 u_char old, new1, new2;
493 outb(addr_6845, 0x35);
494 old = inb(addr_6845+1); /* save */
496 outb(addr_6845, 0x35);
497 outb(addr_6845+1, (old & 0xf0)); /* write 0 */
499 outb(addr_6845, 0x35);
500 new1 = (inb(addr_6845+1)) & 0x0f; /* must read 0 */
502 outb(addr_6845, 0x35);
503 outb(addr_6845+1, (old | 0x0f)); /* write 1 */
505 outb(addr_6845, 0x35);
506 new2 = (inb(addr_6845+1)) & 0x0f; /* must read 1 */
508 outb(addr_6845, 0x35);
509 outb(addr_6845+1, old); /* restore */
511 return((new1==0) && (new2==0x0f));
514 /*---------------------------------------------------------------------------*
515 * return ptr to string describing vga type
516 *---------------------------------------------------------------------------*/
518 vga_string(int number)
520 static char *vga_tab[] = {
556 return(vga_tab[number]);
559 /*---------------------------------------------------------------------------*
560 * toggle vga 80/132 column operation
561 *---------------------------------------------------------------------------*/
563 vga_col(struct video_state *svsp, int cols)
567 if(adaptor_type != VGA_ADAPTOR)
573 ret = et4000_col(cols);
577 ret = wd90c11_col(cols);
584 ret = tri9000_col(cols);
588 ret = v7_1024i_col(cols);
592 ret = s3_928_col(cols);
596 case VGA_CL_GD5402r1:
598 case VGA_CL_GD5420r1:
603 ret = cl_gd542x_col(cols);
609 ret = generic_col(cols);
610 #endif /* PCVT_132GENERIC */
616 return(0); /* failed */
624 /*---------------------------------------------------------------------------*
625 * toggle 80/132 column operation for "generic" SVGAs
626 * NB: this is supposed to work on any (S)VGA as long as the monitor
627 * is able to sync down to 21.5 kHz horizontally. The resulting
628 * vertical frequency is only 50 Hz, so if there is some better board
629 * specific algorithm, we avoid using this generic one.
630 * REPORT ANY FAILURES SO WE CAN IMPROVE THIS
631 *---------------------------------------------------------------------------*/
635 * Some improved (i.e. higher scan rates) figures for the horizontal
636 * timing. USE AT YOUR OWN RISK, THIS MIGHT DAMAGE YOUR MONITOR DUE
637 * TO A LOSS OF HORIZONTAL SYNC!
638 * The figures have been tested with an ET3000 board along with a
639 * NEC MultiSync 3D monitor. If you are playing here, consider
640 * testing with several screen pictures (dark background vs. light
641 * background, even enlightening the border color may impact the
642 * result - you can do this e.g. by "scon -p black,42,42,42")
643 * Remember that all horizontal timing values must be dividable
644 * by 8! (The scheme below is taken so that nifty kernel hackers
645 * are able to patch the figures at run-time.)
647 * The actual numbers result in 23 kHz line scan and 54 Hz vertical
650 #endif /* PCVT_EXP_132COL */
653 generic_col(int cols)
660 /* stable figures for any multisync monitor that syncs down to 22 kHz*/
661 static volatile u_short htotal = 1312;
662 static volatile u_short displayend = 1056;
663 static volatile u_short blankstart = 1072;
664 static volatile u_short syncstart = 1112;
665 static volatile u_short syncend = 1280;
667 #else /* PCVT_EXP_132COL */
669 /* reduced sync-pulse width and sync delays */
670 static volatile u_short htotal = 1232;
671 static volatile u_short displayend = 1056;
672 static volatile u_short blankstart = 1056;
673 static volatile u_short syncstart = 1104;
674 static volatile u_short syncend = 1168;
676 #endif /* PCVT_EXP_132COL */
680 /* enable access to first 7 CRTC registers */
682 outb(addr_6845, CRTC_VSYNCE);
683 byte = inb(addr_6845+1);
684 outb(addr_6845, CRTC_VSYNCE);
685 outb(addr_6845+1, byte & 0x7f);
687 if(cols == SCR_COL132) /* switch 80 -> 132 */
689 /* save state of board for 80 columns */
695 sp = savearea.generic;
697 outb(addr_6845, 0x00); /* Horizontal Total */
698 *sp++ = inb(addr_6845+1);
699 outb(addr_6845, 0x01); /* Horizontal Display End */
700 *sp++ = inb(addr_6845+1);
701 outb(addr_6845, 0x02); /* Horizontal Blank Start */
702 *sp++ = inb(addr_6845+1);
703 outb(addr_6845, 0x03); /* Horizontal Blank End */
704 *sp++ = inb(addr_6845+1);
705 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
706 *sp++ = inb(addr_6845+1);
707 outb(addr_6845, 0x05); /* Horizontal Retrace End */
708 *sp++ = inb(addr_6845+1);
710 outb(addr_6845, 0x13); /* Row Offset Register */
711 *sp++ = inb(addr_6845+1);
713 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
714 *sp++ = inb(TS_DATA);
720 /* ATC Mode control */
721 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
722 *sp++ = inb(ATC_DATAR);
728 /* ATC Horizontal Pixel Panning */
729 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
730 *sp++ = inb(ATC_DATAR);
732 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
735 /* setup chipset for 132 column operation */
738 outb(addr_6845, 0x00); /* Horizontal Total */
739 outb(addr_6845+1, (htotal / 8) - 5);
740 outb(addr_6845, 0x01); /* Horizontal Display End */
741 outb(addr_6845+1, (displayend / 8) - 1);
742 outb(addr_6845, 0x02); /* Horizontal Blank Start */
743 outb(addr_6845+1, blankstart / 8);
744 outb(addr_6845, 0x03); /* Horizontal Blank End */
745 outb(addr_6845+1, ((syncend / 8) & 0x1f) | 0x80);
746 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
747 outb(addr_6845+1, syncstart / 8);
748 outb(addr_6845, 0x05); /* Horizontal Retrace End */
750 (((syncend / 8) & 0x20) * 4)
751 | ((syncend / 8) & 0x1f));
753 outb(addr_6845, 0x13); /* Row Offset Register */
754 outb(addr_6845+1, 0x42);
756 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
757 outb(TS_DATA, 0x01); /* 8 dot char clock */
763 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
764 outb(ATC_DATAW, 0x08); /* Line graphics disable */
770 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
771 outb(ATC_DATAW, 0x00);
773 /* Misc output register */
774 /* use the 28.322 MHz clock */
775 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | 4);
777 else /* switch 132 -> 80 */
779 if(!regsaved) /* failsafe */
781 /* disable access to first 7 CRTC registers */
782 outb(addr_6845, CRTC_VSYNCE);
783 outb(addr_6845+1, byte);
788 sp = savearea.generic;
790 outb(addr_6845, 0x00); /* Horizontal Total */
791 outb(addr_6845+1, *sp++);
792 outb(addr_6845, 0x01); /* Horizontal Display End */
793 outb(addr_6845+1, *sp++);
794 outb(addr_6845, 0x02); /* Horizontal Blank Start */
795 outb(addr_6845+1, *sp++);
796 outb(addr_6845, 0x03); /* Horizontal Blank End */
797 outb(addr_6845+1, *sp++);
798 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
799 outb(addr_6845+1, *sp++);
800 outb(addr_6845, 0x05); /* Horizontal Retrace End */
801 outb(addr_6845+1, *sp++);
803 outb(addr_6845, 0x13); /* Row Offset Register */
804 outb(addr_6845+1, *sp++);
806 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
807 outb(TS_DATA, *sp++);
813 /* ATC Mode control */
814 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
815 outb(ATC_DATAW, *sp++);
821 /* ATC Horizontal Pixel Panning */
822 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
823 outb(ATC_DATAW, *sp++);
825 outb(GN_MISCOUTW, *sp++); /* Misc output register */
828 /* disable access to first 7 CRTC registers */
830 outb(addr_6845, CRTC_VSYNCE);
831 outb(addr_6845+1, byte);
837 #endif /* PCVT_132GENERIC */
839 /*---------------------------------------------------------------------------*
840 * toggle 80/132 column operation for ET4000 based boards
841 *---------------------------------------------------------------------------*/
850 /* enable access to first 7 CRTC registers */
852 outb(addr_6845, CRTC_VSYNCE);
853 byte = inb(addr_6845+1);
854 outb(addr_6845, CRTC_VSYNCE);
855 outb(addr_6845+1, byte & 0x7f);
857 if(cols == SCR_COL132) /* switch 80 -> 132 */
859 /* save state of board for 80 columns */
865 sp = savearea.et4000;
867 outb(addr_6845, 0x00); /* Horizontal Total */
868 *sp++ = inb(addr_6845+1);
869 outb(addr_6845, 0x01); /* Horizontal Display End */
870 *sp++ = inb(addr_6845+1);
871 outb(addr_6845, 0x02); /* Horizontal Blank Start */
872 *sp++ = inb(addr_6845+1);
874 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
875 *sp++ = inb(addr_6845+1);
876 outb(addr_6845, 0x05); /* Horizontal Retrace End */
877 *sp++ = inb(addr_6845+1);
879 outb(addr_6845, 0x13); /* Row Offset Register */
880 *sp++ = inb(addr_6845+1);
882 outb(addr_6845, 0x34); /* 6845 Compatibility */
883 *sp++ = inb(addr_6845+1);
885 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
886 *sp++ = inb(TS_DATA);
892 /* ATC Mode control */
893 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
894 *sp++ = inb(ATC_DATAR);
900 /* ATC Horizontal Pixel Panning */
901 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
902 *sp++ = inb(ATC_DATAR);
904 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
907 /* setup chipset for 132 column operation */
909 outb(addr_6845, 0x00); /* Horizontal Total */
910 outb(addr_6845+1, 0x9f);
911 outb(addr_6845, 0x01); /* Horizontal Display End */
912 outb(addr_6845+1, 0x83);
913 outb(addr_6845, 0x02); /* Horizontal Blank Start */
914 outb(addr_6845+1, 0x84);
916 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
917 outb(addr_6845+1, 0x8b);
918 outb(addr_6845, 0x05); /* Horizontal Retrace End */
919 outb(addr_6845+1, 0x80);
921 outb(addr_6845, 0x13); /* Row Offset Register */
922 outb(addr_6845+1, 0x42);
924 outb(addr_6845, 0x34); /* 6845 Compatibility */
925 outb(addr_6845+1, 0x0a);
927 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
928 outb(TS_DATA, 0x01); /* 8 dot char clock */
934 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
935 outb(ATC_DATAW, 0x08); /* Line graphics disable */
941 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
942 outb(ATC_DATAW, 0x00);
944 /* Misc output register */
946 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c));
948 else /* switch 132 -> 80 */
950 if(!regsaved) /* failsafe */
952 /* disable access to first 7 CRTC registers */
953 outb(addr_6845, CRTC_VSYNCE);
954 outb(addr_6845+1, byte);
959 sp = savearea.et4000;
961 outb(addr_6845, 0x00); /* Horizontal Total */
962 outb(addr_6845+1, *sp++);
964 outb(addr_6845, 0x01); /* Horizontal Display End */
965 outb(addr_6845+1, *sp++);
966 outb(addr_6845, 0x02); /* Horizontal Blank Start */
967 outb(addr_6845+1, *sp++);
970 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
971 outb(addr_6845+1, *sp++);
972 outb(addr_6845, 0x05); /* Horizontal Retrace End */
973 outb(addr_6845+1, *sp++);
975 outb(addr_6845, 0x13); /* Row Offset Register */
976 outb(addr_6845+1, *sp++);
978 outb(addr_6845, 0x34); /* 6845 Compatibility */
979 outb(addr_6845+1, *sp++);
981 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
982 outb(TS_DATA, *sp++);
988 /* ATC Mode control */
989 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
990 outb(ATC_DATAW, *sp++);
996 /* ATC Horizontal Pixel Panning */
997 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
998 outb(ATC_DATAW, *sp++);
1000 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1003 /* disable access to first 7 CRTC registers */
1005 outb(addr_6845, CRTC_VSYNCE);
1006 outb(addr_6845+1, byte);
1013 /*---------------------------------------------------------------------------*
1014 * toggle 80/132 column operation for WD/Paradise based boards
1016 * when this card does 132 cols, the char map select register (TS_INDEX,
1017 * TS_FONTSEL) function bits get REDEFINED. whoever did design this,
1018 * please don't cross my way ever .......
1020 *---------------------------------------------------------------------------*/
1022 wd90c11_col(int cols)
1025 #if !PCVT_BACKUP_FONTS
1026 static unsigned char *sv_fontwd[NVGAFONTS];
1027 #endif /* !PCVT_BACKUP_FONTS */
1035 /* enable access to first 7 CRTC registers */
1037 outb(addr_6845, CRTC_VSYNCE);
1038 byte = inb(addr_6845+1);
1039 outb(addr_6845, CRTC_VSYNCE);
1040 outb(addr_6845+1, byte & 0x7f);
1042 /* enable access to WD/Paradise "control extensions" */
1044 outb(GDC_INDEX, GDC_PR5GPLOCK);
1045 outb(GDC_INDEX, 0x05);
1046 outb(addr_6845, CRTC_PR10);
1047 outb(addr_6845, 0x85);
1048 outb(TS_INDEX, TS_UNLOCKSEQ);
1049 outb(TS_DATA, 0x48);
1051 if(cols == SCR_COL132) /* switch 80 -> 132 */
1053 /* save state of board for 80 columns */
1059 /* save current fonts */
1061 #if !PCVT_BACKUP_FONTS
1062 for(i = 0; i < totalfonts; i++)
1067 (u_char *)malloc(32 * 256,
1071 printf("pcvt: no font buffer\n");
1083 #endif /* !PCVT_BACKUP_FONTS */
1085 sp = savearea.wd90c11;
1087 outb(addr_6845, 0x00); /* Horizontal Total */
1088 *sp++ = inb(addr_6845+1);
1089 outb(addr_6845, 0x01); /* Horizontal Display End */
1090 *sp++ = inb(addr_6845+1);
1091 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1092 *sp++ = inb(addr_6845+1);
1093 outb(addr_6845, 0x03); /* Horizontal Blank End */
1094 *sp++ = inb(addr_6845+1);
1095 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1096 *sp++ = inb(addr_6845+1);
1097 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1098 *sp++ = inb(addr_6845+1);
1100 outb(addr_6845, 0x13); /* Row Offset Register */
1101 *sp++ = inb(addr_6845+1);
1103 outb(addr_6845, 0x2e); /* misc 1 */
1104 *sp++ = inb(addr_6845+1);
1105 outb(addr_6845, 0x2f); /* misc 2 */
1106 *sp++ = inb(addr_6845+1);
1108 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1109 *sp++ = inb(TS_DATA);
1110 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1111 *sp++ = inb(TS_DATA);
1113 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1116 /* setup chipset for 132 column operation */
1118 outb(addr_6845, 0x00); /* Horizontal Total */
1119 outb(addr_6845+1, 0x9c);
1120 outb(addr_6845, 0x01); /* Horizontal Display End */
1121 outb(addr_6845+1, 0x83);
1122 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1123 outb(addr_6845+1, 0x84);
1124 outb(addr_6845, 0x03); /* Horizontal Blank End */
1125 outb(addr_6845+1, 0x9f);
1126 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1127 outb(addr_6845+1, 0x8a);
1128 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1129 outb(addr_6845+1, 0x1c);
1131 outb(addr_6845, 0x13); /* Row Offset Register */
1132 outb(addr_6845+1, 0x42);
1134 outb(addr_6845, 0x2e); /* misc 1 */
1135 outb(addr_6845+1, 0x04);
1136 outb(addr_6845, 0x2f); /* misc 2 */
1137 outb(addr_6845+1, 0x00);
1139 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1140 outb(TS_DATA, 0x21);
1141 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1142 outb(TS_DATA, 0x14);
1144 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x08)); /* Misc output register */
1148 else /* switch 132 -> 80 */
1150 if(!regsaved) /* failsafe */
1152 /* disable access to first 7 CRTC registers */
1154 outb(addr_6845, CRTC_VSYNCE);
1155 outb(addr_6845+1, byte);
1157 /* disable access to WD/Paradise "control extensions" */
1159 outb(GDC_INDEX, GDC_PR5GPLOCK);
1160 outb(GDC_INDEX, 0x00);
1161 outb(addr_6845, CRTC_PR10);
1162 outb(addr_6845, 0x00);
1163 outb(TS_INDEX, TS_UNLOCKSEQ);
1164 outb(TS_DATA, 0x00);
1171 sp = savearea.wd90c11;
1173 outb(addr_6845, 0x00); /* Horizontal Total */
1174 outb(addr_6845+1, *sp++);
1175 outb(addr_6845, 0x01); /* Horizontal Display End */
1176 outb(addr_6845+1, *sp++);
1177 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1178 outb(addr_6845+1, *sp++);
1179 outb(addr_6845, 0x03); /* Horizontal Blank End */
1180 outb(addr_6845+1, *sp++);
1181 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1182 outb(addr_6845+1, *sp++);
1183 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1184 outb(addr_6845+1, *sp++);
1186 outb(addr_6845, 0x13); /* Row Offset Register */
1187 outb(addr_6845+1, *sp++);
1189 outb(addr_6845, 0x2e); /* misc 1 */
1190 outb(addr_6845+1, *sp++);
1191 outb(addr_6845, 0x2f); /* misc 2 */
1192 outb(addr_6845+1, *sp++);
1194 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1195 outb(addr_6845+1, *sp++);
1196 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1197 outb(addr_6845+1, *sp++);
1199 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1206 #if !PCVT_BACKUP_FONTS
1207 for(i = 0; i < totalfonts; i++)
1210 vga_move_charset(i, sv_fontwd[i], 0);
1213 for(i = 0; i < totalfonts; i++)
1214 if(saved_charsets[i])
1215 vga_move_charset(i, 0, 0);
1216 #endif /* !PCVT_BACKUP_FONTS */
1218 select_vga_charset(vsp->vga_charset);
1220 /* disable access to first 7 CRTC registers */
1222 outb(addr_6845, CRTC_VSYNCE);
1223 outb(addr_6845+1, byte);
1225 /* disable access to WD/Paradise "control extensions" */
1227 outb(GDC_INDEX, GDC_PR5GPLOCK);
1228 outb(GDC_INDEX, 0x00);
1229 outb(addr_6845, CRTC_PR10);
1230 outb(addr_6845, 0x00);
1231 outb(TS_INDEX, TS_UNLOCKSEQ);
1232 outb(TS_DATA, 0x00);
1239 /*---------------------------------------------------------------------------*
1240 * toggle 80/132 column operation for TRIDENT 9000 based boards
1241 *---------------------------------------------------------------------------*/
1243 tri9000_col(int cols)
1250 /* sync reset is necessary to preserve memory contents ... */
1252 outb(TS_INDEX, TS_SYNCRESET);
1253 outb(TS_DATA, 0x01); /* synchronous reset */
1255 /* disable protection of misc out and other regs */
1257 outb(addr_6845, CRTC_MTEST);
1258 byte = inb(addr_6845+1);
1259 outb(addr_6845, CRTC_MTEST);
1260 outb(addr_6845+1, byte & ~0x50);
1262 /* enable access to first 7 CRTC registers */
1264 outb(addr_6845, CRTC_VSYNCE);
1265 byte = inb(addr_6845+1);
1266 outb(addr_6845, CRTC_VSYNCE);
1267 outb(addr_6845+1, byte & 0x7f);
1269 if(cols == SCR_COL132) /* switch 80 -> 132 */
1271 /* save state of board for 80 columns */
1277 sp = savearea.tri9000;
1279 outb(addr_6845, 0x00); /* Horizontal Total */
1280 *sp++ = inb(addr_6845+1);
1281 outb(addr_6845, 0x01); /* Horizontal Display End */
1282 *sp++ = inb(addr_6845+1);
1283 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1284 *sp++ = inb(addr_6845+1);
1285 outb(addr_6845, 0x03); /* Horizontal Blank End */
1286 *sp++ = inb(addr_6845+1);
1287 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1288 *sp++ = inb(addr_6845+1);
1289 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1290 *sp++ = inb(addr_6845+1);
1292 outb(addr_6845, 0x13);
1293 *sp++ = inb(addr_6845+1);
1295 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1296 *sp++ = inb(TS_DATA);
1298 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1299 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1300 outb(TS_INDEX, TS_MODEC2);
1301 *sp++ = inb(TS_DATA);
1303 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1304 inb(TS_DATA); /* read switches to NEW */
1305 outb(TS_INDEX, TS_MODEC2);
1306 *sp++ = inb(TS_DATA);
1312 /* ATC Mode control */
1313 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1314 *sp++ = inb(ATC_DATAR);
1320 /* ATC Horizontal Pixel Panning */
1321 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1322 *sp++ = inb(ATC_DATAR);
1324 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1327 /* setup chipset for 132 column operation */
1329 outb(addr_6845, 0x00); /* Horizontal Total */
1330 outb(addr_6845+1, 0x9b);
1331 outb(addr_6845, 0x01); /* Horizontal Display End */
1332 outb(addr_6845+1, 0x83);
1333 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1334 outb(addr_6845+1, 0x84);
1335 outb(addr_6845, 0x03); /* Horizontal Blank End */
1336 outb(addr_6845+1, 0x1e);
1337 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1338 outb(addr_6845+1, 0x87);
1339 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1340 outb(addr_6845+1, 0x1a);
1342 outb(addr_6845, 0x13); /* Row Offset Register */
1343 outb(addr_6845+1, 0x42);
1345 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1346 outb(TS_DATA, 0x01); /* 8 dot char clock */
1348 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1349 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1350 outb(TS_INDEX, TS_MODEC2);
1351 outb(TS_DATA, 0x00);
1353 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1354 inb(TS_DATA); /* read switches to NEW */
1355 outb(TS_INDEX, TS_MODEC2);
1356 outb(TS_DATA, 0x01);
1362 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1363 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1369 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1370 outb(ATC_DATAW, 0x00);
1372 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c)); /* Misc output register */
1374 else /* switch 132 -> 80 */
1376 if(!regsaved) /* failsafe */
1378 /* disable access to first 7 CRTC registers */
1379 outb(addr_6845, CRTC_VSYNCE);
1380 outb(addr_6845+1, byte);
1382 outb(TS_INDEX, TS_SYNCRESET);
1383 outb(TS_DATA, 0x03); /* clear synchronous reset */
1390 sp = savearea.tri9000;
1392 outb(addr_6845, 0x00); /* Horizontal Total */
1393 outb(addr_6845+1, *sp++);
1394 outb(addr_6845, 0x01); /* Horizontal Display End */
1395 outb(addr_6845+1, *sp++);
1396 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1397 outb(addr_6845+1, *sp++);
1398 outb(addr_6845, 0x03); /* Horizontal Blank End */
1399 outb(addr_6845+1, *sp++);
1400 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1401 outb(addr_6845+1, *sp++);
1402 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1403 outb(addr_6845+1, *sp++);
1405 outb(addr_6845, 0x13); /* Row Offset Register */
1406 outb(addr_6845+1, *sp++);
1408 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1409 outb(TS_DATA, *sp++);
1411 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1412 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1413 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1414 outb(TS_DATA, *sp++);
1416 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1417 inb(TS_DATA); /* read switches to NEW */
1418 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1419 outb(TS_DATA, *sp++);
1425 /* ATC Mode control */
1426 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1427 outb(ATC_DATAW, *sp++);
1433 /* ATC Horizontal Pixel Panning */
1434 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1435 outb(ATC_DATAW, *sp++);
1437 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1440 /* disable access to first 7 CRTC registers */
1442 outb(addr_6845, CRTC_VSYNCE);
1443 outb(addr_6845+1, byte);
1445 outb(TS_INDEX, TS_SYNCRESET);
1446 outb(TS_DATA, 0x03); /* clear synchronous reset */
1453 /*---------------------------------------------------------------------------*
1454 * toggle 80/132 column operation for Video7 VGA 1024i
1455 *---------------------------------------------------------------------------*/
1457 v7_1024i_col(int cols)
1465 /* enable access to first 7 CRTC registers */
1467 /* first, enable read access to vertical retrace start/end */
1468 outb(addr_6845, CRTC_HBLANKE);
1469 byte = inb(addr_6845+1);
1470 outb(addr_6845, CRTC_HBLANKE);
1471 outb(addr_6845+1, (byte | 0x80));
1473 /* second, enable access to protected registers */
1474 outb(addr_6845, CRTC_VSYNCE);
1475 save__byte = byte = inb(addr_6845+1);
1476 byte |= 0x20; /* no irq 2 */
1477 byte &= 0x6f; /* wr enable, clr irq flag */
1478 outb(addr_6845, CRTC_VSYNCE);
1479 outb(addr_6845+1, byte);
1481 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
1482 outb(TS_DATA, 0xea);
1485 if(cols == SCR_COL132) /* switch 80 -> 132 */
1487 /* save state of board for 80 columns */
1493 sp = savearea.v7_1024i;
1495 outb(addr_6845, 0x00); /* Horizontal Total */
1496 *sp++ = inb(addr_6845+1);
1497 outb(addr_6845, 0x01); /* Horizontal Display End */
1498 *sp++ = inb(addr_6845+1);
1499 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1500 *sp++ = inb(addr_6845+1);
1501 outb(addr_6845, 0x03); /* Horizontal Blank End */
1502 *sp++ = inb(addr_6845+1);
1503 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1504 *sp++ = inb(addr_6845+1);
1505 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1506 *sp++ = inb(addr_6845+1);
1508 outb(addr_6845, 0x13); /* Row Offset Register */
1509 *sp++ = inb(addr_6845+1);
1511 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1512 *sp++ = inb(TS_DATA);
1518 /* ATC Mode control */
1519 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1520 *sp++ = inb(ATC_DATAR);
1526 /* ATC Horizontal Pixel Panning */
1527 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1528 *sp++ = inb(ATC_DATAR);
1530 outb(TS_INDEX, 0x83);
1531 *sp++ = inb(TS_DATA);
1533 outb(TS_INDEX, 0xa4);
1534 *sp++ = inb(TS_DATA);
1536 outb(TS_INDEX, 0xe0);
1537 *sp++ = inb(TS_DATA);
1539 outb(TS_INDEX, 0xe4);
1540 *sp++ = inb(TS_DATA);
1542 outb(TS_INDEX, 0xf8);
1543 *sp++ = inb(TS_DATA);
1545 outb(TS_INDEX, 0xfd);
1546 *sp++ = inb(TS_DATA);
1548 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1551 /* setup chipset for 132 column operation */
1553 outb(addr_6845, 0x00); /* Horizontal Total */
1554 outb(addr_6845+1, 0x9c);
1555 outb(addr_6845, 0x01); /* Horizontal Display End */
1556 outb(addr_6845+1, 0x83);
1557 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1558 outb(addr_6845+1, 0x86);
1559 outb(addr_6845, 0x03); /* Horizontal Blank End */
1560 outb(addr_6845+1, 0x9e);
1561 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1562 outb(addr_6845+1, 0x89);
1563 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1564 outb(addr_6845+1, 0x1c);
1566 outb(addr_6845, 0x13); /* Row Offset Register */
1567 outb(addr_6845+1, 0x42);
1569 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1570 outb(TS_DATA, 0x01); /* 8 dot char clock */
1576 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1577 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1583 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1584 outb(ATC_DATAW, 0x00);
1586 outb(TS_INDEX, TS_SYNCRESET);
1587 outb(TS_DATA, 0x01); /* synchronous reset */
1589 outb(TS_INDEX, 0x83);
1590 outb(TS_DATA, 0xa0);
1592 outb(TS_INDEX, 0xa4);
1593 outb(TS_DATA, 0x1c);
1595 outb(TS_INDEX, 0xe0);
1596 outb(TS_DATA, 0x00);
1598 outb(TS_INDEX, 0xe4);
1599 outb(TS_DATA, 0xfe);
1601 outb(TS_INDEX, 0xf8);
1602 outb(TS_DATA, 0x1b);
1604 outb(TS_INDEX, 0xfd);
1605 outb(TS_DATA, 0x33);
1607 byte = inb(GN_MISCOUTR);
1609 outb(GN_MISCOUTW, byte); /* Misc output register */
1611 outb(TS_INDEX, TS_SYNCRESET);
1612 outb(TS_DATA, 0x03); /* clear synchronous reset */
1614 else /* switch 132 -> 80 */
1616 if(!regsaved) /* failsafe */
1618 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1619 outb(TS_DATA, 0xae);
1621 /* disable access to first 7 CRTC registers */
1622 outb(addr_6845, CRTC_VSYNCE);
1623 outb(addr_6845+1, byte);
1628 sp = savearea.v7_1024i;
1630 outb(addr_6845, 0x00); /* Horizontal Total */
1631 outb(addr_6845+1, *sp++);
1632 outb(addr_6845, 0x01); /* Horizontal Display End */
1633 outb(addr_6845+1, *sp++);
1634 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1635 outb(addr_6845+1, *sp++);
1636 outb(addr_6845, 0x03); /* Horizontal Blank End */
1637 outb(addr_6845+1, *sp++);
1638 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1639 outb(addr_6845+1, *sp++);
1640 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1641 outb(addr_6845+1, *sp++);
1643 outb(addr_6845, 0x13); /* Row Offset Register */
1644 outb(addr_6845+1, *sp++);
1646 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1647 outb(TS_DATA, *sp++);
1653 /* ATC Mode control */
1654 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1655 outb(ATC_DATAW, *sp++);
1661 /* ATC Horizontal Pixel Panning */
1662 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1663 outb(ATC_DATAW, *sp++);
1665 outb(TS_INDEX, TS_SYNCRESET);
1666 outb(TS_DATA, 0x01); /* synchronous reset */
1668 outb(TS_INDEX, 0x83);
1669 outb(TS_DATA, *sp++);
1671 outb(TS_INDEX, 0xa4);
1672 outb(TS_DATA, *sp++);
1674 outb(TS_INDEX, 0xe0);
1675 outb(TS_DATA, *sp++);
1677 outb(TS_INDEX, 0xe4);
1678 outb(TS_DATA, *sp++);
1680 outb(TS_INDEX, 0xf8);
1681 outb(TS_DATA, *sp++);
1683 outb(TS_INDEX, 0xfd);
1684 outb(TS_DATA, *sp++);
1686 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1688 outb(TS_INDEX, TS_SYNCRESET);
1689 outb(TS_DATA, 0x03); /* clear synchronous reset */
1692 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1693 outb(TS_DATA, 0xae);
1695 /* disable access to first 7 CRTC registers */
1697 outb(addr_6845, CRTC_VSYNCE);
1698 outb(addr_6845+1, save__byte);
1705 /*---------------------------------------------------------------------------*
1706 * toggle 80/132 column operation for S3 86C928 based boards
1707 *---------------------------------------------------------------------------*/
1709 s3_928_col(int cols)
1716 outb(addr_6845, 0x38);
1717 outb(addr_6845+1, 0x48); /* unlock registers */
1718 outb(addr_6845, 0x39);
1719 outb(addr_6845+1, 0xa0); /* unlock registers */
1721 /* enable access to first 7 CRTC registers */
1723 outb(addr_6845, CRTC_VSYNCE);
1724 byte = inb(addr_6845+1);
1725 outb(addr_6845, CRTC_VSYNCE);
1726 outb(addr_6845+1, byte & 0x7f);
1728 if(cols == SCR_COL132) /* switch 80 -> 132 */
1730 /* save state of board for 80 columns */
1736 sp = savearea.s3_928;
1738 outb(addr_6845, 0x00); /* Horizontal Total */
1739 *sp++ = inb(addr_6845+1);
1740 outb(addr_6845, 0x01); /* Horizontal Display End */
1741 *sp++ = inb(addr_6845+1);
1742 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1743 *sp++ = inb(addr_6845+1);
1744 outb(addr_6845, 0x03); /* Horizontal Blank End */
1745 *sp++ = inb(addr_6845+1);
1746 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1747 *sp++ = inb(addr_6845+1);
1748 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1749 *sp++ = inb(addr_6845+1);
1751 outb(addr_6845, 0x13); /* Row Offset Register */
1752 *sp++ = inb(addr_6845+1);
1754 outb(addr_6845, 0x34); /* Backward Compat 3 Reg */
1755 *sp++ = inb(addr_6845+1);
1756 outb(addr_6845, 0x3b); /* Data Xfer Exec Position */
1757 *sp++ = inb(addr_6845+1);
1759 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1760 *sp++ = inb(addr_6845+1);
1762 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1763 *sp++ = inb(TS_DATA);
1769 /* ATC Mode control */
1770 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1771 *sp++ = inb(ATC_DATAR);
1777 /* ATC Horizontal Pixel Panning */
1778 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1779 *sp++ = inb(ATC_DATAR);
1781 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1784 /* setup chipset for 132 column operation */
1786 outb(addr_6845, 0x00); /* Horizontal Total */
1787 outb(addr_6845+1, 0x9a);
1788 outb(addr_6845, 0x01); /* Horizontal Display End */
1789 outb(addr_6845+1, 0x83);
1790 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1791 outb(addr_6845+1, 0x86);
1792 outb(addr_6845, 0x03); /* Horizontal Blank End */
1793 outb(addr_6845+1, 0x9d);
1794 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1795 outb(addr_6845+1, 0x87);
1796 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1797 outb(addr_6845+1, 0x1b);
1799 outb(addr_6845, 0x13); /* Row Offset Register */
1800 outb(addr_6845+1, 0x42);
1802 outb(addr_6845, 0x34);
1803 outb(addr_6845+1, 0x10);/* enable data xfer pos control */
1804 outb(addr_6845, 0x3b);
1805 outb(addr_6845+1, 0x90);/* set data xfer pos value */
1807 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1808 outb(addr_6845+1, 0x02);/* Select 40MHz Clock */
1810 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1811 outb(TS_DATA, 0x01); /* 8 dot char clock */
1817 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1818 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1824 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1825 outb(ATC_DATAW, 0x00);
1827 /* Misc output register */
1829 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c));
1831 else /* switch 132 -> 80 */
1833 if(!regsaved) /* failsafe */
1835 /* disable access to first 7 CRTC registers */
1836 outb(addr_6845, CRTC_VSYNCE);
1837 outb(addr_6845+1, byte);
1839 outb(addr_6845, 0x38);
1840 outb(addr_6845+1, 0x00); /* lock registers */
1841 outb(addr_6845, 0x39);
1842 outb(addr_6845+1, 0x00); /* lock registers */
1848 sp = savearea.s3_928;
1850 outb(addr_6845, 0x00); /* Horizontal Total */
1851 outb(addr_6845+1, *sp++);
1852 outb(addr_6845, 0x01); /* Horizontal Display End */
1853 outb(addr_6845+1, *sp++);
1854 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1855 outb(addr_6845+1, *sp++);
1856 outb(addr_6845, 0x03); /* Horizontal Blank End */
1857 outb(addr_6845+1, *sp++);
1858 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1859 outb(addr_6845+1, *sp++);
1860 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1861 outb(addr_6845+1, *sp++);
1863 outb(addr_6845, 0x13); /* Row Offset Register */
1864 outb(addr_6845+1, *sp++);
1866 outb(addr_6845, 0x34);
1867 outb(addr_6845+1, *sp++);
1868 outb(addr_6845, 0x3b);
1869 outb(addr_6845+1, *sp++);
1871 outb(addr_6845, 0x42); /* Mode control */
1872 outb(addr_6845+1, *sp++);
1874 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1875 outb(TS_DATA, *sp++);
1881 /* ATC Mode control */
1882 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1883 outb(ATC_DATAW, *sp++);
1889 /* ATC Horizontal Pixel Panning */
1890 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1891 outb(ATC_DATAW, *sp++);
1893 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1896 /* disable access to first 7 CRTC registers */
1898 outb(addr_6845, CRTC_VSYNCE);
1899 outb(addr_6845+1, byte);
1901 outb(addr_6845, 0x38);
1902 outb(addr_6845+1, 0x00); /* lock registers */
1903 outb(addr_6845, 0x39);
1904 outb(addr_6845+1, 0x00); /* lock registers */
1911 /*---------------------------------------------------------------------------*
1912 * toggle 80/132 column operation for Cirrus Logic 542x based boards
1913 *---------------------------------------------------------------------------*/
1915 cl_gd542x_col(int cols)
1922 /* enable access to first 7 CRTC registers */
1924 outb(addr_6845, CRTC_VSYNCE);
1925 byte = inb(addr_6845+1);
1926 outb(addr_6845, CRTC_VSYNCE);
1927 outb(addr_6845+1, byte & 0x7f);
1929 /* enable access to cirrus extension registers */
1931 outb(TS_DATA, 0x12);
1933 if(cols == SCR_COL132) /* switch 80 -> 132 */
1935 /* save state of board for 80 columns */
1941 sp = savearea.cirrus;
1943 outb(addr_6845, 0x00); /* Horizontal Total */
1944 *sp++ = inb(addr_6845+1);
1945 outb(addr_6845, 0x01); /* Horizontal Display End */
1946 *sp++ = inb(addr_6845+1);
1947 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1948 *sp++ = inb(addr_6845+1);
1949 outb(addr_6845, 0x03); /* Horizontal Blank End */
1950 *sp++ = inb(addr_6845+1);
1951 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1952 *sp++ = inb(addr_6845+1);
1953 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1954 *sp++ = inb(addr_6845+1);
1956 outb(addr_6845, 0x13); /* Row Offset Register */
1957 *sp++ = inb(addr_6845+1);
1959 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1960 *sp++ = inb(TS_DATA);
1967 /* ATC Mode control */
1968 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1969 *sp++ = inb(ATC_DATAR);
1975 /* ATC Horizontal Pixel Panning */
1976 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1977 *sp++ = inb(ATC_DATAR);
1979 /* VCLK2 Numerator Register */
1980 outb(TS_INDEX, 0xd);
1981 *sp++ = inb(TS_DATA);
1983 /* VCLK2 Denominator and Post-Scalar Value Register */
1984 outb(TS_INDEX, 0x1d);
1985 *sp++ = inb(TS_DATA);
1987 /* Misc output register */
1988 *sp++ = inb(GN_MISCOUTR);
1991 /* setup chipset for 132 column operation */
1993 outb(addr_6845, 0x00); /* Horizontal Total */
1994 outb(addr_6845+1, 0x9f);
1995 outb(addr_6845, 0x01); /* Horizontal Display End */
1996 outb(addr_6845+1, 0x83);
1997 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1998 outb(addr_6845+1, 0x84);
1999 outb(addr_6845, 0x03); /* Horizontal Blank End */
2000 outb(addr_6845+1, 0x82);
2001 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
2002 outb(addr_6845+1, 0x8a);
2003 outb(addr_6845, 0x05); /* Horizontal Retrace End */
2004 outb(addr_6845+1, 0x9e);
2006 outb(addr_6845, 0x13); /* Row Offset Register */
2007 outb(addr_6845+1, 0x42);
2009 /* set VCLK2 to 41.164 MHz ..... */
2010 outb(TS_INDEX, 0xd); /* VCLK2 Numerator Register */
2011 outb(TS_DATA, 0x45);
2013 outb(TS_INDEX, 0x1d); /* VCLK2 Denominator and */
2014 outb(TS_DATA, 0x30); /* Post-Scalar Value Register */
2017 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | (2 << 2));
2019 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2020 outb(TS_DATA, 0x01); /* 8 dot char clock */
2026 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
2027 outb(ATC_DATAW, 0x08); /* Line graphics disable */
2033 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
2034 outb(ATC_DATAW, 0x00);
2036 else /* switch 132 -> 80 */
2038 if(!regsaved) /* failsafe */
2040 /* disable access to first 7 CRTC registers */
2041 outb(addr_6845, CRTC_VSYNCE);
2042 outb(addr_6845+1, byte);
2044 /* disable access to cirrus extension registers */
2052 sp = savearea.cirrus;
2054 outb(addr_6845, 0x00); /* Horizontal Total */
2055 outb(addr_6845+1, *sp++);
2056 outb(addr_6845, 0x01); /* Horizontal Display End */
2057 outb(addr_6845+1, *sp++);
2058 outb(addr_6845, 0x02); /* Horizontal Blank Start */
2059 outb(addr_6845+1, *sp++);
2060 outb(addr_6845, 0x03); /* Horizontal Blank End */
2061 outb(addr_6845+1, *sp++);
2062 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
2063 outb(addr_6845+1, *sp++);
2064 outb(addr_6845, 0x05); /* Horizontal Retrace End */
2065 outb(addr_6845+1, *sp++);
2067 outb(addr_6845, 0x13); /* Row Offset Register */
2068 outb(addr_6845+1, *sp++);
2070 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2071 outb(TS_DATA, *sp++);
2077 /* ATC Mode control */
2078 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
2079 outb(ATC_DATAW, *sp++);
2085 /* ATC Horizontal Pixel Panning */
2086 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
2087 outb(ATC_DATAW, *sp++);
2089 /* VCLK2 Numerator Register */
2090 outb(TS_INDEX, 0xd);
2091 outb(TS_DATA, *sp++);
2093 /* VCLK2 Denominator and Post-Scalar Value Register */
2094 outb(TS_INDEX, 0x1d);
2095 outb(TS_DATA, *sp++);
2097 outb(GN_MISCOUTW, *sp++); /* Misc output register */
2100 /* disable access to cirrus extension registers */
2104 /* disable access to first 7 CRTC registers */
2106 outb(addr_6845, CRTC_VSYNCE);
2107 outb(addr_6845+1, byte);
2114 #if PCVT_USL_VT_COMPAT
2115 /*---------------------------------------------------------------------------*
2116 * switch screen from text mode to X-mode and vice versa
2117 *---------------------------------------------------------------------------*/
2119 switch_screen(int n, int oldgrafx, int newgrafx)
2122 #if PCVT_SCREENSAVER
2123 static unsigned saved_scrnsv_tmo = 0;
2124 #endif /* PCVT_SCREENSAVER */
2128 #endif /* !PCVT_KBD_FIFO */
2130 int cols = vsp->maxcol; /* get current col val */
2132 if(n < 0 || n >= totalscreens)
2136 x = spltty(); /* protect us */
2137 #endif /* !PCVT_KBD_FIFO */
2139 if(!oldgrafx && newgrafx)
2141 /* switch from text to graphics */
2143 #if PCVT_SCREENSAVER
2144 if((saved_scrnsv_tmo = scrnsv_timeout))
2145 pcvt_set_scrnsv_tmo(0); /* screensaver off */
2146 #endif /* PCVT_SCREENSAVER */
2148 async_update(UPDATE_STOP); /* status display off */
2153 /* switch from text mode */
2155 /* video board memory -> kernel memory */
2156 bcopy(vsp->Crtat, vsp->Memory,
2157 vsp->screen_rows * vsp->maxcol * CHR);
2159 vsp->Crtat = vsp->Memory; /* operate in memory now */
2162 /* update global screen pointers/variables */
2163 current_video_screen = n; /* current screen no */
2165 #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
2166 pcconsp = &pccons[n]; /* current tty */
2167 #elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200
2168 pcconsp = pccons[n]; /* current tty */
2170 pcconsp = pc_tty[n]; /* current tty */
2173 vsp = &vs[n]; /* current video state ptr */
2175 if(oldgrafx && !newgrafx)
2177 /* switch from graphics to text mode */
2181 for(i = 0; i < totalfonts; i++)
2182 if(saved_charsets[i])
2183 vga_move_charset(i, 0, 0);
2185 #if PCVT_SCREENSAVER
2186 /* activate screen saver */
2187 if(saved_scrnsv_tmo)
2188 pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
2189 #endif /* PCVT_SCREENSAVER */
2191 /* re-initialize lost MDA information */
2192 if(adaptor_type == MDA_ADAPTOR)
2195 * Due to the fact that HGC registers are write-only,
2196 * the Xserver can only make guesses about the state
2197 * the HGC adaptor has been before turning on X mode.
2198 * Thus, the display must be re-enabled now, and the
2199 * cursor shape and location restored.
2201 outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
2202 outb(addr_6845, CRTC_CURSORH); /* select high register */
2204 ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
2205 outb(addr_6845, CRTC_CURSORL); /* select low register */
2207 ((vsp->Crtat + vsp->cur_offset) - Crtat));
2209 outb(addr_6845, CRTC_CURSTART); /* select high register */
2210 outb(addr_6845+1, vsp->cursor_start);
2211 outb(addr_6845, CRTC_CUREND); /* select low register */
2212 outb(addr_6845+1, vsp->cursor_end);
2215 /* make status display happy */
2216 async_update(UPDATE_START);
2223 /* kernel memory -> video board memory */
2224 bcopy(vsp->Crtat, Crtat,
2225 vsp->screen_rows * vsp->maxcol * CHR);
2227 vsp->Crtat = Crtat; /* operate on screen now */
2229 outb(addr_6845, CRTC_STARTADRH);
2230 outb(addr_6845+1, 0);
2231 outb(addr_6845, CRTC_STARTADRL);
2232 outb(addr_6845+1, 0);
2237 #endif /* !PCVT_KBD_FIFO */
2239 select_vga_charset(vsp->vga_charset);
2241 if(vsp->maxcol != cols)
2242 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
2244 outb(addr_6845, CRTC_CURSORH); /* select high register */
2245 outb(addr_6845+1, vsp->cur_offset >> 8);
2246 outb(addr_6845, CRTC_CURSORL); /* select low register */
2247 outb(addr_6845+1, vsp->cur_offset);
2251 outb(addr_6845, CRTC_CURSTART); /* select high register */
2252 outb(addr_6845+1, vsp->cursor_start);
2253 outb(addr_6845, CRTC_CUREND); /* select low register */
2254 outb(addr_6845+1, vsp->cursor_end);
2261 if(adaptor_type == VGA_ADAPTOR)
2265 /* switch VGA DAC palette entries */
2266 for(i = 0; i < NVGAPEL; i++)
2267 vgapaletteio(i, &vsp->palette[i], 1);
2272 update_led(); /* update led's */
2273 update_hp(vsp); /* update fkey labels, if present */
2275 /* if we switch to a vt with force 24 lines mode and */
2276 /* pure VT emulation and 25 rows charset, then we have */
2277 /* to clear the last line on display ... */
2279 if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) &&
2280 (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS))
2282 fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol,
2288 /*---------------------------------------------------------------------------*
2289 * Change specified vt to VT_AUTO mode
2290 * xxx Maybe this should also reset VT_GRAFX mode; since switching and
2291 * graphics modes are not going to work without VT_PROCESS mode.
2292 *---------------------------------------------------------------------------*/
2294 set_auto_mode (struct video_state *vsx)
2296 unsigned ostatus = vsx->vt_status;
2297 vsx->smode.mode = VT_AUTO;
2300 vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK);
2301 if (ostatus & VT_WAIT_ACK) {
2303 assert (!(ostatus&VT_WAIT_REL));
2304 assert (vsp == vsx &&
2305 vt_switch_pending == current_video_screen + 1);
2306 vt_switch_pending = 0;
2309 vt_switch_pending == current_video_screen + 1)
2310 vt_switch_pending = 0;
2313 if (ostatus&VT_WAIT_REL) {
2314 int new_screen = vt_switch_pending - 1;
2316 assert(vsp == vsx && vt_switch_pending);
2317 vt_switch_pending = 0;
2318 vgapage (new_screen);
2320 if (vsp == vsx && vt_switch_pending) {
2321 vt_switch_pending = 0;
2322 vgapage (new_screen);
2328 /*---------------------------------------------------------------------------*
2329 * Exported function; to be called when a vt is closed down.
2331 * Ideally, we would like to be able to recover from an X server crash;
2332 * but in reality, if the server crashes hard while in control of the
2333 * vga board, then you're not likely to be able to use pcvt ttys
2334 * without rebooting.
2335 *---------------------------------------------------------------------------*/
2337 reset_usl_modes (struct video_state *vsx)
2339 /* Clear graphics mode */
2340 if (vsx->vt_status & VT_GRAFX) {
2341 vsx->vt_status &= ~VT_GRAFX;
2343 switch_screen(current_video_screen, 1, 0);
2346 /* Take kbd out of raw mode */
2347 if (pcvt_kbd_raw && vsp == vsx) {
2348 #if PCVT_SCANSET > 1
2350 #endif /* PCVT_SCANSET > 1 */
2354 /* Clear process controlled mode */
2355 set_auto_mode (vsx);
2358 /*---------------------------------------------------------------------------*
2359 * switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version
2360 * (the name vgapage() stands for historical reasons)
2361 *---------------------------------------------------------------------------*/
2363 vgapage(int new_screen)
2367 if(new_screen < 0 || new_screen >= totalscreens)
2370 /* fallback to VT_AUTO if controlling processes died */
2371 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2373 if(vs[new_screen].proc
2374 && vs[new_screen].proc != pfind(vs[new_screen].pid))
2375 set_auto_mode(&vs[new_screen]);
2377 if (!vt_switch_pending && new_screen == current_video_screen)
2380 if(vt_switch_pending && vt_switch_pending != new_screen + 1) {
2381 /* Try resignaling uncooperative X-window servers */
2382 if (vsp->smode.mode == VT_PROCESS) {
2383 if (vsp->vt_status & VT_WAIT_REL) {
2384 if(vsp->smode.relsig)
2385 psignal(vsp->proc, vsp->smode.relsig);
2386 } else if (vsp->vt_status & VT_WAIT_ACK) {
2387 if(vsp->smode.acqsig)
2388 psignal(vsp->proc, vsp->smode.acqsig);
2394 vt_switch_pending = new_screen + 1;
2396 if(vsp->smode.mode == VT_PROCESS)
2398 /* we cannot switch immediately here */
2399 vsp->vt_status |= VT_WAIT_REL;
2400 if(vsp->smode.relsig)
2401 psignal(vsp->proc, vsp->smode.relsig);
2405 struct video_state *old_vsp = vsp;
2407 switch_screen(new_screen,
2408 vsp->vt_status & VT_GRAFX,
2409 vs[new_screen].vt_status & VT_GRAFX);
2412 if(old_vsp->vt_status & VT_WAIT_ACT)
2414 old_vsp->vt_status &= ~VT_WAIT_ACT;
2415 wakeup((caddr_t)&old_vsp->smode);
2417 if(vsp->vt_status & VT_WAIT_ACT)
2419 vsp->vt_status &= ~VT_WAIT_ACT;
2420 wakeup((caddr_t)&vsp->smode);
2424 if(vsp->smode.mode == VT_PROCESS)
2426 /* if _new_ vt is under process control... */
2427 vsp->vt_status |= VT_WAIT_ACK;
2428 if(vsp->smode.acqsig)
2429 psignal(vsp->proc, vsp->smode.acqsig);
2433 /* we are committed */
2434 vt_switch_pending = 0;
2435 #if PCVT_FREEBSD > 206
2437 * XXX: If pcvt is acting as the systems console,
2438 * avoid panics going to the debugger while we are in
2449 /*---------------------------------------------------------------------------*
2450 * ioctl handling for VT_USL mode
2451 *---------------------------------------------------------------------------*/
2453 usl_vt_ioctl(Dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
2455 int i, j, error, opri;
2456 struct vt_mode newmode;
2462 newmode = *(struct vt_mode *)data;
2466 if (newmode.mode != VT_PROCESS) {
2467 struct video_state *vsx = &vs[minor(dev)];
2468 if (vsx->smode.mode == VT_PROCESS) {
2469 if (vsx->proc != p) {
2480 * NB: XFree86-3.1.1 does the following:
2481 * VT_ACTIVATE (vtnum)
2482 * VT_WAITACTIVE (vtnum)
2483 * VT_SETMODE (VT_PROCESS)
2484 * So it is possible that the screen was switched
2485 * between the WAITACTIVE and the SETMODE (here). This
2486 * can actually happen quite frequently, and it was
2487 * leading to dire consequences. Now it is detected by
2488 * requiring that minor(dev) match current_video_screen.
2489 * An alternative would be to operate on vs[minor(dev)]
2490 * instead of *vsp, but that would leave the server
2491 * confused, because it would believe that its vt was
2492 * currently activated.
2494 if (minor(dev) != current_video_screen) {
2499 /* Check for server died */
2500 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2503 /* Check for server already running */
2504 if (vsp->smode.mode == VT_PROCESS && vsp->proc != p)
2507 return EBUSY; /* already in use on this VT */
2510 if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig)
2511 || !ISSIGVALID(newmode.frsig))
2517 vsp->smode = newmode;
2519 vsp->pid = p->p_pid;
2521 #if PCVT_FREEBSD > 206
2523 * XXX: If pcvt is acting as the systems console,
2524 * avoid panics going to the debugger while we are in
2528 cons_unavail = (newmode.mode == VT_PROCESS);
2534 *(struct vt_mode *)data = vsp->smode;
2538 if (minor(dev) != current_video_screen)
2540 if (vsp->smode.mode != VT_PROCESS)
2544 switch(*(int *)data) {
2546 /* process refuses to release screen; abort */
2547 if(vt_switch_pending
2548 && (vsp->vt_status & VT_WAIT_REL)) {
2549 vsp->vt_status &= ~VT_WAIT_REL;
2550 vt_switch_pending = 0;
2556 /* process releases its VT */
2557 if(vt_switch_pending
2558 && (vsp->vt_status & VT_WAIT_REL)) {
2559 int new_screen = vt_switch_pending - 1;
2560 struct video_state *old_vsp = vsp;
2562 vsp->vt_status &= ~VT_WAIT_REL;
2564 switch_screen(new_screen,
2565 vsp->vt_status & VT_GRAFX,
2566 vs[new_screen].vt_status
2570 if(old_vsp->vt_status & VT_WAIT_ACT)
2572 old_vsp->vt_status &= ~VT_WAIT_ACT;
2573 wakeup((caddr_t)&old_vsp->smode);
2575 if(vsp->vt_status & VT_WAIT_ACT)
2577 vsp->vt_status &= ~VT_WAIT_ACT;
2578 wakeup((caddr_t)&vsp->smode);
2582 if(vsp->smode.mode == VT_PROCESS) {
2584 * if the new vt is also in process
2585 * mode, we have to wait until its
2586 * controlling process acknowledged
2591 if(vsp->smode.acqsig)
2597 /* we are committed */
2598 vt_switch_pending = 0;
2599 #if PCVT_FREEBSD > 206
2610 /* new vts controlling process acknowledged */
2611 if(vsp->vt_status & VT_WAIT_ACK) {
2612 vt_switch_pending = 0;
2613 vsp->vt_status &= ~VT_WAIT_ACK;
2614 #if PCVT_FREEBSD > 206
2623 return EINVAL; /* end case VT_RELDISP */
2627 /* return free vt */
2628 for(i = 0; i < PCVT_NSCREENS; i++)
2630 *(int *)data = i + 1;
2636 *(int *)data = current_video_screen + 1;
2640 return vgapage(*(int *)data - 1);
2643 /* sleep until vt switch happened */
2644 i = *(int *)data - 1;
2647 && (i < 0 || i >= PCVT_NSCREENS))
2650 if(i != -1 && current_video_screen == i)
2659 while (current_video_screen != i &&
2660 (error == 0 || error == ERESTART))
2662 vs[i].vt_status |= VT_WAIT_ACT;
2663 error = tsleep((caddr_t)&vs[i].smode,
2664 PZERO | PCATCH, "waitvt", 0);
2671 /* grant the process IO access; only allowed if euid == 0 */
2675 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2676 struct trapframe *fp = p->p_md.md_regs;
2677 #elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2678 struct trapframe *fp = (struct trapframe *)p->p_regs;
2680 struct syscframe *fp = (struct syscframe *)p->p_regs;
2686 if (securelevel > 0)
2689 #if PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2690 fp->tf_eflags |= PSL_IOPL;
2692 fp->sf_eflags |= PSL_IOPL;
2699 /* abandon IO access permission */
2702 #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2703 struct trapframe *fp = p->p_md.md_regs;
2704 fp->tf_eflags &= ~PSL_IOPL;
2705 #elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2706 struct trapframe *fp = (struct trapframe *)p->p_regs;
2707 fp->tf_eflags &= ~PSL_IOPL;
2709 struct syscframe *fp = (struct syscframe *)p->p_regs;
2710 fp->sf_eflags &= ~PSL_IOPL;
2718 struct video_state *vsx = &vs[minor(dev)];
2721 if(adaptor_type != VGA_ADAPTOR
2722 && adaptor_type != MDA_ADAPTOR)
2723 /* X will only run on those adaptors */
2726 /* set text/graphics mode of current vt */
2727 switch(*(int *)data)
2730 haschanged = (vsx->vt_status & VT_GRAFX) != 0;
2731 vsx->vt_status &= ~VT_GRAFX;
2732 if(haschanged && vsx == vsp)
2733 switch_screen(current_video_screen, 1, 0);
2737 /* xxx It might be a good idea to require that
2738 the vt be in process controlled mode here,
2739 and that the calling process is the owner */
2740 haschanged = (vsx->vt_status & VT_GRAFX) == 0;
2741 vsx->vt_status |= VT_GRAFX;
2742 if(haschanged && vsx == vsp)
2743 switch_screen(current_video_screen, 0, 1);
2747 return EINVAL; /* end case KDSETMODE */
2751 /* set keyboard repeat and delay */
2752 return kbdioctl(dev, KBDSTPMAT, data, flag);
2755 switch(*(int *)data)
2759 #if PCVT_SCANSET > 1
2760 /* put keyboard to return ancient PC scan codes */
2762 #endif /* PCVT_SCANSET > 1 */
2765 shift_down = meta_down = altgr_down = ctrl_down = 0;
2770 #if PCVT_SCANSET > 1
2772 #endif /* PCVT_SCANSET > 1 */
2777 return EINVAL; /* end KDSKBMODE */
2780 /* ring the speaker */
2783 int duration = *(int *)data >> 16;
2784 int pitch = *(int *)data & 0xffff;
2789 sysbeep(PCVT_SYSBEEPF / pitch,
2790 duration * hz / 1000);
2792 #else /* PCVT_NETBSD */
2793 sysbeep(pitch, duration * hz / 3000);
2794 #endif /* PCVT_NETBSD */
2799 sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
2804 /* set kbd LED status */
2805 /* unfortunately, the LED definitions between pcvt and */
2806 /* USL differ some way :-( */
2808 j = (i & LED_CAP? KBD_CAPSLOCK: 0)
2809 + (i & LED_NUM? KBD_NUMLOCK: 0)
2810 + (i & LED_SCR? KBD_SCROLLLOCK: 0);
2811 return kbdioctl(dev, KBDSLOCK, (caddr_t)&j, flag);
2814 /* get kbd LED status */
2815 if((error = kbdioctl(dev, KBDGLOCK, (caddr_t)&j, flag)))
2817 i = (j & KBD_CAPSLOCK? LED_CAP: 0)
2818 + (j & KBD_NUMLOCK? LED_NUM: 0)
2819 + (j & KBD_SCROLLLOCK? LED_SCR: 0);
2824 get_usl_keymap((keymap_t *)data);
2826 } /* end case cmd */
2828 return -1; /* inappropriate usl_vt_compat ioctl */
2830 #endif /* PCVT_USL_VT_COMPAT */
2832 #endif /* NVT > 0 */
2834 /* ------------------------- E O F ------------------------------------------*/