Register keyword removal
[dragonfly.git] / sys / dev / video / pcvt / i386 / pcvt_sup.c
1 /*
2  * Copyright (c) 1999 Hellmuth Michaelis
3  *
4  * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
5  *
6  * Copyright (c) 1992, 1993 Brian Dunford-Shore and Scott Turner.
7  *
8  * Copyright (C) 1992, 1993 Soeren Schmidt.
9  *
10  * All rights reserved.
11  *
12  * For the sake of compatibility, portions of this code regarding the
13  * X server interface are taken from Soeren Schmidt's syscons driver.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. All advertising materials mentioning features or use of this software
24  *    must display the following acknowledgement:
25  *      This product includes software developed by Hellmuth Michaelis,
26  *      Brian Dunford-Shore, Joerg Wunsch, Scott Turner and Soeren Schmidt.
27  * 4. The name authors may not be used to endorse or promote products
28  *    derived from this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
31  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41
42 /*---------------------------------------------------------------------------*
43  *
44  *      pcvt_sup.c      VT220 Driver Support Routines
45  *      ---------------------------------------------
46  *
47  *      Last Edit-Date: [Thu Dec 30 17:01:03 1999]
48  *
49  * $FreeBSD: src/sys/i386/isa/pcvt/pcvt_sup.c,v 1.16 1999/12/30 16:17:10 hm Exp $
50  * $DragonFly: src/sys/dev/video/pcvt/i386/Attic/pcvt_sup.c,v 1.3 2003/07/26 19:07:49 rob Exp $
51  *
52  *---------------------------------------------------------------------------*/
53
54 #include "vt.h"
55 #if NVT > 0
56
57 #include <i386/isa/pcvt/pcvt_hdr.h>     /* global include */
58
59 #include <sys/resource.h>
60
61 static void vid_cursor ( struct cursorshape *data );
62 static void vgasetfontattr ( struct vgafontattr *data );
63 static void vgagetfontattr ( struct vgafontattr *data );
64 static void vgaloadchar ( struct vgaloadchar *data );
65 static void vid_getscreen ( struct screeninfo *data, Dev_t dev );
66 static void vid_setscreen ( struct screeninfo *data, Dev_t dev );
67 static void setchargen ( void );
68 static void setchargen3 ( void );
69 static void resetchargen ( void );
70 static void vgareadpel ( struct vgapel *data, Dev_t dev );
71 static void vgawritepel ( struct vgapel *data, Dev_t dev );
72 static void vgapcvtid ( struct pcvtid *data );
73 static void vgapcvtinfo ( struct pcvtinfo *data );
74
75 #ifdef XSERVER
76 static unsigned char * compute_charset_base ( unsigned fontset );
77 #endif /* XSERVER */
78
79 static struct callout_handle async_update_ch =
80     CALLOUT_HANDLE_INITIALIZER(&async_update_ch);
81
82 #if PCVT_SCREENSAVER
83 static void scrnsv_timedout ( void *arg );
84 static struct callout_handle scrnsv_timeout_ch =
85     CALLOUT_HANDLE_INITIALIZER(&scrnsv_timeout_ch);
86 static u_short *savedscreen = (u_short *)0;     /* ptr to screen contents */
87 static size_t scrnsv_size = (size_t)-1;         /* size of saved image */
88
89 #ifndef XSERVER
90 static unsigned scrnsv_timeout = 0;             /* initially off */
91 static void pcvt_set_scrnsv_tmo ( int timeout );/* else declared global */
92 #endif /* XSERVER */
93
94 #if PCVT_PRETTYSCRNS
95 static u_short *scrnsv_current = (u_short *)0;  /* attention char ptr */
96 static struct callout_handle scrnsv_blink_ch =
97     CALLOUT_HANDLE_INITIALIZER(&scrnsv_blink_ch);
98 static void scrnsv_blink ( void * );
99 static u_short getrand ( void );
100 #endif /* PCVT_PRETTYSCRNS */
101
102 #endif /* PCVT_SCREENSAVER */
103
104
105 /*---------------------------------------------------------------------------*
106  *      execute vga ioctls
107  *---------------------------------------------------------------------------*/
108 int
109 vgaioctl(Dev_t dev, int cmd, caddr_t data, int flag)
110 {
111         if(minor(dev) >= PCVT_NSCREENS)
112                 return -1;
113
114 /*
115  * Some of the commands are not applicable if the vt in question, or the
116  * current vt is in graphics mode (i.e., the X server acts on it); they
117  * will cause an EAGAIN (resource temporarily unavailable) to be returned.
118  */
119
120 #ifdef XSERVER
121 #if PCVT_USL_VT_COMPAT
122 #define is_dev_grafx vs[minor(dev)].vt_status & VT_GRAFX
123 #define is_current_grafx vsp->vt_status & VT_GRAFX
124 #else   /* old X interface */
125 #define is_dev_grafx pcvt_xmode
126 #define is_current_grafx pcvt_xmode
127 #endif /* PCVT_USL_VT_COMPAT */
128 #else /* !XSERVER */
129 #define is_dev_grafx 0  /* not applicable */
130 #define is_current_grafx 0
131 #endif /* XSERVER */
132
133         switch(cmd)
134         {
135                 case VGACURSOR:
136                         if(is_current_grafx)
137                                 return EAGAIN;
138                         vid_cursor((struct cursorshape *)data);
139                         break;
140
141                 case VGALOADCHAR:
142                         if((adaptor_type != VGA_ADAPTOR) &&
143                            (adaptor_type != EGA_ADAPTOR))
144                                 return -1;
145                         if(is_current_grafx)
146                                 return EAGAIN;
147                         vgaloadchar((struct vgaloadchar *)data);
148                         break;
149
150                 case VGASETFONTATTR:
151                         if((adaptor_type != VGA_ADAPTOR) &&
152                            (adaptor_type != EGA_ADAPTOR))
153                                 return -1;
154
155 #if PCVT_SCREENSAVER
156                         pcvt_scrnsv_reset();
157 #endif /* PCVT_SCREENSAVER */
158
159                         vgasetfontattr((struct vgafontattr *)data);
160                         break;
161
162                 case VGAGETFONTATTR:
163                         if((adaptor_type != VGA_ADAPTOR) &&
164                            (adaptor_type != EGA_ADAPTOR))
165                                 return -1;
166                         vgagetfontattr((struct vgafontattr *)data);
167                         break;
168
169                 case VGASETSCREEN:
170
171 #if defined XSERVER && !PCVT_USL_VT_COMPAT
172                         /* avoid screen switch if using old X mode */
173                         if(is_dev_grafx)
174                                 return EAGAIN;
175 #endif /* XSERVER && !PCVT_USL_VT_COMPAT */
176
177 #if PCVT_SCREENSAVER
178                         pcvt_scrnsv_reset();
179 #endif /* PCVT_SCREENSAVER */
180
181                         vid_setscreen((struct screeninfo *)data, dev);
182                         break;
183
184                 case VGAGETSCREEN:
185                         vid_getscreen((struct screeninfo *)data, dev);
186                         break;
187
188                 case VGAREADPEL:
189                         if(adaptor_type != VGA_ADAPTOR)
190                                 return -1;
191                         if(is_dev_grafx)
192                                 return EAGAIN;
193                         vgareadpel((struct vgapel *)data, dev);
194                         break;
195
196                 case VGAWRITEPEL:
197                         if(adaptor_type != VGA_ADAPTOR)
198                                 return -1;
199                         if(is_dev_grafx)
200                                 return EAGAIN;
201                         vgawritepel((struct vgapel *)data, dev);
202                         break;
203
204 #if PCVT_SCREENSAVER
205                 case VGASCREENSAVER:
206                         if(is_current_grafx)
207                                 return EAGAIN;
208                         pcvt_set_scrnsv_tmo(*(int *)data);
209                         pcvt_scrnsv_reset();
210                         break;
211 #endif /* PCVT_SCREENSAVER */
212
213                 case VGAPCVTID:
214                         vgapcvtid((struct pcvtid *)data);
215                         break;
216
217                 case VGAPCVTINFO:
218                         vgapcvtinfo((struct pcvtinfo *)data);
219                         break;
220
221                 case VGASETCOLMS:
222                         if(is_dev_grafx)
223                                 return EAGAIN;
224                         if(*(int *)data == 80)
225                                 (void)vt_col(&vs[minor(dev)], SCR_COL80);
226                         else if(*(int *)data == 132)
227                         {
228                                 if(vt_col(&vs[minor(dev)], SCR_COL132) == 0)
229                                         return EINVAL; /* not a VGA */
230                         }
231                         else
232                                 return EINVAL;
233                         break;
234
235 #if 0                   
236                 case SETSCROLLSIZE:
237                         reallocate_scrollbuffer(vsp, *(u_short *)data);
238                         break;
239 #endif
240
241                 case TIOCSWINSZ:
242                         /* do nothing here */
243                         break;
244
245                 default:
246                         return -1;
247         }
248         return 0;
249
250 #undef is_dev_grafx
251 #undef is_current_grafx
252 }
253
254 /*---------------------------------------------------------------------------*
255  *      video ioctl - return driver id
256  *---------------------------------------------------------------------------*/
257 static void
258 vgapcvtid(struct pcvtid *data)
259 {
260         snprintf(data->name, sizeof(data->name), "%s", PCVTIDNAME);
261         data->rmajor    = PCVTIDMAJOR;
262         data->rminor    = PCVTIDMINOR;
263 }
264
265 /*---------------------------------------------------------------------------*
266  *      video ioctl - return driver compile time options data
267  *---------------------------------------------------------------------------*/
268 static void
269 vgapcvtinfo(struct pcvtinfo *data)
270 {
271 #if PCVT_NETBSD
272         data->opsys     = CONF_NETBSD;
273         data->opsysrel  = PCVT_NETBSD;
274 #elif PCVT_FREEBSD
275         data->opsys     = CONF_FREEBSD;
276         data->opsysrel  = PCVT_FREEBSD;
277 #else
278         data->opsys     = CONF_UNKNOWNOPSYS;
279         data->opsysrel  = 0;
280 #endif
281
282         data->nscreens  = PCVT_NSCREENS;
283         data->scanset   = PCVT_SCANSET;
284         data->updatefast= PCVT_UPDATEFAST;
285         data->updateslow= PCVT_UPDATESLOW;
286         data->sysbeepf  = PCVT_SYSBEEPF;
287
288 #if PCVT_NETBSD || PCVT_FREEBSD >= 200
289         data->pcburst   = PCVT_PCBURST;
290 #else
291         data->pcburst   = 1;
292 #endif
293
294 #if PCVT_KBD_FIFO
295         data->kbd_fifo_sz = PCVT_KBD_FIFO_SZ;
296 #else
297         data->kbd_fifo_sz = 0;
298 #endif
299
300         data->compile_opts = (0
301
302 #if PCVT_VT220KEYB
303         | CONF_VT220KEYB
304 #endif
305 #if PCVT_SCREENSAVER
306         | CONF_SCREENSAVER
307 #endif
308 #if PCVT_PRETTYSCRNS
309         | CONF_PRETTYSCRNS
310 #endif
311 #if PCVT_CTRL_ALT_DEL
312         | CONF_CTRL_ALT_DEL
313 #endif
314 #if PCVT_USEKBDSEC
315         | CONF_USEKBDSEC
316 #endif
317 #if PCVT_24LINESDEF
318         | CONF_24LINESDEF
319 #endif
320 #if PCVT_EMU_MOUSE
321         | CONF_EMU_MOUSE
322 #endif
323 #if PCVT_SHOWKEYS
324         | CONF_SHOWKEYS
325 #endif
326 #if PCVT_KEYBDID
327         | CONF_KEYBDID
328 #endif
329 #if PCVT_SIGWINCH
330         | CONF_SIGWINCH
331 #endif
332 #if PCVT_NULLCHARS
333         | CONF_NULLCHARS
334 #endif
335 #if PCVT_BACKUP_FONTS
336         | CONF_BACKUP_FONTS
337 #endif
338 #if PCVT_SW0CNOUTP      /* was FORCE8BIT */
339         | CONF_SW0CNOUTP
340 #endif
341 #if PCVT_SETCOLOR
342         | CONF_SETCOLOR
343 #endif
344 #if PCVT_132GENERIC
345         | CONF_132GENERIC
346 #endif
347 #if PCVT_PALFLICKER
348         | CONF_PALFLICKER
349 #endif
350 #if PCVT_WAITRETRACE
351         | CONF_WAITRETRACE
352 #endif
353 #ifdef XSERVER
354         | CONF_XSERVER
355 #endif
356 #if PCVT_USL_VT_COMPAT
357         | CONF_USL_VT_COMPAT
358 #endif
359 #if PCVT_PORTIO_DELAY
360         | CONF_PORTIO_DELAY
361 #endif
362 #if PCVT_INHIBIT_NUMLOCK
363         | CONF_INHIBIT_NUMLOCK
364 #endif
365 #if PCVT_META_ESC
366         | CONF_META_ESC
367 #endif
368 #if PCVT_KBD_FIFO
369         | CONF_KBD_FIFO
370 #endif
371 #if PCVT_NOFASTSCROLL
372         | CONF_NOFASTSCROLL
373 #endif
374 #if PCVT_SLOW_INTERRUPT
375         | CONF_SLOW_INTERRUPT
376 #endif
377 #if PCVT_NO_LED_UPDATE
378         | CONF_NO_LED_UPDATE
379 #endif
380         );
381 }
382
383 /*---------------------------------------------------------------------------*
384  *      video ioctl - set cursor appearence
385  *---------------------------------------------------------------------------*/
386 static void
387 vid_cursor(struct cursorshape *data)
388 {
389         int screen;
390         int start;
391         int end;
392         int line_height;
393         int character_set;
394
395         /* for which virtual screen, -1 for current */
396         screen = data->screen_no;
397
398         if(screen == -1)          /* current ? */
399                 screen = current_video_screen;
400         else if(screen > totalscreens - 1)
401                 screen = totalscreens - 1;
402         else if(screen < 0)
403                 screen = 0;
404
405         if(adaptor_type == VGA_ADAPTOR || adaptor_type == EGA_ADAPTOR)
406         {
407                 character_set = vs[screen].vga_charset;
408                 character_set = (character_set < 0) ? 0 :
409                         ((character_set < totalfonts) ?
410                          character_set :
411                          totalfonts-1);
412
413                 line_height = vgacs[character_set].char_scanlines & 0x1F;
414         }
415         else if(adaptor_type == MDA_ADAPTOR)
416         {
417                 line_height = 14;
418         }
419         else
420         {
421                 line_height = 8;        /* CGA */
422         }
423
424         start = (data->start < 0) ? 0 :
425                 ((data->start > line_height) ? line_height : data->start);
426
427         if((vga_family == VGA_F_TRI) && (start == 0))
428                 start = 1;
429
430         end = (data->end < 0) ? 0 :
431                 ((data->end > line_height) ? line_height : data->end);
432
433         vs[screen].cursor_start = start;
434         vs[screen].cursor_end = end;
435
436         if(screen == current_video_screen)
437         {
438                 outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
439                 outb(addr_6845+1, start);
440                 outb(addr_6845,CRTC_CUREND);    /* cursor end reg */
441                 outb(addr_6845+1, end);
442         }
443 }
444
445 /*---------------------------------------------------------------------------*
446  *      ega/vga ioctl - set font attributes
447  *---------------------------------------------------------------------------*/
448 static void
449 vgasetfontattr(struct vgafontattr *data)
450 {
451         int i;
452         int vga_character_set;
453         int lines_per_character;
454         int totscanlines;
455         int size;
456
457         vga_character_set = data->character_set;
458         vga_character_set = (vga_character_set < 0) ? 0 :
459                 ((vga_character_set < totalfonts) ?
460                 vga_character_set : totalfonts-1);
461
462         vgacs[vga_character_set].loaded = data->font_loaded;
463
464         /* Limit Characters to 32 scanlines doubled */
465         vgacs[vga_character_set].char_scanlines =
466                 (data->character_scanlines & 0x1F)
467                 | 0x40; /* always set bit 9 of line cmp reg */
468
469         if(adaptor_type == EGA_ADAPTOR)
470                 /* ...and screen height to scan 350 lines */
471                 vgacs[vga_character_set].scr_scanlines =
472                 (data->screen_scanlines > 0x5d) ?
473                 0x5d : data->screen_scanlines;
474         else
475                 /* ...and screen height to scan 480 lines */
476                 vgacs[vga_character_set].scr_scanlines =
477                 (data->screen_scanlines > 0xdF) ?
478                 0xdF : data->screen_scanlines;
479
480         lines_per_character =
481                 (int)(0x1F & vgacs[vga_character_set].char_scanlines)+1;
482
483         totscanlines = 0x101 + (int)vgacs[vga_character_set].scr_scanlines;
484
485         size = data->screen_size;
486
487         if(adaptor_type == EGA_ADAPTOR)
488         {
489                 switch(size)
490                 {
491                         case SIZ_25ROWS: /* This case is always OK */
492                                 break;
493
494                         case SIZ_35ROWS:
495                                 if(totscanlines/lines_per_character >= 35)
496                                         size = SIZ_35ROWS;
497                                 else
498                                         size = SIZ_25ROWS;
499                                 break;
500
501                         case SIZ_43ROWS:
502                         default:
503                                 if(totscanlines/lines_per_character >= 43)
504                                         size = SIZ_43ROWS;
505                                 else if(totscanlines/lines_per_character >= 35)
506                                         size = SIZ_35ROWS;
507                                 else
508                                         size = SIZ_25ROWS;
509                                 break;
510                 }
511         }
512         else
513         {
514                 switch(size)
515                 {
516                         case SIZ_25ROWS: /* This case is always OK */
517                                 break;
518
519                         case SIZ_28ROWS:
520                                 if(totscanlines/lines_per_character >= 28)
521                                         size = SIZ_28ROWS;
522                                 else
523                                         size = SIZ_25ROWS;
524                                 break;
525
526                         case SIZ_40ROWS:
527                                 if(totscanlines/lines_per_character >= 40)
528                                         size = SIZ_40ROWS;
529                                 else if(totscanlines/lines_per_character >= 28)
530                                         size = SIZ_28ROWS;
531                                 else
532                                         size = SIZ_25ROWS;
533                                 break;
534
535                         case SIZ_50ROWS:
536                         default:
537                                 if(totscanlines/lines_per_character >= 50)
538                                         size = SIZ_50ROWS;
539                                 else if(totscanlines/lines_per_character >= 40)
540                                         size = SIZ_40ROWS;
541                                 else if(totscanlines/lines_per_character >= 28)
542                                         size = SIZ_28ROWS;
543                                 else
544                                         size = SIZ_25ROWS;
545                         break;
546                 }
547         }
548
549         vgacs[vga_character_set].screen_size = size;
550
551         for (i = 0;i < PCVT_NSCREENS;i++)
552         {
553                 if(vga_character_set == vs[i].vga_charset)
554                         set_charset(&(vs[i]),vga_character_set);
555         }
556
557 #if !PCVT_USL_VT_COMPAT
558         vgapage(current_video_screen);
559 #else
560         switch_screen(current_video_screen, 0, 0);
561 #endif /* !PCVT_USL_VT_COMPAT */
562
563 }
564
565 /*---------------------------------------------------------------------------*
566  *      ega/vga ioctl - get font attributes
567  *---------------------------------------------------------------------------*/
568 static void
569 vgagetfontattr(struct vgafontattr *data)
570 {
571         int vga_character_set;
572
573         vga_character_set = data->character_set;
574         vga_character_set = (vga_character_set < 0) ? 0 :
575                 ((vga_character_set < (int)totalfonts) ?
576                  vga_character_set :
577                  (int)(totalfonts-1));
578
579         data->character_set = (int)vga_character_set;
580
581         data->font_loaded = (int)vgacs[vga_character_set].loaded;
582
583         data->character_scanlines =
584                 (int)vgacs[vga_character_set].char_scanlines
585                 & 0x1f;         /* do not display the overflow bits */
586
587         data->screen_scanlines = (int)vgacs[vga_character_set].scr_scanlines;
588
589         data->screen_size = (int)vgacs[vga_character_set].screen_size;
590 }
591
592 /*---------------------------------------------------------------------------*
593  *      ega/vga ioctl - load a character shape into character set
594  *---------------------------------------------------------------------------*/
595 static void
596 vgaloadchar(struct vgaloadchar *data)
597 {
598         int vga_character_set;
599         int character;
600         int lines_per_character;
601
602         vga_character_set = data->character_set;
603         vga_character_set = (vga_character_set < 0) ? 0 :
604                 ((vga_character_set < (int)totalfonts) ?
605                  vga_character_set : (int)(totalfonts-1));
606
607         character = (data->character < 0) ? 0 :
608                 ((data->character > 255) ? 255 : data->character);
609
610         lines_per_character = (int)data->character_scanlines;
611         lines_per_character = (lines_per_character < 0) ? 0 :
612                 ((lines_per_character > 32) ? 32 : lines_per_character);
613
614         loadchar(vga_character_set,character,lines_per_character,
615                  data->char_table);
616 }
617
618 /*---------------------------------------------------------------------------*
619  *      video ioctl - get screen information
620  *---------------------------------------------------------------------------*/
621 static void
622 vid_getscreen(struct screeninfo *data, Dev_t dev)
623 {
624         int device = minor(dev);
625         data->adaptor_type = adaptor_type;      /* video adapter installed */
626         data->monitor_type = color;             /* monitor type installed */
627         data->totalfonts = totalfonts;          /* no of downloadble fonts */
628         data->totalscreens = totalscreens;      /* no of virtual screens */
629         data->screen_no = device;               /* this screen number */
630         data->current_screen = current_video_screen; /* displayed screen no */
631         /* screen size */
632         data->screen_size = vgacs[(vs[device].vga_charset)].screen_size;
633         /* pure VT mode or HP/VT mode */
634         data->pure_vt_mode = vs[device].vt_pure_mode;
635         data->vga_family = vga_family;          /* manufacturer, family */
636         data->vga_type = vga_type;              /* detected chipset type */
637         data->vga_132 = can_do_132col;          /* 132 column support */
638         data->force_24lines = vs[device].force24; /* force 24 lines */
639 }
640
641 /*---------------------------------------------------------------------------*
642  *      video ioctl - set screen information
643  *---------------------------------------------------------------------------*/
644 static void
645 vid_setscreen(struct screeninfo *data, Dev_t dev)
646 {
647         int screen;
648
649         if(data->current_screen == -1)
650         {
651                 screen = minor(dev);
652         }
653         else
654         {
655                 if(data->current_screen >= PCVT_NSCREENS)
656                         return;                                 /* XXXXXX */
657                 screen = data->current_screen;
658         }
659
660         vgapage(screen);
661
662 #if defined XSERVER && PCVT_USL_VT_COMPAT
663         {
664                 int x = spltty(), waitfor = screen + 1;
665                 /* if the vt is yet to be released by a process, wait here */
666                 if(vs[screen].vt_status & VT_WAIT_REL)
667                         (void)usl_vt_ioctl(dev, VT_WAITACTIVE,
668                                            (caddr_t)&waitfor, 0, 0);
669                 splx(x);
670         }
671         /* make sure the switch really happened */
672         if(screen != current_video_screen)
673                 return;         /* XXX should say "EAGAIN" here */
674 #endif /* defined XSERVER && PCVT_USL_VT_COMPAT */
675
676         if((data->screen_size != -1) || (data->force_24lines != -1))
677         {
678                 if(data->screen_size == -1)
679                         data->screen_size =
680                                 vgacs[(vs[screen].vga_charset)].screen_size;
681
682                 if(data->force_24lines != -1)
683                 {
684                         vs[screen].force24 = data->force_24lines;
685
686                         if(vs[screen].force24)
687                         {
688                                 swritefkl(2,(u_char *)"FORCE24 ENABLE *",
689                                           &vs[screen]);
690                         }
691                         else
692                         {
693                                 swritefkl(2,(u_char *)"FORCE24 ENABLE  ",
694                                           &vs[screen]);
695                         }
696                 }
697
698                 if((data->screen_size == SIZ_25ROWS) ||
699                    (data->screen_size == SIZ_28ROWS) ||
700                    (data->screen_size == SIZ_35ROWS) ||
701                    (data->screen_size == SIZ_40ROWS) ||
702                    (data->screen_size == SIZ_43ROWS) ||
703                    (data->screen_size == SIZ_50ROWS))
704                 {
705                         if(data->screen_no == -1)
706                                 set_screen_size(vsp, data->screen_size);
707                         else
708                                 set_screen_size(&vs[minor(dev)],
709                                                 data->screen_size);
710                 }
711         }
712
713         if(data->pure_vt_mode != -1)
714         {
715                 if((data->pure_vt_mode == M_HPVT) ||
716                    (data->pure_vt_mode == M_PUREVT))
717                 {
718                         if(data->screen_no == -1)
719                                 set_emulation_mode(vsp, data->pure_vt_mode);
720                         else
721                                 set_emulation_mode(&vs[minor(dev)],
722                                                    data->pure_vt_mode);
723                 }
724         }
725 }
726
727 /*---------------------------------------------------------------------------*
728  *      set screen size/resolution for a virtual screen
729  *---------------------------------------------------------------------------*/
730 void
731 set_screen_size(struct video_state *svsp, int size)
732 {
733         int i;
734
735         for(i = 0; i < totalfonts; i++)
736         {
737                 if(vgacs[i].screen_size == size)
738                 {
739                         set_charset(svsp, i);
740                         clr_parms(svsp);        /* escape parameter init */
741                         svsp->state = STATE_INIT; /* initial state */
742                         svsp->scrr_beg = 0;     /* start of scrolling region */
743                         svsp->sc_flag = 0;      /* invalidate saved cursor
744                                                  * position */
745                         svsp->transparent = 0;  /* disable control code
746                                                  * processing */
747
748                         /* Update tty to reflect screen size */
749
750                         if (svsp->vs_tty)
751                         {
752                                 svsp->vs_tty->t_winsize.ws_col = svsp->maxcol;
753                                 svsp->vs_tty->t_winsize.ws_xpixel =
754                                         (svsp->maxcol == 80)? 720: 1056;
755                                 svsp->vs_tty->t_winsize.ws_ypixel = 400;
756                                 svsp->vs_tty->t_winsize.ws_row =
757                                         svsp->screen_rows;
758                         }
759                         /* screen_rows already calculated in set_charset() */
760                         if(svsp->vt_pure_mode == M_HPVT && svsp->labels_on)
761                         {
762                                 if(svsp->which_fkl == SYS_FKL)
763                                         sw_sfkl(svsp);
764                                 else if(svsp->which_fkl == USR_FKL)
765                                         sw_ufkl(svsp);
766                         }
767
768
769                         svsp->scrr_len = svsp->screen_rows;
770                         svsp->scrr_end = svsp->scrr_len - 1;
771
772 #if PCVT_SIGWINCH
773                         if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
774                                 pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
775 #endif /* PCVT_SIGWINCH */
776
777                         reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
778                         break;
779                 }
780         }
781 }
782
783 /*---------------------------------------------------------------------------*
784  *      resize the scrollback buffer to the specified number of "pages"
785  *---------------------------------------------------------------------------*/
786 void
787 reallocate_scrollbuffer(struct video_state *svsp, int pages)
788 {
789         int s;
790         u_short *stmp;
791         
792         if(pages < 2)
793                 pages = 2;
794         if(pages > 50)
795                 pages = 50;
796
797         s = splhigh();
798
799         if((stmp = (u_short *)malloc(svsp->maxcol * svsp->screen_rows *
800                         pages * CHR, M_DEVBUF, M_NOWAIT)) == NULL)
801         {
802                 splx(s);
803                 printf("pcvt: reallocate_scrollbuffer, malloc failed\n");
804                 return;
805         }
806
807         svsp->max_off = svsp->screen_rows * pages - 1;
808         
809         if(svsp->Scrollback)
810         {
811                 bcopy(svsp->Scrollback, stmp,
812                         (min(pages, svsp->scrollback_pages)) *
813                         svsp->screen_rows * svsp->maxcol * CHR);
814                 free(svsp->Scrollback, M_DEVBUF);
815                 svsp->Scrollback = stmp;
816         }
817         else
818         {
819                 svsp->scr_offset = 0;
820                 svsp->scrolling = 0;
821                 svsp->Scrollback = stmp;
822
823                 bcopy(svsp->Crtat, svsp->Scrollback,
824                         svsp->screen_rows * svsp->maxcol * CHR);
825
826                 svsp->scr_offset = svsp->row;
827         }
828
829         svsp->scrollback_pages = pages;
830
831         splx(s);
832 }
833
834 /*---------------------------------------------------------------------------*
835  *      VGA ioctl - read DAC palette entry
836  *---------------------------------------------------------------------------*/
837 static void
838 vgareadpel(struct vgapel *data, Dev_t dev)
839 {
840         unsigned vpage = minor(dev);
841         unsigned idx = data->idx;
842
843         if(idx >= NVGAPEL)
844                 return;         /* no such entry */
845
846         /* do not read VGA palette directly, use saved values */
847         data->r = vs[vpage].palette[idx].r;
848         data->g = vs[vpage].palette[idx].g;
849         data->b = vs[vpage].palette[idx].b;
850 }
851
852 /*---------------------------------------------------------------------------*
853  *      VGA ioctl - write DAC palette entry
854  *---------------------------------------------------------------------------*/
855 static void
856 vgawritepel(struct vgapel *data, Dev_t dev)
857 {
858         unsigned vpage = minor(dev);
859         unsigned idx = data->idx;
860
861         if(idx >= NVGAPEL)
862                 return;         /* no such entry */
863
864         /* first, update saved values for this video screen */
865         vs[vpage].palette[idx].r = data->r;
866         vs[vpage].palette[idx].g = data->g;
867         vs[vpage].palette[idx].b = data->b;
868
869         /* if this happens on active screen, update VGA DAC, too */
870         if(vpage == current_video_screen)
871                 vgapaletteio(idx, &vs[vpage].palette[idx], 1);
872 }
873
874 /*---------------------------------------------------------------------------*
875  *      VGA physical IO - read/write one palette entry
876  *---------------------------------------------------------------------------*/
877 void
878 vgapaletteio(unsigned idx, struct rgb *val, int writeit)
879 {
880
881 #if PCVT_PALFLICKER
882         vga_screen_off();
883 #endif /* PCVT_PALFLICKER */
884
885         if(writeit)
886         {
887                 outb(VGA_DAC + 2, idx);
888
889 #if PCVT_WAITRETRACE
890                 wait_retrace();
891 #endif /* PCVT_WAITRETRACE */
892
893                 outb(VGA_DAC + 3, val->r & VGA_PMSK);
894
895 #if PCVT_WAITRETRACE
896                 wait_retrace();
897 #endif /* PCVT_WAITRETRACE */
898
899                 outb(VGA_DAC + 3, val->g & VGA_PMSK);
900
901 #if PCVT_WAITRETRACE
902                 wait_retrace();
903 #endif /* PCVT_WAITRETRACE */
904
905                 outb(VGA_DAC + 3, val->b & VGA_PMSK);
906         }
907         else    /* read it */
908         {
909                 outb(VGA_DAC + 1, idx);
910
911 #if PCVT_WAITRETRACE
912                 wait_retrace();
913 #endif /* PCVT_WAITRETRACE */
914
915                 val->r = inb(VGA_DAC + 3) & VGA_PMSK;
916
917 #if PCVT_WAITRETRACE
918                 wait_retrace();
919 #endif /* PCVT_WAITRETRACE */
920
921                 val->g = inb(VGA_DAC + 3) & VGA_PMSK;
922
923 #if PCVT_WAITRETRACE
924                 wait_retrace();
925 #endif /* PCVT_WAITRETRACE */
926
927                 val->b = inb(VGA_DAC + 3) & VGA_PMSK;
928         }
929
930 #if PCVT_PALFLICKER
931         vga_screen_on();
932 #endif /* PCVT_PALFLICKER */
933
934 }
935
936 /*---------------------------------------------------------------------------*
937  *
938  *      update asynchronous: cursor, cursor pos displ, sys load, keyb scan
939  *
940  *      arg is:
941  *              UPDATE_START = do update; requeue
942  *              UPDATE_STOP  = suspend updates
943  *              UPDATE_KERN  = do update for kernel printfs
944  *
945  *---------------------------------------------------------------------------*/
946 void
947 async_update(void *arg)
948 {
949         static int lastpos = 0;
950         static int counter = PCVT_UPDATESLOW;
951
952 #ifdef XSERVER
953         /* need a method to suspend the updates */
954
955         if(arg == UPDATE_STOP)
956         {
957                 untimeout(async_update, UPDATE_START, async_update_ch);
958                 return;
959         }
960 #endif /* XSERVER */
961
962         /* first check if update is possible */
963
964         if(chargen_access               /* does no-one load characters? */
965 #ifdef XSERVER                          /* is vt0 not in graphics mode? */
966 #if !PCVT_USL_VT_COMPAT
967            || pcvt_xmode                /* XXX necessary ????? */
968 #endif /* PCVT_USL_VT_COMPAT */
969 #endif /* XSERVER */
970            )
971         {
972                 goto async_update_exit; /* do not update anything */
973         }
974
975 #if PCVT_SCREENSAVER
976         if(reset_screen_saver && (counter == PCVT_UPDATESLOW))
977         {
978                 pcvt_scrnsv_reset();    /* yes, do it */
979                 reset_screen_saver = 0; /* re-init */
980         }
981         else if(scrnsv_active)          /* is the screen not blanked? */
982         {
983                 goto async_update_exit; /* do not update anything */
984         }
985 #endif /* PCVT_SCREENSAVER */
986
987         /*-------------------------------------------------------------------*/
988         /* this takes place on EVERY virtual screen (if not in X mode etc...)*/
989         /*-------------------------------------------------------------------*/
990
991         if ( cursor_pos_valid &&
992             (lastpos != (vsp->Crtat + vsp->cur_offset - Crtat)))
993         {
994                 lastpos = vsp->Crtat + vsp->cur_offset - Crtat;
995                 outb(addr_6845, CRTC_CURSORH);  /* high register */
996                 outb(addr_6845+1, ((lastpos) >> 8));
997                 outb(addr_6845, CRTC_CURSORL);  /* low register */
998                 outb(addr_6845+1, (lastpos));
999         }
1000
1001         if (arg == UPDATE_KERN)         /* Magic arg: for kernel printfs */
1002                 return;
1003
1004         if(--counter)                   /* below is possible update */
1005                 goto async_update_exit; /*  just now and then ..... */
1006         counter = PCVT_UPDATESLOW;      /* caution, see screensaver above !! */
1007
1008         /*-------------------------------------------------------------------*/
1009         /* this takes place ONLY on screen 0 if in HP mode, labels on, !X    */
1010         /*-------------------------------------------------------------------*/
1011
1012         /* additional processing for HP necessary ? */
1013
1014         if((vs[0].vt_pure_mode == M_HPVT) && (vs[0].labels_on))
1015         {
1016                 static volatile u_char buffer[] =
1017                        "System Load: 1min: 0.00 5min: 0.00 15min: 0.00";
1018                 int tmp, i;
1019 #if PCVT_SHOWKEYS
1020                 extern u_char rawkeybuf[80];
1021
1022                 if(keyboard_show)
1023                 {
1024                         for(i = 0; i < 80; i++)
1025                         {
1026                                 *((vs[0].Crtat+((vs[0].screen_rows+2)
1027                                         * vs[0].maxcol))+i) =
1028                                  user_attr | rawkeybuf[i];
1029                         }
1030                 }
1031                 else
1032                 {
1033 #endif  /* PCVT_SHOWKEYS */
1034
1035                 /* display load averages in last line (taken from tty.c) */
1036                         i = 18;
1037 #ifdef NEW_AVERUNNABLE
1038                         tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2)
1039                                 >> FSHIFT;
1040 #else
1041                         tmp = (averunnable[0] * 100 + FSCALE / 2) >> FSHIFT;
1042 #endif
1043
1044                         buffer[i++] =
1045                                 ((((tmp/100)/10) == 0) ?
1046                                  ' ' :
1047                                  ((tmp/100)/10) + '0');
1048                         buffer[i++] = ((tmp/100)%10) + '0';
1049                         buffer[i++] = '.';
1050                         buffer[i++] = ((tmp%100)/10) + '0';
1051                         buffer[i++] = ((tmp%100)%10) + '0';
1052                         i += 6;
1053 #ifdef NEW_AVERUNNABLE
1054                         tmp = (averunnable.ldavg[1] * 100 + FSCALE / 2)
1055                                 >> FSHIFT;
1056 #else
1057                         tmp = (averunnable[1] * 100 + FSCALE / 2) >> FSHIFT;
1058 #endif
1059                         buffer[i++] = ((((tmp/100)/10) == 0) ?
1060                                        ' ' :
1061                                        ((tmp/100)/10) + '0');
1062                         buffer[i++] = ((tmp/100)%10) + '0';
1063                         buffer[i++] = '.';
1064                         buffer[i++] = ((tmp%100)/10) + '0';
1065                         buffer[i++] = ((tmp%100)%10) + '0';
1066                         i += 7;
1067 #ifdef NEW_AVERUNNABLE
1068                         tmp = (averunnable.ldavg[2] * 100 + FSCALE / 2)
1069                                 >> FSHIFT;
1070 #else
1071                         tmp = (averunnable[2] * 100 + FSCALE / 2) >> FSHIFT;
1072 #endif
1073                         buffer[i++] = ((((tmp/100)/10) == 0) ?
1074                                        ' ' :
1075                                        ((tmp/100)/10) + '0');
1076                         buffer[i++] = ((tmp/100)%10) + '0';
1077                         buffer[i++] = '.';
1078                         buffer[i++] = ((tmp%100)/10) + '0';
1079                         buffer[i++] = ((tmp%100)%10) + '0';
1080                         buffer[i] = '\0';
1081
1082                         for(i = 0; buffer[i]; i++)
1083                         {
1084                                 *((vs[0].Crtat +
1085                                    ((vs[0].screen_rows + 2) * vs[0].maxcol)
1086                                    ) + i
1087                                   ) = user_attr | buffer[i];
1088                         }
1089
1090 #if PCVT_SHOWKEYS
1091                         for(; i < 77; i++)
1092                         {
1093                                 *((vs[0].Crtat +
1094                                    ((vs[0].screen_rows + 2) * vs[0].maxcol)
1095                                    ) + i
1096                                   ) = user_attr | ' ';
1097                         }
1098
1099                 }
1100 #endif  /* PCVT_SHOWKEYS */
1101         }
1102
1103         /*-------------------------------------------------------------------*/
1104         /* this takes place on EVERY screen which is in HP mode, labels on,!X*/
1105         /*-------------------------------------------------------------------*/
1106
1107         if((vsp->vt_pure_mode == M_HPVT) && (vsp->labels_on))
1108         {
1109                 int col = vsp->col+1;
1110                 u_short *p = vsp->Crtat +
1111                                 (vsp->screen_rows * vsp->maxcol);
1112
1113                 /* update column display between labels */
1114
1115                 if(vsp->maxcol == SCR_COL132)
1116                 {
1117                         p += (SCR_COL132 - SCR_COL80)/2;
1118
1119                         if(col >= 100)
1120                         {
1121                                 *(p + LABEL_COLU) = user_attr | '1';
1122                                 col -= 100;
1123                         }
1124                         else
1125                         {
1126                                 *(p + LABEL_COLU) = user_attr | '0';
1127                         }
1128                 }
1129                 *(p + LABEL_COLH) = user_attr | ((col/10) + '0');
1130                 *(p + LABEL_COLL) = user_attr | ((col%10) + '0');
1131
1132                 /* update row display between labels */
1133
1134                 *(p + LABEL_ROWH) = (user_attr | (((vsp->row+1)/10) + '0'));
1135                 *(p + LABEL_ROWL) = (user_attr | (((vsp->row+1)%10) + '0'));
1136         }
1137
1138 async_update_exit:
1139
1140         if(arg == UPDATE_START)
1141         {
1142            async_update_ch = timeout(async_update, UPDATE_START,
1143                                      PCVT_UPDATEFAST);
1144         }
1145 }
1146
1147 /*---------------------------------------------------------------------------*
1148  *      set character set for virtual screen
1149  *---------------------------------------------------------------------------*/
1150 void
1151 set_charset(struct video_state *svsp, int curvgacs)
1152 {
1153         static int sizetab[] = { 25, 28, 35, 40, 43, 50 };
1154         int oldsize, oldrows, newsize, newrows;
1155
1156         if((curvgacs < 0) || (curvgacs > (NVGAFONTS-1)))
1157                 return;
1158
1159         svsp->vga_charset = curvgacs;
1160
1161         select_vga_charset(curvgacs);
1162
1163         oldsize = svsp->screen_rowsize;
1164         oldrows = svsp->screen_rows;
1165         newsize = sizetab[(vgacs[curvgacs].screen_size)];
1166         newrows = newsize;
1167         if (svsp->vt_pure_mode == M_HPVT)
1168                 newrows -= 3;
1169         if (newrows == 25 && svsp->force24)
1170                 newrows = 24;
1171         if (newrows < oldrows) {
1172                 int nscroll = svsp->row + 1 - newrows;
1173
1174                 if (svsp->row >= oldrows) /* Sanity check */
1175                         nscroll = oldrows - newrows;
1176                 if (nscroll > 0) {
1177                         /* Scroll up */
1178                         bcopy (svsp->Crtat + nscroll * svsp->maxcol,
1179                                svsp->Crtat,
1180                                newrows * svsp->maxcol * CHR);
1181                         svsp->row -= nscroll;
1182                         svsp->cur_offset -= nscroll * svsp->maxcol;
1183                 }
1184                 if (newrows < newsize)
1185                         fillw(user_attr | ' ',
1186                               svsp->Crtat + newrows * svsp->maxcol,
1187                               (newsize - newrows) * svsp->maxcol);
1188         } else if (oldrows < newsize)
1189                 fillw(user_attr | ' ',
1190                       svsp->Crtat + oldrows * svsp->maxcol,
1191                       (newsize - oldrows) * svsp->maxcol);
1192
1193         svsp->screen_rowsize = newsize;
1194         svsp->screen_rows = newrows;
1195
1196         /* Clip scrolling region */
1197         if(svsp->scrr_end > svsp->screen_rows - 1)
1198                 svsp->scrr_end = svsp->screen_rows - 1;
1199         svsp->scrr_len = svsp->scrr_end - svsp->scrr_beg + 1;
1200
1201         /* Clip cursor pos */
1202
1203         if(svsp->cur_offset > (svsp->scrr_len * svsp->maxcol))
1204                 svsp->cur_offset = (svsp->scrr_len * svsp->maxcol) + svsp->col;
1205 }
1206
1207 /*---------------------------------------------------------------------------*
1208  *      select a vga character set
1209  *---------------------------------------------------------------------------*/
1210 void
1211 select_vga_charset(int vga_charset)
1212 {
1213         int first, second;
1214         int fflag = 0;
1215         int sflag = 0;
1216         u_char cmap = 0;
1217
1218         static u_char cmaptaba[] =
1219                 {0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13};
1220
1221         static u_char cmaptabb[] =
1222                 {0x00, 0x04, 0x08, 0x0c, 0x20, 0x24, 0x28, 0x2c};
1223
1224         if((adaptor_type != EGA_ADAPTOR) && (adaptor_type != VGA_ADAPTOR))
1225                 return;
1226
1227         if((vga_charset < 0) || (vga_charset >= totalfonts))
1228                 return;
1229
1230         if(!vgacs[vga_charset].loaded)
1231                 return;
1232
1233         /*--------------------------------------------------------------
1234            find the the first and second charset of a given resolution.
1235            the first is used for lower 256 and the second (if any) is
1236            used for the upper 256 entries of a complete 512 entry ega/
1237            vga charset.
1238         --------------------------------------------------------------*/
1239
1240         for(first = 0; first < totalfonts; first++)
1241         {
1242                 if(!vgacs[first].loaded)
1243                         continue;
1244                 if(vgacs[first].screen_size != vgacs[vga_charset].screen_size)
1245                         continue;
1246                 if(vgacs[first].char_scanlines !=
1247                    vgacs[vga_charset].char_scanlines)
1248                         continue;
1249                 if(vgacs[first].scr_scanlines !=
1250                    vgacs[vga_charset].scr_scanlines)
1251                         continue;
1252                 fflag = 1;
1253                 break;
1254         }
1255
1256         if(fflag != 1)
1257                 return;
1258
1259         for(second = first+1; second < totalfonts; second++)
1260         {
1261                 if(!vgacs[second].loaded)
1262                         continue;
1263                 if(vgacs[second].screen_size != vgacs[vga_charset].screen_size)
1264                         continue;
1265                 if(vgacs[second].char_scanlines !=
1266                    vgacs[vga_charset].char_scanlines)
1267                         continue;
1268                 if(vgacs[second].scr_scanlines !=
1269                    vgacs[vga_charset].scr_scanlines)
1270                         continue;
1271                 sflag = 1;
1272                 break;
1273         }
1274
1275         cmap = cmaptaba[first];
1276         if(sflag)
1277         {
1278                 cmap |= cmaptabb[second];
1279                 vgacs[first].secondloaded = second;
1280         }
1281         else
1282         {
1283                 vgacs[first].secondloaded = 0; /*cs 0 can never become a 2nd!*/
1284         }
1285
1286         if(vsp->wd132col)
1287         {
1288                 cmap = (vga_charset & 0x07);
1289                 cmap |= 0x10;
1290         }
1291
1292         outb(TS_INDEX, TS_FONTSEL);     /* character map select register */
1293         outb(TS_DATA, cmap);            /* new char map */
1294
1295         outb(addr_6845, CRTC_MAXROW);   /* max scan line reg */
1296         outb(addr_6845+1,
1297                 vgacs[first].char_scanlines); /* scanlines/char */
1298
1299         outb(addr_6845, CRTC_VDE);      /* vert display enable end */
1300         outb(addr_6845+1,
1301                 vgacs[first].scr_scanlines);  /* low byte of scr scanlines */
1302
1303         if((color == 0) && (adaptor_type == VGA_ADAPTOR))
1304         {
1305                 outb(addr_6845, CRTC_ULOC);     /* underline location reg */
1306                 outb(addr_6845+1, (vgacs[first].char_scanlines & 0x1F));
1307         }
1308 }
1309
1310 /*---------------------------------------------------------------------------*
1311  *      switch vga-card to load a character set
1312  *---------------------------------------------------------------------------*/
1313 static void
1314 setchargen(void)
1315 {
1316         chargen_access = 1;     /* flag we are accessing the chargen ram */
1317
1318         /* program sequencer to access character generator */
1319
1320         outb(TS_INDEX, TS_SYNCRESET);
1321         outb(TS_DATA, 0x01);    /* synchronous reset */
1322
1323         outb(TS_INDEX, TS_WRPLMASK);
1324         outb(TS_DATA, 0x04);    /* write to map 2 */
1325
1326         outb(TS_INDEX, TS_MEMMODE);
1327         outb(TS_DATA, 0x07);    /* sequential addressing */
1328
1329         outb(TS_INDEX, TS_SYNCRESET);
1330         outb(TS_DATA, 0x03);    /* clear synchronous reset */
1331
1332         /* program graphics controller to access character generator */
1333
1334         outb(GDC_INDEX, GDC_RDPLANESEL);
1335         outb(GDC_DATA, 0x02);   /* select map 2 for cpu reads */
1336
1337         outb(GDC_INDEX, GDC_MODE);
1338         outb(GDC_DATA, 0x00);   /* disable odd-even addressing */
1339
1340         outb(GDC_INDEX, GDC_MISC);
1341         outb(GDC_DATA, 0x00);   /* map starts at 0xA000 */
1342 }
1343
1344 /*---------------------------------------------------------------------------*
1345  *      switch vga-card to load a character set to plane 3
1346  *---------------------------------------------------------------------------*/
1347 static void
1348 setchargen3(void)
1349 {
1350         chargen_access = 1;     /* flag we are accessing the chargen ram */
1351
1352         /* program sequencer to access character generator */
1353
1354         outb(TS_INDEX, TS_SYNCRESET);
1355         outb(TS_DATA, 0x01);    /* synchronous reset */
1356
1357         outb(TS_INDEX, TS_WRPLMASK);
1358         outb(TS_DATA, 0x08);    /* write to map 3 */
1359
1360         outb(TS_INDEX, TS_MEMMODE);
1361         outb(TS_DATA, 0x07);    /* sequential addressing */
1362
1363         outb(TS_INDEX, TS_SYNCRESET);
1364         outb(TS_DATA, 0x03);    /* clear synchronous reset */
1365
1366         /* program graphics controller to access character generator */
1367
1368         outb(GDC_INDEX, GDC_RDPLANESEL);
1369         outb(GDC_DATA, 0x03);   /* select map 3 for cpu reads */
1370
1371         outb(GDC_INDEX, GDC_MODE);
1372         outb(GDC_DATA, 0x00);   /* disable odd-even addressing */
1373
1374         outb(GDC_INDEX, GDC_MISC);
1375         outb(GDC_DATA, 0x00);   /* map starts at 0xA000 */
1376 }
1377
1378 /*---------------------------------------------------------------------------*
1379  *      switch back vga-card to normal operation
1380  *---------------------------------------------------------------------------*/
1381 static void
1382 resetchargen(void)
1383 {
1384         /* program sequencer to access video ram */
1385
1386         outb(TS_INDEX, TS_SYNCRESET);
1387         outb(TS_DATA, 0x01);    /* synchronous reset */
1388
1389         outb(TS_INDEX, TS_WRPLMASK);
1390         outb(TS_DATA, 0x03);    /* write to map 0 & 1 */
1391
1392         outb(TS_INDEX, TS_MEMMODE);
1393         outb(TS_DATA, 0x03);    /* odd-even addressing */
1394
1395         outb(TS_INDEX, TS_SYNCRESET);
1396         outb(TS_DATA, 0x03);    /* clear synchronous reset */
1397
1398         /* program graphics controller to access character generator */
1399
1400         outb(GDC_INDEX, GDC_RDPLANESEL);
1401         outb(GDC_DATA, 0x00);   /* select map 0 for cpu reads */
1402
1403         outb(GDC_INDEX, GDC_MODE);
1404         outb(GDC_DATA, 0x10);   /* enable odd-even addressing */
1405
1406         outb(GDC_INDEX, GDC_MISC);
1407         if(color)
1408                 outb(GDC_DATA, 0x0e);   /* map starts at 0xb800 */
1409         else
1410                 outb(GDC_DATA, 0x0a);   /* map starts at 0xb000 */
1411
1412         chargen_access = 0;     /* flag we are NOT accessing the chargen ram */
1413 }
1414
1415 #if PCVT_WAITRETRACE
1416 /*---------------------------------------------------------------------------*
1417  *      wait for being in a retrace time window
1418  *      NOTE: this is __VERY__ bad programming practice in this environment !!
1419  *---------------------------------------------------------------------------*/
1420
1421 static void
1422 wait_retrace(void)
1423 {
1424         if(color)
1425         {
1426                 while(!(inb(GN_INPSTAT1C) & 0x01))
1427                         ;
1428         }
1429         else
1430         {
1431                 while(!(inb(GN_INPSTAT1M) & 0x01))
1432                         ;
1433         }
1434 }
1435
1436 #endif /* PCVT_WAITRETRACE */
1437
1438 /*---------------------------------------------------------------------------*
1439  *      switch screen off (VGA only)
1440  *---------------------------------------------------------------------------*/
1441 void
1442 vga_screen_off(void)
1443 {
1444         unsigned char old;
1445
1446         outb(TS_INDEX, TS_SYNCRESET);
1447         outb(TS_DATA, 0x01);            /* synchronous reset */
1448
1449         outb(TS_INDEX, TS_MODE);        /* clocking mode reg */
1450         old = inb(TS_DATA);             /* get current value */
1451
1452         outb(TS_INDEX, TS_MODE);        /* clocking mode reg */
1453         outb(TS_DATA, (old | 0x20));    /* screen off bit on */
1454
1455         outb(TS_INDEX, TS_SYNCRESET);
1456         outb(TS_DATA, 0x03);            /* clear synchronous reset */
1457 }
1458
1459 /*---------------------------------------------------------------------------*
1460  *      switch screen back on (VGA only)
1461  *---------------------------------------------------------------------------*/
1462 void
1463 vga_screen_on(void)
1464 {
1465         unsigned char old;
1466
1467         outb(TS_INDEX, TS_SYNCRESET);
1468         outb(TS_DATA, 0x01);            /* synchronous reset */
1469
1470         outb(TS_INDEX, TS_MODE);        /* clocking mode reg */
1471         old = inb(TS_DATA);             /* get current value */
1472
1473         outb(TS_INDEX, TS_MODE);        /* clocking mode reg */
1474         outb(TS_DATA, (old & ~0x20));   /* screen off bit off */
1475
1476         outb(TS_INDEX, TS_SYNCRESET);
1477         outb(TS_DATA, 0x03);            /* clear synchronous reset */
1478 }
1479
1480 /*---------------------------------------------------------------------------*
1481  *      compute character set base address (in kernel map)
1482  *---------------------------------------------------------------------------*/
1483 static unsigned char *
1484 compute_charset_base(unsigned fontset)
1485 {
1486         unsigned char *d = (unsigned char *)Crtat;
1487
1488         static int charset_offset[8] = { 0x0000, 0x4000, 0x8000, 0xC000,
1489                                          0x2000, 0x6000, 0xA000, 0xE000 };
1490
1491         static int charsetw_offset[8] = { 0x0000, 0x2000, 0x4000, 0x6000,
1492                                           0x8000, 0xA000, 0xC000, 0xE000 };
1493
1494         switch(adaptor_type)
1495         {
1496                 case EGA_ADAPTOR:
1497                         fontset = (fontset > 3) ? 3 : fontset;
1498                         break;
1499
1500                 case VGA_ADAPTOR:
1501                         fontset = (fontset > 7) ? 7 : fontset;
1502                         break;
1503
1504                 default:
1505                         return 0;
1506         }
1507
1508         if(color)
1509                 d -= (0xB8000 - 0xA0000);       /* Point to 0xA0000 */
1510         else
1511                 d -= (0xB0000 - 0xA0000);       /* Point to 0xA0000 */
1512
1513         if(vsp->wd132col)
1514                 d += charsetw_offset[fontset];  /* Load into Character set n */
1515         else
1516                 d += charset_offset[fontset];   /* Load into Character set n */
1517
1518         return d;
1519 }
1520
1521 /*---------------------------------------------------------------------------*
1522  *      load a char into ega/vga character generator ram
1523  *---------------------------------------------------------------------------*/
1524 void
1525 loadchar(int fontset, int character, int char_scanlines, u_char *char_table)
1526 {
1527         unsigned char *d;
1528
1529 #if PCVT_BACKUP_FONTS
1530         unsigned char *bak;
1531 #endif /* PCVT_BACKUP_FONTS */
1532
1533         int j, k;
1534
1535         if((d = compute_charset_base(fontset)) == 0)
1536                 return;
1537
1538         d += (character * 32);          /* 32 bytes per character */
1539
1540         if(vsp->wd132col &&
1541            (fontset == 1||fontset == 3||fontset == 5||fontset == 7))
1542                 setchargen3();                  /* access chargen ram */
1543         else
1544                 setchargen();                   /* access chargen ram */
1545
1546         for(j = k = 0; j < char_scanlines; j++) /* x bit high characters */
1547         {
1548                 *d = char_table[k];
1549                 d++;
1550                 k++;
1551         }
1552         for(; j < 32; j++)              /* Up to 32 bytes per character image*/
1553         {
1554                 *d = 0x00;
1555                 d++;
1556         }
1557
1558         resetchargen();                 /* access video ram */
1559
1560 #if PCVT_BACKUP_FONTS
1561         if(saved_charsets[fontset] == 0)
1562                 saved_charsets[fontset] =
1563                         (u_char *)malloc(32 * 256, M_DEVBUF, M_WAITOK);
1564
1565         if((bak = saved_charsets[fontset]))
1566         {
1567                 /* make a backup copy of this char */
1568                 bak += (character * 32);
1569                 bzero(bak, 32);
1570                 bcopy(char_table, bak, char_scanlines);
1571         }
1572 #ifdef DIAGNOSTIC
1573         else
1574                 panic("pcvt loadchar: no backup buffer");
1575 #endif /* DIAGNOSTIC */
1576
1577 #endif /* PCVT_BACKUP_FONTS */
1578
1579 }
1580
1581 /*---------------------------------------------------------------------------*
1582  *      save/restore character set n to addr b
1583  *---------------------------------------------------------------------------*/
1584 #if !PCVT_BACKUP_FONTS
1585
1586 void
1587 vga_move_charset(unsigned n, unsigned char *b, int save_it)
1588 {
1589         unsigned char *d = compute_charset_base(n);
1590
1591 #ifdef DIAGNOSTIC
1592         if(d == 0)
1593                 panic("vga_move_charset: wrong adaptor");
1594 #endif
1595
1596         if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
1597         {
1598                 setchargen3();
1599                 d -= 0x2000;
1600         }
1601         else
1602         {
1603                 setchargen();
1604         }
1605
1606         /* PLEASE, leave the following alone using bcopyb, as several   */
1607         /* chipsets have problems if their memory is accessed with 32   */
1608         /* or 16 bits wide, don't change this to using bcopy for speed! */
1609
1610         if(save_it)
1611                 bcopyb(d, b, 256 /* chars */ * 32 /* bytes per char */);
1612         else
1613                 bcopyb(b, d, 256 /* chars */ * 32 /* bytes per char */);
1614
1615         resetchargen();
1616 }
1617
1618 #else /* PCVT_BACKUP_FONTS */
1619
1620 /* since there are always backed up copies, we do not save anything here */
1621 /* parameter "b" is totally ignored */
1622
1623 void
1624 vga_move_charset(unsigned n, unsigned char *b, int save_it)
1625 {
1626         unsigned char *d = compute_charset_base(n);
1627
1628         if(save_it)
1629                 return;
1630
1631         if(saved_charsets[n] == 0)
1632 #ifdef DIAGNOSTIC
1633                 panic("pcvt: restoring unbuffered charset");
1634 #else
1635                 return;
1636 #endif
1637
1638 #ifdef DIAGNOSTIC
1639         if(d == 0)
1640                 panic("vga_move_charset: wrong adaptor");
1641 #endif
1642
1643         if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
1644         {
1645                 setchargen3();
1646                 d -= 0x2000;
1647         }
1648         else
1649         {
1650                 setchargen();
1651         }
1652
1653         /* PLEASE, leave the following alone using bcopyb, as several   */
1654         /* chipsets have problems if their memory is accessed with 32   */
1655         /* or 16 bits wide, don't change this to using bcopy for speed! */
1656
1657         bcopyb(saved_charsets[n], d,
1658                256 /* chars */ * 32 /* bytes per char */);
1659
1660         resetchargen();
1661 }
1662
1663 #endif /* PCVT_BACKUP_FONTS */
1664
1665
1666 #if !PCVT_USL_VT_COMPAT
1667 /*---------------------------------------------------------------------------*
1668  *      switch to virtual screen n (0 ... PCVT_NSCREENS-1)
1669  *---------------------------------------------------------------------------*/
1670 void
1671 vgapage(int n)
1672 {
1673
1674 #if !PCVT_KBD_FIFO
1675         int x;
1676 #endif  /* !PCVT_KBD_FIFO */
1677
1678         int cols = vsp->maxcol;         /* get current col val */
1679
1680         if(n < 0 || n >= totalscreens)
1681                 return;
1682
1683 #if !PCVT_KBD_FIFO
1684         x = spltty();                   /* protect us */
1685 #endif  /* !PCVT_KBD_FIFO */
1686
1687         /* video board memory -> kernel memory */
1688
1689         bcopy(vsp->Crtat, vsp->Memory, vsp->screen_rows * vsp->maxcol * CHR);
1690
1691         vsp->Crtat = vsp->Memory;       /* operate in memory now */
1692
1693         /* update global screen pointers/variables */
1694
1695         current_video_screen = n;       /* current screen no */
1696
1697 #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
1698         pcconsp = &pccons[n];           /* current tty */
1699 #elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200
1700         pcconsp = pccons[n];            /* current tty */
1701 #else
1702         pcconsp = pc_tty[n];            /* current tty */
1703 #endif
1704
1705         vsp = &vs[n];                   /* current video state ptr */
1706
1707         /* kernel memory -> video board memory */
1708
1709         bcopy(vsp->Crtat, Crtat, vsp->screen_rows * vsp->maxcol * CHR);
1710
1711         vsp->Crtat = Crtat;             /* operate on screen now */
1712
1713         outb(addr_6845, CRTC_STARTADRH);
1714         outb(addr_6845+1, 0);
1715         outb(addr_6845, CRTC_STARTADRL);
1716         outb(addr_6845+1, 0);
1717
1718 #if !PCVT_KBD_FIFO
1719         splx(x);
1720 #endif  /* !PCVT_KBD_FIFO */
1721
1722         select_vga_charset(vsp->vga_charset);
1723
1724         if(vsp->maxcol != cols)
1725                 vga_col(vsp, vsp->maxcol);      /* select 80/132 columns */
1726
1727         outb(addr_6845, CRTC_CURSORH);  /* select high register */
1728         outb(addr_6845+1, vsp->cur_offset >> 8);
1729         outb(addr_6845, CRTC_CURSORL);  /* select low register */
1730         outb(addr_6845+1, vsp->cur_offset);
1731
1732         if(vsp->cursor_on)
1733         {
1734                 outb(addr_6845, CRTC_CURSTART); /* select high register */
1735                 outb(addr_6845+1, vsp->cursor_start);
1736                 outb(addr_6845, CRTC_CUREND);   /* select low register */
1737                 outb(addr_6845+1, vsp->cursor_end);
1738         }
1739         else
1740         {
1741                 sw_cursor(0);
1742         }
1743
1744         if(adaptor_type == VGA_ADAPTOR)
1745         {
1746                 unsigned i;
1747
1748                 /* switch VGA DAC palette entries */
1749
1750                 for(i = 0; i < NVGAPEL; i++)
1751                         vgapaletteio(i, &vsp->palette[i], 1);
1752         }
1753
1754         update_led();                   /* update led's */
1755
1756         update_hp(vsp);                 /* update fkey labels, if present */
1757 }
1758 #endif /* !PCVT_USL_VT_COMPAT */
1759
1760 /*---------------------------------------------------------------------------*
1761  *      test if it is a vga
1762  *---------------------------------------------------------------------------*/
1763
1764 int
1765 vga_test(void)
1766 {
1767         u_char old, new, check;
1768
1769         outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1770         old = inb(addr_6845+1);         /* get current value */
1771
1772         new = old | CURSOR_ON_BIT;      /* set cursor on by setting bit 5 on */
1773
1774         outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1775         outb(addr_6845+1,new);          /* cursor should be on now */
1776
1777         outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1778         check = inb(addr_6845+1);       /* get current value */
1779
1780         if(check != new)
1781         {
1782                 outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1783                 outb(addr_6845+1,old);          /* failsafe */
1784                 return(0);                      /* must be ega */
1785         }
1786
1787         new = old & ~CURSOR_ON_BIT;     /* turn cursor off by clearing bit 5 */
1788
1789         outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1790         outb(addr_6845+1,new);          /* cursor should be off now */
1791
1792         outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1793         check = inb(addr_6845+1);       /* get current value */
1794
1795         if(check != new)
1796         {
1797                 outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1798                 outb(addr_6845+1,old);          /* failsafe */
1799                 return(0);                      /* must be ega */
1800         }
1801
1802         outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
1803         outb(addr_6845+1,old);          /* failsafe */
1804
1805         return(1);      /* vga */
1806 }
1807
1808 /*---------------------------------------------------------------------------*
1809  *      convert upper/lower sixel font array to vga font array
1810  *---------------------------------------------------------------------------*/
1811 void
1812 sixel_vga(struct sixels *sixelp, u_char *vgachar)
1813 {
1814         int i, j;
1815         int shift;
1816         u_char mask;
1817
1818         for(j = 0; j < 16; j++)
1819                 vgachar[j] = 0;
1820
1821         mask = 0x01;
1822         for(j = 0; j < 6; j++)
1823         {
1824                 for(i = 0, shift = 7; i < 8; i++, shift--)
1825                         vgachar[j] |= ((((sixelp->upper[i]) & mask) >> j)
1826                                        << shift);
1827                 mask <<= 1;
1828         }
1829
1830         mask = 0x01;
1831         for(j = 0; j < 4; j++)
1832         {
1833                 for(i = 0, shift = 7; i < 8; i++, shift--)
1834                         vgachar[j+6] |= ((((sixelp->lower[i]) & mask) >>j)
1835                                          << shift);
1836                 mask <<= 1;
1837         }
1838 }
1839
1840 /*---------------------------------------------------------------------------*
1841  *      Expand 8x10 EGA/VGA characters to 8x16 EGA/VGA characters
1842  *---------------------------------------------------------------------------*/
1843 void
1844 vga10_vga16(u_char *invga, u_char *outvga)
1845 {
1846         int i,j;
1847
1848         /*
1849          * Keep the top and bottom scanlines the same and double every scan
1850          * line in between.
1851          */
1852
1853         outvga[0] = invga[0];
1854         outvga[1] = invga[1];
1855         outvga[14] = invga[8];
1856         outvga[15] = invga[9];
1857
1858         for(i = j = 2;i < 8 && j < 14;i++,j += 2)
1859         {
1860                 outvga[j]   = invga[i];
1861                 outvga[j+1] = invga[i];
1862         }
1863 }
1864
1865 /*---------------------------------------------------------------------------*
1866  *      Expand 8x10 EGA/VGA characters to 8x14 EGA/VGA characters
1867  *---------------------------------------------------------------------------*/
1868 void
1869 vga10_vga14(u_char *invga, u_char *outvga)
1870 {
1871         int i;
1872
1873         /*
1874          * Double the top two and bottom two scanlines and copy everything
1875          * in between.
1876          */
1877
1878         outvga[0] = invga[0];
1879         outvga[1] = invga[0];
1880         outvga[2] = invga[1];
1881         outvga[3] = invga[1];
1882         outvga[10] = invga[8];
1883         outvga[11] = invga[8];
1884         outvga[12] = invga[9];
1885         outvga[13] = invga[9];
1886
1887         for(i = 2;i < 8;i++)
1888                 outvga[i+2]   = invga[i];
1889 }
1890
1891 /*---------------------------------------------------------------------------*
1892  *      Expand 8x10 EGA/VGA characters to 8x10 EGA/VGA characters
1893  *---------------------------------------------------------------------------*/
1894 void
1895 vga10_vga10(u_char *invga, u_char *outvga)
1896 {
1897         int i;
1898
1899         for(i = 0;i < 10;i++)
1900                 outvga[i]   = invga[i];
1901 }
1902
1903 /*---------------------------------------------------------------------------*
1904  *      Contract 8x10 EGA/VGA characters to 8x8 EGA/VGA characters
1905  *---------------------------------------------------------------------------*/
1906 void
1907 vga10_vga8(u_char *invga, u_char *outvga)
1908 {
1909         /* Skip scanlines 3 and 7 */
1910
1911         outvga[0] = invga[0];
1912         outvga[1] = invga[1];
1913         outvga[2] = invga[2];
1914         outvga[3] = invga[4];
1915         outvga[4] = invga[5];
1916         outvga[5] = invga[6];
1917         outvga[6] = invga[8];
1918         outvga[7] = invga[9];
1919 }
1920
1921 /*---------------------------------------------------------------------------*
1922  *      force a vga card to behave like an ega for debugging
1923  *---------------------------------------------------------------------------*/
1924 #if FORCE_EGA
1925 void
1926 force_ega(void)
1927 {
1928         unsigned char vgareg;
1929
1930         if(adaptor_type == VGA_ADAPTOR)
1931         {
1932                 adaptor_type = EGA_ADAPTOR;
1933                 totalfonts = 4;
1934                 vgareg = inb(GN_MISCOUTR); /* Miscellaneous Output Register */
1935                 vgareg |= 128;             /* Set 350 scanline mode */
1936                 vgareg &= ~64;
1937                 outb(GN_MISCOUTW,vgareg);
1938         }
1939 }
1940 #endif /* FORCE_EGA */
1941
1942 /*---------------------------------------------------------------------------*
1943  *      disconnect attribute bit 3 from generating intensity
1944  *      (and use it for a second character set !)
1945  *---------------------------------------------------------------------------*/
1946 void
1947 set_2ndcharset(void)
1948 {
1949         if(color)                       /* prepare to access index register! */
1950                 inb(GN_INPSTAT1C);
1951         else
1952                 inb(GN_INPSTAT1M);
1953
1954         /* select color plane enable reg, caution: set ATC access bit ! */
1955
1956         outb(ATC_INDEX, (ATC_COLPLEN | ATC_ACCESS));
1957         outb(ATC_DATAW, 0x07);          /* disable plane 3 */
1958 }
1959
1960 #if PCVT_SCREENSAVER
1961 #if PCVT_PRETTYSCRNS
1962
1963 /*---------------------------------------------------------------------------*
1964  * produce some kinda random number, had a look into the system library...
1965  *---------------------------------------------------------------------------*/
1966 static u_short
1967 getrand(void)
1968 {
1969 #if !PCVT_FREEBSD
1970         extern struct timeval time; /* time-of-day register */
1971 #endif
1972         static unsigned long seed = 1;
1973         u_short res = (u_short)seed;
1974         seed = seed * 1103515245L + time_second;
1975         return res;
1976 }
1977
1978 /*---------------------------------------------------------------------------*
1979  *      produce "nice" screensaving ....
1980  *---------------------------------------------------------------------------*/
1981 static void
1982 scrnsv_blink(void * arg)
1983 {
1984         static struct rgb blink_rgb[8] =
1985         {
1986                 {63, 63, 63},   /* white */
1987                 {0, 63, 42},    /* pale green */
1988                 {63, 63, 0},    /* yellow */
1989                 {63, 21, 63},   /* violet */
1990                 {42, 63, 0},    /* yellow-green */
1991                 {63, 42, 0},    /* amber */
1992                 {63, 42, 42},   /* rose */
1993                 {21, 42, 42}    /* cyan */
1994         };
1995         u_short r = getrand();
1996         unsigned pos = (r % (scrnsv_size / 2));
1997
1998         *scrnsv_current = /* (0 << 8) + */ ' ';
1999         scrnsv_current = vsp->Crtat + pos;
2000         *scrnsv_current = (7 /* LIGHTGRAY */ << 8) + '*';
2001         if(adaptor_type == VGA_ADAPTOR)
2002                 vgapaletteio(7 /* LIGHTGRAY */, &blink_rgb[(r >> 4) & 7], 1);
2003         scrnsv_blink_ch = timeout(scrnsv_blink, NULL, hz);
2004 }
2005
2006 #endif /* PCVT_PRETTYSCRNS */
2007
2008 /*---------------------------------------------------------------------------*
2009  *      set timeout time
2010  *---------------------------------------------------------------------------*/
2011 #ifndef XSERVER
2012 static void
2013 pcvt_set_scrnsv_tmo(int timeout)
2014 #else
2015 void
2016 pcvt_set_scrnsv_tmo(int timeout)
2017 #endif /* XSERVER */
2018 {
2019         int x = splhigh();
2020
2021         if(scrnsv_timeout)
2022                 untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
2023
2024         scrnsv_timeout = timeout;
2025         pcvt_scrnsv_reset();            /* sanity */
2026         splx(x);
2027         if(timeout == 0 && savedscreen)
2028         {
2029                 /* release buffer when screen saver turned off */
2030                 free(savedscreen, M_TEMP);
2031                 savedscreen = (u_short *)0;
2032         }
2033 }
2034
2035 /*---------------------------------------------------------------------------*
2036  *      we were timed out
2037  *---------------------------------------------------------------------------*/
2038 static void
2039 scrnsv_timedout(void *arg)
2040 {
2041         /* this function is called by timeout() */
2042         /* raise priority to avoid conflicts with kbd intr */
2043         int x = spltty();
2044
2045         /*
2046          * due to some undefined problems with video adaptor RAM
2047          * access timing, the following has been splitted into
2048          * two pieces called subsequently with a time difference
2049          * of 100 millisec
2050          */
2051
2052         if(++scrnsv_active == 1)
2053         {
2054                 size_t s;
2055                 /*
2056                  * first, allocate a buffer
2057                  * do only if none allocated yet or another size required
2058                  * this reduces malloc() overhead by avoiding successive
2059                  * calls to malloc() and free() if they would have requested
2060                  * the same buffer
2061                  *
2062                  * XXX This is inherited from old days where no buffering
2063                  * happened at all. Meanwhile we should use the standard
2064                  * screen buffer instead. Any volunteers? :-) [At least,
2065                  * this code proved to work...]
2066                  */
2067
2068                 s = sizeof(u_short) * vsp->screen_rowsize * vsp->maxcol;
2069
2070                 if(savedscreen == (u_short *)0 || s != scrnsv_size)
2071                 {
2072                         /* really need to allocate */
2073                         if(savedscreen)
2074                                 free(savedscreen, M_TEMP);
2075                         scrnsv_size = s;
2076                         if((savedscreen =
2077                             (u_short *)malloc(s, M_TEMP, M_NOWAIT))
2078                            == (u_short *)0)
2079                         {
2080                                 /*
2081                                  * didn't get the buffer memory,
2082                                  * turn off screen saver
2083                                  */
2084                                 scrnsv_timeout = scrnsv_active = 0;
2085                                 splx(x);
2086                                 return;
2087                         }
2088                 }
2089                 /* save current screen */
2090                 bcopy(vsp->Crtat, savedscreen, scrnsv_size);
2091
2092                 /* on VGA's, make sure palette is set to blank screen */
2093                 if(adaptor_type == VGA_ADAPTOR)
2094                 {
2095                         struct rgb black = {0, 0, 0};
2096                         vgapaletteio(0 /* BLACK */, &black, 1);
2097                 }
2098                 /* prepare for next time... */
2099                 scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL, hz / 10);
2100         }
2101         else
2102         {
2103                 /* second call, now blank the screen */
2104                 /* fill screen with blanks */
2105                 fillw(/* (BLACK<<8) + */ ' ', vsp->Crtat, scrnsv_size / 2);
2106
2107 #if PCVT_PRETTYSCRNS
2108                 scrnsv_current = vsp->Crtat;
2109                 scrnsv_blink_ch = timeout(scrnsv_blink, NULL, hz);
2110 #endif /* PCVT_PRETTYSCRNS */
2111
2112                 sw_cursor(0);   /* cursor off on mda/cga */
2113         }
2114         splx(x);
2115 }
2116
2117 /*---------------------------------------------------------------------------*
2118  *      interface to screensaver "subsystem"
2119  *---------------------------------------------------------------------------*/
2120 void
2121 pcvt_scrnsv_reset(void)
2122 {
2123         /*
2124          * to save lotta time with superfluous timeout()/untimeout() calls
2125          * when having massive output operations, we remember the last
2126          * second of kernel timer we've rescheduled scrnsv_timedout()
2127          */
2128         static long last_schedule = 0L;
2129         int x = splhigh();
2130         int reschedule = 0;
2131
2132         if((scrnsv_active == 1 || scrnsv_timeout) &&
2133            last_schedule != time_second)
2134         {
2135                 last_schedule = time_second;
2136                 reschedule = 1;
2137                 untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
2138         }
2139         if(scrnsv_active)
2140         {
2141
2142 #if PCVT_PRETTYSCRNS
2143                 if(scrnsv_active > 1)
2144                         untimeout(scrnsv_blink, NULL, scrnsv_blink_ch);
2145 #endif /* PCVT_PRETTYSCRNS */
2146
2147                 bcopy(savedscreen, vsp->Crtat, scrnsv_size);
2148                 if(adaptor_type == VGA_ADAPTOR)
2149                 {
2150                         /* back up VGA palette info */
2151                         vgapaletteio(0 /* BLACK */, &vsp->palette[0], 1);
2152
2153 #if PCVT_PRETTYSCRNS
2154                         vgapaletteio(7 /* LIGHTGRAY */, &vsp->palette[7], 1);
2155 #endif /* PCVT_PRETTYSCRNS */
2156
2157                 }
2158                 scrnsv_active = 0;
2159
2160                 if(vsp->cursor_on)
2161                         sw_cursor(1);   /* cursor on */
2162         }
2163
2164         if(reschedule)
2165         {
2166                 /* mark next timeout */
2167                 scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL,
2168                                             scrnsv_timeout * hz);
2169         }
2170         splx(x);
2171 }
2172
2173 #endif /* PCVT_SCREENSAVER */
2174
2175 /*---------------------------------------------------------------------------*
2176  *      switch cursor on/off
2177  *---------------------------------------------------------------------------*/
2178 void
2179 sw_cursor(int onoff)
2180 {
2181         if(adaptor_type == EGA_ADAPTOR)
2182         {
2183                 int start, end;
2184                 if(onoff)
2185                 {
2186                         start = vsp->cursor_start;
2187                         end = vsp->cursor_end;
2188                 }
2189                 else
2190                 {
2191                         int cs = vs[current_video_screen].vga_charset;
2192
2193                         cs = (cs < 0) ? 0 : ((cs < totalfonts) ?
2194                                              cs : totalfonts-1);
2195
2196                         start = (vgacs[cs].char_scanlines & 0x1F) + 1;
2197                         end = 0;
2198                 }
2199                 outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
2200                 outb(addr_6845+1, start);
2201                 outb(addr_6845,CRTC_CUREND);    /* cursor end reg */
2202                 outb(addr_6845+1, end);
2203         }
2204         else    /* mda, cga, vga */
2205         {
2206                 outb(addr_6845,CRTC_CURSTART);  /* cursor start reg */
2207                 if(onoff)
2208                         outb(addr_6845+1, vsp->cursor_start);
2209                 else
2210                         outb(addr_6845+1, CURSOR_ON_BIT);
2211         }
2212 }
2213
2214 /*---------------------------------------------------------------------------*
2215  *      cold init support, if a mono monitor is attached to a
2216  *      vga or ega, it comes up with a mda emulation. switch
2217  *      board to generic ega/vga mode in this case.
2218  *---------------------------------------------------------------------------*/
2219 void
2220 mda2egaorvga(void)
2221 {
2222         /*
2223          * program sequencer to access
2224          * video ram
2225          */
2226
2227         /* synchronous reset */
2228         outb(TS_INDEX, TS_SYNCRESET);
2229         outb(TS_DATA, 0x01);
2230
2231         /* write to map 0 & 1 */
2232         outb(TS_INDEX, TS_WRPLMASK);
2233         outb(TS_DATA, 0x03);
2234
2235         /* odd-even addressing */
2236         outb(TS_INDEX, TS_MEMMODE);
2237         outb(TS_DATA, 0x03);
2238
2239         /* clear synchronous reset */
2240         outb(TS_INDEX, TS_SYNCRESET);
2241         outb(TS_DATA, 0x03);
2242
2243         /*
2244          * program graphics controller
2245          * to access character
2246          * generator
2247          */
2248
2249         /* select map 0 for cpu reads */
2250         outb(GDC_INDEX, GDC_RDPLANESEL);
2251         outb(GDC_DATA, 0x00);
2252
2253         /* enable odd-even addressing */
2254         outb(GDC_INDEX, GDC_MODE);
2255         outb(GDC_DATA, 0x10);
2256
2257         /* map starts at 0xb000 */
2258         outb(GDC_INDEX, GDC_MISC);
2259         outb(GDC_DATA, 0x0a);
2260 }
2261
2262 #endif  /* NVT > 0 */
2263
2264 /* ------------------------- E O F ------------------------------------------*/