proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / dev / video / pcvt / i386 / pcvt_ext.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1999 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: [Mon Dec 27 14:05:16 1999]
46 *
47 * $FreeBSD: src/sys/i386/isa/pcvt/pcvt_ext.c,v 1.17 1999/12/30 16:17:09 hm Exp $
dadab5e9 48 * $DragonFly: src/sys/dev/video/pcvt/i386/Attic/pcvt_ext.c,v 1.3 2003/06/25 03:55:54 dillon Exp $
984263bc
MD
49 *
50 *---------------------------------------------------------------------------*/
51
52#include "vt.h"
53#if NVT > 0
54
55#include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
56
57#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
58
59static int s3testwritable( void );
60static int et4000_col( int );
61static int wd90c11_col( int );
62static int tri9000_col( int );
63static int v7_1024i_col( int );
64static int s3_928_col( int );
65static int cl_gd542x_col( int );
66
67/* storage to save video timing values of 80 columns text mode */
68static 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}
77savearea;
78
79static 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 *---------------------------------------------------------------------------*/
95u_char
96vga_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 *---------------------------------------------------------------------------*/
470static int
471s3testwritable(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 *---------------------------------------------------------------------------*/
499char *
500vga_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 *---------------------------------------------------------------------------*/
544int
545vga_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
634int
635generic_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 *---------------------------------------------------------------------------*/
824int
825et4000_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 *---------------------------------------------------------------------------*/
1003int
1004wd90c11_col(int cols)
1005{
1006
1007#if !PCVT_BACKUP_FONTS
1008 static unsigned char *sv_fontwd[NVGAFONTS];
1009#endif /* !PCVT_BACKUP_FONTS */
1010
1011 u_char *sp;
1012 u_char byte;
1013 int i;
1014
1015 vga_screen_off();
1016
1017 /* enable access to first 7 CRTC registers */
1018
1019 outb(addr_6845, CRTC_VSYNCE);
1020 byte = inb(addr_6845+1);
1021 outb(addr_6845, CRTC_VSYNCE);
1022 outb(addr_6845+1, byte & 0x7f);
1023
1024 /* enable access to WD/Paradise "control extensions" */
1025
1026 outb(GDC_INDEX, GDC_PR5GPLOCK);
1027 outb(GDC_INDEX, 0x05);
1028 outb(addr_6845, CRTC_PR10);
1029 outb(addr_6845, 0x85);
1030 outb(TS_INDEX, TS_UNLOCKSEQ);
1031 outb(TS_DATA, 0x48);
1032
1033 if(cols == SCR_COL132) /* switch 80 -> 132 */
1034 {
1035 /* save state of board for 80 columns */
1036
1037 if(!regsaved)
1038 {
1039 regsaved = 1;
1040
1041 /* save current fonts */
1042
1043#if !PCVT_BACKUP_FONTS
1044 for(i = 0; i < totalfonts; i++)
1045 {
1046 if(vgacs[i].loaded)
1047 {
1048 if((sv_fontwd[i] =
1049 (u_char *)malloc(32 * 256,
1050 M_DEVBUF,
1051 M_WAITOK))
1052 == NULL)
1053 printf("pcvt: no font buffer\n");
1054 else
1055 vga_move_charset(i,
1056 sv_fontwd[i],
1057 1);
1058 }
1059 else
1060 {
1061 sv_fontwd[i] = 0;
1062 }
1063 }
1064
1065#endif /* !PCVT_BACKUP_FONTS */
1066
1067 sp = savearea.wd90c11;
1068
1069 outb(addr_6845, 0x00); /* Horizontal Total */
1070 *sp++ = inb(addr_6845+1);
1071 outb(addr_6845, 0x01); /* Horizontal Display End */
1072 *sp++ = inb(addr_6845+1);
1073 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1074 *sp++ = inb(addr_6845+1);
1075 outb(addr_6845, 0x03); /* Horizontal Blank End */
1076 *sp++ = inb(addr_6845+1);
1077 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1078 *sp++ = inb(addr_6845+1);
1079 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1080 *sp++ = inb(addr_6845+1);
1081
1082 outb(addr_6845, 0x13); /* Row Offset Register */
1083 *sp++ = inb(addr_6845+1);
1084
1085 outb(addr_6845, 0x2e); /* misc 1 */
1086 *sp++ = inb(addr_6845+1);
1087 outb(addr_6845, 0x2f); /* misc 2 */
1088 *sp++ = inb(addr_6845+1);
1089
1090 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1091 *sp++ = inb(TS_DATA);
1092 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1093 *sp++ = inb(TS_DATA);
1094
1095 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1096 }
1097
1098 /* setup chipset for 132 column operation */
1099
1100 outb(addr_6845, 0x00); /* Horizontal Total */
1101 outb(addr_6845+1, 0x9c);
1102 outb(addr_6845, 0x01); /* Horizontal Display End */
1103 outb(addr_6845+1, 0x83);
1104 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1105 outb(addr_6845+1, 0x84);
1106 outb(addr_6845, 0x03); /* Horizontal Blank End */
1107 outb(addr_6845+1, 0x9f);
1108 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1109 outb(addr_6845+1, 0x8a);
1110 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1111 outb(addr_6845+1, 0x1c);
1112
1113 outb(addr_6845, 0x13); /* Row Offset Register */
1114 outb(addr_6845+1, 0x42);
1115
1116 outb(addr_6845, 0x2e); /* misc 1 */
1117 outb(addr_6845+1, 0x04);
1118 outb(addr_6845, 0x2f); /* misc 2 */
1119 outb(addr_6845+1, 0x00);
1120
1121 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1122 outb(TS_DATA, 0x21);
1123 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1124 outb(TS_DATA, 0x14);
1125
1126 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x08)); /* Misc output register */
1127
1128 vsp->wd132col = 1;
1129 }
1130 else /* switch 132 -> 80 */
1131 {
1132 if(!regsaved) /* failsafe */
1133 {
1134 /* disable access to first 7 CRTC registers */
1135
1136 outb(addr_6845, CRTC_VSYNCE);
1137 outb(addr_6845+1, byte);
1138
1139 /* disable access to WD/Paradise "control extensions" */
1140
1141 outb(GDC_INDEX, GDC_PR5GPLOCK);
1142 outb(GDC_INDEX, 0x00);
1143 outb(addr_6845, CRTC_PR10);
1144 outb(addr_6845, 0x00);
1145 outb(TS_INDEX, TS_UNLOCKSEQ);
1146 outb(TS_DATA, 0x00);
1147
1148 vga_screen_on();
1149
1150 return(0);
1151 }
1152
1153 sp = savearea.wd90c11;
1154
1155 outb(addr_6845, 0x00); /* Horizontal Total */
1156 outb(addr_6845+1, *sp++);
1157 outb(addr_6845, 0x01); /* Horizontal Display End */
1158 outb(addr_6845+1, *sp++);
1159 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1160 outb(addr_6845+1, *sp++);
1161 outb(addr_6845, 0x03); /* Horizontal Blank End */
1162 outb(addr_6845+1, *sp++);
1163 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1164 outb(addr_6845+1, *sp++);
1165 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1166 outb(addr_6845+1, *sp++);
1167
1168 outb(addr_6845, 0x13); /* Row Offset Register */
1169 outb(addr_6845+1, *sp++);
1170
1171 outb(addr_6845, 0x2e); /* misc 1 */
1172 outb(addr_6845+1, *sp++);
1173 outb(addr_6845, 0x2f); /* misc 2 */
1174 outb(addr_6845+1, *sp++);
1175
1176 outb(TS_INDEX, 0x10);/* Timing Sequencer */
1177 outb(addr_6845+1, *sp++);
1178 outb(TS_INDEX, 0x12);/* Timing Sequencer */
1179 outb(addr_6845+1, *sp++);
1180
1181 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1182
1183 vsp->wd132col = 0;
1184 }
1185
1186 /* restore fonts */
1187
1188#if !PCVT_BACKUP_FONTS
1189 for(i = 0; i < totalfonts; i++)
1190 {
1191 if(sv_fontwd[i])
1192 vga_move_charset(i, sv_fontwd[i], 0);
1193 }
1194#else
1195 for(i = 0; i < totalfonts; i++)
1196 if(saved_charsets[i])
1197 vga_move_charset(i, 0, 0);
1198#endif /* !PCVT_BACKUP_FONTS */
1199
1200 select_vga_charset(vsp->vga_charset);
1201
1202 /* disable access to first 7 CRTC registers */
1203
1204 outb(addr_6845, CRTC_VSYNCE);
1205 outb(addr_6845+1, byte);
1206
1207 /* disable access to WD/Paradise "control extensions" */
1208
1209 outb(GDC_INDEX, GDC_PR5GPLOCK);
1210 outb(GDC_INDEX, 0x00);
1211 outb(addr_6845, CRTC_PR10);
1212 outb(addr_6845, 0x00);
1213 outb(TS_INDEX, TS_UNLOCKSEQ);
1214 outb(TS_DATA, 0x00);
1215
1216 vga_screen_on();
1217
1218 return(1);
1219}
1220
1221/*---------------------------------------------------------------------------*
1222 * toggle 80/132 column operation for TRIDENT 9000 based boards
1223 *---------------------------------------------------------------------------*/
1224int
1225tri9000_col(int cols)
1226{
1227 u_char *sp;
1228 u_char byte;
1229
1230 vga_screen_off();
1231
1232 /* sync reset is necessary to preserve memory contents ... */
1233
1234 outb(TS_INDEX, TS_SYNCRESET);
1235 outb(TS_DATA, 0x01); /* synchronous reset */
1236
1237 /* disable protection of misc out and other regs */
1238
1239 outb(addr_6845, CRTC_MTEST);
1240 byte = inb(addr_6845+1);
1241 outb(addr_6845, CRTC_MTEST);
1242 outb(addr_6845+1, byte & ~0x50);
1243
1244 /* enable access to first 7 CRTC registers */
1245
1246 outb(addr_6845, CRTC_VSYNCE);
1247 byte = inb(addr_6845+1);
1248 outb(addr_6845, CRTC_VSYNCE);
1249 outb(addr_6845+1, byte & 0x7f);
1250
1251 if(cols == SCR_COL132) /* switch 80 -> 132 */
1252 {
1253 /* save state of board for 80 columns */
1254
1255 if(!regsaved)
1256 {
1257 regsaved = 1;
1258
1259 sp = savearea.tri9000;
1260
1261 outb(addr_6845, 0x00); /* Horizontal Total */
1262 *sp++ = inb(addr_6845+1);
1263 outb(addr_6845, 0x01); /* Horizontal Display End */
1264 *sp++ = inb(addr_6845+1);
1265 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1266 *sp++ = inb(addr_6845+1);
1267 outb(addr_6845, 0x03); /* Horizontal Blank End */
1268 *sp++ = inb(addr_6845+1);
1269 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1270 *sp++ = inb(addr_6845+1);
1271 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1272 *sp++ = inb(addr_6845+1);
1273
1274 outb(addr_6845, 0x13);
1275 *sp++ = inb(addr_6845+1);
1276
1277 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1278 *sp++ = inb(TS_DATA);
1279
1280 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1281 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1282 outb(TS_INDEX, TS_MODEC2);
1283 *sp++ = inb(TS_DATA);
1284
1285 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1286 inb(TS_DATA); /* read switches to NEW */
1287 outb(TS_INDEX, TS_MODEC2);
1288 *sp++ = inb(TS_DATA);
1289
1290 if(color)
1291 inb(GN_INPSTAT1C);
1292 else
1293 inb(GN_INPSTAT1M);
1294 /* ATC Mode control */
1295 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1296 *sp++ = inb(ATC_DATAR);
1297
1298 if(color)
1299 inb(GN_INPSTAT1C);
1300 else
1301 inb(GN_INPSTAT1M);
1302 /* ATC Horizontal Pixel Panning */
1303 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1304 *sp++ = inb(ATC_DATAR);
1305
1306 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1307 }
1308
1309 /* setup chipset for 132 column operation */
1310
1311 outb(addr_6845, 0x00); /* Horizontal Total */
1312 outb(addr_6845+1, 0x9b);
1313 outb(addr_6845, 0x01); /* Horizontal Display End */
1314 outb(addr_6845+1, 0x83);
1315 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1316 outb(addr_6845+1, 0x84);
1317 outb(addr_6845, 0x03); /* Horizontal Blank End */
1318 outb(addr_6845+1, 0x1e);
1319 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1320 outb(addr_6845+1, 0x87);
1321 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1322 outb(addr_6845+1, 0x1a);
1323
1324 outb(addr_6845, 0x13); /* Row Offset Register */
1325 outb(addr_6845+1, 0x42);
1326
1327 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1328 outb(TS_DATA, 0x01); /* 8 dot char clock */
1329
1330 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1331 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1332 outb(TS_INDEX, TS_MODEC2);
1333 outb(TS_DATA, 0x00);
1334
1335 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1336 inb(TS_DATA); /* read switches to NEW */
1337 outb(TS_INDEX, TS_MODEC2);
1338 outb(TS_DATA, 0x01);
1339
1340 if(color)
1341 inb(GN_INPSTAT1C);
1342 else
1343 inb(GN_INPSTAT1M);
1344 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1345 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1346
1347 if(color)
1348 inb(GN_INPSTAT1C);
1349 else
1350 inb(GN_INPSTAT1M);
1351 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1352 outb(ATC_DATAW, 0x00);
1353
1354 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c)); /* Misc output register */
1355 }
1356 else /* switch 132 -> 80 */
1357 {
1358 if(!regsaved) /* failsafe */
1359 {
1360 /* disable access to first 7 CRTC registers */
1361 outb(addr_6845, CRTC_VSYNCE);
1362 outb(addr_6845+1, byte);
1363
1364 outb(TS_INDEX, TS_SYNCRESET);
1365 outb(TS_DATA, 0x03); /* clear synchronous reset */
1366
1367 vga_screen_on();
1368
1369 return(0);
1370 }
1371
1372 sp = savearea.tri9000;
1373
1374 outb(addr_6845, 0x00); /* Horizontal Total */
1375 outb(addr_6845+1, *sp++);
1376 outb(addr_6845, 0x01); /* Horizontal Display End */
1377 outb(addr_6845+1, *sp++);
1378 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1379 outb(addr_6845+1, *sp++);
1380 outb(addr_6845, 0x03); /* Horizontal Blank End */
1381 outb(addr_6845+1, *sp++);
1382 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1383 outb(addr_6845+1, *sp++);
1384 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1385 outb(addr_6845+1, *sp++);
1386
1387 outb(addr_6845, 0x13); /* Row Offset Register */
1388 outb(addr_6845+1, *sp++);
1389
1390 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1391 outb(TS_DATA, *sp++);
1392
1393 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1394 outb(TS_DATA, 0x00); /* write ANYTHING switches to OLD */
1395 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1396 outb(TS_DATA, *sp++);
1397
1398 outb(TS_INDEX, TS_HWVERS);/* Hardware Version register */
1399 inb(TS_DATA); /* read switches to NEW */
1400 outb(TS_INDEX, TS_MODEC2);/* Timing Sequencer */
1401 outb(TS_DATA, *sp++);
1402
1403 if(color)
1404 inb(GN_INPSTAT1C);
1405 else
1406 inb(GN_INPSTAT1M);
1407 /* ATC Mode control */
1408 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1409 outb(ATC_DATAW, *sp++);
1410
1411 if(color)
1412 inb(GN_INPSTAT1C);
1413 else
1414 inb(GN_INPSTAT1M);
1415 /* ATC Horizontal Pixel Panning */
1416 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1417 outb(ATC_DATAW, *sp++);
1418
1419 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1420 }
1421
1422 /* disable access to first 7 CRTC registers */
1423
1424 outb(addr_6845, CRTC_VSYNCE);
1425 outb(addr_6845+1, byte);
1426
1427 outb(TS_INDEX, TS_SYNCRESET);
1428 outb(TS_DATA, 0x03); /* clear synchronous reset */
1429
1430 vga_screen_on();
1431
1432 return(1);
1433}
1434
1435/*---------------------------------------------------------------------------*
1436 * toggle 80/132 column operation for Video7 VGA 1024i
1437 *---------------------------------------------------------------------------*/
1438int
1439v7_1024i_col(int cols)
1440{
1441 u_char *sp;
1442 u_char byte;
1443 u_char save__byte;
1444
1445 vga_screen_off();
1446
1447 /* enable access to first 7 CRTC registers */
1448
1449 /* first, enable read access to vertical retrace start/end */
1450 outb(addr_6845, CRTC_HBLANKE);
1451 byte = inb(addr_6845+1);
1452 outb(addr_6845, CRTC_HBLANKE);
1453 outb(addr_6845+1, (byte | 0x80));
1454
1455 /* second, enable access to protected registers */
1456 outb(addr_6845, CRTC_VSYNCE);
1457 save__byte = byte = inb(addr_6845+1);
1458 byte |= 0x20; /* no irq 2 */
1459 byte &= 0x6f; /* wr enable, clr irq flag */
1460 outb(addr_6845, CRTC_VSYNCE);
1461 outb(addr_6845+1, byte);
1462
1463 outb(TS_INDEX, TS_EXTCNTL); /* enable extensions */
1464 outb(TS_DATA, 0xea);
1465
1466
1467 if(cols == SCR_COL132) /* switch 80 -> 132 */
1468 {
1469 /* save state of board for 80 columns */
1470
1471 if(!regsaved)
1472 {
1473 regsaved = 1;
1474
1475 sp = savearea.v7_1024i;
1476
1477 outb(addr_6845, 0x00); /* Horizontal Total */
1478 *sp++ = inb(addr_6845+1);
1479 outb(addr_6845, 0x01); /* Horizontal Display End */
1480 *sp++ = inb(addr_6845+1);
1481 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1482 *sp++ = inb(addr_6845+1);
1483 outb(addr_6845, 0x03); /* Horizontal Blank End */
1484 *sp++ = inb(addr_6845+1);
1485 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1486 *sp++ = inb(addr_6845+1);
1487 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1488 *sp++ = inb(addr_6845+1);
1489
1490 outb(addr_6845, 0x13); /* Row Offset Register */
1491 *sp++ = inb(addr_6845+1);
1492
1493 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1494 *sp++ = inb(TS_DATA);
1495
1496 if(color)
1497 inb(GN_INPSTAT1C);
1498 else
1499 inb(GN_INPSTAT1M);
1500 /* ATC Mode control */
1501 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1502 *sp++ = inb(ATC_DATAR);
1503
1504 if(color)
1505 inb(GN_INPSTAT1C);
1506 else
1507 inb(GN_INPSTAT1M);
1508 /* ATC Horizontal Pixel Panning */
1509 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1510 *sp++ = inb(ATC_DATAR);
1511
1512 outb(TS_INDEX, 0x83);
1513 *sp++ = inb(TS_DATA);
1514
1515 outb(TS_INDEX, 0xa4);
1516 *sp++ = inb(TS_DATA);
1517
1518 outb(TS_INDEX, 0xe0);
1519 *sp++ = inb(TS_DATA);
1520
1521 outb(TS_INDEX, 0xe4);
1522 *sp++ = inb(TS_DATA);
1523
1524 outb(TS_INDEX, 0xf8);
1525 *sp++ = inb(TS_DATA);
1526
1527 outb(TS_INDEX, 0xfd);
1528 *sp++ = inb(TS_DATA);
1529
1530 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1531 }
1532
1533 /* setup chipset for 132 column operation */
1534
1535 outb(addr_6845, 0x00); /* Horizontal Total */
1536 outb(addr_6845+1, 0x9c);
1537 outb(addr_6845, 0x01); /* Horizontal Display End */
1538 outb(addr_6845+1, 0x83);
1539 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1540 outb(addr_6845+1, 0x86);
1541 outb(addr_6845, 0x03); /* Horizontal Blank End */
1542 outb(addr_6845+1, 0x9e);
1543 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1544 outb(addr_6845+1, 0x89);
1545 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1546 outb(addr_6845+1, 0x1c);
1547
1548 outb(addr_6845, 0x13); /* Row Offset Register */
1549 outb(addr_6845+1, 0x42);
1550
1551 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1552 outb(TS_DATA, 0x01); /* 8 dot char clock */
1553
1554 if(color)
1555 inb(GN_INPSTAT1C);
1556 else
1557 inb(GN_INPSTAT1M);
1558 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1559 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1560
1561 if(color)
1562 inb(GN_INPSTAT1C);
1563 else
1564 inb(GN_INPSTAT1M);
1565 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1566 outb(ATC_DATAW, 0x00);
1567
1568 outb(TS_INDEX, TS_SYNCRESET);
1569 outb(TS_DATA, 0x01); /* synchronous reset */
1570
1571 outb(TS_INDEX, 0x83);
1572 outb(TS_DATA, 0xa0);
1573
1574 outb(TS_INDEX, 0xa4);
1575 outb(TS_DATA, 0x1c);
1576
1577 outb(TS_INDEX, 0xe0);
1578 outb(TS_DATA, 0x00);
1579
1580 outb(TS_INDEX, 0xe4);
1581 outb(TS_DATA, 0xfe);
1582
1583 outb(TS_INDEX, 0xf8);
1584 outb(TS_DATA, 0x1b);
1585
1586 outb(TS_INDEX, 0xfd);
1587 outb(TS_DATA, 0x33);
1588
1589 byte = inb(GN_MISCOUTR);
1590 byte |= 0x0c;
1591 outb(GN_MISCOUTW, byte); /* Misc output register */
1592
1593 outb(TS_INDEX, TS_SYNCRESET);
1594 outb(TS_DATA, 0x03); /* clear synchronous reset */
1595 }
1596 else /* switch 132 -> 80 */
1597 {
1598 if(!regsaved) /* failsafe */
1599 {
1600 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1601 outb(TS_DATA, 0xae);
1602
1603 /* disable access to first 7 CRTC registers */
1604 outb(addr_6845, CRTC_VSYNCE);
1605 outb(addr_6845+1, byte);
1606 vga_screen_on();
1607 return(0);
1608 }
1609
1610 sp = savearea.v7_1024i;
1611
1612 outb(addr_6845, 0x00); /* Horizontal Total */
1613 outb(addr_6845+1, *sp++);
1614 outb(addr_6845, 0x01); /* Horizontal Display End */
1615 outb(addr_6845+1, *sp++);
1616 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1617 outb(addr_6845+1, *sp++);
1618 outb(addr_6845, 0x03); /* Horizontal Blank End */
1619 outb(addr_6845+1, *sp++);
1620 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1621 outb(addr_6845+1, *sp++);
1622 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1623 outb(addr_6845+1, *sp++);
1624
1625 outb(addr_6845, 0x13); /* Row Offset Register */
1626 outb(addr_6845+1, *sp++);
1627
1628 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1629 outb(TS_DATA, *sp++);
1630
1631 if(color)
1632 inb(GN_INPSTAT1C);
1633 else
1634 inb(GN_INPSTAT1M);
1635 /* ATC Mode control */
1636 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1637 outb(ATC_DATAW, *sp++);
1638
1639 if(color)
1640 inb(GN_INPSTAT1C);
1641 else
1642 inb(GN_INPSTAT1M);
1643 /* ATC Horizontal Pixel Panning */
1644 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1645 outb(ATC_DATAW, *sp++);
1646
1647 outb(TS_INDEX, TS_SYNCRESET);
1648 outb(TS_DATA, 0x01); /* synchronous reset */
1649
1650 outb(TS_INDEX, 0x83);
1651 outb(TS_DATA, *sp++);
1652
1653 outb(TS_INDEX, 0xa4);
1654 outb(TS_DATA, *sp++);
1655
1656 outb(TS_INDEX, 0xe0);
1657 outb(TS_DATA, *sp++);
1658
1659 outb(TS_INDEX, 0xe4);
1660 outb(TS_DATA, *sp++);
1661
1662 outb(TS_INDEX, 0xf8);
1663 outb(TS_DATA, *sp++);
1664
1665 outb(TS_INDEX, 0xfd);
1666 outb(TS_DATA, *sp++);
1667
1668 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1669
1670 outb(TS_INDEX, TS_SYNCRESET);
1671 outb(TS_DATA, 0x03); /* clear synchronous reset */
1672 }
1673
1674 outb(TS_INDEX, TS_EXTCNTL); /* disable extensions */
1675 outb(TS_DATA, 0xae);
1676
1677 /* disable access to first 7 CRTC registers */
1678
1679 outb(addr_6845, CRTC_VSYNCE);
1680 outb(addr_6845+1, save__byte);
1681
1682 vga_screen_on();
1683
1684 return(1);
1685}
1686
1687/*---------------------------------------------------------------------------*
1688 * toggle 80/132 column operation for S3 86C928 based boards
1689 *---------------------------------------------------------------------------*/
1690int
1691s3_928_col(int cols)
1692{
1693 u_char *sp;
1694 u_char byte;
1695
1696 vga_screen_off();
1697
1698 outb(addr_6845, 0x38);
1699 outb(addr_6845+1, 0x48); /* unlock registers */
1700 outb(addr_6845, 0x39);
1701 outb(addr_6845+1, 0xa0); /* unlock registers */
1702
1703 /* enable access to first 7 CRTC registers */
1704
1705 outb(addr_6845, CRTC_VSYNCE);
1706 byte = inb(addr_6845+1);
1707 outb(addr_6845, CRTC_VSYNCE);
1708 outb(addr_6845+1, byte & 0x7f);
1709
1710 if(cols == SCR_COL132) /* switch 80 -> 132 */
1711 {
1712 /* save state of board for 80 columns */
1713
1714 if(!regsaved)
1715 {
1716 regsaved = 1;
1717
1718 sp = savearea.s3_928;
1719
1720 outb(addr_6845, 0x00); /* Horizontal Total */
1721 *sp++ = inb(addr_6845+1);
1722 outb(addr_6845, 0x01); /* Horizontal Display End */
1723 *sp++ = inb(addr_6845+1);
1724 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1725 *sp++ = inb(addr_6845+1);
1726 outb(addr_6845, 0x03); /* Horizontal Blank End */
1727 *sp++ = inb(addr_6845+1);
1728 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1729 *sp++ = inb(addr_6845+1);
1730 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1731 *sp++ = inb(addr_6845+1);
1732
1733 outb(addr_6845, 0x13); /* Row Offset Register */
1734 *sp++ = inb(addr_6845+1);
1735
1736 outb(addr_6845, 0x34); /* Backward Compat 3 Reg */
1737 *sp++ = inb(addr_6845+1);
1738 outb(addr_6845, 0x3b); /* Data Xfer Exec Position */
1739 *sp++ = inb(addr_6845+1);
1740
1741 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1742 *sp++ = inb(addr_6845+1);
1743
1744 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1745 *sp++ = inb(TS_DATA);
1746
1747 if(color)
1748 inb(GN_INPSTAT1C);
1749 else
1750 inb(GN_INPSTAT1M);
1751 /* ATC Mode control */
1752 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1753 *sp++ = inb(ATC_DATAR);
1754
1755 if(color)
1756 inb(GN_INPSTAT1C);
1757 else
1758 inb(GN_INPSTAT1M);
1759 /* ATC Horizontal Pixel Panning */
1760 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1761 *sp++ = inb(ATC_DATAR);
1762
1763 *sp++ = inb(GN_MISCOUTR); /* Misc output register */
1764 }
1765
1766 /* setup chipset for 132 column operation */
1767
1768 outb(addr_6845, 0x00); /* Horizontal Total */
1769 outb(addr_6845+1, 0x9a);
1770 outb(addr_6845, 0x01); /* Horizontal Display End */
1771 outb(addr_6845+1, 0x83);
1772 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1773 outb(addr_6845+1, 0x86);
1774 outb(addr_6845, 0x03); /* Horizontal Blank End */
1775 outb(addr_6845+1, 0x9d);
1776 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1777 outb(addr_6845+1, 0x87);
1778 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1779 outb(addr_6845+1, 0x1b);
1780
1781 outb(addr_6845, 0x13); /* Row Offset Register */
1782 outb(addr_6845+1, 0x42);
1783
1784 outb(addr_6845, 0x34);
1785 outb(addr_6845+1, 0x10);/* enable data xfer pos control */
1786 outb(addr_6845, 0x3b);
1787 outb(addr_6845+1, 0x90);/* set data xfer pos value */
1788
1789 outb(addr_6845, 0x42); /* (Clock) Mode Control */
1790 outb(addr_6845+1, 0x02);/* Select 40MHz Clock */
1791
1792 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1793 outb(TS_DATA, 0x01); /* 8 dot char clock */
1794
1795 if(color)
1796 inb(GN_INPSTAT1C);
1797 else
1798 inb(GN_INPSTAT1M);
1799 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
1800 outb(ATC_DATAW, 0x08); /* Line graphics disable */
1801
1802 if(color)
1803 inb(GN_INPSTAT1C);
1804 else
1805 inb(GN_INPSTAT1M);
1806 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
1807 outb(ATC_DATAW, 0x00);
1808
1809 /* Misc output register */
1810
1811 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) | 0x0c));
1812 }
1813 else /* switch 132 -> 80 */
1814 {
1815 if(!regsaved) /* failsafe */
1816 {
1817 /* disable access to first 7 CRTC registers */
1818 outb(addr_6845, CRTC_VSYNCE);
1819 outb(addr_6845+1, byte);
1820
1821 outb(addr_6845, 0x38);
1822 outb(addr_6845+1, 0x00); /* lock registers */
1823 outb(addr_6845, 0x39);
1824 outb(addr_6845+1, 0x00); /* lock registers */
1825
1826 vga_screen_on();
1827 return(0);
1828 }
1829
1830 sp = savearea.s3_928;
1831
1832 outb(addr_6845, 0x00); /* Horizontal Total */
1833 outb(addr_6845+1, *sp++);
1834 outb(addr_6845, 0x01); /* Horizontal Display End */
1835 outb(addr_6845+1, *sp++);
1836 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1837 outb(addr_6845+1, *sp++);
1838 outb(addr_6845, 0x03); /* Horizontal Blank End */
1839 outb(addr_6845+1, *sp++);
1840 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1841 outb(addr_6845+1, *sp++);
1842 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1843 outb(addr_6845+1, *sp++);
1844
1845 outb(addr_6845, 0x13); /* Row Offset Register */
1846 outb(addr_6845+1, *sp++);
1847
1848 outb(addr_6845, 0x34);
1849 outb(addr_6845+1, *sp++);
1850 outb(addr_6845, 0x3b);
1851 outb(addr_6845+1, *sp++);
1852
1853 outb(addr_6845, 0x42); /* Mode control */
1854 outb(addr_6845+1, *sp++);
1855
1856 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1857 outb(TS_DATA, *sp++);
1858
1859 if(color)
1860 inb(GN_INPSTAT1C);
1861 else
1862 inb(GN_INPSTAT1M);
1863 /* ATC Mode control */
1864 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1865 outb(ATC_DATAW, *sp++);
1866
1867 if(color)
1868 inb(GN_INPSTAT1C);
1869 else
1870 inb(GN_INPSTAT1M);
1871 /* ATC Horizontal Pixel Panning */
1872 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1873 outb(ATC_DATAW, *sp++);
1874
1875 outb(GN_MISCOUTW, *sp++); /* Misc output register */
1876 }
1877
1878 /* disable access to first 7 CRTC registers */
1879
1880 outb(addr_6845, CRTC_VSYNCE);
1881 outb(addr_6845+1, byte);
1882
1883 outb(addr_6845, 0x38);
1884 outb(addr_6845+1, 0x00); /* lock registers */
1885 outb(addr_6845, 0x39);
1886 outb(addr_6845+1, 0x00); /* lock registers */
1887
1888 vga_screen_on();
1889
1890 return(1);
1891}
1892
1893/*---------------------------------------------------------------------------*
1894 * toggle 80/132 column operation for Cirrus Logic 542x based boards
1895 *---------------------------------------------------------------------------*/
1896int
1897cl_gd542x_col(int cols)
1898{
1899 u_char *sp;
1900 u_char byte;
1901
1902 vga_screen_off();
1903
1904 /* enable access to first 7 CRTC registers */
1905
1906 outb(addr_6845, CRTC_VSYNCE);
1907 byte = inb(addr_6845+1);
1908 outb(addr_6845, CRTC_VSYNCE);
1909 outb(addr_6845+1, byte & 0x7f);
1910
1911 /* enable access to cirrus extension registers */
1912 outb(TS_INDEX, 6);
1913 outb(TS_DATA, 0x12);
1914
1915 if(cols == SCR_COL132) /* switch 80 -> 132 */
1916 {
1917 /* save state of board for 80 columns */
1918
1919 if(!regsaved)
1920 {
1921 regsaved = 1;
1922
1923 sp = savearea.cirrus;
1924
1925 outb(addr_6845, 0x00); /* Horizontal Total */
1926 *sp++ = inb(addr_6845+1);
1927 outb(addr_6845, 0x01); /* Horizontal Display End */
1928 *sp++ = inb(addr_6845+1);
1929 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1930 *sp++ = inb(addr_6845+1);
1931 outb(addr_6845, 0x03); /* Horizontal Blank End */
1932 *sp++ = inb(addr_6845+1);
1933 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1934 *sp++ = inb(addr_6845+1);
1935 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1936 *sp++ = inb(addr_6845+1);
1937
1938 outb(addr_6845, 0x13); /* Row Offset Register */
1939 *sp++ = inb(addr_6845+1);
1940
1941 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
1942 *sp++ = inb(TS_DATA);
1943
1944
1945 if(color)
1946 inb(GN_INPSTAT1C);
1947 else
1948 inb(GN_INPSTAT1M);
1949 /* ATC Mode control */
1950 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
1951 *sp++ = inb(ATC_DATAR);
1952
1953 if(color)
1954 inb(GN_INPSTAT1C);
1955 else
1956 inb(GN_INPSTAT1M);
1957 /* ATC Horizontal Pixel Panning */
1958 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
1959 *sp++ = inb(ATC_DATAR);
1960
1961 /* VCLK2 Numerator Register */
1962 outb(TS_INDEX, 0xd);
1963 *sp++ = inb(TS_DATA);
1964
1965 /* VCLK2 Denominator and Post-Scalar Value Register */
1966 outb(TS_INDEX, 0x1d);
1967 *sp++ = inb(TS_DATA);
1968
1969 /* Misc output register */
1970 *sp++ = inb(GN_MISCOUTR);
1971 }
1972
1973 /* setup chipset for 132 column operation */
1974
1975 outb(addr_6845, 0x00); /* Horizontal Total */
1976 outb(addr_6845+1, 0x9f);
1977 outb(addr_6845, 0x01); /* Horizontal Display End */
1978 outb(addr_6845+1, 0x83);
1979 outb(addr_6845, 0x02); /* Horizontal Blank Start */
1980 outb(addr_6845+1, 0x84);
1981 outb(addr_6845, 0x03); /* Horizontal Blank End */
1982 outb(addr_6845+1, 0x82);
1983 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
1984 outb(addr_6845+1, 0x8a);
1985 outb(addr_6845, 0x05); /* Horizontal Retrace End */
1986 outb(addr_6845+1, 0x9e);
1987
1988 outb(addr_6845, 0x13); /* Row Offset Register */
1989 outb(addr_6845+1, 0x42);
1990
1991 /* set VCLK2 to 41.164 MHz ..... */
1992 outb(TS_INDEX, 0xd); /* VCLK2 Numerator Register */
1993 outb(TS_DATA, 0x45);
1994
1995 outb(TS_INDEX, 0x1d); /* VCLK2 Denominator and */
1996 outb(TS_DATA, 0x30); /* Post-Scalar Value Register */
1997
1998 /* and use it. */
1999 outb(GN_MISCOUTW, (inb(GN_MISCOUTR) & ~0x0c) | (2 << 2));
2000
2001 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2002 outb(TS_DATA, 0x01); /* 8 dot char clock */
2003
2004 if(color)
2005 inb(GN_INPSTAT1C);
2006 else
2007 inb(GN_INPSTAT1M);
2008 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS); /* ATC Mode control */
2009 outb(ATC_DATAW, 0x08); /* Line graphics disable */
2010
2011 if(color)
2012 inb(GN_INPSTAT1C);
2013 else
2014 inb(GN_INPSTAT1M);
2015 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS); /* ATC Horizontal Pixel Panning */
2016 outb(ATC_DATAW, 0x00);
2017 }
2018 else /* switch 132 -> 80 */
2019 {
2020 if(!regsaved) /* failsafe */
2021 {
2022 /* disable access to first 7 CRTC registers */
2023 outb(addr_6845, CRTC_VSYNCE);
2024 outb(addr_6845+1, byte);
2025
2026 /* disable access to cirrus extension registers */
2027 outb(TS_INDEX, 6);
2028 outb(TS_DATA, 0);
2029
2030 vga_screen_on();
2031 return(0);
2032 }
2033
2034 sp = savearea.cirrus;
2035
2036 outb(addr_6845, 0x00); /* Horizontal Total */
2037 outb(addr_6845+1, *sp++);
2038 outb(addr_6845, 0x01); /* Horizontal Display End */
2039 outb(addr_6845+1, *sp++);
2040 outb(addr_6845, 0x02); /* Horizontal Blank Start */
2041 outb(addr_6845+1, *sp++);
2042 outb(addr_6845, 0x03); /* Horizontal Blank End */
2043 outb(addr_6845+1, *sp++);
2044 outb(addr_6845, 0x04); /* Horizontal Retrace Start */
2045 outb(addr_6845+1, *sp++);
2046 outb(addr_6845, 0x05); /* Horizontal Retrace End */
2047 outb(addr_6845+1, *sp++);
2048
2049 outb(addr_6845, 0x13); /* Row Offset Register */
2050 outb(addr_6845+1, *sp++);
2051
2052 outb(TS_INDEX, TS_MODE);/* Timing Sequencer */
2053 outb(TS_DATA, *sp++);
2054
2055 if(color)
2056 inb(GN_INPSTAT1C);
2057 else
2058 inb(GN_INPSTAT1M);
2059 /* ATC Mode control */
2060 outb(ATC_INDEX, ATC_MODE | ATC_ACCESS);
2061 outb(ATC_DATAW, *sp++);
2062
2063 if(color)
2064 inb(GN_INPSTAT1C);
2065 else
2066 inb(GN_INPSTAT1M);
2067 /* ATC Horizontal Pixel Panning */
2068 outb(ATC_INDEX, ATC_HORPIXPAN | ATC_ACCESS);
2069 outb(ATC_DATAW, *sp++);
2070
2071 /* VCLK2 Numerator Register */
2072 outb(TS_INDEX, 0xd);
2073 outb(TS_DATA, *sp++);
2074
2075 /* VCLK2 Denominator and Post-Scalar Value Register */
2076 outb(TS_INDEX, 0x1d);
2077 outb(TS_DATA, *sp++);
2078
2079 outb(GN_MISCOUTW, *sp++); /* Misc output register */
2080 }
2081
2082 /* disable access to cirrus extension registers */
2083 outb(TS_INDEX, 6);
2084 outb(TS_DATA, 0);
2085
2086 /* disable access to first 7 CRTC registers */
2087
2088 outb(addr_6845, CRTC_VSYNCE);
2089 outb(addr_6845+1, byte);
2090
2091 vga_screen_on();
2092
2093 return(1);
2094}
2095
2096#if PCVT_USL_VT_COMPAT
2097/*---------------------------------------------------------------------------*
2098 * switch screen from text mode to X-mode and vice versa
2099 *---------------------------------------------------------------------------*/
2100void
2101switch_screen(int n, int oldgrafx, int newgrafx)
2102{
2103
2104#if PCVT_SCREENSAVER
2105 static unsigned saved_scrnsv_tmo = 0;
2106#endif /* PCVT_SCREENSAVER */
2107
2108#if !PCVT_KBD_FIFO
2109 int x;
2110#endif /* !PCVT_KBD_FIFO */
2111
2112 int cols = vsp->maxcol; /* get current col val */
2113
2114 if(n < 0 || n >= totalscreens)
2115 return;
2116
2117#if !PCVT_KBD_FIFO
2118 x = spltty(); /* protect us */
2119#endif /* !PCVT_KBD_FIFO */
2120
2121 if(!oldgrafx && newgrafx)
2122 {
2123 /* switch from text to graphics */
2124
2125#if PCVT_SCREENSAVER
2126 if((saved_scrnsv_tmo = scrnsv_timeout))
2127 pcvt_set_scrnsv_tmo(0); /* screensaver off */
2128#endif /* PCVT_SCREENSAVER */
2129
2130 async_update(UPDATE_STOP); /* status display off */
2131 }
2132
2133 if(!oldgrafx)
2134 {
2135 /* switch from text mode */
2136
2137 /* video board memory -> kernel memory */
2138 bcopy(vsp->Crtat, vsp->Memory,
2139 vsp->screen_rows * vsp->maxcol * CHR);
2140
2141 vsp->Crtat = vsp->Memory; /* operate in memory now */
2142 }
2143
2144 /* update global screen pointers/variables */
2145 current_video_screen = n; /* current screen no */
2146
2147#if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
2148 pcconsp = &pccons[n]; /* current tty */
2149#elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200
2150 pcconsp = pccons[n]; /* current tty */
2151#else
2152 pcconsp = pc_tty[n]; /* current tty */
2153#endif
2154
2155 vsp = &vs[n]; /* current video state ptr */
2156
2157 if(oldgrafx && !newgrafx)
2158 {
2159 /* switch from graphics to text mode */
2160 unsigned i;
2161
2162 /* restore fonts */
2163 for(i = 0; i < totalfonts; i++)
2164 if(saved_charsets[i])
2165 vga_move_charset(i, 0, 0);
2166
2167#if PCVT_SCREENSAVER
2168 /* activate screen saver */
2169 if(saved_scrnsv_tmo)
2170 pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
2171#endif /* PCVT_SCREENSAVER */
2172
2173 /* re-initialize lost MDA information */
2174 if(adaptor_type == MDA_ADAPTOR)
2175 {
2176 /*
2177 * Due to the fact that HGC registers are write-only,
2178 * the Xserver can only make guesses about the state
2179 * the HGC adaptor has been before turning on X mode.
2180 * Thus, the display must be re-enabled now, and the
2181 * cursor shape and location restored.
2182 */
2183 outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
2184 outb(addr_6845, CRTC_CURSORH); /* select high register */
2185 outb(addr_6845+1,
2186 ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
2187 outb(addr_6845, CRTC_CURSORL); /* select low register */
2188 outb(addr_6845+1,
2189 ((vsp->Crtat + vsp->cur_offset) - Crtat));
2190
2191 outb(addr_6845, CRTC_CURSTART); /* select high register */
2192 outb(addr_6845+1, vsp->cursor_start);
2193 outb(addr_6845, CRTC_CUREND); /* select low register */
2194 outb(addr_6845+1, vsp->cursor_end);
2195 }
2196
2197 /* make status display happy */
2198 async_update(UPDATE_START);
2199 }
2200
2201 if(!newgrafx)
2202 {
2203 /* to text mode */
2204
2205 /* kernel memory -> video board memory */
2206 bcopy(vsp->Crtat, Crtat,
2207 vsp->screen_rows * vsp->maxcol * CHR);
2208
2209 vsp->Crtat = Crtat; /* operate on screen now */
2210
2211 outb(addr_6845, CRTC_STARTADRH);
2212 outb(addr_6845+1, 0);
2213 outb(addr_6845, CRTC_STARTADRL);
2214 outb(addr_6845+1, 0);
2215 }
2216
2217#if !PCVT_KBD_FIFO
2218 splx(x);
2219#endif /* !PCVT_KBD_FIFO */
2220
2221 select_vga_charset(vsp->vga_charset);
2222
2223 if(vsp->maxcol != cols)
2224 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
2225
2226 outb(addr_6845, CRTC_CURSORH); /* select high register */
2227 outb(addr_6845+1, vsp->cur_offset >> 8);
2228 outb(addr_6845, CRTC_CURSORL); /* select low register */
2229 outb(addr_6845+1, vsp->cur_offset);
2230
2231 if(vsp->cursor_on)
2232 {
2233 outb(addr_6845, CRTC_CURSTART); /* select high register */
2234 outb(addr_6845+1, vsp->cursor_start);
2235 outb(addr_6845, CRTC_CUREND); /* select low register */
2236 outb(addr_6845+1, vsp->cursor_end);
2237 }
2238 else
2239 {
2240 sw_cursor(0);
2241 }
2242
2243 if(adaptor_type == VGA_ADAPTOR)
2244 {
2245 unsigned i;
2246
2247 /* switch VGA DAC palette entries */
2248 for(i = 0; i < NVGAPEL; i++)
2249 vgapaletteio(i, &vsp->palette[i], 1);
2250 }
2251
2252 if(!newgrafx)
2253 {
2254 update_led(); /* update led's */
2255 update_hp(vsp); /* update fkey labels, if present */
2256
2257 /* if we switch to a vt with force 24 lines mode and */
2258 /* pure VT emulation and 25 rows charset, then we have */
2259 /* to clear the last line on display ... */
2260
2261 if(vsp->force24 && (vsp->vt_pure_mode == M_PUREVT) &&
2262 (vgacs[vsp->vga_charset].screen_size == SIZ_25ROWS))
2263 {
2264 fillw(' ', vsp->Crtat + vsp->screen_rows * vsp->maxcol,
2265 vsp->maxcol);
2266 }
2267 }
2268}
2269
2270/*---------------------------------------------------------------------------*
2271 * Change specified vt to VT_AUTO mode
2272 * xxx Maybe this should also reset VT_GRAFX mode; since switching and
2273 * graphics modes are not going to work without VT_PROCESS mode.
2274 *---------------------------------------------------------------------------*/
2275static void
2276set_auto_mode (struct video_state *vsx)
2277{
2278 unsigned ostatus = vsx->vt_status;
2279 vsx->smode.mode = VT_AUTO;
2280 vsx->proc = NULL;
2281 vsx->pid = 0;
2282 vsx->vt_status &= ~(VT_WAIT_REL|VT_WAIT_ACK);
2283 if (ostatus & VT_WAIT_ACK) {
2284#if 0
2285 assert (!(ostatus&VT_WAIT_REL));
2286 assert (vsp == vsx &&
2287 vt_switch_pending == current_video_screen + 1);
2288 vt_switch_pending = 0;
2289#else
2290 if (vsp == vsx &&
2291 vt_switch_pending == current_video_screen + 1)
2292 vt_switch_pending = 0;
2293#endif
2294 }
2295 if (ostatus&VT_WAIT_REL) {
2296 int new_screen = vt_switch_pending - 1;
2297#if 0
2298 assert(vsp == vsx && vt_switch_pending);
2299 vt_switch_pending = 0;
2300 vgapage (new_screen);
2301#else
2302 if (vsp == vsx && vt_switch_pending) {
2303 vt_switch_pending = 0;
2304 vgapage (new_screen);
2305 }
2306#endif
2307 }
2308}
2309
2310/*---------------------------------------------------------------------------*
2311 * Exported function; to be called when a vt is closed down.
2312 *
2313 * Ideally, we would like to be able to recover from an X server crash;
2314 * but in reality, if the server crashes hard while in control of the
2315 * vga board, then you're not likely to be able to use pcvt ttys
2316 * without rebooting.
2317 *---------------------------------------------------------------------------*/
2318void
2319reset_usl_modes (struct video_state *vsx)
2320{
2321 /* Clear graphics mode */
2322 if (vsx->vt_status & VT_GRAFX) {
2323 vsx->vt_status &= ~VT_GRAFX;
2324 if (vsp == vsx)
2325 switch_screen(current_video_screen, 1, 0);
2326 }
2327
2328 /* Take kbd out of raw mode */
2329 if (pcvt_kbd_raw && vsp == vsx) {
2330#if PCVT_SCANSET > 1
2331 kbd_emulate_pc(0);
2332#endif /* PCVT_SCANSET > 1 */
2333 pcvt_kbd_raw = 0;
2334 }
2335
2336 /* Clear process controlled mode */
2337 set_auto_mode (vsx);
2338}
2339
2340/*---------------------------------------------------------------------------*
2341 * switch to virtual screen n (0 ... PCVT_NSCREENS-1), VT_USL version
2342 * (the name vgapage() stands for historical reasons)
2343 *---------------------------------------------------------------------------*/
2344int
2345vgapage(int new_screen)
2346{
2347 int x;
2348
2349 if(new_screen < 0 || new_screen >= totalscreens)
2350 return EINVAL;
2351
2352 /* fallback to VT_AUTO if controlling processes died */
2353 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2354 set_auto_mode(vsp);
2355
2356 if(vs[new_screen].proc
2357 && vs[new_screen].proc != pfind(vs[new_screen].pid))
2358 set_auto_mode(&vs[new_screen]);
2359
2360 if (!vt_switch_pending && new_screen == current_video_screen)
2361 return 0;
2362
2363 if(vt_switch_pending && vt_switch_pending != new_screen + 1) {
2364 /* Try resignaling uncooperative X-window servers */
2365 if (vsp->smode.mode == VT_PROCESS) {
2366 if (vsp->vt_status & VT_WAIT_REL) {
2367 if(vsp->smode.relsig)
2368 psignal(vsp->proc, vsp->smode.relsig);
2369 } else if (vsp->vt_status & VT_WAIT_ACK) {
2370 if(vsp->smode.acqsig)
2371 psignal(vsp->proc, vsp->smode.acqsig);
2372 }
2373 }
2374 return EAGAIN;
2375 }
2376
2377 vt_switch_pending = new_screen + 1;
2378
2379 if(vsp->smode.mode == VT_PROCESS)
2380 {
2381 /* we cannot switch immediately here */
2382 vsp->vt_status |= VT_WAIT_REL;
2383 if(vsp->smode.relsig)
2384 psignal(vsp->proc, vsp->smode.relsig);
2385 }
2386 else
2387 {
2388 struct video_state *old_vsp = vsp;
2389
2390 switch_screen(new_screen,
2391 vsp->vt_status & VT_GRAFX,
2392 vs[new_screen].vt_status & VT_GRAFX);
2393
2394 x = spltty();
2395
2396 if(old_vsp->vt_status & VT_WAIT_ACT)
2397 {
2398 old_vsp->vt_status &= ~VT_WAIT_ACT;
2399 wakeup((caddr_t)&old_vsp->smode);
2400 }
2401
2402 if(vsp->vt_status & VT_WAIT_ACT)
2403 {
2404 vsp->vt_status &= ~VT_WAIT_ACT;
2405 wakeup((caddr_t)&vsp->smode);
2406 }
2407
2408 splx(x);
2409
2410 if(vsp->smode.mode == VT_PROCESS)
2411 {
2412 /* if _new_ vt is under process control... */
2413 vsp->vt_status |= VT_WAIT_ACK;
2414 if(vsp->smode.acqsig)
2415 psignal(vsp->proc, vsp->smode.acqsig);
2416 }
2417 else
2418 {
2419 /* we are committed */
2420 vt_switch_pending = 0;
2421
2422#if PCVT_FREEBSD > 206
2423 /*
2424 * XXX: If pcvt is acting as the systems console,
2425 * avoid panics going to the debugger while we are in
2426 * process mode.
2427 */
2428 if(pcvt_is_console)
2429 cons_unavail = 0;
2430#endif
2431 }
2432 }
2433 return 0;
2434}
2435
2436/*---------------------------------------------------------------------------*
2437 * ioctl handling for VT_USL mode
2438 *---------------------------------------------------------------------------*/
2439int
2440usl_vt_ioctl(Dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
2441{
2442 int i, j, error, opri;
2443 struct vt_mode newmode;
2444
2445 switch(cmd)
2446 {
2447
2448 case VT_SETMODE:
2449 newmode = *(struct vt_mode *)data;
2450
2451 opri = spltty();
2452
2453 if (newmode.mode != VT_PROCESS) {
2454 struct video_state *vsx = &vs[minor(dev)];
2455 if (vsx->smode.mode == VT_PROCESS) {
2456 if (vsx->proc != p) {
2457 splx(opri);
2458 return EPERM;
2459 }
2460 set_auto_mode(vsx);
2461 }
2462 splx(opri);
2463 return 0;
2464 }
2465
2466 /*
2467 * NB: XFree86-3.1.1 does the following:
2468 * VT_ACTIVATE (vtnum)
2469 * VT_WAITACTIVE (vtnum)
2470 * VT_SETMODE (VT_PROCESS)
2471 * So it is possible that the screen was switched
2472 * between the WAITACTIVE and the SETMODE (here). This
2473 * can actually happen quite frequently, and it was
2474 * leading to dire consequences. Now it is detected by
2475 * requiring that minor(dev) match current_video_screen.
2476 * An alternative would be to operate on vs[minor(dev)]
2477 * instead of *vsp, but that would leave the server
2478 * confused, because it would believe that its vt was
2479 * currently activated.
2480 */
2481 if (minor(dev) != current_video_screen) {
2482 splx(opri);
2483 return EPERM;
2484 }
2485
2486 /* Check for server died */
2487 if(vsp->proc && vsp->proc != pfind(vsp->pid))
2488 set_auto_mode(vsp);
2489
2490 /* Check for server already running */
2491 if (vsp->smode.mode == VT_PROCESS && vsp->proc != p)
2492 {
2493 splx(opri);
2494 return EBUSY; /* already in use on this VT */
2495 }
2496
2497 if (!ISSIGVALID(newmode.relsig) || !ISSIGVALID(newmode.acqsig)
2498 || !ISSIGVALID(newmode.frsig))
2499 {
2500 splx(opri);
2501 return EINVAL;
2502 }
2503
2504 vsp->smode = newmode;
2505 vsp->proc = p;
2506 vsp->pid = p->p_pid;
2507
2508#if PCVT_FREEBSD > 206
2509 /*
2510 * XXX: If pcvt is acting as the systems console,
2511 * avoid panics going to the debugger while we are in
2512 * process mode.
2513 */
2514 if(pcvt_is_console)
2515 cons_unavail = (newmode.mode == VT_PROCESS);
2516#endif
2517 splx(opri);
2518 return 0;
2519
2520 case VT_GETMODE:
2521 *(struct vt_mode *)data = vsp->smode;
2522 return 0;
2523
2524 case VT_RELDISP:
2525 if (minor(dev) != current_video_screen)
2526 return EPERM;
2527 if (vsp->smode.mode != VT_PROCESS)
2528 return EINVAL;
2529 if (vsp->proc != p)
2530 return EPERM;
2531 switch(*(int *)data) {
2532 case VT_FALSE:
2533 /* process refuses to release screen; abort */
2534 if(vt_switch_pending
2535 && (vsp->vt_status & VT_WAIT_REL)) {
2536 vsp->vt_status &= ~VT_WAIT_REL;
2537 vt_switch_pending = 0;
2538 return 0;
2539 }
2540 break;
2541
2542 case VT_TRUE:
2543 /* process releases its VT */
2544 if(vt_switch_pending
2545 && (vsp->vt_status & VT_WAIT_REL)) {
2546 int new_screen = vt_switch_pending - 1;
2547 struct video_state *old_vsp = vsp;
2548
2549 vsp->vt_status &= ~VT_WAIT_REL;
2550
2551 switch_screen(new_screen,
2552 vsp->vt_status & VT_GRAFX,
2553 vs[new_screen].vt_status
2554 & VT_GRAFX);
2555
2556 opri = spltty();
2557 if(old_vsp->vt_status & VT_WAIT_ACT)
2558 {
2559 old_vsp->vt_status &= ~VT_WAIT_ACT;
2560 wakeup((caddr_t)&old_vsp->smode);
2561 }
2562 if(vsp->vt_status & VT_WAIT_ACT)
2563 {
2564 vsp->vt_status &= ~VT_WAIT_ACT;
2565 wakeup((caddr_t)&vsp->smode);
2566 }
2567 splx(opri);
2568
2569 if(vsp->smode.mode == VT_PROCESS) {
2570 /*
2571 * if the new vt is also in process
2572 * mode, we have to wait until its
2573 * controlling process acknowledged
2574 * the switch
2575 */
2576 vsp->vt_status
2577 |= VT_WAIT_ACK;
2578 if(vsp->smode.acqsig)
2579 psignal(vsp->proc,
2580 vsp->smode.acqsig);
2581 }
2582 else
2583 {
2584 /* we are committed */
2585 vt_switch_pending = 0;
2586#if PCVT_FREEBSD > 206
2587 /* XXX */
2588 if(pcvt_is_console)
2589 cons_unavail = 0;
2590#endif
2591 }
2592 return 0;
2593 }
2594 break;
2595
2596 case VT_ACKACQ:
2597 /* new vts controlling process acknowledged */
2598 if(vsp->vt_status & VT_WAIT_ACK) {
2599 vt_switch_pending = 0;
2600 vsp->vt_status &= ~VT_WAIT_ACK;
2601#if PCVT_FREEBSD > 206
2602 /* XXX */
2603 if(pcvt_is_console)
2604 cons_unavail = 1;
2605#endif
2606 return 0;
2607 }
2608 break;
2609 }
2610 return EINVAL; /* end case VT_RELDISP */
2611
2612
2613 case VT_OPENQRY:
2614 /* return free vt */
2615 for(i = 0; i < PCVT_NSCREENS; i++)
2616 if(!vs[i].openf) {
2617 *(int *)data = i + 1;
2618 return 0;
2619 }
2620 return EAGAIN;
2621
2622 case VT_GETACTIVE:
2623 *(int *)data = current_video_screen + 1;
2624 return 0;
2625
2626 case VT_ACTIVATE:
2627 return vgapage(*(int *)data - 1);
2628
2629 case VT_WAITACTIVE:
2630 /* sleep until vt switch happened */
2631 i = *(int *)data - 1;
2632
2633 if(i != -1
2634 && (i < 0 || i >= PCVT_NSCREENS))
2635 return EINVAL;
2636
2637 if(i != -1 && current_video_screen == i)
2638 return 0;
2639
2640 if(i == -1)
2641 i = minor(dev);
2642
2643 {
2644 int x = spltty();
2645 error = 0;
2646 while (current_video_screen != i &&
2647 (error == 0 || error == ERESTART))
2648 {
2649 vs[i].vt_status |= VT_WAIT_ACT;
2650 error = tsleep((caddr_t)&vs[i].smode,
2651 PZERO | PCATCH, "waitvt", 0);
2652 }
2653 splx(x);
2654 }
2655 return error;
2656
2657 case KDENABIO:
2658 /* grant the process IO access; only allowed if euid == 0 */
2659 /* and insecure */
2660 {
2661
2662#if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2663 struct trapframe *fp = p->p_md.md_regs;
2664#elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2665 struct trapframe *fp = (struct trapframe *)p->p_regs;
2666#else
2667 struct syscframe *fp = (struct syscframe *)p->p_regs;
2668#endif
2669
dadab5e9 2670 error = suser(td);
984263bc
MD
2671 if (error != 0)
2672 return (error);
2673 if (securelevel > 0)
2674 return (EPERM);
2675
2676#if PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2677 fp->tf_eflags |= PSL_IOPL;
2678#else
2679 fp->sf_eflags |= PSL_IOPL;
2680#endif
2681
2682 return 0;
2683 }
2684
2685 case KDDISABIO:
2686 /* abandon IO access permission */
2687 {
2688
2689#if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
2690 struct trapframe *fp = p->p_md.md_regs;
2691 fp->tf_eflags &= ~PSL_IOPL;
2692#elif PCVT_NETBSD || (PCVT_FREEBSD && PCVT_FREEBSD > 102)
2693 struct trapframe *fp = (struct trapframe *)p->p_regs;
2694 fp->tf_eflags &= ~PSL_IOPL;
2695#else
2696 struct syscframe *fp = (struct syscframe *)p->p_regs;
2697 fp->sf_eflags &= ~PSL_IOPL;
2698#endif
2699
2700 return 0;
2701 }
2702
2703 case KDSETMODE:
2704 {
2705 struct video_state *vsx = &vs[minor(dev)];
2706 int haschanged = 0;
2707
2708 if(adaptor_type != VGA_ADAPTOR
2709 && adaptor_type != MDA_ADAPTOR)
2710 /* X will only run on those adaptors */
2711 return (EINVAL);
2712
2713 /* set text/graphics mode of current vt */
2714 switch(*(int *)data)
2715 {
2716 case KD_TEXT:
2717 haschanged = (vsx->vt_status & VT_GRAFX) != 0;
2718 vsx->vt_status &= ~VT_GRAFX;
2719 if(haschanged && vsx == vsp)
2720 switch_screen(current_video_screen, 1, 0);
2721 return 0;
2722
2723 case KD_GRAPHICS:
2724 /* xxx It might be a good idea to require that
2725 the vt be in process controlled mode here,
2726 and that the calling process is the owner */
2727 haschanged = (vsx->vt_status & VT_GRAFX) == 0;
2728 vsx->vt_status |= VT_GRAFX;
2729 if(haschanged && vsx == vsp)
2730 switch_screen(current_video_screen, 0, 1);
2731 return 0;
2732
2733 }
2734 return EINVAL; /* end case KDSETMODE */
2735 }
2736
2737 case KDSETRAD:
2738 /* set keyboard repeat and delay */
2739 return kbdioctl(dev, KBDSTPMAT, data, flag);
2740
2741 case KDSKBMODE:
2742 switch(*(int *)data)
2743 {
2744 case K_RAW:
2745
2746#if PCVT_SCANSET > 1
2747 /* put keyboard to return ancient PC scan codes */
2748 kbd_emulate_pc(1);
2749#endif /* PCVT_SCANSET > 1 */
2750
2751 pcvt_kbd_raw = 1;
2752 shift_down = meta_down = altgr_down = ctrl_down = 0;
2753 return 0;
2754
2755 case K_XLATE:
2756
2757#if PCVT_SCANSET > 1
2758 kbd_emulate_pc(0);
2759#endif /* PCVT_SCANSET > 1 */
2760
2761 pcvt_kbd_raw = 0;
2762 return 0;
2763 }
2764 return EINVAL; /* end KDSKBMODE */
2765
2766 case KDMKTONE:
2767 /* ring the speaker */
2768 if(data)
2769 {
2770 int duration = *(int *)data >> 16;
2771 int pitch = *(int *)data & 0xffff;
2772
2773#if PCVT_NETBSD
2774 if(pitch != 0)
2775 {
2776 sysbeep(PCVT_SYSBEEPF / pitch,
2777 duration * hz / 1000);
2778 }
2779#else /* PCVT_NETBSD */
2780 sysbeep(pitch, duration * hz / 3000);
2781#endif /* PCVT_NETBSD */
2782
2783 }
2784 else
2785 {
2786 sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
2787 }
2788 return 0;
2789
2790 case KDSETLED:
2791 /* set kbd LED status */
2792 /* unfortunately, the LED definitions between pcvt and */
2793 /* USL differ some way :-( */
2794 i = *(int *)data;
2795 j = (i & LED_CAP? KBD_CAPSLOCK: 0)
2796 + (i & LED_NUM? KBD_NUMLOCK: 0)
2797 + (i & LED_SCR? KBD_SCROLLLOCK: 0);
2798 return kbdioctl(dev, KBDSLOCK, (caddr_t)&j, flag);
2799
2800 case KDGETLED:
2801 /* get kbd LED status */
2802 if((error = kbdioctl(dev, KBDGLOCK, (caddr_t)&j, flag)))
2803 return error;
2804 i = (j & KBD_CAPSLOCK? LED_CAP: 0)
2805 + (j & KBD_NUMLOCK? LED_NUM: 0)
2806 + (j & KBD_SCROLLLOCK? LED_SCR: 0);
2807 *(int *)data = i;
2808 return 0;
2809
2810 case GIO_KEYMAP:
2811 get_usl_keymap((keymap_t *)data);
2812 return 0;
2813 } /* end case cmd */
2814
2815 return -1; /* inappropriate usl_vt_compat ioctl */
2816}
2817#endif /* PCVT_USL_VT_COMPAT */
2818
2819#endif /* NVT > 0 */
2820
2821/* ------------------------- E O F ------------------------------------------*/
2822