2 * Copyright (c) 1999 Hellmuth Michaelis
4 * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
6 * Copyright (c) 1992, 1993 Brian Dunford-Shore and Scott Turner.
8 * Copyright (C) 1992, 1993 Soeren Schmidt.
10 * All rights reserved.
12 * For the sake of compatibility, portions of this code regarding the
13 * X server interface are taken from Soeren Schmidt's syscons driver.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
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.
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.
42 /*---------------------------------------------------------------------------*
44 * pcvt_sup.c VT220 Driver Support Routines
45 * ---------------------------------------------
47 * Last Edit-Date: [Thu Dec 30 17:01:03 1999]
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.5 2004/09/18 20:23:04 dillon Exp $
52 *---------------------------------------------------------------------------*/
57 #include "pcvt_hdr.h" /* global include */
59 #include <sys/resource.h>
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 );
76 static unsigned char * compute_charset_base ( unsigned fontset );
79 static struct callout async_update_ch;
82 static void scrnsv_timedout ( void *arg );
83 static struct callout scrnsv_timeout_ch;
84 static u_short *savedscreen = (u_short *)0; /* ptr to screen contents */
85 static size_t scrnsv_size = (size_t)-1; /* size of saved image */
88 static unsigned scrnsv_timeout = 0; /* initially off */
89 static void pcvt_set_scrnsv_tmo ( int timeout );/* else declared global */
93 static u_short *scrnsv_current = (u_short *)0; /* attention char ptr */
94 static struct callout scrnsv_blink_ch;
95 static void scrnsv_blink ( void * );
96 static u_short getrand ( void );
97 #endif /* PCVT_PRETTYSCRNS */
99 #endif /* PCVT_SCREENSAVER */
102 pcvt_support_init(void)
104 callout_init(&async_update_ch);
106 callout_init(&scrnsv_timeout_ch);
109 callout_init(&scrnsv_blink_ch);
114 /*---------------------------------------------------------------------------*
116 *---------------------------------------------------------------------------*/
118 vgaioctl(Dev_t dev, int cmd, caddr_t data, int flag)
120 if(minor(dev) >= PCVT_NSCREENS)
124 * Some of the commands are not applicable if the vt in question, or the
125 * current vt is in graphics mode (i.e., the X server acts on it); they
126 * will cause an EAGAIN (resource temporarily unavailable) to be returned.
130 #if PCVT_USL_VT_COMPAT
131 #define is_dev_grafx vs[minor(dev)].vt_status & VT_GRAFX
132 #define is_current_grafx vsp->vt_status & VT_GRAFX
133 #else /* old X interface */
134 #define is_dev_grafx pcvt_xmode
135 #define is_current_grafx pcvt_xmode
136 #endif /* PCVT_USL_VT_COMPAT */
138 #define is_dev_grafx 0 /* not applicable */
139 #define is_current_grafx 0
147 vid_cursor((struct cursorshape *)data);
151 if((adaptor_type != VGA_ADAPTOR) &&
152 (adaptor_type != EGA_ADAPTOR))
156 vgaloadchar((struct vgaloadchar *)data);
160 if((adaptor_type != VGA_ADAPTOR) &&
161 (adaptor_type != EGA_ADAPTOR))
166 #endif /* PCVT_SCREENSAVER */
168 vgasetfontattr((struct vgafontattr *)data);
172 if((adaptor_type != VGA_ADAPTOR) &&
173 (adaptor_type != EGA_ADAPTOR))
175 vgagetfontattr((struct vgafontattr *)data);
180 #if defined XSERVER && !PCVT_USL_VT_COMPAT
181 /* avoid screen switch if using old X mode */
184 #endif /* XSERVER && !PCVT_USL_VT_COMPAT */
188 #endif /* PCVT_SCREENSAVER */
190 vid_setscreen((struct screeninfo *)data, dev);
194 vid_getscreen((struct screeninfo *)data, dev);
198 if(adaptor_type != VGA_ADAPTOR)
202 vgareadpel((struct vgapel *)data, dev);
206 if(adaptor_type != VGA_ADAPTOR)
210 vgawritepel((struct vgapel *)data, dev);
217 pcvt_set_scrnsv_tmo(*(int *)data);
220 #endif /* PCVT_SCREENSAVER */
223 vgapcvtid((struct pcvtid *)data);
227 vgapcvtinfo((struct pcvtinfo *)data);
233 if(*(int *)data == 80)
234 (void)vt_col(&vs[minor(dev)], SCR_COL80);
235 else if(*(int *)data == 132)
237 if(vt_col(&vs[minor(dev)], SCR_COL132) == 0)
238 return EINVAL; /* not a VGA */
246 reallocate_scrollbuffer(vsp, *(u_short *)data);
251 /* do nothing here */
260 #undef is_current_grafx
263 /*---------------------------------------------------------------------------*
264 * video ioctl - return driver id
265 *---------------------------------------------------------------------------*/
267 vgapcvtid(struct pcvtid *data)
269 snprintf(data->name, sizeof(data->name), "%s", PCVTIDNAME);
270 data->rmajor = PCVTIDMAJOR;
271 data->rminor = PCVTIDMINOR;
274 /*---------------------------------------------------------------------------*
275 * video ioctl - return driver compile time options data
276 *---------------------------------------------------------------------------*/
278 vgapcvtinfo(struct pcvtinfo *data)
281 data->opsys = CONF_NETBSD;
282 data->opsysrel = PCVT_NETBSD;
284 data->opsys = CONF_FREEBSD;
285 data->opsysrel = PCVT_FREEBSD;
287 data->opsys = CONF_UNKNOWNOPSYS;
291 data->nscreens = PCVT_NSCREENS;
292 data->scanset = PCVT_SCANSET;
293 data->updatefast= PCVT_UPDATEFAST;
294 data->updateslow= PCVT_UPDATESLOW;
295 data->sysbeepf = PCVT_SYSBEEPF;
297 #if PCVT_NETBSD || PCVT_FREEBSD >= 200
298 data->pcburst = PCVT_PCBURST;
304 data->kbd_fifo_sz = PCVT_KBD_FIFO_SZ;
306 data->kbd_fifo_sz = 0;
309 data->compile_opts = (0
320 #if PCVT_CTRL_ALT_DEL
344 #if PCVT_BACKUP_FONTS
347 #if PCVT_SW0CNOUTP /* was FORCE8BIT */
365 #if PCVT_USL_VT_COMPAT
368 #if PCVT_PORTIO_DELAY
371 #if PCVT_INHIBIT_NUMLOCK
372 | CONF_INHIBIT_NUMLOCK
380 #if PCVT_NOFASTSCROLL
383 #if PCVT_SLOW_INTERRUPT
384 | CONF_SLOW_INTERRUPT
386 #if PCVT_NO_LED_UPDATE
392 /*---------------------------------------------------------------------------*
393 * video ioctl - set cursor appearence
394 *---------------------------------------------------------------------------*/
396 vid_cursor(struct cursorshape *data)
404 /* for which virtual screen, -1 for current */
405 screen = data->screen_no;
407 if(screen == -1) /* current ? */
408 screen = current_video_screen;
409 else if(screen > totalscreens - 1)
410 screen = totalscreens - 1;
414 if(adaptor_type == VGA_ADAPTOR || adaptor_type == EGA_ADAPTOR)
416 character_set = vs[screen].vga_charset;
417 character_set = (character_set < 0) ? 0 :
418 ((character_set < totalfonts) ?
422 line_height = vgacs[character_set].char_scanlines & 0x1F;
424 else if(adaptor_type == MDA_ADAPTOR)
430 line_height = 8; /* CGA */
433 start = (data->start < 0) ? 0 :
434 ((data->start > line_height) ? line_height : data->start);
436 if((vga_family == VGA_F_TRI) && (start == 0))
439 end = (data->end < 0) ? 0 :
440 ((data->end > line_height) ? line_height : data->end);
442 vs[screen].cursor_start = start;
443 vs[screen].cursor_end = end;
445 if(screen == current_video_screen)
447 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
448 outb(addr_6845+1, start);
449 outb(addr_6845,CRTC_CUREND); /* cursor end reg */
450 outb(addr_6845+1, end);
454 /*---------------------------------------------------------------------------*
455 * ega/vga ioctl - set font attributes
456 *---------------------------------------------------------------------------*/
458 vgasetfontattr(struct vgafontattr *data)
461 int vga_character_set;
462 int lines_per_character;
466 vga_character_set = data->character_set;
467 vga_character_set = (vga_character_set < 0) ? 0 :
468 ((vga_character_set < totalfonts) ?
469 vga_character_set : totalfonts-1);
471 vgacs[vga_character_set].loaded = data->font_loaded;
473 /* Limit Characters to 32 scanlines doubled */
474 vgacs[vga_character_set].char_scanlines =
475 (data->character_scanlines & 0x1F)
476 | 0x40; /* always set bit 9 of line cmp reg */
478 if(adaptor_type == EGA_ADAPTOR)
479 /* ...and screen height to scan 350 lines */
480 vgacs[vga_character_set].scr_scanlines =
481 (data->screen_scanlines > 0x5d) ?
482 0x5d : data->screen_scanlines;
484 /* ...and screen height to scan 480 lines */
485 vgacs[vga_character_set].scr_scanlines =
486 (data->screen_scanlines > 0xdF) ?
487 0xdF : data->screen_scanlines;
489 lines_per_character =
490 (int)(0x1F & vgacs[vga_character_set].char_scanlines)+1;
492 totscanlines = 0x101 + (int)vgacs[vga_character_set].scr_scanlines;
494 size = data->screen_size;
496 if(adaptor_type == EGA_ADAPTOR)
500 case SIZ_25ROWS: /* This case is always OK */
504 if(totscanlines/lines_per_character >= 35)
512 if(totscanlines/lines_per_character >= 43)
514 else if(totscanlines/lines_per_character >= 35)
525 case SIZ_25ROWS: /* This case is always OK */
529 if(totscanlines/lines_per_character >= 28)
536 if(totscanlines/lines_per_character >= 40)
538 else if(totscanlines/lines_per_character >= 28)
546 if(totscanlines/lines_per_character >= 50)
548 else if(totscanlines/lines_per_character >= 40)
550 else if(totscanlines/lines_per_character >= 28)
558 vgacs[vga_character_set].screen_size = size;
560 for (i = 0;i < PCVT_NSCREENS;i++)
562 if(vga_character_set == vs[i].vga_charset)
563 set_charset(&(vs[i]),vga_character_set);
566 #if !PCVT_USL_VT_COMPAT
567 vgapage(current_video_screen);
569 switch_screen(current_video_screen, 0, 0);
570 #endif /* !PCVT_USL_VT_COMPAT */
574 /*---------------------------------------------------------------------------*
575 * ega/vga ioctl - get font attributes
576 *---------------------------------------------------------------------------*/
578 vgagetfontattr(struct vgafontattr *data)
580 int vga_character_set;
582 vga_character_set = data->character_set;
583 vga_character_set = (vga_character_set < 0) ? 0 :
584 ((vga_character_set < (int)totalfonts) ?
586 (int)(totalfonts-1));
588 data->character_set = (int)vga_character_set;
590 data->font_loaded = (int)vgacs[vga_character_set].loaded;
592 data->character_scanlines =
593 (int)vgacs[vga_character_set].char_scanlines
594 & 0x1f; /* do not display the overflow bits */
596 data->screen_scanlines = (int)vgacs[vga_character_set].scr_scanlines;
598 data->screen_size = (int)vgacs[vga_character_set].screen_size;
601 /*---------------------------------------------------------------------------*
602 * ega/vga ioctl - load a character shape into character set
603 *---------------------------------------------------------------------------*/
605 vgaloadchar(struct vgaloadchar *data)
607 int vga_character_set;
609 int lines_per_character;
611 vga_character_set = data->character_set;
612 vga_character_set = (vga_character_set < 0) ? 0 :
613 ((vga_character_set < (int)totalfonts) ?
614 vga_character_set : (int)(totalfonts-1));
616 character = (data->character < 0) ? 0 :
617 ((data->character > 255) ? 255 : data->character);
619 lines_per_character = (int)data->character_scanlines;
620 lines_per_character = (lines_per_character < 0) ? 0 :
621 ((lines_per_character > 32) ? 32 : lines_per_character);
623 loadchar(vga_character_set,character,lines_per_character,
627 /*---------------------------------------------------------------------------*
628 * video ioctl - get screen information
629 *---------------------------------------------------------------------------*/
631 vid_getscreen(struct screeninfo *data, Dev_t dev)
633 int device = minor(dev);
634 data->adaptor_type = adaptor_type; /* video adapter installed */
635 data->monitor_type = color; /* monitor type installed */
636 data->totalfonts = totalfonts; /* no of downloadble fonts */
637 data->totalscreens = totalscreens; /* no of virtual screens */
638 data->screen_no = device; /* this screen number */
639 data->current_screen = current_video_screen; /* displayed screen no */
641 data->screen_size = vgacs[(vs[device].vga_charset)].screen_size;
642 /* pure VT mode or HP/VT mode */
643 data->pure_vt_mode = vs[device].vt_pure_mode;
644 data->vga_family = vga_family; /* manufacturer, family */
645 data->vga_type = vga_type; /* detected chipset type */
646 data->vga_132 = can_do_132col; /* 132 column support */
647 data->force_24lines = vs[device].force24; /* force 24 lines */
650 /*---------------------------------------------------------------------------*
651 * video ioctl - set screen information
652 *---------------------------------------------------------------------------*/
654 vid_setscreen(struct screeninfo *data, Dev_t dev)
658 if(data->current_screen == -1)
664 if(data->current_screen >= PCVT_NSCREENS)
666 screen = data->current_screen;
671 #if defined XSERVER && PCVT_USL_VT_COMPAT
673 int x = spltty(), waitfor = screen + 1;
674 /* if the vt is yet to be released by a process, wait here */
675 if(vs[screen].vt_status & VT_WAIT_REL)
676 (void)usl_vt_ioctl(dev, VT_WAITACTIVE,
677 (caddr_t)&waitfor, 0, 0);
680 /* make sure the switch really happened */
681 if(screen != current_video_screen)
682 return; /* XXX should say "EAGAIN" here */
683 #endif /* defined XSERVER && PCVT_USL_VT_COMPAT */
685 if((data->screen_size != -1) || (data->force_24lines != -1))
687 if(data->screen_size == -1)
689 vgacs[(vs[screen].vga_charset)].screen_size;
691 if(data->force_24lines != -1)
693 vs[screen].force24 = data->force_24lines;
695 if(vs[screen].force24)
697 swritefkl(2,(u_char *)"FORCE24 ENABLE *",
702 swritefkl(2,(u_char *)"FORCE24 ENABLE ",
707 if((data->screen_size == SIZ_25ROWS) ||
708 (data->screen_size == SIZ_28ROWS) ||
709 (data->screen_size == SIZ_35ROWS) ||
710 (data->screen_size == SIZ_40ROWS) ||
711 (data->screen_size == SIZ_43ROWS) ||
712 (data->screen_size == SIZ_50ROWS))
714 if(data->screen_no == -1)
715 set_screen_size(vsp, data->screen_size);
717 set_screen_size(&vs[minor(dev)],
722 if(data->pure_vt_mode != -1)
724 if((data->pure_vt_mode == M_HPVT) ||
725 (data->pure_vt_mode == M_PUREVT))
727 if(data->screen_no == -1)
728 set_emulation_mode(vsp, data->pure_vt_mode);
730 set_emulation_mode(&vs[minor(dev)],
736 /*---------------------------------------------------------------------------*
737 * set screen size/resolution for a virtual screen
738 *---------------------------------------------------------------------------*/
740 set_screen_size(struct video_state *svsp, int size)
744 for(i = 0; i < totalfonts; i++)
746 if(vgacs[i].screen_size == size)
748 set_charset(svsp, i);
749 clr_parms(svsp); /* escape parameter init */
750 svsp->state = STATE_INIT; /* initial state */
751 svsp->scrr_beg = 0; /* start of scrolling region */
752 svsp->sc_flag = 0; /* invalidate saved cursor
754 svsp->transparent = 0; /* disable control code
757 /* Update tty to reflect screen size */
761 svsp->vs_tty->t_winsize.ws_col = svsp->maxcol;
762 svsp->vs_tty->t_winsize.ws_xpixel =
763 (svsp->maxcol == 80)? 720: 1056;
764 svsp->vs_tty->t_winsize.ws_ypixel = 400;
765 svsp->vs_tty->t_winsize.ws_row =
768 /* screen_rows already calculated in set_charset() */
769 if(svsp->vt_pure_mode == M_HPVT && svsp->labels_on)
771 if(svsp->which_fkl == SYS_FKL)
773 else if(svsp->which_fkl == USR_FKL)
778 svsp->scrr_len = svsp->screen_rows;
779 svsp->scrr_end = svsp->scrr_len - 1;
782 if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
783 pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
784 #endif /* PCVT_SIGWINCH */
786 reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
792 /*---------------------------------------------------------------------------*
793 * resize the scrollback buffer to the specified number of "pages"
794 *---------------------------------------------------------------------------*/
796 reallocate_scrollbuffer(struct video_state *svsp, int pages)
808 if((stmp = (u_short *)malloc(svsp->maxcol * svsp->screen_rows *
809 pages * CHR, M_DEVBUF, M_NOWAIT)) == NULL)
812 printf("pcvt: reallocate_scrollbuffer, malloc failed\n");
816 svsp->max_off = svsp->screen_rows * pages - 1;
820 bcopy(svsp->Scrollback, stmp,
821 (min(pages, svsp->scrollback_pages)) *
822 svsp->screen_rows * svsp->maxcol * CHR);
823 free(svsp->Scrollback, M_DEVBUF);
824 svsp->Scrollback = stmp;
828 svsp->scr_offset = 0;
830 svsp->Scrollback = stmp;
832 bcopy(svsp->Crtat, svsp->Scrollback,
833 svsp->screen_rows * svsp->maxcol * CHR);
835 svsp->scr_offset = svsp->row;
838 svsp->scrollback_pages = pages;
843 /*---------------------------------------------------------------------------*
844 * VGA ioctl - read DAC palette entry
845 *---------------------------------------------------------------------------*/
847 vgareadpel(struct vgapel *data, Dev_t dev)
849 unsigned vpage = minor(dev);
850 unsigned idx = data->idx;
853 return; /* no such entry */
855 /* do not read VGA palette directly, use saved values */
856 data->r = vs[vpage].palette[idx].r;
857 data->g = vs[vpage].palette[idx].g;
858 data->b = vs[vpage].palette[idx].b;
861 /*---------------------------------------------------------------------------*
862 * VGA ioctl - write DAC palette entry
863 *---------------------------------------------------------------------------*/
865 vgawritepel(struct vgapel *data, Dev_t dev)
867 unsigned vpage = minor(dev);
868 unsigned idx = data->idx;
871 return; /* no such entry */
873 /* first, update saved values for this video screen */
874 vs[vpage].palette[idx].r = data->r;
875 vs[vpage].palette[idx].g = data->g;
876 vs[vpage].palette[idx].b = data->b;
878 /* if this happens on active screen, update VGA DAC, too */
879 if(vpage == current_video_screen)
880 vgapaletteio(idx, &vs[vpage].palette[idx], 1);
883 /*---------------------------------------------------------------------------*
884 * VGA physical IO - read/write one palette entry
885 *---------------------------------------------------------------------------*/
887 vgapaletteio(unsigned idx, struct rgb *val, int writeit)
892 #endif /* PCVT_PALFLICKER */
896 outb(VGA_DAC + 2, idx);
900 #endif /* PCVT_WAITRETRACE */
902 outb(VGA_DAC + 3, val->r & VGA_PMSK);
906 #endif /* PCVT_WAITRETRACE */
908 outb(VGA_DAC + 3, val->g & VGA_PMSK);
912 #endif /* PCVT_WAITRETRACE */
914 outb(VGA_DAC + 3, val->b & VGA_PMSK);
918 outb(VGA_DAC + 1, idx);
922 #endif /* PCVT_WAITRETRACE */
924 val->r = inb(VGA_DAC + 3) & VGA_PMSK;
928 #endif /* PCVT_WAITRETRACE */
930 val->g = inb(VGA_DAC + 3) & VGA_PMSK;
934 #endif /* PCVT_WAITRETRACE */
936 val->b = inb(VGA_DAC + 3) & VGA_PMSK;
941 #endif /* PCVT_PALFLICKER */
945 /*---------------------------------------------------------------------------*
947 * update asynchronous: cursor, cursor pos displ, sys load, keyb scan
950 * UPDATE_START = do update; requeue
951 * UPDATE_STOP = suspend updates
952 * UPDATE_KERN = do update for kernel printfs
954 *---------------------------------------------------------------------------*/
956 async_update(void *arg)
958 static int lastpos = 0;
959 static int counter = PCVT_UPDATESLOW;
962 /* need a method to suspend the updates */
964 if(arg == UPDATE_STOP)
966 callout_stop(&async_update_ch);
971 /* first check if update is possible */
973 if(chargen_access /* does no-one load characters? */
974 #ifdef XSERVER /* is vt0 not in graphics mode? */
975 #if !PCVT_USL_VT_COMPAT
976 || pcvt_xmode /* XXX necessary ????? */
977 #endif /* PCVT_USL_VT_COMPAT */
981 goto async_update_exit; /* do not update anything */
985 if(reset_screen_saver && (counter == PCVT_UPDATESLOW))
987 pcvt_scrnsv_reset(); /* yes, do it */
988 reset_screen_saver = 0; /* re-init */
990 else if(scrnsv_active) /* is the screen not blanked? */
992 goto async_update_exit; /* do not update anything */
994 #endif /* PCVT_SCREENSAVER */
996 /*-------------------------------------------------------------------*/
997 /* this takes place on EVERY virtual screen (if not in X mode etc...)*/
998 /*-------------------------------------------------------------------*/
1000 if ( cursor_pos_valid &&
1001 (lastpos != (vsp->Crtat + vsp->cur_offset - Crtat)))
1003 lastpos = vsp->Crtat + vsp->cur_offset - Crtat;
1004 outb(addr_6845, CRTC_CURSORH); /* high register */
1005 outb(addr_6845+1, ((lastpos) >> 8));
1006 outb(addr_6845, CRTC_CURSORL); /* low register */
1007 outb(addr_6845+1, (lastpos));
1010 if (arg == UPDATE_KERN) /* Magic arg: for kernel printfs */
1013 if(--counter) /* below is possible update */
1014 goto async_update_exit; /* just now and then ..... */
1015 counter = PCVT_UPDATESLOW; /* caution, see screensaver above !! */
1017 /*-------------------------------------------------------------------*/
1018 /* this takes place ONLY on screen 0 if in HP mode, labels on, !X */
1019 /*-------------------------------------------------------------------*/
1021 /* additional processing for HP necessary ? */
1023 if((vs[0].vt_pure_mode == M_HPVT) && (vs[0].labels_on))
1025 static volatile u_char buffer[] =
1026 "System Load: 1min: 0.00 5min: 0.00 15min: 0.00";
1029 extern u_char rawkeybuf[80];
1033 for(i = 0; i < 80; i++)
1035 *((vs[0].Crtat+((vs[0].screen_rows+2)
1036 * vs[0].maxcol))+i) =
1037 user_attr | rawkeybuf[i];
1042 #endif /* PCVT_SHOWKEYS */
1044 /* display load averages in last line (taken from tty.c) */
1046 #ifdef NEW_AVERUNNABLE
1047 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2)
1050 tmp = (averunnable[0] * 100 + FSCALE / 2) >> FSHIFT;
1054 ((((tmp/100)/10) == 0) ?
1056 ((tmp/100)/10) + '0');
1057 buffer[i++] = ((tmp/100)%10) + '0';
1059 buffer[i++] = ((tmp%100)/10) + '0';
1060 buffer[i++] = ((tmp%100)%10) + '0';
1062 #ifdef NEW_AVERUNNABLE
1063 tmp = (averunnable.ldavg[1] * 100 + FSCALE / 2)
1066 tmp = (averunnable[1] * 100 + FSCALE / 2) >> FSHIFT;
1068 buffer[i++] = ((((tmp/100)/10) == 0) ?
1070 ((tmp/100)/10) + '0');
1071 buffer[i++] = ((tmp/100)%10) + '0';
1073 buffer[i++] = ((tmp%100)/10) + '0';
1074 buffer[i++] = ((tmp%100)%10) + '0';
1076 #ifdef NEW_AVERUNNABLE
1077 tmp = (averunnable.ldavg[2] * 100 + FSCALE / 2)
1080 tmp = (averunnable[2] * 100 + FSCALE / 2) >> FSHIFT;
1082 buffer[i++] = ((((tmp/100)/10) == 0) ?
1084 ((tmp/100)/10) + '0');
1085 buffer[i++] = ((tmp/100)%10) + '0';
1087 buffer[i++] = ((tmp%100)/10) + '0';
1088 buffer[i++] = ((tmp%100)%10) + '0';
1091 for(i = 0; buffer[i]; i++)
1094 ((vs[0].screen_rows + 2) * vs[0].maxcol)
1096 ) = user_attr | buffer[i];
1103 ((vs[0].screen_rows + 2) * vs[0].maxcol)
1105 ) = user_attr | ' ';
1109 #endif /* PCVT_SHOWKEYS */
1112 /*-------------------------------------------------------------------*/
1113 /* this takes place on EVERY screen which is in HP mode, labels on,!X*/
1114 /*-------------------------------------------------------------------*/
1116 if((vsp->vt_pure_mode == M_HPVT) && (vsp->labels_on))
1118 int col = vsp->col+1;
1119 u_short *p = vsp->Crtat +
1120 (vsp->screen_rows * vsp->maxcol);
1122 /* update column display between labels */
1124 if(vsp->maxcol == SCR_COL132)
1126 p += (SCR_COL132 - SCR_COL80)/2;
1130 *(p + LABEL_COLU) = user_attr | '1';
1135 *(p + LABEL_COLU) = user_attr | '0';
1138 *(p + LABEL_COLH) = user_attr | ((col/10) + '0');
1139 *(p + LABEL_COLL) = user_attr | ((col%10) + '0');
1141 /* update row display between labels */
1143 *(p + LABEL_ROWH) = (user_attr | (((vsp->row+1)/10) + '0'));
1144 *(p + LABEL_ROWL) = (user_attr | (((vsp->row+1)%10) + '0'));
1149 if(arg == UPDATE_START)
1151 callout_reset(&async_update_ch, PCVT_UPDATEFAST,
1152 async_update, (void *)UPDATE_START);
1156 /*---------------------------------------------------------------------------*
1157 * set character set for virtual screen
1158 *---------------------------------------------------------------------------*/
1160 set_charset(struct video_state *svsp, int curvgacs)
1162 static int sizetab[] = { 25, 28, 35, 40, 43, 50 };
1163 int oldsize, oldrows, newsize, newrows;
1165 if((curvgacs < 0) || (curvgacs > (NVGAFONTS-1)))
1168 svsp->vga_charset = curvgacs;
1170 select_vga_charset(curvgacs);
1172 oldsize = svsp->screen_rowsize;
1173 oldrows = svsp->screen_rows;
1174 newsize = sizetab[(vgacs[curvgacs].screen_size)];
1176 if (svsp->vt_pure_mode == M_HPVT)
1178 if (newrows == 25 && svsp->force24)
1180 if (newrows < oldrows) {
1181 int nscroll = svsp->row + 1 - newrows;
1183 if (svsp->row >= oldrows) /* Sanity check */
1184 nscroll = oldrows - newrows;
1187 bcopy (svsp->Crtat + nscroll * svsp->maxcol,
1189 newrows * svsp->maxcol * CHR);
1190 svsp->row -= nscroll;
1191 svsp->cur_offset -= nscroll * svsp->maxcol;
1193 if (newrows < newsize)
1194 fillw(user_attr | ' ',
1195 svsp->Crtat + newrows * svsp->maxcol,
1196 (newsize - newrows) * svsp->maxcol);
1197 } else if (oldrows < newsize)
1198 fillw(user_attr | ' ',
1199 svsp->Crtat + oldrows * svsp->maxcol,
1200 (newsize - oldrows) * svsp->maxcol);
1202 svsp->screen_rowsize = newsize;
1203 svsp->screen_rows = newrows;
1205 /* Clip scrolling region */
1206 if(svsp->scrr_end > svsp->screen_rows - 1)
1207 svsp->scrr_end = svsp->screen_rows - 1;
1208 svsp->scrr_len = svsp->scrr_end - svsp->scrr_beg + 1;
1210 /* Clip cursor pos */
1212 if(svsp->cur_offset > (svsp->scrr_len * svsp->maxcol))
1213 svsp->cur_offset = (svsp->scrr_len * svsp->maxcol) + svsp->col;
1216 /*---------------------------------------------------------------------------*
1217 * select a vga character set
1218 *---------------------------------------------------------------------------*/
1220 select_vga_charset(int vga_charset)
1227 static u_char cmaptaba[] =
1228 {0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13};
1230 static u_char cmaptabb[] =
1231 {0x00, 0x04, 0x08, 0x0c, 0x20, 0x24, 0x28, 0x2c};
1233 if((adaptor_type != EGA_ADAPTOR) && (adaptor_type != VGA_ADAPTOR))
1236 if((vga_charset < 0) || (vga_charset >= totalfonts))
1239 if(!vgacs[vga_charset].loaded)
1242 /*--------------------------------------------------------------
1243 find the the first and second charset of a given resolution.
1244 the first is used for lower 256 and the second (if any) is
1245 used for the upper 256 entries of a complete 512 entry ega/
1247 --------------------------------------------------------------*/
1249 for(first = 0; first < totalfonts; first++)
1251 if(!vgacs[first].loaded)
1253 if(vgacs[first].screen_size != vgacs[vga_charset].screen_size)
1255 if(vgacs[first].char_scanlines !=
1256 vgacs[vga_charset].char_scanlines)
1258 if(vgacs[first].scr_scanlines !=
1259 vgacs[vga_charset].scr_scanlines)
1268 for(second = first+1; second < totalfonts; second++)
1270 if(!vgacs[second].loaded)
1272 if(vgacs[second].screen_size != vgacs[vga_charset].screen_size)
1274 if(vgacs[second].char_scanlines !=
1275 vgacs[vga_charset].char_scanlines)
1277 if(vgacs[second].scr_scanlines !=
1278 vgacs[vga_charset].scr_scanlines)
1284 cmap = cmaptaba[first];
1287 cmap |= cmaptabb[second];
1288 vgacs[first].secondloaded = second;
1292 vgacs[first].secondloaded = 0; /*cs 0 can never become a 2nd!*/
1297 cmap = (vga_charset & 0x07);
1301 outb(TS_INDEX, TS_FONTSEL); /* character map select register */
1302 outb(TS_DATA, cmap); /* new char map */
1304 outb(addr_6845, CRTC_MAXROW); /* max scan line reg */
1306 vgacs[first].char_scanlines); /* scanlines/char */
1308 outb(addr_6845, CRTC_VDE); /* vert display enable end */
1310 vgacs[first].scr_scanlines); /* low byte of scr scanlines */
1312 if((color == 0) && (adaptor_type == VGA_ADAPTOR))
1314 outb(addr_6845, CRTC_ULOC); /* underline location reg */
1315 outb(addr_6845+1, (vgacs[first].char_scanlines & 0x1F));
1319 /*---------------------------------------------------------------------------*
1320 * switch vga-card to load a character set
1321 *---------------------------------------------------------------------------*/
1325 chargen_access = 1; /* flag we are accessing the chargen ram */
1327 /* program sequencer to access character generator */
1329 outb(TS_INDEX, TS_SYNCRESET);
1330 outb(TS_DATA, 0x01); /* synchronous reset */
1332 outb(TS_INDEX, TS_WRPLMASK);
1333 outb(TS_DATA, 0x04); /* write to map 2 */
1335 outb(TS_INDEX, TS_MEMMODE);
1336 outb(TS_DATA, 0x07); /* sequential addressing */
1338 outb(TS_INDEX, TS_SYNCRESET);
1339 outb(TS_DATA, 0x03); /* clear synchronous reset */
1341 /* program graphics controller to access character generator */
1343 outb(GDC_INDEX, GDC_RDPLANESEL);
1344 outb(GDC_DATA, 0x02); /* select map 2 for cpu reads */
1346 outb(GDC_INDEX, GDC_MODE);
1347 outb(GDC_DATA, 0x00); /* disable odd-even addressing */
1349 outb(GDC_INDEX, GDC_MISC);
1350 outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
1353 /*---------------------------------------------------------------------------*
1354 * switch vga-card to load a character set to plane 3
1355 *---------------------------------------------------------------------------*/
1359 chargen_access = 1; /* flag we are accessing the chargen ram */
1361 /* program sequencer to access character generator */
1363 outb(TS_INDEX, TS_SYNCRESET);
1364 outb(TS_DATA, 0x01); /* synchronous reset */
1366 outb(TS_INDEX, TS_WRPLMASK);
1367 outb(TS_DATA, 0x08); /* write to map 3 */
1369 outb(TS_INDEX, TS_MEMMODE);
1370 outb(TS_DATA, 0x07); /* sequential addressing */
1372 outb(TS_INDEX, TS_SYNCRESET);
1373 outb(TS_DATA, 0x03); /* clear synchronous reset */
1375 /* program graphics controller to access character generator */
1377 outb(GDC_INDEX, GDC_RDPLANESEL);
1378 outb(GDC_DATA, 0x03); /* select map 3 for cpu reads */
1380 outb(GDC_INDEX, GDC_MODE);
1381 outb(GDC_DATA, 0x00); /* disable odd-even addressing */
1383 outb(GDC_INDEX, GDC_MISC);
1384 outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
1387 /*---------------------------------------------------------------------------*
1388 * switch back vga-card to normal operation
1389 *---------------------------------------------------------------------------*/
1393 /* program sequencer to access video ram */
1395 outb(TS_INDEX, TS_SYNCRESET);
1396 outb(TS_DATA, 0x01); /* synchronous reset */
1398 outb(TS_INDEX, TS_WRPLMASK);
1399 outb(TS_DATA, 0x03); /* write to map 0 & 1 */
1401 outb(TS_INDEX, TS_MEMMODE);
1402 outb(TS_DATA, 0x03); /* odd-even addressing */
1404 outb(TS_INDEX, TS_SYNCRESET);
1405 outb(TS_DATA, 0x03); /* clear synchronous reset */
1407 /* program graphics controller to access character generator */
1409 outb(GDC_INDEX, GDC_RDPLANESEL);
1410 outb(GDC_DATA, 0x00); /* select map 0 for cpu reads */
1412 outb(GDC_INDEX, GDC_MODE);
1413 outb(GDC_DATA, 0x10); /* enable odd-even addressing */
1415 outb(GDC_INDEX, GDC_MISC);
1417 outb(GDC_DATA, 0x0e); /* map starts at 0xb800 */
1419 outb(GDC_DATA, 0x0a); /* map starts at 0xb000 */
1421 chargen_access = 0; /* flag we are NOT accessing the chargen ram */
1424 #if PCVT_WAITRETRACE
1425 /*---------------------------------------------------------------------------*
1426 * wait for being in a retrace time window
1427 * NOTE: this is __VERY__ bad programming practice in this environment !!
1428 *---------------------------------------------------------------------------*/
1435 while(!(inb(GN_INPSTAT1C) & 0x01))
1440 while(!(inb(GN_INPSTAT1M) & 0x01))
1445 #endif /* PCVT_WAITRETRACE */
1447 /*---------------------------------------------------------------------------*
1448 * switch screen off (VGA only)
1449 *---------------------------------------------------------------------------*/
1451 vga_screen_off(void)
1455 outb(TS_INDEX, TS_SYNCRESET);
1456 outb(TS_DATA, 0x01); /* synchronous reset */
1458 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1459 old = inb(TS_DATA); /* get current value */
1461 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1462 outb(TS_DATA, (old | 0x20)); /* screen off bit on */
1464 outb(TS_INDEX, TS_SYNCRESET);
1465 outb(TS_DATA, 0x03); /* clear synchronous reset */
1468 /*---------------------------------------------------------------------------*
1469 * switch screen back on (VGA only)
1470 *---------------------------------------------------------------------------*/
1476 outb(TS_INDEX, TS_SYNCRESET);
1477 outb(TS_DATA, 0x01); /* synchronous reset */
1479 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1480 old = inb(TS_DATA); /* get current value */
1482 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1483 outb(TS_DATA, (old & ~0x20)); /* screen off bit off */
1485 outb(TS_INDEX, TS_SYNCRESET);
1486 outb(TS_DATA, 0x03); /* clear synchronous reset */
1489 /*---------------------------------------------------------------------------*
1490 * compute character set base address (in kernel map)
1491 *---------------------------------------------------------------------------*/
1492 static unsigned char *
1493 compute_charset_base(unsigned fontset)
1495 unsigned char *d = (unsigned char *)Crtat;
1497 static int charset_offset[8] = { 0x0000, 0x4000, 0x8000, 0xC000,
1498 0x2000, 0x6000, 0xA000, 0xE000 };
1500 static int charsetw_offset[8] = { 0x0000, 0x2000, 0x4000, 0x6000,
1501 0x8000, 0xA000, 0xC000, 0xE000 };
1503 switch(adaptor_type)
1506 fontset = (fontset > 3) ? 3 : fontset;
1510 fontset = (fontset > 7) ? 7 : fontset;
1518 d -= (0xB8000 - 0xA0000); /* Point to 0xA0000 */
1520 d -= (0xB0000 - 0xA0000); /* Point to 0xA0000 */
1523 d += charsetw_offset[fontset]; /* Load into Character set n */
1525 d += charset_offset[fontset]; /* Load into Character set n */
1530 /*---------------------------------------------------------------------------*
1531 * load a char into ega/vga character generator ram
1532 *---------------------------------------------------------------------------*/
1534 loadchar(int fontset, int character, int char_scanlines, u_char *char_table)
1538 #if PCVT_BACKUP_FONTS
1540 #endif /* PCVT_BACKUP_FONTS */
1544 if((d = compute_charset_base(fontset)) == 0)
1547 d += (character * 32); /* 32 bytes per character */
1550 (fontset == 1||fontset == 3||fontset == 5||fontset == 7))
1551 setchargen3(); /* access chargen ram */
1553 setchargen(); /* access chargen ram */
1555 for(j = k = 0; j < char_scanlines; j++) /* x bit high characters */
1561 for(; j < 32; j++) /* Up to 32 bytes per character image*/
1567 resetchargen(); /* access video ram */
1569 #if PCVT_BACKUP_FONTS
1570 if(saved_charsets[fontset] == 0)
1571 saved_charsets[fontset] =
1572 (u_char *)malloc(32 * 256, M_DEVBUF, M_WAITOK);
1574 if((bak = saved_charsets[fontset]))
1576 /* make a backup copy of this char */
1577 bak += (character * 32);
1579 bcopy(char_table, bak, char_scanlines);
1583 panic("pcvt loadchar: no backup buffer");
1584 #endif /* DIAGNOSTIC */
1586 #endif /* PCVT_BACKUP_FONTS */
1590 /*---------------------------------------------------------------------------*
1591 * save/restore character set n to addr b
1592 *---------------------------------------------------------------------------*/
1593 #if !PCVT_BACKUP_FONTS
1596 vga_move_charset(unsigned n, unsigned char *b, int save_it)
1598 unsigned char *d = compute_charset_base(n);
1602 panic("vga_move_charset: wrong adaptor");
1605 if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
1615 /* PLEASE, leave the following alone using bcopyb, as several */
1616 /* chipsets have problems if their memory is accessed with 32 */
1617 /* or 16 bits wide, don't change this to using bcopy for speed! */
1620 bcopyb(d, b, 256 /* chars */ * 32 /* bytes per char */);
1622 bcopyb(b, d, 256 /* chars */ * 32 /* bytes per char */);
1627 #else /* PCVT_BACKUP_FONTS */
1629 /* since there are always backed up copies, we do not save anything here */
1630 /* parameter "b" is totally ignored */
1633 vga_move_charset(unsigned n, unsigned char *b, int save_it)
1635 unsigned char *d = compute_charset_base(n);
1640 if(saved_charsets[n] == 0)
1642 panic("pcvt: restoring unbuffered charset");
1649 panic("vga_move_charset: wrong adaptor");
1652 if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
1662 /* PLEASE, leave the following alone using bcopyb, as several */
1663 /* chipsets have problems if their memory is accessed with 32 */
1664 /* or 16 bits wide, don't change this to using bcopy for speed! */
1666 bcopyb(saved_charsets[n], d,
1667 256 /* chars */ * 32 /* bytes per char */);
1672 #endif /* PCVT_BACKUP_FONTS */
1675 #if !PCVT_USL_VT_COMPAT
1676 /*---------------------------------------------------------------------------*
1677 * switch to virtual screen n (0 ... PCVT_NSCREENS-1)
1678 *---------------------------------------------------------------------------*/
1685 #endif /* !PCVT_KBD_FIFO */
1687 int cols = vsp->maxcol; /* get current col val */
1689 if(n < 0 || n >= totalscreens)
1693 x = spltty(); /* protect us */
1694 #endif /* !PCVT_KBD_FIFO */
1696 /* video board memory -> kernel memory */
1698 bcopy(vsp->Crtat, vsp->Memory, vsp->screen_rows * vsp->maxcol * CHR);
1700 vsp->Crtat = vsp->Memory; /* operate in memory now */
1702 /* update global screen pointers/variables */
1704 current_video_screen = n; /* current screen no */
1706 #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
1707 pcconsp = &pccons[n]; /* current tty */
1708 #elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200
1709 pcconsp = pccons[n]; /* current tty */
1711 pcconsp = pc_tty[n]; /* current tty */
1714 vsp = &vs[n]; /* current video state ptr */
1716 /* kernel memory -> video board memory */
1718 bcopy(vsp->Crtat, Crtat, vsp->screen_rows * vsp->maxcol * CHR);
1720 vsp->Crtat = Crtat; /* operate on screen now */
1722 outb(addr_6845, CRTC_STARTADRH);
1723 outb(addr_6845+1, 0);
1724 outb(addr_6845, CRTC_STARTADRL);
1725 outb(addr_6845+1, 0);
1729 #endif /* !PCVT_KBD_FIFO */
1731 select_vga_charset(vsp->vga_charset);
1733 if(vsp->maxcol != cols)
1734 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
1736 outb(addr_6845, CRTC_CURSORH); /* select high register */
1737 outb(addr_6845+1, vsp->cur_offset >> 8);
1738 outb(addr_6845, CRTC_CURSORL); /* select low register */
1739 outb(addr_6845+1, vsp->cur_offset);
1743 outb(addr_6845, CRTC_CURSTART); /* select high register */
1744 outb(addr_6845+1, vsp->cursor_start);
1745 outb(addr_6845, CRTC_CUREND); /* select low register */
1746 outb(addr_6845+1, vsp->cursor_end);
1753 if(adaptor_type == VGA_ADAPTOR)
1757 /* switch VGA DAC palette entries */
1759 for(i = 0; i < NVGAPEL; i++)
1760 vgapaletteio(i, &vsp->palette[i], 1);
1763 update_led(); /* update led's */
1765 update_hp(vsp); /* update fkey labels, if present */
1767 #endif /* !PCVT_USL_VT_COMPAT */
1769 /*---------------------------------------------------------------------------*
1770 * test if it is a vga
1771 *---------------------------------------------------------------------------*/
1776 u_char old, new, check;
1778 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1779 old = inb(addr_6845+1); /* get current value */
1781 new = old | CURSOR_ON_BIT; /* set cursor on by setting bit 5 on */
1783 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1784 outb(addr_6845+1,new); /* cursor should be on now */
1786 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1787 check = inb(addr_6845+1); /* get current value */
1791 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1792 outb(addr_6845+1,old); /* failsafe */
1793 return(0); /* must be ega */
1796 new = old & ~CURSOR_ON_BIT; /* turn cursor off by clearing bit 5 */
1798 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1799 outb(addr_6845+1,new); /* cursor should be off now */
1801 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1802 check = inb(addr_6845+1); /* get current value */
1806 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1807 outb(addr_6845+1,old); /* failsafe */
1808 return(0); /* must be ega */
1811 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1812 outb(addr_6845+1,old); /* failsafe */
1814 return(1); /* vga */
1817 /*---------------------------------------------------------------------------*
1818 * convert upper/lower sixel font array to vga font array
1819 *---------------------------------------------------------------------------*/
1821 sixel_vga(struct sixels *sixelp, u_char *vgachar)
1827 for(j = 0; j < 16; j++)
1831 for(j = 0; j < 6; j++)
1833 for(i = 0, shift = 7; i < 8; i++, shift--)
1834 vgachar[j] |= ((((sixelp->upper[i]) & mask) >> j)
1840 for(j = 0; j < 4; j++)
1842 for(i = 0, shift = 7; i < 8; i++, shift--)
1843 vgachar[j+6] |= ((((sixelp->lower[i]) & mask) >>j)
1849 /*---------------------------------------------------------------------------*
1850 * Expand 8x10 EGA/VGA characters to 8x16 EGA/VGA characters
1851 *---------------------------------------------------------------------------*/
1853 vga10_vga16(u_char *invga, u_char *outvga)
1858 * Keep the top and bottom scanlines the same and double every scan
1862 outvga[0] = invga[0];
1863 outvga[1] = invga[1];
1864 outvga[14] = invga[8];
1865 outvga[15] = invga[9];
1867 for(i = j = 2;i < 8 && j < 14;i++,j += 2)
1869 outvga[j] = invga[i];
1870 outvga[j+1] = invga[i];
1874 /*---------------------------------------------------------------------------*
1875 * Expand 8x10 EGA/VGA characters to 8x14 EGA/VGA characters
1876 *---------------------------------------------------------------------------*/
1878 vga10_vga14(u_char *invga, u_char *outvga)
1883 * Double the top two and bottom two scanlines and copy everything
1887 outvga[0] = invga[0];
1888 outvga[1] = invga[0];
1889 outvga[2] = invga[1];
1890 outvga[3] = invga[1];
1891 outvga[10] = invga[8];
1892 outvga[11] = invga[8];
1893 outvga[12] = invga[9];
1894 outvga[13] = invga[9];
1896 for(i = 2;i < 8;i++)
1897 outvga[i+2] = invga[i];
1900 /*---------------------------------------------------------------------------*
1901 * Expand 8x10 EGA/VGA characters to 8x10 EGA/VGA characters
1902 *---------------------------------------------------------------------------*/
1904 vga10_vga10(u_char *invga, u_char *outvga)
1908 for(i = 0;i < 10;i++)
1909 outvga[i] = invga[i];
1912 /*---------------------------------------------------------------------------*
1913 * Contract 8x10 EGA/VGA characters to 8x8 EGA/VGA characters
1914 *---------------------------------------------------------------------------*/
1916 vga10_vga8(u_char *invga, u_char *outvga)
1918 /* Skip scanlines 3 and 7 */
1920 outvga[0] = invga[0];
1921 outvga[1] = invga[1];
1922 outvga[2] = invga[2];
1923 outvga[3] = invga[4];
1924 outvga[4] = invga[5];
1925 outvga[5] = invga[6];
1926 outvga[6] = invga[8];
1927 outvga[7] = invga[9];
1930 /*---------------------------------------------------------------------------*
1931 * force a vga card to behave like an ega for debugging
1932 *---------------------------------------------------------------------------*/
1937 unsigned char vgareg;
1939 if(adaptor_type == VGA_ADAPTOR)
1941 adaptor_type = EGA_ADAPTOR;
1943 vgareg = inb(GN_MISCOUTR); /* Miscellaneous Output Register */
1944 vgareg |= 128; /* Set 350 scanline mode */
1946 outb(GN_MISCOUTW,vgareg);
1949 #endif /* FORCE_EGA */
1951 /*---------------------------------------------------------------------------*
1952 * disconnect attribute bit 3 from generating intensity
1953 * (and use it for a second character set !)
1954 *---------------------------------------------------------------------------*/
1956 set_2ndcharset(void)
1958 if(color) /* prepare to access index register! */
1963 /* select color plane enable reg, caution: set ATC access bit ! */
1965 outb(ATC_INDEX, (ATC_COLPLEN | ATC_ACCESS));
1966 outb(ATC_DATAW, 0x07); /* disable plane 3 */
1969 #if PCVT_SCREENSAVER
1970 #if PCVT_PRETTYSCRNS
1972 /*---------------------------------------------------------------------------*
1973 * produce some kinda random number, had a look into the system library...
1974 *---------------------------------------------------------------------------*/
1979 extern struct timeval time; /* time-of-day register */
1981 static unsigned long seed = 1;
1982 u_short res = (u_short)seed;
1983 seed = seed * 1103515245L + time_second;
1987 /*---------------------------------------------------------------------------*
1988 * produce "nice" screensaving ....
1989 *---------------------------------------------------------------------------*/
1991 scrnsv_blink(void * arg)
1993 static struct rgb blink_rgb[8] =
1995 {63, 63, 63}, /* white */
1996 {0, 63, 42}, /* pale green */
1997 {63, 63, 0}, /* yellow */
1998 {63, 21, 63}, /* violet */
1999 {42, 63, 0}, /* yellow-green */
2000 {63, 42, 0}, /* amber */
2001 {63, 42, 42}, /* rose */
2002 {21, 42, 42} /* cyan */
2004 u_short r = getrand();
2005 unsigned pos = (r % (scrnsv_size / 2));
2007 *scrnsv_current = /* (0 << 8) + */ ' ';
2008 scrnsv_current = vsp->Crtat + pos;
2009 *scrnsv_current = (7 /* LIGHTGRAY */ << 8) + '*';
2010 if(adaptor_type == VGA_ADAPTOR)
2011 vgapaletteio(7 /* LIGHTGRAY */, &blink_rgb[(r >> 4) & 7], 1);
2012 callout_reset(&scrnsv_blink_ch, hz, scrnsv_blink, NULL);
2015 #endif /* PCVT_PRETTYSCRNS */
2017 /*---------------------------------------------------------------------------*
2019 *---------------------------------------------------------------------------*/
2022 pcvt_set_scrnsv_tmo(int timeout)
2025 pcvt_set_scrnsv_tmo(int timeout)
2026 #endif /* XSERVER */
2031 callout_stop(&scrnsv_timeout_ch);
2033 scrnsv_timeout = timeout;
2034 pcvt_scrnsv_reset(); /* sanity */
2036 if(timeout == 0 && savedscreen)
2038 /* release buffer when screen saver turned off */
2039 free(savedscreen, M_TEMP);
2040 savedscreen = (u_short *)0;
2044 /*---------------------------------------------------------------------------*
2046 *---------------------------------------------------------------------------*/
2048 scrnsv_timedout(void *arg)
2050 /* this function is called by timeout() */
2051 /* raise priority to avoid conflicts with kbd intr */
2055 * due to some undefined problems with video adaptor RAM
2056 * access timing, the following has been splitted into
2057 * two pieces called subsequently with a time difference
2061 if(++scrnsv_active == 1)
2065 * first, allocate a buffer
2066 * do only if none allocated yet or another size required
2067 * this reduces malloc() overhead by avoiding successive
2068 * calls to malloc() and free() if they would have requested
2071 * XXX This is inherited from old days where no buffering
2072 * happened at all. Meanwhile we should use the standard
2073 * screen buffer instead. Any volunteers? :-) [At least,
2074 * this code proved to work...]
2077 s = sizeof(u_short) * vsp->screen_rowsize * vsp->maxcol;
2079 if(savedscreen == (u_short *)0 || s != scrnsv_size)
2081 /* really need to allocate */
2083 free(savedscreen, M_TEMP);
2086 (u_short *)malloc(s, M_TEMP, M_NOWAIT))
2090 * didn't get the buffer memory,
2091 * turn off screen saver
2093 scrnsv_timeout = scrnsv_active = 0;
2098 /* save current screen */
2099 bcopy(vsp->Crtat, savedscreen, scrnsv_size);
2101 /* on VGA's, make sure palette is set to blank screen */
2102 if(adaptor_type == VGA_ADAPTOR)
2104 struct rgb black = {0, 0, 0};
2105 vgapaletteio(0 /* BLACK */, &black, 1);
2107 /* prepare for next time... */
2108 callout_reset(&scrnsv_timeout_ch, hz / 10,
2109 scrnsv_timedout, NULL);
2113 /* second call, now blank the screen */
2114 /* fill screen with blanks */
2115 fillw(/* (BLACK<<8) + */ ' ', vsp->Crtat, scrnsv_size / 2);
2117 #if PCVT_PRETTYSCRNS
2118 scrnsv_current = vsp->Crtat;
2119 callout_reset(&scrnsv_blink_ch, hz, scrnsv_blink, NULL);
2120 #endif /* PCVT_PRETTYSCRNS */
2122 sw_cursor(0); /* cursor off on mda/cga */
2127 /*---------------------------------------------------------------------------*
2128 * interface to screensaver "subsystem"
2129 *---------------------------------------------------------------------------*/
2131 pcvt_scrnsv_reset(void)
2134 * to save lotta time with superfluous timeout()/untimeout() calls
2135 * when having massive output operations, we remember the last
2136 * second of kernel timer we've rescheduled scrnsv_timedout()
2138 static long last_schedule = 0L;
2142 if((scrnsv_active == 1 || scrnsv_timeout) &&
2143 last_schedule != time_second)
2145 last_schedule = time_second;
2147 callout_stop(&scrnsv_timeout_ch);
2152 #if PCVT_PRETTYSCRNS
2153 if(scrnsv_active > 1)
2154 callout_stop(&scrnsv_blink_ch);
2155 #endif /* PCVT_PRETTYSCRNS */
2157 bcopy(savedscreen, vsp->Crtat, scrnsv_size);
2158 if(adaptor_type == VGA_ADAPTOR)
2160 /* back up VGA palette info */
2161 vgapaletteio(0 /* BLACK */, &vsp->palette[0], 1);
2163 #if PCVT_PRETTYSCRNS
2164 vgapaletteio(7 /* LIGHTGRAY */, &vsp->palette[7], 1);
2165 #endif /* PCVT_PRETTYSCRNS */
2171 sw_cursor(1); /* cursor on */
2176 /* mark next timeout */
2177 callout_reset(&scrnsv_timeout_ch, scrnsv_timeout * hz,
2178 scrnsv_timedout, NULL);
2183 #endif /* PCVT_SCREENSAVER */
2185 /*---------------------------------------------------------------------------*
2186 * switch cursor on/off
2187 *---------------------------------------------------------------------------*/
2189 sw_cursor(int onoff)
2191 if(adaptor_type == EGA_ADAPTOR)
2196 start = vsp->cursor_start;
2197 end = vsp->cursor_end;
2201 int cs = vs[current_video_screen].vga_charset;
2203 cs = (cs < 0) ? 0 : ((cs < totalfonts) ?
2206 start = (vgacs[cs].char_scanlines & 0x1F) + 1;
2209 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
2210 outb(addr_6845+1, start);
2211 outb(addr_6845,CRTC_CUREND); /* cursor end reg */
2212 outb(addr_6845+1, end);
2214 else /* mda, cga, vga */
2216 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
2218 outb(addr_6845+1, vsp->cursor_start);
2220 outb(addr_6845+1, CURSOR_ON_BIT);
2224 /*---------------------------------------------------------------------------*
2225 * cold init support, if a mono monitor is attached to a
2226 * vga or ega, it comes up with a mda emulation. switch
2227 * board to generic ega/vga mode in this case.
2228 *---------------------------------------------------------------------------*/
2233 * program sequencer to access
2237 /* synchronous reset */
2238 outb(TS_INDEX, TS_SYNCRESET);
2239 outb(TS_DATA, 0x01);
2241 /* write to map 0 & 1 */
2242 outb(TS_INDEX, TS_WRPLMASK);
2243 outb(TS_DATA, 0x03);
2245 /* odd-even addressing */
2246 outb(TS_INDEX, TS_MEMMODE);
2247 outb(TS_DATA, 0x03);
2249 /* clear synchronous reset */
2250 outb(TS_INDEX, TS_SYNCRESET);
2251 outb(TS_DATA, 0x03);
2254 * program graphics controller
2255 * to access character
2259 /* select map 0 for cpu reads */
2260 outb(GDC_INDEX, GDC_RDPLANESEL);
2261 outb(GDC_DATA, 0x00);
2263 /* enable odd-even addressing */
2264 outb(GDC_INDEX, GDC_MODE);
2265 outb(GDC_DATA, 0x10);
2267 /* map starts at 0xb000 */
2268 outb(GDC_INDEX, GDC_MISC);
2269 outb(GDC_DATA, 0x0a);
2272 #endif /* NVT > 0 */
2274 /* ------------------------- E O F ------------------------------------------*/