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.4 2003/08/07 21:17:16 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_handle async_update_ch =
80 CALLOUT_HANDLE_INITIALIZER(&async_update_ch);
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 */
90 static unsigned scrnsv_timeout = 0; /* initially off */
91 static void pcvt_set_scrnsv_tmo ( int timeout );/* else declared global */
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 */
102 #endif /* PCVT_SCREENSAVER */
105 /*---------------------------------------------------------------------------*
107 *---------------------------------------------------------------------------*/
109 vgaioctl(Dev_t dev, int cmd, caddr_t data, int flag)
111 if(minor(dev) >= PCVT_NSCREENS)
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.
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 */
129 #define is_dev_grafx 0 /* not applicable */
130 #define is_current_grafx 0
138 vid_cursor((struct cursorshape *)data);
142 if((adaptor_type != VGA_ADAPTOR) &&
143 (adaptor_type != EGA_ADAPTOR))
147 vgaloadchar((struct vgaloadchar *)data);
151 if((adaptor_type != VGA_ADAPTOR) &&
152 (adaptor_type != EGA_ADAPTOR))
157 #endif /* PCVT_SCREENSAVER */
159 vgasetfontattr((struct vgafontattr *)data);
163 if((adaptor_type != VGA_ADAPTOR) &&
164 (adaptor_type != EGA_ADAPTOR))
166 vgagetfontattr((struct vgafontattr *)data);
171 #if defined XSERVER && !PCVT_USL_VT_COMPAT
172 /* avoid screen switch if using old X mode */
175 #endif /* XSERVER && !PCVT_USL_VT_COMPAT */
179 #endif /* PCVT_SCREENSAVER */
181 vid_setscreen((struct screeninfo *)data, dev);
185 vid_getscreen((struct screeninfo *)data, dev);
189 if(adaptor_type != VGA_ADAPTOR)
193 vgareadpel((struct vgapel *)data, dev);
197 if(adaptor_type != VGA_ADAPTOR)
201 vgawritepel((struct vgapel *)data, dev);
208 pcvt_set_scrnsv_tmo(*(int *)data);
211 #endif /* PCVT_SCREENSAVER */
214 vgapcvtid((struct pcvtid *)data);
218 vgapcvtinfo((struct pcvtinfo *)data);
224 if(*(int *)data == 80)
225 (void)vt_col(&vs[minor(dev)], SCR_COL80);
226 else if(*(int *)data == 132)
228 if(vt_col(&vs[minor(dev)], SCR_COL132) == 0)
229 return EINVAL; /* not a VGA */
237 reallocate_scrollbuffer(vsp, *(u_short *)data);
242 /* do nothing here */
251 #undef is_current_grafx
254 /*---------------------------------------------------------------------------*
255 * video ioctl - return driver id
256 *---------------------------------------------------------------------------*/
258 vgapcvtid(struct pcvtid *data)
260 snprintf(data->name, sizeof(data->name), "%s", PCVTIDNAME);
261 data->rmajor = PCVTIDMAJOR;
262 data->rminor = PCVTIDMINOR;
265 /*---------------------------------------------------------------------------*
266 * video ioctl - return driver compile time options data
267 *---------------------------------------------------------------------------*/
269 vgapcvtinfo(struct pcvtinfo *data)
272 data->opsys = CONF_NETBSD;
273 data->opsysrel = PCVT_NETBSD;
275 data->opsys = CONF_FREEBSD;
276 data->opsysrel = PCVT_FREEBSD;
278 data->opsys = CONF_UNKNOWNOPSYS;
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;
288 #if PCVT_NETBSD || PCVT_FREEBSD >= 200
289 data->pcburst = PCVT_PCBURST;
295 data->kbd_fifo_sz = PCVT_KBD_FIFO_SZ;
297 data->kbd_fifo_sz = 0;
300 data->compile_opts = (0
311 #if PCVT_CTRL_ALT_DEL
335 #if PCVT_BACKUP_FONTS
338 #if PCVT_SW0CNOUTP /* was FORCE8BIT */
356 #if PCVT_USL_VT_COMPAT
359 #if PCVT_PORTIO_DELAY
362 #if PCVT_INHIBIT_NUMLOCK
363 | CONF_INHIBIT_NUMLOCK
371 #if PCVT_NOFASTSCROLL
374 #if PCVT_SLOW_INTERRUPT
375 | CONF_SLOW_INTERRUPT
377 #if PCVT_NO_LED_UPDATE
383 /*---------------------------------------------------------------------------*
384 * video ioctl - set cursor appearence
385 *---------------------------------------------------------------------------*/
387 vid_cursor(struct cursorshape *data)
395 /* for which virtual screen, -1 for current */
396 screen = data->screen_no;
398 if(screen == -1) /* current ? */
399 screen = current_video_screen;
400 else if(screen > totalscreens - 1)
401 screen = totalscreens - 1;
405 if(adaptor_type == VGA_ADAPTOR || adaptor_type == EGA_ADAPTOR)
407 character_set = vs[screen].vga_charset;
408 character_set = (character_set < 0) ? 0 :
409 ((character_set < totalfonts) ?
413 line_height = vgacs[character_set].char_scanlines & 0x1F;
415 else if(adaptor_type == MDA_ADAPTOR)
421 line_height = 8; /* CGA */
424 start = (data->start < 0) ? 0 :
425 ((data->start > line_height) ? line_height : data->start);
427 if((vga_family == VGA_F_TRI) && (start == 0))
430 end = (data->end < 0) ? 0 :
431 ((data->end > line_height) ? line_height : data->end);
433 vs[screen].cursor_start = start;
434 vs[screen].cursor_end = end;
436 if(screen == current_video_screen)
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);
445 /*---------------------------------------------------------------------------*
446 * ega/vga ioctl - set font attributes
447 *---------------------------------------------------------------------------*/
449 vgasetfontattr(struct vgafontattr *data)
452 int vga_character_set;
453 int lines_per_character;
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);
462 vgacs[vga_character_set].loaded = data->font_loaded;
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 */
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;
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;
480 lines_per_character =
481 (int)(0x1F & vgacs[vga_character_set].char_scanlines)+1;
483 totscanlines = 0x101 + (int)vgacs[vga_character_set].scr_scanlines;
485 size = data->screen_size;
487 if(adaptor_type == EGA_ADAPTOR)
491 case SIZ_25ROWS: /* This case is always OK */
495 if(totscanlines/lines_per_character >= 35)
503 if(totscanlines/lines_per_character >= 43)
505 else if(totscanlines/lines_per_character >= 35)
516 case SIZ_25ROWS: /* This case is always OK */
520 if(totscanlines/lines_per_character >= 28)
527 if(totscanlines/lines_per_character >= 40)
529 else if(totscanlines/lines_per_character >= 28)
537 if(totscanlines/lines_per_character >= 50)
539 else if(totscanlines/lines_per_character >= 40)
541 else if(totscanlines/lines_per_character >= 28)
549 vgacs[vga_character_set].screen_size = size;
551 for (i = 0;i < PCVT_NSCREENS;i++)
553 if(vga_character_set == vs[i].vga_charset)
554 set_charset(&(vs[i]),vga_character_set);
557 #if !PCVT_USL_VT_COMPAT
558 vgapage(current_video_screen);
560 switch_screen(current_video_screen, 0, 0);
561 #endif /* !PCVT_USL_VT_COMPAT */
565 /*---------------------------------------------------------------------------*
566 * ega/vga ioctl - get font attributes
567 *---------------------------------------------------------------------------*/
569 vgagetfontattr(struct vgafontattr *data)
571 int vga_character_set;
573 vga_character_set = data->character_set;
574 vga_character_set = (vga_character_set < 0) ? 0 :
575 ((vga_character_set < (int)totalfonts) ?
577 (int)(totalfonts-1));
579 data->character_set = (int)vga_character_set;
581 data->font_loaded = (int)vgacs[vga_character_set].loaded;
583 data->character_scanlines =
584 (int)vgacs[vga_character_set].char_scanlines
585 & 0x1f; /* do not display the overflow bits */
587 data->screen_scanlines = (int)vgacs[vga_character_set].scr_scanlines;
589 data->screen_size = (int)vgacs[vga_character_set].screen_size;
592 /*---------------------------------------------------------------------------*
593 * ega/vga ioctl - load a character shape into character set
594 *---------------------------------------------------------------------------*/
596 vgaloadchar(struct vgaloadchar *data)
598 int vga_character_set;
600 int lines_per_character;
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));
607 character = (data->character < 0) ? 0 :
608 ((data->character > 255) ? 255 : data->character);
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);
614 loadchar(vga_character_set,character,lines_per_character,
618 /*---------------------------------------------------------------------------*
619 * video ioctl - get screen information
620 *---------------------------------------------------------------------------*/
622 vid_getscreen(struct screeninfo *data, Dev_t dev)
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 */
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 */
641 /*---------------------------------------------------------------------------*
642 * video ioctl - set screen information
643 *---------------------------------------------------------------------------*/
645 vid_setscreen(struct screeninfo *data, Dev_t dev)
649 if(data->current_screen == -1)
655 if(data->current_screen >= PCVT_NSCREENS)
657 screen = data->current_screen;
662 #if defined XSERVER && PCVT_USL_VT_COMPAT
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);
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 */
676 if((data->screen_size != -1) || (data->force_24lines != -1))
678 if(data->screen_size == -1)
680 vgacs[(vs[screen].vga_charset)].screen_size;
682 if(data->force_24lines != -1)
684 vs[screen].force24 = data->force_24lines;
686 if(vs[screen].force24)
688 swritefkl(2,(u_char *)"FORCE24 ENABLE *",
693 swritefkl(2,(u_char *)"FORCE24 ENABLE ",
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))
705 if(data->screen_no == -1)
706 set_screen_size(vsp, data->screen_size);
708 set_screen_size(&vs[minor(dev)],
713 if(data->pure_vt_mode != -1)
715 if((data->pure_vt_mode == M_HPVT) ||
716 (data->pure_vt_mode == M_PUREVT))
718 if(data->screen_no == -1)
719 set_emulation_mode(vsp, data->pure_vt_mode);
721 set_emulation_mode(&vs[minor(dev)],
727 /*---------------------------------------------------------------------------*
728 * set screen size/resolution for a virtual screen
729 *---------------------------------------------------------------------------*/
731 set_screen_size(struct video_state *svsp, int size)
735 for(i = 0; i < totalfonts; i++)
737 if(vgacs[i].screen_size == size)
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
745 svsp->transparent = 0; /* disable control code
748 /* Update tty to reflect screen size */
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 =
759 /* screen_rows already calculated in set_charset() */
760 if(svsp->vt_pure_mode == M_HPVT && svsp->labels_on)
762 if(svsp->which_fkl == SYS_FKL)
764 else if(svsp->which_fkl == USR_FKL)
769 svsp->scrr_len = svsp->screen_rows;
770 svsp->scrr_end = svsp->scrr_len - 1;
773 if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
774 pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
775 #endif /* PCVT_SIGWINCH */
777 reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
783 /*---------------------------------------------------------------------------*
784 * resize the scrollback buffer to the specified number of "pages"
785 *---------------------------------------------------------------------------*/
787 reallocate_scrollbuffer(struct video_state *svsp, int pages)
799 if((stmp = (u_short *)malloc(svsp->maxcol * svsp->screen_rows *
800 pages * CHR, M_DEVBUF, M_NOWAIT)) == NULL)
803 printf("pcvt: reallocate_scrollbuffer, malloc failed\n");
807 svsp->max_off = svsp->screen_rows * pages - 1;
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;
819 svsp->scr_offset = 0;
821 svsp->Scrollback = stmp;
823 bcopy(svsp->Crtat, svsp->Scrollback,
824 svsp->screen_rows * svsp->maxcol * CHR);
826 svsp->scr_offset = svsp->row;
829 svsp->scrollback_pages = pages;
834 /*---------------------------------------------------------------------------*
835 * VGA ioctl - read DAC palette entry
836 *---------------------------------------------------------------------------*/
838 vgareadpel(struct vgapel *data, Dev_t dev)
840 unsigned vpage = minor(dev);
841 unsigned idx = data->idx;
844 return; /* no such entry */
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;
852 /*---------------------------------------------------------------------------*
853 * VGA ioctl - write DAC palette entry
854 *---------------------------------------------------------------------------*/
856 vgawritepel(struct vgapel *data, Dev_t dev)
858 unsigned vpage = minor(dev);
859 unsigned idx = data->idx;
862 return; /* no such entry */
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;
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);
874 /*---------------------------------------------------------------------------*
875 * VGA physical IO - read/write one palette entry
876 *---------------------------------------------------------------------------*/
878 vgapaletteio(unsigned idx, struct rgb *val, int writeit)
883 #endif /* PCVT_PALFLICKER */
887 outb(VGA_DAC + 2, idx);
891 #endif /* PCVT_WAITRETRACE */
893 outb(VGA_DAC + 3, val->r & VGA_PMSK);
897 #endif /* PCVT_WAITRETRACE */
899 outb(VGA_DAC + 3, val->g & VGA_PMSK);
903 #endif /* PCVT_WAITRETRACE */
905 outb(VGA_DAC + 3, val->b & VGA_PMSK);
909 outb(VGA_DAC + 1, idx);
913 #endif /* PCVT_WAITRETRACE */
915 val->r = inb(VGA_DAC + 3) & VGA_PMSK;
919 #endif /* PCVT_WAITRETRACE */
921 val->g = inb(VGA_DAC + 3) & VGA_PMSK;
925 #endif /* PCVT_WAITRETRACE */
927 val->b = inb(VGA_DAC + 3) & VGA_PMSK;
932 #endif /* PCVT_PALFLICKER */
936 /*---------------------------------------------------------------------------*
938 * update asynchronous: cursor, cursor pos displ, sys load, keyb scan
941 * UPDATE_START = do update; requeue
942 * UPDATE_STOP = suspend updates
943 * UPDATE_KERN = do update for kernel printfs
945 *---------------------------------------------------------------------------*/
947 async_update(void *arg)
949 static int lastpos = 0;
950 static int counter = PCVT_UPDATESLOW;
953 /* need a method to suspend the updates */
955 if(arg == UPDATE_STOP)
957 untimeout(async_update, UPDATE_START, async_update_ch);
962 /* first check if update is possible */
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 */
972 goto async_update_exit; /* do not update anything */
976 if(reset_screen_saver && (counter == PCVT_UPDATESLOW))
978 pcvt_scrnsv_reset(); /* yes, do it */
979 reset_screen_saver = 0; /* re-init */
981 else if(scrnsv_active) /* is the screen not blanked? */
983 goto async_update_exit; /* do not update anything */
985 #endif /* PCVT_SCREENSAVER */
987 /*-------------------------------------------------------------------*/
988 /* this takes place on EVERY virtual screen (if not in X mode etc...)*/
989 /*-------------------------------------------------------------------*/
991 if ( cursor_pos_valid &&
992 (lastpos != (vsp->Crtat + vsp->cur_offset - Crtat)))
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));
1001 if (arg == UPDATE_KERN) /* Magic arg: for kernel printfs */
1004 if(--counter) /* below is possible update */
1005 goto async_update_exit; /* just now and then ..... */
1006 counter = PCVT_UPDATESLOW; /* caution, see screensaver above !! */
1008 /*-------------------------------------------------------------------*/
1009 /* this takes place ONLY on screen 0 if in HP mode, labels on, !X */
1010 /*-------------------------------------------------------------------*/
1012 /* additional processing for HP necessary ? */
1014 if((vs[0].vt_pure_mode == M_HPVT) && (vs[0].labels_on))
1016 static volatile u_char buffer[] =
1017 "System Load: 1min: 0.00 5min: 0.00 15min: 0.00";
1020 extern u_char rawkeybuf[80];
1024 for(i = 0; i < 80; i++)
1026 *((vs[0].Crtat+((vs[0].screen_rows+2)
1027 * vs[0].maxcol))+i) =
1028 user_attr | rawkeybuf[i];
1033 #endif /* PCVT_SHOWKEYS */
1035 /* display load averages in last line (taken from tty.c) */
1037 #ifdef NEW_AVERUNNABLE
1038 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2)
1041 tmp = (averunnable[0] * 100 + FSCALE / 2) >> FSHIFT;
1045 ((((tmp/100)/10) == 0) ?
1047 ((tmp/100)/10) + '0');
1048 buffer[i++] = ((tmp/100)%10) + '0';
1050 buffer[i++] = ((tmp%100)/10) + '0';
1051 buffer[i++] = ((tmp%100)%10) + '0';
1053 #ifdef NEW_AVERUNNABLE
1054 tmp = (averunnable.ldavg[1] * 100 + FSCALE / 2)
1057 tmp = (averunnable[1] * 100 + FSCALE / 2) >> FSHIFT;
1059 buffer[i++] = ((((tmp/100)/10) == 0) ?
1061 ((tmp/100)/10) + '0');
1062 buffer[i++] = ((tmp/100)%10) + '0';
1064 buffer[i++] = ((tmp%100)/10) + '0';
1065 buffer[i++] = ((tmp%100)%10) + '0';
1067 #ifdef NEW_AVERUNNABLE
1068 tmp = (averunnable.ldavg[2] * 100 + FSCALE / 2)
1071 tmp = (averunnable[2] * 100 + FSCALE / 2) >> FSHIFT;
1073 buffer[i++] = ((((tmp/100)/10) == 0) ?
1075 ((tmp/100)/10) + '0');
1076 buffer[i++] = ((tmp/100)%10) + '0';
1078 buffer[i++] = ((tmp%100)/10) + '0';
1079 buffer[i++] = ((tmp%100)%10) + '0';
1082 for(i = 0; buffer[i]; i++)
1085 ((vs[0].screen_rows + 2) * vs[0].maxcol)
1087 ) = user_attr | buffer[i];
1094 ((vs[0].screen_rows + 2) * vs[0].maxcol)
1096 ) = user_attr | ' ';
1100 #endif /* PCVT_SHOWKEYS */
1103 /*-------------------------------------------------------------------*/
1104 /* this takes place on EVERY screen which is in HP mode, labels on,!X*/
1105 /*-------------------------------------------------------------------*/
1107 if((vsp->vt_pure_mode == M_HPVT) && (vsp->labels_on))
1109 int col = vsp->col+1;
1110 u_short *p = vsp->Crtat +
1111 (vsp->screen_rows * vsp->maxcol);
1113 /* update column display between labels */
1115 if(vsp->maxcol == SCR_COL132)
1117 p += (SCR_COL132 - SCR_COL80)/2;
1121 *(p + LABEL_COLU) = user_attr | '1';
1126 *(p + LABEL_COLU) = user_attr | '0';
1129 *(p + LABEL_COLH) = user_attr | ((col/10) + '0');
1130 *(p + LABEL_COLL) = user_attr | ((col%10) + '0');
1132 /* update row display between labels */
1134 *(p + LABEL_ROWH) = (user_attr | (((vsp->row+1)/10) + '0'));
1135 *(p + LABEL_ROWL) = (user_attr | (((vsp->row+1)%10) + '0'));
1140 if(arg == UPDATE_START)
1142 async_update_ch = timeout(async_update, UPDATE_START,
1147 /*---------------------------------------------------------------------------*
1148 * set character set for virtual screen
1149 *---------------------------------------------------------------------------*/
1151 set_charset(struct video_state *svsp, int curvgacs)
1153 static int sizetab[] = { 25, 28, 35, 40, 43, 50 };
1154 int oldsize, oldrows, newsize, newrows;
1156 if((curvgacs < 0) || (curvgacs > (NVGAFONTS-1)))
1159 svsp->vga_charset = curvgacs;
1161 select_vga_charset(curvgacs);
1163 oldsize = svsp->screen_rowsize;
1164 oldrows = svsp->screen_rows;
1165 newsize = sizetab[(vgacs[curvgacs].screen_size)];
1167 if (svsp->vt_pure_mode == M_HPVT)
1169 if (newrows == 25 && svsp->force24)
1171 if (newrows < oldrows) {
1172 int nscroll = svsp->row + 1 - newrows;
1174 if (svsp->row >= oldrows) /* Sanity check */
1175 nscroll = oldrows - newrows;
1178 bcopy (svsp->Crtat + nscroll * svsp->maxcol,
1180 newrows * svsp->maxcol * CHR);
1181 svsp->row -= nscroll;
1182 svsp->cur_offset -= nscroll * svsp->maxcol;
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);
1193 svsp->screen_rowsize = newsize;
1194 svsp->screen_rows = newrows;
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;
1201 /* Clip cursor pos */
1203 if(svsp->cur_offset > (svsp->scrr_len * svsp->maxcol))
1204 svsp->cur_offset = (svsp->scrr_len * svsp->maxcol) + svsp->col;
1207 /*---------------------------------------------------------------------------*
1208 * select a vga character set
1209 *---------------------------------------------------------------------------*/
1211 select_vga_charset(int vga_charset)
1218 static u_char cmaptaba[] =
1219 {0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13};
1221 static u_char cmaptabb[] =
1222 {0x00, 0x04, 0x08, 0x0c, 0x20, 0x24, 0x28, 0x2c};
1224 if((adaptor_type != EGA_ADAPTOR) && (adaptor_type != VGA_ADAPTOR))
1227 if((vga_charset < 0) || (vga_charset >= totalfonts))
1230 if(!vgacs[vga_charset].loaded)
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/
1238 --------------------------------------------------------------*/
1240 for(first = 0; first < totalfonts; first++)
1242 if(!vgacs[first].loaded)
1244 if(vgacs[first].screen_size != vgacs[vga_charset].screen_size)
1246 if(vgacs[first].char_scanlines !=
1247 vgacs[vga_charset].char_scanlines)
1249 if(vgacs[first].scr_scanlines !=
1250 vgacs[vga_charset].scr_scanlines)
1259 for(second = first+1; second < totalfonts; second++)
1261 if(!vgacs[second].loaded)
1263 if(vgacs[second].screen_size != vgacs[vga_charset].screen_size)
1265 if(vgacs[second].char_scanlines !=
1266 vgacs[vga_charset].char_scanlines)
1268 if(vgacs[second].scr_scanlines !=
1269 vgacs[vga_charset].scr_scanlines)
1275 cmap = cmaptaba[first];
1278 cmap |= cmaptabb[second];
1279 vgacs[first].secondloaded = second;
1283 vgacs[first].secondloaded = 0; /*cs 0 can never become a 2nd!*/
1288 cmap = (vga_charset & 0x07);
1292 outb(TS_INDEX, TS_FONTSEL); /* character map select register */
1293 outb(TS_DATA, cmap); /* new char map */
1295 outb(addr_6845, CRTC_MAXROW); /* max scan line reg */
1297 vgacs[first].char_scanlines); /* scanlines/char */
1299 outb(addr_6845, CRTC_VDE); /* vert display enable end */
1301 vgacs[first].scr_scanlines); /* low byte of scr scanlines */
1303 if((color == 0) && (adaptor_type == VGA_ADAPTOR))
1305 outb(addr_6845, CRTC_ULOC); /* underline location reg */
1306 outb(addr_6845+1, (vgacs[first].char_scanlines & 0x1F));
1310 /*---------------------------------------------------------------------------*
1311 * switch vga-card to load a character set
1312 *---------------------------------------------------------------------------*/
1316 chargen_access = 1; /* flag we are accessing the chargen ram */
1318 /* program sequencer to access character generator */
1320 outb(TS_INDEX, TS_SYNCRESET);
1321 outb(TS_DATA, 0x01); /* synchronous reset */
1323 outb(TS_INDEX, TS_WRPLMASK);
1324 outb(TS_DATA, 0x04); /* write to map 2 */
1326 outb(TS_INDEX, TS_MEMMODE);
1327 outb(TS_DATA, 0x07); /* sequential addressing */
1329 outb(TS_INDEX, TS_SYNCRESET);
1330 outb(TS_DATA, 0x03); /* clear synchronous reset */
1332 /* program graphics controller to access character generator */
1334 outb(GDC_INDEX, GDC_RDPLANESEL);
1335 outb(GDC_DATA, 0x02); /* select map 2 for cpu reads */
1337 outb(GDC_INDEX, GDC_MODE);
1338 outb(GDC_DATA, 0x00); /* disable odd-even addressing */
1340 outb(GDC_INDEX, GDC_MISC);
1341 outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
1344 /*---------------------------------------------------------------------------*
1345 * switch vga-card to load a character set to plane 3
1346 *---------------------------------------------------------------------------*/
1350 chargen_access = 1; /* flag we are accessing the chargen ram */
1352 /* program sequencer to access character generator */
1354 outb(TS_INDEX, TS_SYNCRESET);
1355 outb(TS_DATA, 0x01); /* synchronous reset */
1357 outb(TS_INDEX, TS_WRPLMASK);
1358 outb(TS_DATA, 0x08); /* write to map 3 */
1360 outb(TS_INDEX, TS_MEMMODE);
1361 outb(TS_DATA, 0x07); /* sequential addressing */
1363 outb(TS_INDEX, TS_SYNCRESET);
1364 outb(TS_DATA, 0x03); /* clear synchronous reset */
1366 /* program graphics controller to access character generator */
1368 outb(GDC_INDEX, GDC_RDPLANESEL);
1369 outb(GDC_DATA, 0x03); /* select map 3 for cpu reads */
1371 outb(GDC_INDEX, GDC_MODE);
1372 outb(GDC_DATA, 0x00); /* disable odd-even addressing */
1374 outb(GDC_INDEX, GDC_MISC);
1375 outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
1378 /*---------------------------------------------------------------------------*
1379 * switch back vga-card to normal operation
1380 *---------------------------------------------------------------------------*/
1384 /* program sequencer to access video ram */
1386 outb(TS_INDEX, TS_SYNCRESET);
1387 outb(TS_DATA, 0x01); /* synchronous reset */
1389 outb(TS_INDEX, TS_WRPLMASK);
1390 outb(TS_DATA, 0x03); /* write to map 0 & 1 */
1392 outb(TS_INDEX, TS_MEMMODE);
1393 outb(TS_DATA, 0x03); /* odd-even addressing */
1395 outb(TS_INDEX, TS_SYNCRESET);
1396 outb(TS_DATA, 0x03); /* clear synchronous reset */
1398 /* program graphics controller to access character generator */
1400 outb(GDC_INDEX, GDC_RDPLANESEL);
1401 outb(GDC_DATA, 0x00); /* select map 0 for cpu reads */
1403 outb(GDC_INDEX, GDC_MODE);
1404 outb(GDC_DATA, 0x10); /* enable odd-even addressing */
1406 outb(GDC_INDEX, GDC_MISC);
1408 outb(GDC_DATA, 0x0e); /* map starts at 0xb800 */
1410 outb(GDC_DATA, 0x0a); /* map starts at 0xb000 */
1412 chargen_access = 0; /* flag we are NOT accessing the chargen ram */
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 *---------------------------------------------------------------------------*/
1426 while(!(inb(GN_INPSTAT1C) & 0x01))
1431 while(!(inb(GN_INPSTAT1M) & 0x01))
1436 #endif /* PCVT_WAITRETRACE */
1438 /*---------------------------------------------------------------------------*
1439 * switch screen off (VGA only)
1440 *---------------------------------------------------------------------------*/
1442 vga_screen_off(void)
1446 outb(TS_INDEX, TS_SYNCRESET);
1447 outb(TS_DATA, 0x01); /* synchronous reset */
1449 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1450 old = inb(TS_DATA); /* get current value */
1452 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1453 outb(TS_DATA, (old | 0x20)); /* screen off bit on */
1455 outb(TS_INDEX, TS_SYNCRESET);
1456 outb(TS_DATA, 0x03); /* clear synchronous reset */
1459 /*---------------------------------------------------------------------------*
1460 * switch screen back on (VGA only)
1461 *---------------------------------------------------------------------------*/
1467 outb(TS_INDEX, TS_SYNCRESET);
1468 outb(TS_DATA, 0x01); /* synchronous reset */
1470 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1471 old = inb(TS_DATA); /* get current value */
1473 outb(TS_INDEX, TS_MODE); /* clocking mode reg */
1474 outb(TS_DATA, (old & ~0x20)); /* screen off bit off */
1476 outb(TS_INDEX, TS_SYNCRESET);
1477 outb(TS_DATA, 0x03); /* clear synchronous reset */
1480 /*---------------------------------------------------------------------------*
1481 * compute character set base address (in kernel map)
1482 *---------------------------------------------------------------------------*/
1483 static unsigned char *
1484 compute_charset_base(unsigned fontset)
1486 unsigned char *d = (unsigned char *)Crtat;
1488 static int charset_offset[8] = { 0x0000, 0x4000, 0x8000, 0xC000,
1489 0x2000, 0x6000, 0xA000, 0xE000 };
1491 static int charsetw_offset[8] = { 0x0000, 0x2000, 0x4000, 0x6000,
1492 0x8000, 0xA000, 0xC000, 0xE000 };
1494 switch(adaptor_type)
1497 fontset = (fontset > 3) ? 3 : fontset;
1501 fontset = (fontset > 7) ? 7 : fontset;
1509 d -= (0xB8000 - 0xA0000); /* Point to 0xA0000 */
1511 d -= (0xB0000 - 0xA0000); /* Point to 0xA0000 */
1514 d += charsetw_offset[fontset]; /* Load into Character set n */
1516 d += charset_offset[fontset]; /* Load into Character set n */
1521 /*---------------------------------------------------------------------------*
1522 * load a char into ega/vga character generator ram
1523 *---------------------------------------------------------------------------*/
1525 loadchar(int fontset, int character, int char_scanlines, u_char *char_table)
1529 #if PCVT_BACKUP_FONTS
1531 #endif /* PCVT_BACKUP_FONTS */
1535 if((d = compute_charset_base(fontset)) == 0)
1538 d += (character * 32); /* 32 bytes per character */
1541 (fontset == 1||fontset == 3||fontset == 5||fontset == 7))
1542 setchargen3(); /* access chargen ram */
1544 setchargen(); /* access chargen ram */
1546 for(j = k = 0; j < char_scanlines; j++) /* x bit high characters */
1552 for(; j < 32; j++) /* Up to 32 bytes per character image*/
1558 resetchargen(); /* access video ram */
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);
1565 if((bak = saved_charsets[fontset]))
1567 /* make a backup copy of this char */
1568 bak += (character * 32);
1570 bcopy(char_table, bak, char_scanlines);
1574 panic("pcvt loadchar: no backup buffer");
1575 #endif /* DIAGNOSTIC */
1577 #endif /* PCVT_BACKUP_FONTS */
1581 /*---------------------------------------------------------------------------*
1582 * save/restore character set n to addr b
1583 *---------------------------------------------------------------------------*/
1584 #if !PCVT_BACKUP_FONTS
1587 vga_move_charset(unsigned n, unsigned char *b, int save_it)
1589 unsigned char *d = compute_charset_base(n);
1593 panic("vga_move_charset: wrong adaptor");
1596 if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
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! */
1611 bcopyb(d, b, 256 /* chars */ * 32 /* bytes per char */);
1613 bcopyb(b, d, 256 /* chars */ * 32 /* bytes per char */);
1618 #else /* PCVT_BACKUP_FONTS */
1620 /* since there are always backed up copies, we do not save anything here */
1621 /* parameter "b" is totally ignored */
1624 vga_move_charset(unsigned n, unsigned char *b, int save_it)
1626 unsigned char *d = compute_charset_base(n);
1631 if(saved_charsets[n] == 0)
1633 panic("pcvt: restoring unbuffered charset");
1640 panic("vga_move_charset: wrong adaptor");
1643 if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
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! */
1657 bcopyb(saved_charsets[n], d,
1658 256 /* chars */ * 32 /* bytes per char */);
1663 #endif /* PCVT_BACKUP_FONTS */
1666 #if !PCVT_USL_VT_COMPAT
1667 /*---------------------------------------------------------------------------*
1668 * switch to virtual screen n (0 ... PCVT_NSCREENS-1)
1669 *---------------------------------------------------------------------------*/
1676 #endif /* !PCVT_KBD_FIFO */
1678 int cols = vsp->maxcol; /* get current col val */
1680 if(n < 0 || n >= totalscreens)
1684 x = spltty(); /* protect us */
1685 #endif /* !PCVT_KBD_FIFO */
1687 /* video board memory -> kernel memory */
1689 bcopy(vsp->Crtat, vsp->Memory, vsp->screen_rows * vsp->maxcol * CHR);
1691 vsp->Crtat = vsp->Memory; /* operate in memory now */
1693 /* update global screen pointers/variables */
1695 current_video_screen = n; /* current screen no */
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 */
1702 pcconsp = pc_tty[n]; /* current tty */
1705 vsp = &vs[n]; /* current video state ptr */
1707 /* kernel memory -> video board memory */
1709 bcopy(vsp->Crtat, Crtat, vsp->screen_rows * vsp->maxcol * CHR);
1711 vsp->Crtat = Crtat; /* operate on screen now */
1713 outb(addr_6845, CRTC_STARTADRH);
1714 outb(addr_6845+1, 0);
1715 outb(addr_6845, CRTC_STARTADRL);
1716 outb(addr_6845+1, 0);
1720 #endif /* !PCVT_KBD_FIFO */
1722 select_vga_charset(vsp->vga_charset);
1724 if(vsp->maxcol != cols)
1725 vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
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);
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);
1744 if(adaptor_type == VGA_ADAPTOR)
1748 /* switch VGA DAC palette entries */
1750 for(i = 0; i < NVGAPEL; i++)
1751 vgapaletteio(i, &vsp->palette[i], 1);
1754 update_led(); /* update led's */
1756 update_hp(vsp); /* update fkey labels, if present */
1758 #endif /* !PCVT_USL_VT_COMPAT */
1760 /*---------------------------------------------------------------------------*
1761 * test if it is a vga
1762 *---------------------------------------------------------------------------*/
1767 u_char old, new, check;
1769 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1770 old = inb(addr_6845+1); /* get current value */
1772 new = old | CURSOR_ON_BIT; /* set cursor on by setting bit 5 on */
1774 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1775 outb(addr_6845+1,new); /* cursor should be on now */
1777 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1778 check = inb(addr_6845+1); /* get current value */
1782 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1783 outb(addr_6845+1,old); /* failsafe */
1784 return(0); /* must be ega */
1787 new = old & ~CURSOR_ON_BIT; /* turn cursor off by clearing bit 5 */
1789 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1790 outb(addr_6845+1,new); /* cursor should be off now */
1792 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1793 check = inb(addr_6845+1); /* get current value */
1797 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1798 outb(addr_6845+1,old); /* failsafe */
1799 return(0); /* must be ega */
1802 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
1803 outb(addr_6845+1,old); /* failsafe */
1805 return(1); /* vga */
1808 /*---------------------------------------------------------------------------*
1809 * convert upper/lower sixel font array to vga font array
1810 *---------------------------------------------------------------------------*/
1812 sixel_vga(struct sixels *sixelp, u_char *vgachar)
1818 for(j = 0; j < 16; j++)
1822 for(j = 0; j < 6; j++)
1824 for(i = 0, shift = 7; i < 8; i++, shift--)
1825 vgachar[j] |= ((((sixelp->upper[i]) & mask) >> j)
1831 for(j = 0; j < 4; j++)
1833 for(i = 0, shift = 7; i < 8; i++, shift--)
1834 vgachar[j+6] |= ((((sixelp->lower[i]) & mask) >>j)
1840 /*---------------------------------------------------------------------------*
1841 * Expand 8x10 EGA/VGA characters to 8x16 EGA/VGA characters
1842 *---------------------------------------------------------------------------*/
1844 vga10_vga16(u_char *invga, u_char *outvga)
1849 * Keep the top and bottom scanlines the same and double every scan
1853 outvga[0] = invga[0];
1854 outvga[1] = invga[1];
1855 outvga[14] = invga[8];
1856 outvga[15] = invga[9];
1858 for(i = j = 2;i < 8 && j < 14;i++,j += 2)
1860 outvga[j] = invga[i];
1861 outvga[j+1] = invga[i];
1865 /*---------------------------------------------------------------------------*
1866 * Expand 8x10 EGA/VGA characters to 8x14 EGA/VGA characters
1867 *---------------------------------------------------------------------------*/
1869 vga10_vga14(u_char *invga, u_char *outvga)
1874 * Double the top two and bottom two scanlines and copy everything
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];
1887 for(i = 2;i < 8;i++)
1888 outvga[i+2] = invga[i];
1891 /*---------------------------------------------------------------------------*
1892 * Expand 8x10 EGA/VGA characters to 8x10 EGA/VGA characters
1893 *---------------------------------------------------------------------------*/
1895 vga10_vga10(u_char *invga, u_char *outvga)
1899 for(i = 0;i < 10;i++)
1900 outvga[i] = invga[i];
1903 /*---------------------------------------------------------------------------*
1904 * Contract 8x10 EGA/VGA characters to 8x8 EGA/VGA characters
1905 *---------------------------------------------------------------------------*/
1907 vga10_vga8(u_char *invga, u_char *outvga)
1909 /* Skip scanlines 3 and 7 */
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];
1921 /*---------------------------------------------------------------------------*
1922 * force a vga card to behave like an ega for debugging
1923 *---------------------------------------------------------------------------*/
1928 unsigned char vgareg;
1930 if(adaptor_type == VGA_ADAPTOR)
1932 adaptor_type = EGA_ADAPTOR;
1934 vgareg = inb(GN_MISCOUTR); /* Miscellaneous Output Register */
1935 vgareg |= 128; /* Set 350 scanline mode */
1937 outb(GN_MISCOUTW,vgareg);
1940 #endif /* FORCE_EGA */
1942 /*---------------------------------------------------------------------------*
1943 * disconnect attribute bit 3 from generating intensity
1944 * (and use it for a second character set !)
1945 *---------------------------------------------------------------------------*/
1947 set_2ndcharset(void)
1949 if(color) /* prepare to access index register! */
1954 /* select color plane enable reg, caution: set ATC access bit ! */
1956 outb(ATC_INDEX, (ATC_COLPLEN | ATC_ACCESS));
1957 outb(ATC_DATAW, 0x07); /* disable plane 3 */
1960 #if PCVT_SCREENSAVER
1961 #if PCVT_PRETTYSCRNS
1963 /*---------------------------------------------------------------------------*
1964 * produce some kinda random number, had a look into the system library...
1965 *---------------------------------------------------------------------------*/
1970 extern struct timeval time; /* time-of-day register */
1972 static unsigned long seed = 1;
1973 u_short res = (u_short)seed;
1974 seed = seed * 1103515245L + time_second;
1978 /*---------------------------------------------------------------------------*
1979 * produce "nice" screensaving ....
1980 *---------------------------------------------------------------------------*/
1982 scrnsv_blink(void * arg)
1984 static struct rgb blink_rgb[8] =
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 */
1995 u_short r = getrand();
1996 unsigned pos = (r % (scrnsv_size / 2));
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);
2006 #endif /* PCVT_PRETTYSCRNS */
2008 /*---------------------------------------------------------------------------*
2010 *---------------------------------------------------------------------------*/
2013 pcvt_set_scrnsv_tmo(int timeout)
2016 pcvt_set_scrnsv_tmo(int timeout)
2017 #endif /* XSERVER */
2022 untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
2024 scrnsv_timeout = timeout;
2025 pcvt_scrnsv_reset(); /* sanity */
2027 if(timeout == 0 && savedscreen)
2029 /* release buffer when screen saver turned off */
2030 free(savedscreen, M_TEMP);
2031 savedscreen = (u_short *)0;
2035 /*---------------------------------------------------------------------------*
2037 *---------------------------------------------------------------------------*/
2039 scrnsv_timedout(void *arg)
2041 /* this function is called by timeout() */
2042 /* raise priority to avoid conflicts with kbd intr */
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
2052 if(++scrnsv_active == 1)
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
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...]
2068 s = sizeof(u_short) * vsp->screen_rowsize * vsp->maxcol;
2070 if(savedscreen == (u_short *)0 || s != scrnsv_size)
2072 /* really need to allocate */
2074 free(savedscreen, M_TEMP);
2077 (u_short *)malloc(s, M_TEMP, M_NOWAIT))
2081 * didn't get the buffer memory,
2082 * turn off screen saver
2084 scrnsv_timeout = scrnsv_active = 0;
2089 /* save current screen */
2090 bcopy(vsp->Crtat, savedscreen, scrnsv_size);
2092 /* on VGA's, make sure palette is set to blank screen */
2093 if(adaptor_type == VGA_ADAPTOR)
2095 struct rgb black = {0, 0, 0};
2096 vgapaletteio(0 /* BLACK */, &black, 1);
2098 /* prepare for next time... */
2099 scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL, hz / 10);
2103 /* second call, now blank the screen */
2104 /* fill screen with blanks */
2105 fillw(/* (BLACK<<8) + */ ' ', vsp->Crtat, scrnsv_size / 2);
2107 #if PCVT_PRETTYSCRNS
2108 scrnsv_current = vsp->Crtat;
2109 scrnsv_blink_ch = timeout(scrnsv_blink, NULL, hz);
2110 #endif /* PCVT_PRETTYSCRNS */
2112 sw_cursor(0); /* cursor off on mda/cga */
2117 /*---------------------------------------------------------------------------*
2118 * interface to screensaver "subsystem"
2119 *---------------------------------------------------------------------------*/
2121 pcvt_scrnsv_reset(void)
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()
2128 static long last_schedule = 0L;
2132 if((scrnsv_active == 1 || scrnsv_timeout) &&
2133 last_schedule != time_second)
2135 last_schedule = time_second;
2137 untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
2142 #if PCVT_PRETTYSCRNS
2143 if(scrnsv_active > 1)
2144 untimeout(scrnsv_blink, NULL, scrnsv_blink_ch);
2145 #endif /* PCVT_PRETTYSCRNS */
2147 bcopy(savedscreen, vsp->Crtat, scrnsv_size);
2148 if(adaptor_type == VGA_ADAPTOR)
2150 /* back up VGA palette info */
2151 vgapaletteio(0 /* BLACK */, &vsp->palette[0], 1);
2153 #if PCVT_PRETTYSCRNS
2154 vgapaletteio(7 /* LIGHTGRAY */, &vsp->palette[7], 1);
2155 #endif /* PCVT_PRETTYSCRNS */
2161 sw_cursor(1); /* cursor on */
2166 /* mark next timeout */
2167 scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL,
2168 scrnsv_timeout * hz);
2173 #endif /* PCVT_SCREENSAVER */
2175 /*---------------------------------------------------------------------------*
2176 * switch cursor on/off
2177 *---------------------------------------------------------------------------*/
2179 sw_cursor(int onoff)
2181 if(adaptor_type == EGA_ADAPTOR)
2186 start = vsp->cursor_start;
2187 end = vsp->cursor_end;
2191 int cs = vs[current_video_screen].vga_charset;
2193 cs = (cs < 0) ? 0 : ((cs < totalfonts) ?
2196 start = (vgacs[cs].char_scanlines & 0x1F) + 1;
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);
2204 else /* mda, cga, vga */
2206 outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
2208 outb(addr_6845+1, vsp->cursor_start);
2210 outb(addr_6845+1, CURSOR_ON_BIT);
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 *---------------------------------------------------------------------------*/
2223 * program sequencer to access
2227 /* synchronous reset */
2228 outb(TS_INDEX, TS_SYNCRESET);
2229 outb(TS_DATA, 0x01);
2231 /* write to map 0 & 1 */
2232 outb(TS_INDEX, TS_WRPLMASK);
2233 outb(TS_DATA, 0x03);
2235 /* odd-even addressing */
2236 outb(TS_INDEX, TS_MEMMODE);
2237 outb(TS_DATA, 0x03);
2239 /* clear synchronous reset */
2240 outb(TS_INDEX, TS_SYNCRESET);
2241 outb(TS_DATA, 0x03);
2244 * program graphics controller
2245 * to access character
2249 /* select map 0 for cpu reads */
2250 outb(GDC_INDEX, GDC_RDPLANESEL);
2251 outb(GDC_DATA, 0x00);
2253 /* enable odd-even addressing */
2254 outb(GDC_INDEX, GDC_MODE);
2255 outb(GDC_DATA, 0x10);
2257 /* map starts at 0xb000 */
2258 outb(GDC_INDEX, GDC_MISC);
2259 outb(GDC_DATA, 0x0a);
2262 #endif /* NVT > 0 */
2264 /* ------------------------- E O F ------------------------------------------*/