227ee8a188
"time" wasn't a atomic variable, so splfoo() protection were needed around any access to it, unless you just wanted the seconds part. Most uses of time.tv_sec now uses the new variable time_second instead. gettime() changed to getmicrotime(0. Remove a couple of unneeded splfoo() protections, the new getmicrotime() is atomic, (until Bruce sets a breakpoint in it). A couple of places needed random data, so use read_random() instead of mucking about with time which isn't random. Add a new nfs_curusec() function. Mark a couple of bogosities involving the now disappeard time variable. Update ffs_update() to avoid the weird "== &time" checks, by fixing the one remaining call that passwd &time as args. Change profiling in ncr.c to use ticks instead of time. Resolution is the same. Add new function "tvtohz()" to avoid the bogus "splfoo(), add time, call hzto() which subtracts time" sequences. Reviewed by: bde
2217 lines
56 KiB
C
2217 lines
56 KiB
C
/*
|
|
* Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
|
|
*
|
|
* Copyright (c) 1992, 1993 Brian Dunford-Shore and Scott Turner.
|
|
*
|
|
* Copyright (C) 1992, 1993 Soeren Schmidt.
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* For the sake of compatibility, portions of this code regarding the
|
|
* X server interface are taken from Soeren Schmidt's syscons driver.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Hellmuth Michaelis,
|
|
* Brian Dunford-Shore, Joerg Wunsch, Scott Turner and Soeren Schmidt.
|
|
* 4. The name authors may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*
|
|
* @(#)pcvt_sup.c, 3.20, Last Edit-Date: [Thu Apr 6 10:49:44 1995]
|
|
*
|
|
*/
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
*
|
|
* pcvt_sup.c VT220 Driver Support Routines
|
|
* ---------------------------------------------
|
|
* -hm ------------ Release 3.00 --------------
|
|
* -hm integrating NetBSD-current patches
|
|
* -hm removed paranoid delay()/DELAY() from vga_test()
|
|
* -hm removing vgapage() protection if PCVT_KBD_FIFO
|
|
* -hm some new CONF_ - values
|
|
* -hm Joerg's patches for FreeBSD ttymalloc
|
|
* -hm applying Joerg's patches for FreeBSD 2.0
|
|
* -hm applying Lon Willet's patches for NetBSD
|
|
* -hm NetBSD PR #400: patch to short-circuit TIOCSWINSZ
|
|
* -hm getting PCVT_BURST reported correctly for FreeBSD 2.0
|
|
* -hm applying patch from Joerg fixing Crtat bug
|
|
* -hm moving ega/vga coldinit support code to mda2egaorvga()
|
|
* -hm patch from Thomas Eberhardt fixing force 24 lines fkey update
|
|
*
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
#include "vt.h"
|
|
#if NVT > 0
|
|
|
|
#include <i386/isa/pcvt/pcvt_hdr.h> /* global include */
|
|
|
|
#include <sys/resource.h>
|
|
|
|
static void vid_cursor ( struct cursorshape *data );
|
|
static void vgasetfontattr ( struct vgafontattr *data );
|
|
static void vgagetfontattr ( struct vgafontattr *data );
|
|
static void vgaloadchar ( struct vgaloadchar *data );
|
|
static void vid_getscreen ( struct screeninfo *data, Dev_t dev );
|
|
static void vid_setscreen ( struct screeninfo *data, Dev_t dev );
|
|
static void setchargen ( void );
|
|
static void setchargen3 ( void );
|
|
static void resetchargen ( void );
|
|
static void vgareadpel ( struct vgapel *data, Dev_t dev );
|
|
static void vgawritepel ( struct vgapel *data, Dev_t dev );
|
|
static void vgapcvtid ( struct pcvtid *data );
|
|
static void vgapcvtinfo ( struct pcvtinfo *data );
|
|
|
|
#ifdef XSERVER
|
|
static unsigned char * compute_charset_base ( unsigned fontset );
|
|
#endif /* XSERVER */
|
|
|
|
static struct callout_handle async_update_ch =
|
|
CALLOUT_HANDLE_INITIALIZER(&async_update_ch);
|
|
|
|
#if PCVT_SCREENSAVER
|
|
static void scrnsv_timedout ( void *arg );
|
|
static struct callout_handle scrnsv_timeout_ch =
|
|
CALLOUT_HANDLE_INITIALIZER(&scrnsv_timeout_ch);
|
|
static u_short *savedscreen = (u_short *)0; /* ptr to screen contents */
|
|
static size_t scrnsv_size = (size_t)-1; /* size of saved image */
|
|
|
|
#ifndef XSERVER
|
|
static unsigned scrnsv_timeout = 0; /* initially off */
|
|
static void pcvt_set_scrnsv_tmo ( int timeout );/* else declared global */
|
|
#endif /* XSERVER */
|
|
|
|
#if PCVT_PRETTYSCRNS
|
|
static u_short *scrnsv_current = (u_short *)0; /* attention char ptr */
|
|
static struct callout_handle scrnsv_blink_ch =
|
|
CALLOUT_HANDLE_INITIALIZER(&scrnsv_blink_ch);
|
|
static void scrnsv_blink ( void * );
|
|
static u_short getrand ( void );
|
|
#endif /* PCVT_PRETTYSCRNS */
|
|
|
|
#endif /* PCVT_SCREENSAVER */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* execute vga ioctls
|
|
*---------------------------------------------------------------------------*/
|
|
int
|
|
vgaioctl(Dev_t dev, int cmd, caddr_t data, int flag)
|
|
{
|
|
if(minor(dev) >= PCVT_NSCREENS)
|
|
return -1;
|
|
|
|
/*
|
|
* Some of the commands are not applicable if the vt in question, or the
|
|
* current vt is in graphics mode (i.e., the X server acts on it); they
|
|
* will cause an EAGAIN (resource temporarily unavailable) to be returned.
|
|
*/
|
|
|
|
#ifdef XSERVER
|
|
#if PCVT_USL_VT_COMPAT
|
|
#define is_dev_grafx vs[minor(dev)].vt_status & VT_GRAFX
|
|
#define is_current_grafx vsp->vt_status & VT_GRAFX
|
|
#else /* old X interface */
|
|
#define is_dev_grafx pcvt_xmode
|
|
#define is_current_grafx pcvt_xmode
|
|
#endif /* PCVT_USL_VT_COMPAT */
|
|
#else /* !XSERVER */
|
|
#define is_dev_grafx 0 /* not applicable */
|
|
#define is_current_grafx 0
|
|
#endif /* XSERVER */
|
|
|
|
switch(cmd)
|
|
{
|
|
case VGACURSOR:
|
|
if(is_current_grafx)
|
|
return EAGAIN;
|
|
vid_cursor((struct cursorshape *)data);
|
|
break;
|
|
|
|
case VGALOADCHAR:
|
|
if((adaptor_type != VGA_ADAPTOR) &&
|
|
(adaptor_type != EGA_ADAPTOR))
|
|
return -1;
|
|
if(is_current_grafx)
|
|
return EAGAIN;
|
|
vgaloadchar((struct vgaloadchar *)data);
|
|
break;
|
|
|
|
case VGASETFONTATTR:
|
|
if((adaptor_type != VGA_ADAPTOR) &&
|
|
(adaptor_type != EGA_ADAPTOR))
|
|
return -1;
|
|
|
|
#if PCVT_SCREENSAVER
|
|
pcvt_scrnsv_reset();
|
|
#endif /* PCVT_SCREENSAVER */
|
|
|
|
vgasetfontattr((struct vgafontattr *)data);
|
|
break;
|
|
|
|
case VGAGETFONTATTR:
|
|
if((adaptor_type != VGA_ADAPTOR) &&
|
|
(adaptor_type != EGA_ADAPTOR))
|
|
return -1;
|
|
vgagetfontattr((struct vgafontattr *)data);
|
|
break;
|
|
|
|
case VGASETSCREEN:
|
|
|
|
#if defined XSERVER && !PCVT_USL_VT_COMPAT
|
|
/* avoid screen switch if using old X mode */
|
|
if(is_dev_grafx)
|
|
return EAGAIN;
|
|
#endif /* XSERVER && !PCVT_USL_VT_COMPAT */
|
|
|
|
#if PCVT_SCREENSAVER
|
|
pcvt_scrnsv_reset();
|
|
#endif /* PCVT_SCREENSAVER */
|
|
|
|
vid_setscreen((struct screeninfo *)data, dev);
|
|
break;
|
|
|
|
case VGAGETSCREEN:
|
|
vid_getscreen((struct screeninfo *)data, dev);
|
|
break;
|
|
|
|
case VGAREADPEL:
|
|
if(adaptor_type != VGA_ADAPTOR)
|
|
return -1;
|
|
if(is_dev_grafx)
|
|
return EAGAIN;
|
|
vgareadpel((struct vgapel *)data, dev);
|
|
break;
|
|
|
|
case VGAWRITEPEL:
|
|
if(adaptor_type != VGA_ADAPTOR)
|
|
return -1;
|
|
if(is_dev_grafx)
|
|
return EAGAIN;
|
|
vgawritepel((struct vgapel *)data, dev);
|
|
break;
|
|
|
|
#if PCVT_SCREENSAVER
|
|
case VGASCREENSAVER:
|
|
if(is_current_grafx)
|
|
return EAGAIN;
|
|
pcvt_set_scrnsv_tmo(*(int *)data);
|
|
pcvt_scrnsv_reset();
|
|
break;
|
|
#endif /* PCVT_SCREENSAVER */
|
|
|
|
case VGAPCVTID:
|
|
vgapcvtid((struct pcvtid *)data);
|
|
break;
|
|
|
|
case VGAPCVTINFO:
|
|
vgapcvtinfo((struct pcvtinfo *)data);
|
|
break;
|
|
|
|
case VGASETCOLMS:
|
|
if(is_dev_grafx)
|
|
return EAGAIN;
|
|
if(*(int *)data == 80)
|
|
(void)vt_col(&vs[minor(dev)], SCR_COL80);
|
|
else if(*(int *)data == 132)
|
|
{
|
|
if(vt_col(&vs[minor(dev)], SCR_COL132) == 0)
|
|
return EINVAL; /* not a VGA */
|
|
}
|
|
else
|
|
return EINVAL;
|
|
break;
|
|
|
|
case TIOCSWINSZ:
|
|
/* do nothing here */
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
#undef is_dev_grafx
|
|
#undef is_current_grafx
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* video ioctl - return driver id
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vgapcvtid(struct pcvtid *data)
|
|
{
|
|
strcpy(data->name, PCVTIDNAME);
|
|
data->rmajor = PCVTIDMAJOR;
|
|
data->rminor = PCVTIDMINOR;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* video ioctl - return driver compile time options data
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vgapcvtinfo(struct pcvtinfo *data)
|
|
{
|
|
#if PCVT_NETBSD
|
|
data->opsys = CONF_NETBSD;
|
|
data->opsysrel = PCVT_NETBSD;
|
|
#elif PCVT_FREEBSD
|
|
data->opsys = CONF_FREEBSD;
|
|
data->opsysrel = PCVT_FREEBSD;
|
|
#else
|
|
data->opsys = CONF_UNKNOWNOPSYS;
|
|
data->opsysrel = 0;
|
|
#endif
|
|
|
|
data->nscreens = PCVT_NSCREENS;
|
|
data->scanset = PCVT_SCANSET;
|
|
data->updatefast= PCVT_UPDATEFAST;
|
|
data->updateslow= PCVT_UPDATESLOW;
|
|
data->sysbeepf = PCVT_SYSBEEPF;
|
|
|
|
#if PCVT_NETBSD || PCVT_FREEBSD >= 200
|
|
data->pcburst = PCVT_PCBURST;
|
|
#else
|
|
data->pcburst = 1;
|
|
#endif
|
|
|
|
#if PCVT_KBD_FIFO
|
|
data->kbd_fifo_sz = PCVT_KBD_FIFO_SZ;
|
|
#else
|
|
data->kbd_fifo_sz = 0;
|
|
#endif
|
|
|
|
data->compile_opts = (0
|
|
|
|
#if PCVT_VT220KEYB
|
|
| CONF_VT220KEYB
|
|
#endif
|
|
#if PCVT_SCREENSAVER
|
|
| CONF_SCREENSAVER
|
|
#endif
|
|
#if PCVT_PRETTYSCRNS
|
|
| CONF_PRETTYSCRNS
|
|
#endif
|
|
#if PCVT_CTRL_ALT_DEL
|
|
| CONF_CTRL_ALT_DEL
|
|
#endif
|
|
#if PCVT_USEKBDSEC
|
|
| CONF_USEKBDSEC
|
|
#endif
|
|
#if PCVT_24LINESDEF
|
|
| CONF_24LINESDEF
|
|
#endif
|
|
#if PCVT_EMU_MOUSE
|
|
| CONF_EMU_MOUSE
|
|
#endif
|
|
#if PCVT_SHOWKEYS
|
|
| CONF_SHOWKEYS
|
|
#endif
|
|
#if PCVT_KEYBDID
|
|
| CONF_KEYBDID
|
|
#endif
|
|
#if PCVT_SIGWINCH
|
|
| CONF_SIGWINCH
|
|
#endif
|
|
#if PCVT_NULLCHARS
|
|
| CONF_NULLCHARS
|
|
#endif
|
|
#if PCVT_BACKUP_FONTS
|
|
| CONF_BACKUP_FONTS
|
|
#endif
|
|
#if PCVT_SW0CNOUTP /* was FORCE8BIT */
|
|
| CONF_SW0CNOUTP
|
|
#endif
|
|
#if PCVT_SETCOLOR
|
|
| CONF_SETCOLOR
|
|
#endif
|
|
#if PCVT_132GENERIC
|
|
| CONF_132GENERIC
|
|
#endif
|
|
#if PCVT_PALFLICKER
|
|
| CONF_PALFLICKER
|
|
#endif
|
|
#if PCVT_WAITRETRACE
|
|
| CONF_WAITRETRACE
|
|
#endif
|
|
#ifdef XSERVER
|
|
| CONF_XSERVER
|
|
#endif
|
|
#if PCVT_USL_VT_COMPAT
|
|
| CONF_USL_VT_COMPAT
|
|
#endif
|
|
#if PCVT_PORTIO_DELAY
|
|
| CONF_PORTIO_DELAY
|
|
#endif
|
|
#if PCVT_INHIBIT_NUMLOCK
|
|
| CONF_INHIBIT_NUMLOCK
|
|
#endif
|
|
#if PCVT_META_ESC
|
|
| CONF_META_ESC
|
|
#endif
|
|
#if PCVT_KBD_FIFO
|
|
| CONF_KBD_FIFO
|
|
#endif
|
|
#if PCVT_NOFASTSCROLL
|
|
| CONF_NOFASTSCROLL
|
|
#endif
|
|
#if PCVT_SLOW_INTERRUPT
|
|
| CONF_SLOW_INTERRUPT
|
|
#endif
|
|
#if PCVT_NO_LED_UPDATE
|
|
| CONF_NO_LED_UPDATE
|
|
#endif
|
|
);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* video ioctl - set cursor appearence
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vid_cursor(struct cursorshape *data)
|
|
{
|
|
int screen;
|
|
int start;
|
|
int end;
|
|
int line_height;
|
|
int character_set;
|
|
|
|
/* for which virtual screen, -1 for current */
|
|
screen = data->screen_no;
|
|
|
|
if(screen == -1) /* current ? */
|
|
screen = current_video_screen;
|
|
else if(screen > totalscreens - 1)
|
|
screen = totalscreens - 1;
|
|
else if(screen < 0)
|
|
screen = 0;
|
|
|
|
if(adaptor_type == VGA_ADAPTOR || adaptor_type == EGA_ADAPTOR)
|
|
{
|
|
character_set = vs[screen].vga_charset;
|
|
character_set = (character_set < 0) ? 0 :
|
|
((character_set < totalfonts) ?
|
|
character_set :
|
|
totalfonts-1);
|
|
|
|
line_height = vgacs[character_set].char_scanlines & 0x1F;
|
|
}
|
|
else if(adaptor_type == MDA_ADAPTOR)
|
|
{
|
|
line_height = 14;
|
|
}
|
|
else
|
|
{
|
|
line_height = 8; /* CGA */
|
|
}
|
|
|
|
start = (data->start < 0) ? 0 :
|
|
((data->start > line_height) ? line_height : data->start);
|
|
|
|
if((vga_family == VGA_F_TRI) && (start == 0))
|
|
start = 1;
|
|
|
|
end = (data->end < 0) ? 0 :
|
|
((data->end > line_height) ? line_height : data->end);
|
|
|
|
vs[screen].cursor_start = start;
|
|
vs[screen].cursor_end = end;
|
|
|
|
if(screen == current_video_screen)
|
|
{
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
outb(addr_6845+1, start);
|
|
outb(addr_6845,CRTC_CUREND); /* cursor end reg */
|
|
outb(addr_6845+1, end);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* ega/vga ioctl - set font attributes
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vgasetfontattr(struct vgafontattr *data)
|
|
{
|
|
register int i;
|
|
int vga_character_set;
|
|
int lines_per_character;
|
|
int totscanlines;
|
|
int size;
|
|
|
|
vga_character_set = data->character_set;
|
|
vga_character_set = (vga_character_set < 0) ? 0 :
|
|
((vga_character_set < totalfonts) ?
|
|
vga_character_set : totalfonts-1);
|
|
|
|
vgacs[vga_character_set].loaded = data->font_loaded;
|
|
|
|
/* Limit Characters to 32 scanlines doubled */
|
|
vgacs[vga_character_set].char_scanlines =
|
|
(data->character_scanlines & 0x1F)
|
|
| 0x40; /* always set bit 9 of line cmp reg */
|
|
|
|
if(adaptor_type == EGA_ADAPTOR)
|
|
/* ...and screen height to scan 350 lines */
|
|
vgacs[vga_character_set].scr_scanlines =
|
|
(data->screen_scanlines > 0x5d) ?
|
|
0x5d : data->screen_scanlines;
|
|
else
|
|
/* ...and screen height to scan 480 lines */
|
|
vgacs[vga_character_set].scr_scanlines =
|
|
(data->screen_scanlines > 0xdF) ?
|
|
0xdF : data->screen_scanlines;
|
|
|
|
lines_per_character =
|
|
(int)(0x1F & vgacs[vga_character_set].char_scanlines)+1;
|
|
|
|
totscanlines = 0x101 + (int)vgacs[vga_character_set].scr_scanlines;
|
|
|
|
size = data->screen_size;
|
|
|
|
if(adaptor_type == EGA_ADAPTOR)
|
|
{
|
|
switch(size)
|
|
{
|
|
case SIZ_25ROWS: /* This case is always OK */
|
|
break;
|
|
|
|
case SIZ_35ROWS:
|
|
if(totscanlines/lines_per_character >= 35)
|
|
size = SIZ_35ROWS;
|
|
else
|
|
size = SIZ_25ROWS;
|
|
break;
|
|
|
|
case SIZ_43ROWS:
|
|
default:
|
|
if(totscanlines/lines_per_character >= 43)
|
|
size = SIZ_43ROWS;
|
|
else if(totscanlines/lines_per_character >= 35)
|
|
size = SIZ_35ROWS;
|
|
else
|
|
size = SIZ_25ROWS;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch(size)
|
|
{
|
|
case SIZ_25ROWS: /* This case is always OK */
|
|
break;
|
|
|
|
case SIZ_28ROWS:
|
|
if(totscanlines/lines_per_character >= 28)
|
|
size = SIZ_28ROWS;
|
|
else
|
|
size = SIZ_25ROWS;
|
|
break;
|
|
|
|
case SIZ_40ROWS:
|
|
if(totscanlines/lines_per_character >= 40)
|
|
size = SIZ_40ROWS;
|
|
else if(totscanlines/lines_per_character >= 28)
|
|
size = SIZ_28ROWS;
|
|
else
|
|
size = SIZ_25ROWS;
|
|
break;
|
|
|
|
case SIZ_50ROWS:
|
|
default:
|
|
if(totscanlines/lines_per_character >= 50)
|
|
size = SIZ_50ROWS;
|
|
else if(totscanlines/lines_per_character >= 40)
|
|
size = SIZ_40ROWS;
|
|
else if(totscanlines/lines_per_character >= 28)
|
|
size = SIZ_28ROWS;
|
|
else
|
|
size = SIZ_25ROWS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
vgacs[vga_character_set].screen_size = size;
|
|
|
|
for (i = 0;i < PCVT_NSCREENS;i++)
|
|
{
|
|
if(vga_character_set == vs[i].vga_charset)
|
|
set_charset(&(vs[i]),vga_character_set);
|
|
}
|
|
|
|
#if !PCVT_USL_VT_COMPAT
|
|
vgapage(current_video_screen);
|
|
#else
|
|
switch_screen(current_video_screen, 0, 0);
|
|
#endif /* !PCVT_USL_VT_COMPAT */
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* ega/vga ioctl - get font attributes
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vgagetfontattr(struct vgafontattr *data)
|
|
{
|
|
int vga_character_set;
|
|
|
|
vga_character_set = data->character_set;
|
|
vga_character_set = (vga_character_set < 0) ? 0 :
|
|
((vga_character_set < (int)totalfonts) ?
|
|
vga_character_set :
|
|
(int)(totalfonts-1));
|
|
|
|
data->character_set = (int)vga_character_set;
|
|
|
|
data->font_loaded = (int)vgacs[vga_character_set].loaded;
|
|
|
|
data->character_scanlines =
|
|
(int)vgacs[vga_character_set].char_scanlines
|
|
& 0x1f; /* do not display the overflow bits */
|
|
|
|
data->screen_scanlines = (int)vgacs[vga_character_set].scr_scanlines;
|
|
|
|
data->screen_size = (int)vgacs[vga_character_set].screen_size;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* ega/vga ioctl - load a character shape into character set
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vgaloadchar(struct vgaloadchar *data)
|
|
{
|
|
int vga_character_set;
|
|
int character;
|
|
int lines_per_character;
|
|
|
|
vga_character_set = data->character_set;
|
|
vga_character_set = (vga_character_set < 0) ? 0 :
|
|
((vga_character_set < (int)totalfonts) ?
|
|
vga_character_set : (int)(totalfonts-1));
|
|
|
|
character = (data->character < 0) ? 0 :
|
|
((data->character > 255) ? 255 : data->character);
|
|
|
|
lines_per_character = (int)data->character_scanlines;
|
|
lines_per_character = (lines_per_character < 0) ? 0 :
|
|
((lines_per_character > 32) ? 32 : lines_per_character);
|
|
|
|
loadchar(vga_character_set,character,lines_per_character,
|
|
data->char_table);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* video ioctl - get screen information
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vid_getscreen(struct screeninfo *data, Dev_t dev)
|
|
{
|
|
int device = minor(dev);
|
|
data->adaptor_type = adaptor_type; /* video adapter installed */
|
|
data->monitor_type = color; /* monitor type installed */
|
|
data->totalfonts = totalfonts; /* no of downloadble fonts */
|
|
data->totalscreens = totalscreens; /* no of virtual screens */
|
|
data->screen_no = device; /* this screen number */
|
|
data->current_screen = current_video_screen; /* displayed screen no */
|
|
/* screen size */
|
|
data->screen_size = vgacs[(vs[device].vga_charset)].screen_size;
|
|
/* pure VT mode or HP/VT mode */
|
|
data->pure_vt_mode = vs[device].vt_pure_mode;
|
|
data->vga_family = vga_family; /* manufacturer, family */
|
|
data->vga_type = vga_type; /* detected chipset type */
|
|
data->vga_132 = can_do_132col; /* 132 column support */
|
|
data->force_24lines = vs[device].force24; /* force 24 lines */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* video ioctl - set screen information
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vid_setscreen(struct screeninfo *data, Dev_t dev)
|
|
{
|
|
int screen;
|
|
|
|
if(data->current_screen == -1)
|
|
{
|
|
screen = minor(dev);
|
|
}
|
|
else
|
|
{
|
|
if(data->current_screen >= PCVT_NSCREENS)
|
|
return; /* XXXXXX */
|
|
screen = data->current_screen;
|
|
}
|
|
|
|
vgapage(screen);
|
|
|
|
#if defined XSERVER && PCVT_USL_VT_COMPAT
|
|
{
|
|
int x = spltty(), waitfor = screen + 1;
|
|
/* if the vt is yet to be released by a process, wait here */
|
|
if(vs[screen].vt_status & VT_WAIT_REL)
|
|
(void)usl_vt_ioctl(dev, VT_WAITACTIVE,
|
|
(caddr_t)&waitfor, 0, 0);
|
|
splx(x);
|
|
}
|
|
/* make sure the switch really happened */
|
|
if(screen != current_video_screen)
|
|
return; /* XXX should say "EAGAIN" here */
|
|
#endif /* defined XSERVER && PCVT_USL_VT_COMPAT */
|
|
|
|
if((data->screen_size != -1) || (data->force_24lines != -1))
|
|
{
|
|
if(data->screen_size == -1)
|
|
data->screen_size =
|
|
vgacs[(vs[screen].vga_charset)].screen_size;
|
|
|
|
if(data->force_24lines != -1)
|
|
{
|
|
vs[screen].force24 = data->force_24lines;
|
|
|
|
if(vs[screen].force24)
|
|
{
|
|
swritefkl(2,(u_char *)"FORCE24 ENABLE *",
|
|
&vs[screen]);
|
|
}
|
|
else
|
|
{
|
|
swritefkl(2,(u_char *)"FORCE24 ENABLE ",
|
|
&vs[screen]);
|
|
}
|
|
}
|
|
|
|
if((data->screen_size == SIZ_25ROWS) ||
|
|
(data->screen_size == SIZ_28ROWS) ||
|
|
(data->screen_size == SIZ_35ROWS) ||
|
|
(data->screen_size == SIZ_40ROWS) ||
|
|
(data->screen_size == SIZ_43ROWS) ||
|
|
(data->screen_size == SIZ_50ROWS))
|
|
{
|
|
if(data->screen_no == -1)
|
|
set_screen_size(vsp, data->screen_size);
|
|
else
|
|
set_screen_size(&vs[minor(dev)],
|
|
data->screen_size);
|
|
}
|
|
}
|
|
|
|
if(data->pure_vt_mode != -1)
|
|
{
|
|
if((data->pure_vt_mode == M_HPVT) ||
|
|
(data->pure_vt_mode == M_PUREVT))
|
|
{
|
|
if(data->screen_no == -1)
|
|
set_emulation_mode(vsp, data->pure_vt_mode);
|
|
else
|
|
set_emulation_mode(&vs[minor(dev)],
|
|
data->pure_vt_mode);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* set screen size/resolution for a virtual screen
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
set_screen_size(struct video_state *svsp, int size)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < totalfonts; i++)
|
|
{
|
|
if(vgacs[i].screen_size == size)
|
|
{
|
|
set_charset(svsp, i);
|
|
clr_parms(svsp); /* escape parameter init */
|
|
svsp->state = STATE_INIT; /* initial state */
|
|
svsp->scrr_beg = 0; /* start of scrolling region */
|
|
svsp->sc_flag = 0; /* invalidate saved cursor
|
|
* position */
|
|
svsp->transparent = 0; /* disable control code
|
|
* processing */
|
|
|
|
/* Update tty to reflect screen size */
|
|
|
|
if (svsp->vs_tty)
|
|
{
|
|
svsp->vs_tty->t_winsize.ws_col = svsp->maxcol;
|
|
svsp->vs_tty->t_winsize.ws_xpixel =
|
|
(svsp->maxcol == 80)? 720: 1056;
|
|
svsp->vs_tty->t_winsize.ws_ypixel = 400;
|
|
svsp->vs_tty->t_winsize.ws_row =
|
|
svsp->screen_rows;
|
|
}
|
|
/* screen_rows already calculated in set_charset() */
|
|
if(svsp->vt_pure_mode == M_HPVT && svsp->labels_on)
|
|
{
|
|
if(svsp->which_fkl == SYS_FKL)
|
|
sw_sfkl(svsp);
|
|
else if(svsp->which_fkl == USR_FKL)
|
|
sw_ufkl(svsp);
|
|
}
|
|
|
|
|
|
svsp->scrr_len = svsp->screen_rows;
|
|
svsp->scrr_end = svsp->scrr_len - 1;
|
|
|
|
#if PCVT_SIGWINCH
|
|
if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
|
|
pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
|
|
#endif /* PCVT_SIGWINCH */
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* VGA ioctl - read DAC palette entry
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vgareadpel(struct vgapel *data, Dev_t dev)
|
|
{
|
|
register unsigned vpage = minor(dev);
|
|
register unsigned idx = data->idx;
|
|
|
|
if(idx >= NVGAPEL)
|
|
return; /* no such entry */
|
|
|
|
/* do not read VGA palette directly, use saved values */
|
|
data->r = vs[vpage].palette[idx].r;
|
|
data->g = vs[vpage].palette[idx].g;
|
|
data->b = vs[vpage].palette[idx].b;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* VGA ioctl - write DAC palette entry
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
vgawritepel(struct vgapel *data, Dev_t dev)
|
|
{
|
|
register unsigned vpage = minor(dev);
|
|
register unsigned idx = data->idx;
|
|
|
|
if(idx >= NVGAPEL)
|
|
return; /* no such entry */
|
|
|
|
/* first, update saved values for this video screen */
|
|
vs[vpage].palette[idx].r = data->r;
|
|
vs[vpage].palette[idx].g = data->g;
|
|
vs[vpage].palette[idx].b = data->b;
|
|
|
|
/* if this happens on active screen, update VGA DAC, too */
|
|
if(vpage == current_video_screen)
|
|
vgapaletteio(idx, &vs[vpage].palette[idx], 1);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* VGA physical IO - read/write one palette entry
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vgapaletteio(unsigned idx, struct rgb *val, int writeit)
|
|
{
|
|
|
|
#if PCVT_PALFLICKER
|
|
vga_screen_off();
|
|
#endif /* PCVT_PALFLICKER */
|
|
|
|
if(writeit)
|
|
{
|
|
outb(VGA_DAC + 2, idx);
|
|
|
|
#if PCVT_WAITRETRACE
|
|
wait_retrace();
|
|
#endif /* PCVT_WAITRETRACE */
|
|
|
|
outb(VGA_DAC + 3, val->r & VGA_PMSK);
|
|
|
|
#if PCVT_WAITRETRACE
|
|
wait_retrace();
|
|
#endif /* PCVT_WAITRETRACE */
|
|
|
|
outb(VGA_DAC + 3, val->g & VGA_PMSK);
|
|
|
|
#if PCVT_WAITRETRACE
|
|
wait_retrace();
|
|
#endif /* PCVT_WAITRETRACE */
|
|
|
|
outb(VGA_DAC + 3, val->b & VGA_PMSK);
|
|
}
|
|
else /* read it */
|
|
{
|
|
outb(VGA_DAC + 1, idx);
|
|
|
|
#if PCVT_WAITRETRACE
|
|
wait_retrace();
|
|
#endif /* PCVT_WAITRETRACE */
|
|
|
|
val->r = inb(VGA_DAC + 3) & VGA_PMSK;
|
|
|
|
#if PCVT_WAITRETRACE
|
|
wait_retrace();
|
|
#endif /* PCVT_WAITRETRACE */
|
|
|
|
val->g = inb(VGA_DAC + 3) & VGA_PMSK;
|
|
|
|
#if PCVT_WAITRETRACE
|
|
wait_retrace();
|
|
#endif /* PCVT_WAITRETRACE */
|
|
|
|
val->b = inb(VGA_DAC + 3) & VGA_PMSK;
|
|
}
|
|
|
|
#if PCVT_PALFLICKER
|
|
vga_screen_on();
|
|
#endif /* PCVT_PALFLICKER */
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
*
|
|
* update asynchronous: cursor, cursor pos displ, sys load, keyb scan
|
|
*
|
|
* arg is:
|
|
* UPDATE_START = do update; requeue
|
|
* UPDATE_STOP = suspend updates
|
|
* UPDATE_KERN = do update for kernel printfs
|
|
*
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
async_update(void *arg)
|
|
{
|
|
static int lastpos = 0;
|
|
static int counter = PCVT_UPDATESLOW;
|
|
|
|
#ifdef XSERVER
|
|
/* need a method to suspend the updates */
|
|
|
|
if(arg == UPDATE_STOP)
|
|
{
|
|
untimeout(async_update, UPDATE_START, async_update_ch);
|
|
return;
|
|
}
|
|
#endif /* XSERVER */
|
|
|
|
/* first check if update is possible */
|
|
|
|
if(chargen_access /* does no-one load characters? */
|
|
#ifdef XSERVER /* is vt0 not in graphics mode? */
|
|
#if !PCVT_USL_VT_COMPAT
|
|
|| pcvt_xmode /* XXX necessary ????? */
|
|
#endif /* PCVT_USL_VT_COMPAT */
|
|
#endif /* XSERVER */
|
|
)
|
|
{
|
|
goto async_update_exit; /* do not update anything */
|
|
}
|
|
|
|
#if PCVT_SCREENSAVER
|
|
if(reset_screen_saver && (counter == PCVT_UPDATESLOW))
|
|
{
|
|
pcvt_scrnsv_reset(); /* yes, do it */
|
|
reset_screen_saver = 0; /* re-init */
|
|
}
|
|
else if(scrnsv_active) /* is the screen not blanked? */
|
|
{
|
|
goto async_update_exit; /* do not update anything */
|
|
}
|
|
#endif /* PCVT_SCREENSAVER */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* this takes place on EVERY virtual screen (if not in X mode etc...)*/
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
if ( cursor_pos_valid &&
|
|
(lastpos != (vsp->Crtat + vsp->cur_offset - Crtat)))
|
|
{
|
|
lastpos = vsp->Crtat + vsp->cur_offset - Crtat;
|
|
outb(addr_6845, CRTC_CURSORH); /* high register */
|
|
outb(addr_6845+1, ((lastpos) >> 8));
|
|
outb(addr_6845, CRTC_CURSORL); /* low register */
|
|
outb(addr_6845+1, (lastpos));
|
|
}
|
|
|
|
if (arg == UPDATE_KERN) /* Magic arg: for kernel printfs */
|
|
return;
|
|
|
|
if(--counter) /* below is possible update */
|
|
goto async_update_exit; /* just now and then ..... */
|
|
counter = PCVT_UPDATESLOW; /* caution, see screensaver above !! */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* this takes place ONLY on screen 0 if in HP mode, labels on, !X */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
/* additional processing for HP necessary ? */
|
|
|
|
if((vs[0].vt_pure_mode == M_HPVT) && (vs[0].labels_on))
|
|
{
|
|
static volatile u_char buffer[] =
|
|
"System Load: 1min: 0.00 5min: 0.00 15min: 0.00";
|
|
register int tmp, i;
|
|
#if PCVT_SHOWKEYS
|
|
extern u_char rawkeybuf[80];
|
|
|
|
if(keyboard_show)
|
|
{
|
|
for(i = 0; i < 80; i++)
|
|
{
|
|
*((vs[0].Crtat+((vs[0].screen_rows+2)
|
|
* vs[0].maxcol))+i) =
|
|
user_attr | rawkeybuf[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#endif /* PCVT_SHOWKEYS */
|
|
|
|
/* display load averages in last line (taken from tty.c) */
|
|
i = 18;
|
|
#ifdef NEW_AVERUNNABLE
|
|
tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2)
|
|
>> FSHIFT;
|
|
#else
|
|
tmp = (averunnable[0] * 100 + FSCALE / 2) >> FSHIFT;
|
|
#endif
|
|
|
|
buffer[i++] =
|
|
((((tmp/100)/10) == 0) ?
|
|
' ' :
|
|
((tmp/100)/10) + '0');
|
|
buffer[i++] = ((tmp/100)%10) + '0';
|
|
buffer[i++] = '.';
|
|
buffer[i++] = ((tmp%100)/10) + '0';
|
|
buffer[i++] = ((tmp%100)%10) + '0';
|
|
i += 6;
|
|
#ifdef NEW_AVERUNNABLE
|
|
tmp = (averunnable.ldavg[1] * 100 + FSCALE / 2)
|
|
>> FSHIFT;
|
|
#else
|
|
tmp = (averunnable[1] * 100 + FSCALE / 2) >> FSHIFT;
|
|
#endif
|
|
buffer[i++] = ((((tmp/100)/10) == 0) ?
|
|
' ' :
|
|
((tmp/100)/10) + '0');
|
|
buffer[i++] = ((tmp/100)%10) + '0';
|
|
buffer[i++] = '.';
|
|
buffer[i++] = ((tmp%100)/10) + '0';
|
|
buffer[i++] = ((tmp%100)%10) + '0';
|
|
i += 7;
|
|
#ifdef NEW_AVERUNNABLE
|
|
tmp = (averunnable.ldavg[2] * 100 + FSCALE / 2)
|
|
>> FSHIFT;
|
|
#else
|
|
tmp = (averunnable[2] * 100 + FSCALE / 2) >> FSHIFT;
|
|
#endif
|
|
buffer[i++] = ((((tmp/100)/10) == 0) ?
|
|
' ' :
|
|
((tmp/100)/10) + '0');
|
|
buffer[i++] = ((tmp/100)%10) + '0';
|
|
buffer[i++] = '.';
|
|
buffer[i++] = ((tmp%100)/10) + '0';
|
|
buffer[i++] = ((tmp%100)%10) + '0';
|
|
buffer[i] = '\0';
|
|
|
|
for(i = 0; buffer[i]; i++)
|
|
{
|
|
*((vs[0].Crtat +
|
|
((vs[0].screen_rows + 2) * vs[0].maxcol)
|
|
) + i
|
|
) = user_attr | buffer[i];
|
|
}
|
|
|
|
#if PCVT_SHOWKEYS
|
|
for(; i < 77; i++)
|
|
{
|
|
*((vs[0].Crtat +
|
|
((vs[0].screen_rows + 2) * vs[0].maxcol)
|
|
) + i
|
|
) = user_attr | ' ';
|
|
}
|
|
|
|
}
|
|
#endif /* PCVT_SHOWKEYS */
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* this takes place on EVERY screen which is in HP mode, labels on,!X*/
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
if((vsp->vt_pure_mode == M_HPVT) && (vsp->labels_on))
|
|
{
|
|
register int col = vsp->col+1;
|
|
register u_short *p = vsp->Crtat +
|
|
(vsp->screen_rows * vsp->maxcol);
|
|
|
|
/* update column display between labels */
|
|
|
|
if(vsp->maxcol == SCR_COL132)
|
|
{
|
|
p += (SCR_COL132 - SCR_COL80)/2;
|
|
|
|
if(col >= 100)
|
|
{
|
|
*(p + LABEL_COLU) = user_attr | '1';
|
|
col -= 100;
|
|
}
|
|
else
|
|
{
|
|
*(p + LABEL_COLU) = user_attr | '0';
|
|
}
|
|
}
|
|
*(p + LABEL_COLH) = user_attr | ((col/10) + '0');
|
|
*(p + LABEL_COLL) = user_attr | ((col%10) + '0');
|
|
|
|
/* update row display between labels */
|
|
|
|
*(p + LABEL_ROWH) = (user_attr | (((vsp->row+1)/10) + '0'));
|
|
*(p + LABEL_ROWL) = (user_attr | (((vsp->row+1)%10) + '0'));
|
|
}
|
|
|
|
async_update_exit:
|
|
|
|
if(arg == UPDATE_START)
|
|
{
|
|
async_update_ch = timeout(async_update, UPDATE_START,
|
|
PCVT_UPDATEFAST);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* set character set for virtual screen
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
set_charset(struct video_state *svsp, int curvgacs)
|
|
{
|
|
static int sizetab[] = { 25, 28, 35, 40, 43, 50 };
|
|
int oldsize, oldrows, newsize, newrows;
|
|
|
|
if((curvgacs < 0) || (curvgacs > (NVGAFONTS-1)))
|
|
return;
|
|
|
|
svsp->vga_charset = curvgacs;
|
|
|
|
select_vga_charset(curvgacs);
|
|
|
|
oldsize = svsp->screen_rowsize;
|
|
oldrows = svsp->screen_rows;
|
|
newsize = sizetab[(vgacs[curvgacs].screen_size)];
|
|
newrows = newsize;
|
|
if (svsp->vt_pure_mode == M_HPVT)
|
|
newrows -= 3;
|
|
if (newrows == 25 && svsp->force24)
|
|
newrows = 24;
|
|
if (newrows < oldrows) {
|
|
int nscroll = svsp->row + 1 - newrows;
|
|
|
|
if (svsp->row >= oldrows) /* Sanity check */
|
|
nscroll = oldrows - newrows;
|
|
if (nscroll > 0) {
|
|
/* Scroll up */
|
|
bcopy (svsp->Crtat + nscroll * svsp->maxcol,
|
|
svsp->Crtat,
|
|
newrows * svsp->maxcol * CHR);
|
|
svsp->row -= nscroll;
|
|
svsp->cur_offset -= nscroll * svsp->maxcol;
|
|
}
|
|
if (newrows < newsize)
|
|
fillw(user_attr | ' ',
|
|
svsp->Crtat + newrows * svsp->maxcol,
|
|
(newsize - newrows) * svsp->maxcol);
|
|
} else if (oldrows < newsize)
|
|
fillw(user_attr | ' ',
|
|
svsp->Crtat + oldrows * svsp->maxcol,
|
|
(newsize - oldrows) * svsp->maxcol);
|
|
|
|
svsp->screen_rowsize = newsize;
|
|
svsp->screen_rows = newrows;
|
|
|
|
/* Clip scrolling region */
|
|
if(svsp->scrr_end > svsp->screen_rows - 1)
|
|
svsp->scrr_end = svsp->screen_rows - 1;
|
|
svsp->scrr_len = svsp->scrr_end - svsp->scrr_beg + 1;
|
|
|
|
/* Clip cursor pos */
|
|
|
|
if(svsp->cur_offset > (svsp->scrr_len * svsp->maxcol))
|
|
svsp->cur_offset = (svsp->scrr_len * svsp->maxcol) + svsp->col;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* select a vga character set
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
select_vga_charset(int vga_charset)
|
|
{
|
|
int first, second;
|
|
int fflag = 0;
|
|
int sflag = 0;
|
|
u_char cmap = 0;
|
|
|
|
static u_char cmaptaba[] =
|
|
{0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13};
|
|
|
|
static u_char cmaptabb[] =
|
|
{0x00, 0x04, 0x08, 0x0c, 0x20, 0x24, 0x28, 0x2c};
|
|
|
|
if((adaptor_type != EGA_ADAPTOR) && (adaptor_type != VGA_ADAPTOR))
|
|
return;
|
|
|
|
if((vga_charset < 0) || (vga_charset >= totalfonts))
|
|
return;
|
|
|
|
if(!vgacs[vga_charset].loaded)
|
|
return;
|
|
|
|
/*--------------------------------------------------------------
|
|
find the the first and second charset of a given resolution.
|
|
the first is used for lower 256 and the second (if any) is
|
|
used for the upper 256 entries of a complete 512 entry ega/
|
|
vga charset.
|
|
--------------------------------------------------------------*/
|
|
|
|
for(first = 0; first < totalfonts; first++)
|
|
{
|
|
if(!vgacs[first].loaded)
|
|
continue;
|
|
if(vgacs[first].screen_size != vgacs[vga_charset].screen_size)
|
|
continue;
|
|
if(vgacs[first].char_scanlines !=
|
|
vgacs[vga_charset].char_scanlines)
|
|
continue;
|
|
if(vgacs[first].scr_scanlines !=
|
|
vgacs[vga_charset].scr_scanlines)
|
|
continue;
|
|
fflag = 1;
|
|
break;
|
|
}
|
|
|
|
if(fflag != 1)
|
|
return;
|
|
|
|
for(second = first+1; second < totalfonts; second++)
|
|
{
|
|
if(!vgacs[second].loaded)
|
|
continue;
|
|
if(vgacs[second].screen_size != vgacs[vga_charset].screen_size)
|
|
continue;
|
|
if(vgacs[second].char_scanlines !=
|
|
vgacs[vga_charset].char_scanlines)
|
|
continue;
|
|
if(vgacs[second].scr_scanlines !=
|
|
vgacs[vga_charset].scr_scanlines)
|
|
continue;
|
|
sflag = 1;
|
|
break;
|
|
}
|
|
|
|
cmap = cmaptaba[first];
|
|
if(sflag)
|
|
{
|
|
cmap |= cmaptabb[second];
|
|
vgacs[first].secondloaded = second;
|
|
}
|
|
else
|
|
{
|
|
vgacs[first].secondloaded = 0; /*cs 0 can never become a 2nd!*/
|
|
}
|
|
|
|
if(vsp->wd132col)
|
|
{
|
|
cmap = (vga_charset & 0x07);
|
|
cmap |= 0x10;
|
|
}
|
|
|
|
outb(TS_INDEX, TS_FONTSEL); /* character map select register */
|
|
outb(TS_DATA, cmap); /* new char map */
|
|
|
|
outb(addr_6845, CRTC_MAXROW); /* max scan line reg */
|
|
outb(addr_6845+1,
|
|
vgacs[first].char_scanlines); /* scanlines/char */
|
|
|
|
outb(addr_6845, CRTC_VDE); /* vert display enable end */
|
|
outb(addr_6845+1,
|
|
vgacs[first].scr_scanlines); /* low byte of scr scanlines */
|
|
|
|
if((color == 0) && (adaptor_type == VGA_ADAPTOR))
|
|
{
|
|
outb(addr_6845, CRTC_ULOC); /* underline location reg */
|
|
outb(addr_6845+1, (vgacs[first].char_scanlines & 0x1F));
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch vga-card to load a character set
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
setchargen(void)
|
|
{
|
|
chargen_access = 1; /* flag we are accessing the chargen ram */
|
|
|
|
/* program sequencer to access character generator */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x01); /* synchronous reset */
|
|
|
|
outb(TS_INDEX, TS_WRPLMASK);
|
|
outb(TS_DATA, 0x04); /* write to map 2 */
|
|
|
|
outb(TS_INDEX, TS_MEMMODE);
|
|
outb(TS_DATA, 0x07); /* sequential addressing */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x03); /* clear synchronous reset */
|
|
|
|
/* program graphics controller to access character generator */
|
|
|
|
outb(GDC_INDEX, GDC_RDPLANESEL);
|
|
outb(GDC_DATA, 0x02); /* select map 2 for cpu reads */
|
|
|
|
outb(GDC_INDEX, GDC_MODE);
|
|
outb(GDC_DATA, 0x00); /* disable odd-even addressing */
|
|
|
|
outb(GDC_INDEX, GDC_MISC);
|
|
outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch vga-card to load a character set to plane 3
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
setchargen3(void)
|
|
{
|
|
chargen_access = 1; /* flag we are accessing the chargen ram */
|
|
|
|
/* program sequencer to access character generator */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x01); /* synchronous reset */
|
|
|
|
outb(TS_INDEX, TS_WRPLMASK);
|
|
outb(TS_DATA, 0x08); /* write to map 3 */
|
|
|
|
outb(TS_INDEX, TS_MEMMODE);
|
|
outb(TS_DATA, 0x07); /* sequential addressing */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x03); /* clear synchronous reset */
|
|
|
|
/* program graphics controller to access character generator */
|
|
|
|
outb(GDC_INDEX, GDC_RDPLANESEL);
|
|
outb(GDC_DATA, 0x03); /* select map 3 for cpu reads */
|
|
|
|
outb(GDC_INDEX, GDC_MODE);
|
|
outb(GDC_DATA, 0x00); /* disable odd-even addressing */
|
|
|
|
outb(GDC_INDEX, GDC_MISC);
|
|
outb(GDC_DATA, 0x00); /* map starts at 0xA000 */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch back vga-card to normal operation
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
resetchargen(void)
|
|
{
|
|
/* program sequencer to access video ram */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x01); /* synchronous reset */
|
|
|
|
outb(TS_INDEX, TS_WRPLMASK);
|
|
outb(TS_DATA, 0x03); /* write to map 0 & 1 */
|
|
|
|
outb(TS_INDEX, TS_MEMMODE);
|
|
outb(TS_DATA, 0x03); /* odd-even addressing */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x03); /* clear synchronous reset */
|
|
|
|
/* program graphics controller to access character generator */
|
|
|
|
outb(GDC_INDEX, GDC_RDPLANESEL);
|
|
outb(GDC_DATA, 0x00); /* select map 0 for cpu reads */
|
|
|
|
outb(GDC_INDEX, GDC_MODE);
|
|
outb(GDC_DATA, 0x10); /* enable odd-even addressing */
|
|
|
|
outb(GDC_INDEX, GDC_MISC);
|
|
if(color)
|
|
outb(GDC_DATA, 0x0e); /* map starts at 0xb800 */
|
|
else
|
|
outb(GDC_DATA, 0x0a); /* map starts at 0xb000 */
|
|
|
|
chargen_access = 0; /* flag we are NOT accessing the chargen ram */
|
|
}
|
|
|
|
#if PCVT_WAITRETRACE
|
|
/*---------------------------------------------------------------------------*
|
|
* wait for being in a retrace time window
|
|
* NOTE: this is __VERY__ bad programming practice in this environment !!
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
wait_retrace(void)
|
|
{
|
|
if(color)
|
|
{
|
|
while(!(inb(GN_INPSTAT1C) & 0x01))
|
|
;
|
|
}
|
|
else
|
|
{
|
|
while(!(inb(GN_INPSTAT1M) & 0x01))
|
|
;
|
|
}
|
|
}
|
|
|
|
#endif /* PCVT_WAITRETRACE */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch screen off (VGA only)
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vga_screen_off(void)
|
|
{
|
|
unsigned char old;
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x01); /* synchronous reset */
|
|
|
|
outb(TS_INDEX, TS_MODE); /* clocking mode reg */
|
|
old = inb(TS_DATA); /* get current value */
|
|
|
|
outb(TS_INDEX, TS_MODE); /* clocking mode reg */
|
|
outb(TS_DATA, (old | 0x20)); /* screen off bit on */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x03); /* clear synchronous reset */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch screen back on (VGA only)
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vga_screen_on(void)
|
|
{
|
|
unsigned char old;
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x01); /* synchronous reset */
|
|
|
|
outb(TS_INDEX, TS_MODE); /* clocking mode reg */
|
|
old = inb(TS_DATA); /* get current value */
|
|
|
|
outb(TS_INDEX, TS_MODE); /* clocking mode reg */
|
|
outb(TS_DATA, (old & ~0x20)); /* screen off bit off */
|
|
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x03); /* clear synchronous reset */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* compute character set base address (in kernel map)
|
|
*---------------------------------------------------------------------------*/
|
|
static unsigned char *
|
|
compute_charset_base(unsigned fontset)
|
|
{
|
|
unsigned char *d = (unsigned char *)Crtat;
|
|
|
|
static int charset_offset[8] = { 0x0000, 0x4000, 0x8000, 0xC000,
|
|
0x2000, 0x6000, 0xA000, 0xE000 };
|
|
|
|
static int charsetw_offset[8] = { 0x0000, 0x2000, 0x4000, 0x6000,
|
|
0x8000, 0xA000, 0xC000, 0xE000 };
|
|
|
|
switch(adaptor_type)
|
|
{
|
|
case EGA_ADAPTOR:
|
|
fontset = (fontset > 3) ? 3 : fontset;
|
|
break;
|
|
|
|
case VGA_ADAPTOR:
|
|
fontset = (fontset > 7) ? 7 : fontset;
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
if(color)
|
|
d -= (0xB8000 - 0xA0000); /* Point to 0xA0000 */
|
|
else
|
|
d -= (0xB0000 - 0xA0000); /* Point to 0xA0000 */
|
|
|
|
if(vsp->wd132col)
|
|
d += charsetw_offset[fontset]; /* Load into Character set n */
|
|
else
|
|
d += charset_offset[fontset]; /* Load into Character set n */
|
|
|
|
return d;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* load a char into ega/vga character generator ram
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
loadchar(int fontset, int character, int char_scanlines, u_char *char_table)
|
|
{
|
|
unsigned char *d;
|
|
|
|
#if PCVT_BACKUP_FONTS
|
|
unsigned char *bak;
|
|
#endif /* PCVT_BACKUP_FONTS */
|
|
|
|
int j, k;
|
|
|
|
if((d = compute_charset_base(fontset)) == 0)
|
|
return;
|
|
|
|
d += (character * 32); /* 32 bytes per character */
|
|
|
|
if(vsp->wd132col &&
|
|
(fontset == 1||fontset == 3||fontset == 5||fontset == 7))
|
|
setchargen3(); /* access chargen ram */
|
|
else
|
|
setchargen(); /* access chargen ram */
|
|
|
|
for(j = k = 0; j < char_scanlines; j++) /* x bit high characters */
|
|
{
|
|
*d = char_table[k];
|
|
d++;
|
|
k++;
|
|
}
|
|
for(; j < 32; j++) /* Up to 32 bytes per character image*/
|
|
{
|
|
*d = 0x00;
|
|
d++;
|
|
}
|
|
|
|
resetchargen(); /* access video ram */
|
|
|
|
#if PCVT_BACKUP_FONTS
|
|
if(saved_charsets[fontset] == 0)
|
|
saved_charsets[fontset] =
|
|
(u_char *)malloc(32 * 256, M_DEVBUF, M_WAITOK);
|
|
|
|
if((bak = saved_charsets[fontset]))
|
|
{
|
|
/* make a backup copy of this char */
|
|
bak += (character * 32);
|
|
bzero(bak, 32);
|
|
bcopy(char_table, bak, char_scanlines);
|
|
}
|
|
#ifdef DIAGNOSTIC
|
|
else
|
|
panic("pcvt loadchar: no backup buffer");
|
|
#endif /* DIAGNOSTIC */
|
|
|
|
#endif /* PCVT_BACKUP_FONTS */
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* save/restore character set n to addr b
|
|
*---------------------------------------------------------------------------*/
|
|
#if !PCVT_BACKUP_FONTS
|
|
|
|
void
|
|
vga_move_charset(unsigned n, unsigned char *b, int save_it)
|
|
{
|
|
unsigned char *d = compute_charset_base(n);
|
|
|
|
#ifdef DIAGNOSTIC
|
|
if(d == 0)
|
|
panic("vga_move_charset: wrong adaptor");
|
|
#endif
|
|
|
|
if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
|
|
{
|
|
setchargen3();
|
|
d -= 0x2000;
|
|
}
|
|
else
|
|
{
|
|
setchargen();
|
|
}
|
|
|
|
/* PLEASE, leave the following alone using bcopyb, as several */
|
|
/* chipsets have problems if their memory is accessed with 32 */
|
|
/* or 16 bits wide, don't change this to using bcopy for speed! */
|
|
|
|
if(save_it)
|
|
bcopyb(d, b, 256 /* chars */ * 32 /* bytes per char */);
|
|
else
|
|
bcopyb(b, d, 256 /* chars */ * 32 /* bytes per char */);
|
|
|
|
resetchargen();
|
|
}
|
|
|
|
#else /* PCVT_BACKUP_FONTS */
|
|
|
|
/* since there are always backed up copies, we do not save anything here */
|
|
/* parameter "b" is totally ignored */
|
|
|
|
void
|
|
vga_move_charset(unsigned n, unsigned char *b, int save_it)
|
|
{
|
|
unsigned char *d = compute_charset_base(n);
|
|
|
|
if(save_it)
|
|
return;
|
|
|
|
if(saved_charsets[n] == 0)
|
|
#ifdef DIAGNOSTIC
|
|
panic("pcvt: restoring unbuffered charset");
|
|
#else
|
|
return;
|
|
#endif
|
|
|
|
#ifdef DIAGNOSTIC
|
|
if(d == 0)
|
|
panic("vga_move_charset: wrong adaptor");
|
|
#endif
|
|
|
|
if(vsp->wd132col && (n == 1||n == 3||n == 5||n == 7))
|
|
{
|
|
setchargen3();
|
|
d -= 0x2000;
|
|
}
|
|
else
|
|
{
|
|
setchargen();
|
|
}
|
|
|
|
/* PLEASE, leave the following alone using bcopyb, as several */
|
|
/* chipsets have problems if their memory is accessed with 32 */
|
|
/* or 16 bits wide, don't change this to using bcopy for speed! */
|
|
|
|
bcopyb(saved_charsets[n], d,
|
|
256 /* chars */ * 32 /* bytes per char */);
|
|
|
|
resetchargen();
|
|
}
|
|
|
|
#endif /* PCVT_BACKUP_FONTS */
|
|
|
|
|
|
#if !PCVT_USL_VT_COMPAT
|
|
/*---------------------------------------------------------------------------*
|
|
* switch to virtual screen n (0 ... PCVT_NSCREENS-1)
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vgapage(int n)
|
|
{
|
|
|
|
#if !PCVT_KBD_FIFO
|
|
int x;
|
|
#endif /* !PCVT_KBD_FIFO */
|
|
|
|
int cols = vsp->maxcol; /* get current col val */
|
|
|
|
if(n < 0 || n >= totalscreens)
|
|
return;
|
|
|
|
#if !PCVT_KBD_FIFO
|
|
x = spltty(); /* protect us */
|
|
#endif /* !PCVT_KBD_FIFO */
|
|
|
|
/* video board memory -> kernel memory */
|
|
|
|
bcopy(vsp->Crtat, vsp->Memory, vsp->screen_rows * vsp->maxcol * CHR);
|
|
|
|
vsp->Crtat = vsp->Memory; /* operate in memory now */
|
|
|
|
/* update global screen pointers/variables */
|
|
|
|
current_video_screen = n; /* current screen no */
|
|
|
|
#if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
|
|
pcconsp = &pccons[n]; /* current tty */
|
|
#elif PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200
|
|
pcconsp = pccons[n]; /* current tty */
|
|
#else
|
|
pcconsp = pc_tty[n]; /* current tty */
|
|
#endif
|
|
|
|
vsp = &vs[n]; /* current video state ptr */
|
|
|
|
/* kernel memory -> video board memory */
|
|
|
|
bcopy(vsp->Crtat, Crtat, vsp->screen_rows * vsp->maxcol * CHR);
|
|
|
|
vsp->Crtat = Crtat; /* operate on screen now */
|
|
|
|
outb(addr_6845, CRTC_STARTADRH);
|
|
outb(addr_6845+1, 0);
|
|
outb(addr_6845, CRTC_STARTADRL);
|
|
outb(addr_6845+1, 0);
|
|
|
|
#if !PCVT_KBD_FIFO
|
|
splx(x);
|
|
#endif /* !PCVT_KBD_FIFO */
|
|
|
|
select_vga_charset(vsp->vga_charset);
|
|
|
|
if(vsp->maxcol != cols)
|
|
vga_col(vsp, vsp->maxcol); /* select 80/132 columns */
|
|
|
|
outb(addr_6845, CRTC_CURSORH); /* select high register */
|
|
outb(addr_6845+1, vsp->cur_offset >> 8);
|
|
outb(addr_6845, CRTC_CURSORL); /* select low register */
|
|
outb(addr_6845+1, vsp->cur_offset);
|
|
|
|
if(vsp->cursor_on)
|
|
{
|
|
outb(addr_6845, CRTC_CURSTART); /* select high register */
|
|
outb(addr_6845+1, vsp->cursor_start);
|
|
outb(addr_6845, CRTC_CUREND); /* select low register */
|
|
outb(addr_6845+1, vsp->cursor_end);
|
|
}
|
|
else
|
|
{
|
|
sw_cursor(0);
|
|
}
|
|
|
|
if(adaptor_type == VGA_ADAPTOR)
|
|
{
|
|
unsigned i;
|
|
|
|
/* switch VGA DAC palette entries */
|
|
|
|
for(i = 0; i < NVGAPEL; i++)
|
|
vgapaletteio(i, &vsp->palette[i], 1);
|
|
}
|
|
|
|
update_led(); /* update led's */
|
|
|
|
update_hp(vsp); /* update fkey labels, if present */
|
|
}
|
|
#endif /* !PCVT_USL_VT_COMPAT */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* test if it is a vga
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
int
|
|
vga_test(void)
|
|
{
|
|
u_char old, new, check;
|
|
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
old = inb(addr_6845+1); /* get current value */
|
|
|
|
new = old | CURSOR_ON_BIT; /* set cursor on by setting bit 5 on */
|
|
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
outb(addr_6845+1,new); /* cursor should be on now */
|
|
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
check = inb(addr_6845+1); /* get current value */
|
|
|
|
if(check != new)
|
|
{
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
outb(addr_6845+1,old); /* failsafe */
|
|
return(0); /* must be ega */
|
|
}
|
|
|
|
new = old & ~CURSOR_ON_BIT; /* turn cursor off by clearing bit 5 */
|
|
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
outb(addr_6845+1,new); /* cursor should be off now */
|
|
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
check = inb(addr_6845+1); /* get current value */
|
|
|
|
if(check != new)
|
|
{
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
outb(addr_6845+1,old); /* failsafe */
|
|
return(0); /* must be ega */
|
|
}
|
|
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
outb(addr_6845+1,old); /* failsafe */
|
|
|
|
return(1); /* vga */
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* convert upper/lower sixel font array to vga font array
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
sixel_vga(struct sixels *sixelp, u_char *vgachar)
|
|
{
|
|
register int i, j;
|
|
register int shift;
|
|
register u_char mask;
|
|
|
|
for(j = 0; j < 16; j++)
|
|
vgachar[j] = 0;
|
|
|
|
mask = 0x01;
|
|
for(j = 0; j < 6; j++)
|
|
{
|
|
for(i = 0, shift = 7; i < 8; i++, shift--)
|
|
vgachar[j] |= ((((sixelp->upper[i]) & mask) >> j)
|
|
<< shift);
|
|
mask <<= 1;
|
|
}
|
|
|
|
mask = 0x01;
|
|
for(j = 0; j < 4; j++)
|
|
{
|
|
for(i = 0, shift = 7; i < 8; i++, shift--)
|
|
vgachar[j+6] |= ((((sixelp->lower[i]) & mask) >>j)
|
|
<< shift);
|
|
mask <<= 1;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Expand 8x10 EGA/VGA characters to 8x16 EGA/VGA characters
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vga10_vga16(u_char *invga, u_char *outvga)
|
|
{
|
|
register int i,j;
|
|
|
|
/*
|
|
* Keep the top and bottom scanlines the same and double every scan
|
|
* line in between.
|
|
*/
|
|
|
|
outvga[0] = invga[0];
|
|
outvga[1] = invga[1];
|
|
outvga[14] = invga[8];
|
|
outvga[15] = invga[9];
|
|
|
|
for(i = j = 2;i < 8 && j < 14;i++,j += 2)
|
|
{
|
|
outvga[j] = invga[i];
|
|
outvga[j+1] = invga[i];
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Expand 8x10 EGA/VGA characters to 8x14 EGA/VGA characters
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vga10_vga14(u_char *invga, u_char *outvga)
|
|
{
|
|
register int i;
|
|
|
|
/*
|
|
* Double the top two and bottom two scanlines and copy everything
|
|
* in between.
|
|
*/
|
|
|
|
outvga[0] = invga[0];
|
|
outvga[1] = invga[0];
|
|
outvga[2] = invga[1];
|
|
outvga[3] = invga[1];
|
|
outvga[10] = invga[8];
|
|
outvga[11] = invga[8];
|
|
outvga[12] = invga[9];
|
|
outvga[13] = invga[9];
|
|
|
|
for(i = 2;i < 8;i++)
|
|
outvga[i+2] = invga[i];
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Expand 8x10 EGA/VGA characters to 8x10 EGA/VGA characters
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vga10_vga10(u_char *invga, u_char *outvga)
|
|
{
|
|
register int i;
|
|
|
|
for(i = 0;i < 10;i++)
|
|
outvga[i] = invga[i];
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* Contract 8x10 EGA/VGA characters to 8x8 EGA/VGA characters
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
vga10_vga8(u_char *invga, u_char *outvga)
|
|
{
|
|
/* Skip scanlines 3 and 7 */
|
|
|
|
outvga[0] = invga[0];
|
|
outvga[1] = invga[1];
|
|
outvga[2] = invga[2];
|
|
outvga[3] = invga[4];
|
|
outvga[4] = invga[5];
|
|
outvga[5] = invga[6];
|
|
outvga[6] = invga[8];
|
|
outvga[7] = invga[9];
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* force a vga card to behave like an ega for debugging
|
|
*---------------------------------------------------------------------------*/
|
|
#if FORCE_EGA
|
|
void
|
|
force_ega(void)
|
|
{
|
|
unsigned char vgareg;
|
|
|
|
if(adaptor_type == VGA_ADAPTOR)
|
|
{
|
|
adaptor_type = EGA_ADAPTOR;
|
|
totalfonts = 4;
|
|
vgareg = inb(GN_MISCOUTR); /* Miscellaneous Output Register */
|
|
vgareg |= 128; /* Set 350 scanline mode */
|
|
vgareg &= ~64;
|
|
outb(GN_MISCOUTW,vgareg);
|
|
}
|
|
}
|
|
#endif /* FORCE_EGA */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* disconnect attribute bit 3 from generating intensity
|
|
* (and use it for a second character set !)
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
set_2ndcharset(void)
|
|
{
|
|
if(color) /* prepare to access index register! */
|
|
inb(GN_INPSTAT1C);
|
|
else
|
|
inb(GN_INPSTAT1M);
|
|
|
|
/* select color plane enable reg, caution: set ATC access bit ! */
|
|
|
|
outb(ATC_INDEX, (ATC_COLPLEN | ATC_ACCESS));
|
|
outb(ATC_DATAW, 0x07); /* disable plane 3 */
|
|
}
|
|
|
|
#if PCVT_SCREENSAVER
|
|
#if PCVT_PRETTYSCRNS
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* produce some kinda random number, had a look into the system library...
|
|
*---------------------------------------------------------------------------*/
|
|
static u_short
|
|
getrand(void)
|
|
{
|
|
#if !PCVT_FREEBSD
|
|
extern struct timeval time; /* time-of-day register */
|
|
#endif
|
|
static unsigned long seed = 1;
|
|
register u_short res = (u_short)seed;
|
|
seed = seed * 1103515245L + time_second;
|
|
return res;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* produce "nice" screensaving ....
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
scrnsv_blink(void * arg)
|
|
{
|
|
static struct rgb blink_rgb[8] =
|
|
{
|
|
{63, 63, 63}, /* white */
|
|
{0, 63, 42}, /* pale green */
|
|
{63, 63, 0}, /* yellow */
|
|
{63, 21, 63}, /* violet */
|
|
{42, 63, 0}, /* yellow-green */
|
|
{63, 42, 0}, /* amber */
|
|
{63, 42, 42}, /* rose */
|
|
{21, 42, 42} /* cyan */
|
|
};
|
|
register u_short r = getrand();
|
|
unsigned pos = (r % (scrnsv_size / 2));
|
|
|
|
*scrnsv_current = /* (0 << 8) + */ ' ';
|
|
scrnsv_current = vsp->Crtat + pos;
|
|
*scrnsv_current = (7 /* LIGHTGRAY */ << 8) + '*';
|
|
if(adaptor_type == VGA_ADAPTOR)
|
|
vgapaletteio(7 /* LIGHTGRAY */, &blink_rgb[(r >> 4) & 7], 1);
|
|
scrnsv_blink_ch = timeout(scrnsv_blink, NULL, hz);
|
|
}
|
|
|
|
#endif /* PCVT_PRETTYSCRNS */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* set timeout time
|
|
*---------------------------------------------------------------------------*/
|
|
#ifndef XSERVER
|
|
static void
|
|
pcvt_set_scrnsv_tmo(int timeout)
|
|
#else
|
|
void
|
|
pcvt_set_scrnsv_tmo(int timeout)
|
|
#endif /* XSERVER */
|
|
{
|
|
int x = splhigh();
|
|
|
|
if(scrnsv_timeout)
|
|
untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
|
|
|
|
scrnsv_timeout = timeout;
|
|
pcvt_scrnsv_reset(); /* sanity */
|
|
splx(x);
|
|
if(timeout == 0 && savedscreen)
|
|
{
|
|
/* release buffer when screen saver turned off */
|
|
free(savedscreen, M_TEMP);
|
|
savedscreen = (u_short *)0;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* we were timed out
|
|
*---------------------------------------------------------------------------*/
|
|
static void
|
|
scrnsv_timedout(void *arg)
|
|
{
|
|
/* this function is called by timeout() */
|
|
/* raise priority to avoid conflicts with kbd intr */
|
|
int x = spltty();
|
|
|
|
/*
|
|
* due to some undefined problems with video adaptor RAM
|
|
* access timing, the following has been splitted into
|
|
* two pieces called subsequently with a time difference
|
|
* of 100 millisec
|
|
*/
|
|
|
|
if(++scrnsv_active == 1)
|
|
{
|
|
register size_t s;
|
|
/*
|
|
* first, allocate a buffer
|
|
* do only if none allocated yet or another size required
|
|
* this reduces malloc() overhead by avoiding successive
|
|
* calls to malloc() and free() if they would have requested
|
|
* the same buffer
|
|
*
|
|
* XXX This is inherited from old days where no buffering
|
|
* happened at all. Meanwhile we should use the standard
|
|
* screen buffer instead. Any volunteers? :-) [At least,
|
|
* this code proved to work...]
|
|
*/
|
|
|
|
s = sizeof(u_short) * vsp->screen_rowsize * vsp->maxcol;
|
|
|
|
if(savedscreen == (u_short *)0 || s != scrnsv_size)
|
|
{
|
|
/* really need to allocate */
|
|
if(savedscreen)
|
|
free(savedscreen, M_TEMP);
|
|
scrnsv_size = s;
|
|
if((savedscreen =
|
|
(u_short *)malloc(s, M_TEMP, M_NOWAIT))
|
|
== (u_short *)0)
|
|
{
|
|
/*
|
|
* didn't get the buffer memory,
|
|
* turn off screen saver
|
|
*/
|
|
scrnsv_timeout = scrnsv_active = 0;
|
|
splx(x);
|
|
return;
|
|
}
|
|
}
|
|
/* save current screen */
|
|
bcopy(vsp->Crtat, savedscreen, scrnsv_size);
|
|
|
|
/* on VGA's, make sure palette is set to blank screen */
|
|
if(adaptor_type == VGA_ADAPTOR)
|
|
{
|
|
struct rgb black = {0, 0, 0};
|
|
vgapaletteio(0 /* BLACK */, &black, 1);
|
|
}
|
|
/* prepare for next time... */
|
|
scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL, hz / 10);
|
|
}
|
|
else
|
|
{
|
|
/* second call, now blank the screen */
|
|
/* fill screen with blanks */
|
|
fillw(/* (BLACK<<8) + */ ' ', vsp->Crtat, scrnsv_size / 2);
|
|
|
|
#if PCVT_PRETTYSCRNS
|
|
scrnsv_current = vsp->Crtat;
|
|
scrnsv_blink_ch = timeout(scrnsv_blink, NULL, hz);
|
|
#endif /* PCVT_PRETTYSCRNS */
|
|
|
|
sw_cursor(0); /* cursor off on mda/cga */
|
|
}
|
|
splx(x);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* interface to screensaver "subsystem"
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
pcvt_scrnsv_reset(void)
|
|
{
|
|
/*
|
|
* to save lotta time with superfluous timeout()/untimeout() calls
|
|
* when having massive output operations, we remember the last
|
|
* second of kernel timer we've rescheduled scrnsv_timedout()
|
|
*/
|
|
static long last_schedule = 0L;
|
|
register int x = splhigh();
|
|
int reschedule = 0;
|
|
|
|
if((scrnsv_active == 1 || scrnsv_timeout) &&
|
|
last_schedule != time_second)
|
|
{
|
|
last_schedule = time_second;
|
|
reschedule = 1;
|
|
untimeout(scrnsv_timedout, NULL, scrnsv_timeout_ch);
|
|
}
|
|
if(scrnsv_active)
|
|
{
|
|
|
|
#if PCVT_PRETTYSCRNS
|
|
if(scrnsv_active > 1)
|
|
untimeout(scrnsv_blink, NULL, scrnsv_blink_ch);
|
|
#endif /* PCVT_PRETTYSCRNS */
|
|
|
|
bcopy(savedscreen, vsp->Crtat, scrnsv_size);
|
|
if(adaptor_type == VGA_ADAPTOR)
|
|
{
|
|
/* back up VGA palette info */
|
|
vgapaletteio(0 /* BLACK */, &vsp->palette[0], 1);
|
|
|
|
#if PCVT_PRETTYSCRNS
|
|
vgapaletteio(7 /* LIGHTGRAY */, &vsp->palette[7], 1);
|
|
#endif /* PCVT_PRETTYSCRNS */
|
|
|
|
}
|
|
scrnsv_active = 0;
|
|
|
|
if(vsp->cursor_on)
|
|
sw_cursor(1); /* cursor on */
|
|
}
|
|
|
|
if(reschedule)
|
|
{
|
|
/* mark next timeout */
|
|
scrnsv_timeout_ch = timeout(scrnsv_timedout, NULL,
|
|
scrnsv_timeout * hz);
|
|
}
|
|
splx(x);
|
|
}
|
|
|
|
#endif /* PCVT_SCREENSAVER */
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* switch cursor on/off
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
sw_cursor(int onoff)
|
|
{
|
|
if(adaptor_type == EGA_ADAPTOR)
|
|
{
|
|
int start, end;
|
|
if(onoff)
|
|
{
|
|
start = vsp->cursor_start;
|
|
end = vsp->cursor_end;
|
|
}
|
|
else
|
|
{
|
|
int cs = vs[current_video_screen].vga_charset;
|
|
|
|
cs = (cs < 0) ? 0 : ((cs < totalfonts) ?
|
|
cs : totalfonts-1);
|
|
|
|
start = (vgacs[cs].char_scanlines & 0x1F) + 1;
|
|
end = 0;
|
|
}
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
outb(addr_6845+1, start);
|
|
outb(addr_6845,CRTC_CUREND); /* cursor end reg */
|
|
outb(addr_6845+1, end);
|
|
}
|
|
else /* mda, cga, vga */
|
|
{
|
|
outb(addr_6845,CRTC_CURSTART); /* cursor start reg */
|
|
if(onoff)
|
|
outb(addr_6845+1, vsp->cursor_start);
|
|
else
|
|
outb(addr_6845+1, CURSOR_ON_BIT);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
* cold init support, if a mono monitor is attached to a
|
|
* vga or ega, it comes up with a mda emulation. switch
|
|
* board to generic ega/vga mode in this case.
|
|
*---------------------------------------------------------------------------*/
|
|
void
|
|
mda2egaorvga(void)
|
|
{
|
|
/*
|
|
* program sequencer to access
|
|
* video ram
|
|
*/
|
|
|
|
/* synchronous reset */
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x01);
|
|
|
|
/* write to map 0 & 1 */
|
|
outb(TS_INDEX, TS_WRPLMASK);
|
|
outb(TS_DATA, 0x03);
|
|
|
|
/* odd-even addressing */
|
|
outb(TS_INDEX, TS_MEMMODE);
|
|
outb(TS_DATA, 0x03);
|
|
|
|
/* clear synchronous reset */
|
|
outb(TS_INDEX, TS_SYNCRESET);
|
|
outb(TS_DATA, 0x03);
|
|
|
|
/*
|
|
* program graphics controller
|
|
* to access character
|
|
* generator
|
|
*/
|
|
|
|
/* select map 0 for cpu reads */
|
|
outb(GDC_INDEX, GDC_RDPLANESEL);
|
|
outb(GDC_DATA, 0x00);
|
|
|
|
/* enable odd-even addressing */
|
|
outb(GDC_INDEX, GDC_MODE);
|
|
outb(GDC_DATA, 0x10);
|
|
|
|
/* map starts at 0xb000 */
|
|
outb(GDC_INDEX, GDC_MISC);
|
|
outb(GDC_DATA, 0x0a);
|
|
}
|
|
|
|
#endif /* NVT > 0 */
|
|
|
|
/* ------------------------- E O F ------------------------------------------*/
|