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