Let the OS instead of X save/restore text console fonts on Linux. So far we

relied on the generic VGA layer to restore text console fonts for us
    when shutting down the server or VT switching back to the text console.
    This has worked rather well but it has some downsides on Linux: a. Many
    people use fbdev as console text mode. In this case it is not necessary
    to save/restore console fonts as the console is running in graphics
    mode anyway. b. Some architectures don't have a fbdev console but
    require a full POST of even the primary card (ie. IA64). This posting
    has to take place before we even have a chance to save anything.
    Therefore the fonts we save are the once written to the chip by POST,
    not what has been programmed by the user. c. Certain chipsets utilize
    the BIOS to perform mode setting. This may interfer with the vga
    save/restore font function in a strange way. It would therefore be
    preferrable to let the OS - which has been used to set up the font in
    the first place - take care of saving/restoring the data. I will attach
    a patch which will do so for Linux. To make this fully functional a
    small patch needs to be applied to the Linux kernel. To disable this
    feature add: #define DoOSFontRestore NO to your host.def. (Bugzilla
    #2277)
This commit is contained in:
Egbert Eich 2005-01-14 18:42:26 +00:00
parent 6c0b03a236
commit 16f9d2d72a
6 changed files with 371 additions and 36 deletions

View File

@ -1,4 +1,4 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx.h,v 3.3 2002/11/25 14:05:04 eich Exp $ */
/* $XFree86: Exp $ */
#ifndef LNX_H_
# ifdef __alpha__
@ -39,6 +39,13 @@ extern long (*_iobase)(unsigned, int, int, int);
# endif
# endif /* __alpha__ */
# if defined(DO_OS_FONTRESTORE)
Bool lnx_savefont(void);
Bool lnx_restorefont(void);
Bool lnx_switchaway(void);
void lnx_freefontdata(void);
# endif
#define LNX_H_
#endif

View File

@ -0,0 +1,258 @@
/*
* Copyright 2004, Egbert Eich
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* EGBERT EICH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
* NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Egbert Eich shall not
* be used in advertising or otherwise to promote the sale, use or other deal-
*ings in this Software without prior written authorization from Egbert Eich.
*
*/
#include "X.h"
#include "Xmd.h"
#include "compiler.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "lnx.h"
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
struct {
int width;
int height;
int charcount;
unsigned char *data;
} lnxfont = { 0, 0, 0, NULL };
static Bool
getfont(int *width, int *height,
int *charcount, unsigned char *data)
{
struct console_font_op op;
struct consolefontdesc ds;
int result;
op.op = KD_FONT_OP_GET;
op.width = *width;
op.height = *height;
op.charcount = *charcount;
op.data = data;
op.flags = 0;
SYSCALL(result = ioctl(xf86Info.consoleFd, KDFONTOP, &op));
#ifdef DEBUG
ErrorF("Console font read: h: %i count: %i\n",op.height,op.charcount);
#endif
if (!result) {
*width = op.width;
*height = op.height;
*charcount = op.charcount;
return TRUE;
}
if (errno != ENOSYS && errno != EINVAL)
return FALSE;
/* GIO_FONTX fallback */
ds.charcount = *charcount;
ds.charheight = *height;
ds.chardata = (char *)data;
*width = 8;
SYSCALL(result = ioctl(xf86Info.consoleFd, GIO_FONTX, &ds));
if (!result) {
*charcount = ds.charcount;
*height = ds.charheight;
return TRUE;
}
if (errno != ENOSYS && errno != EINVAL)
return FALSE;
/* GIO_FONT fallback */
if (*charcount < 256)
return FALSE;
SYSCALL(result = ioctl(xf86Info.consoleFd, GIO_FONT, data));
if (!result) {
*height = 0;
*charcount = 512;
return TRUE;
}
return FALSE;
}
Bool
lnx_savefont(void)
{
unsigned char *fontdata;
int size;
int fd;
int width = 32, height = 32, charcount = 2048;
#ifdef DEBUG
ErrorF("SAVE font\n");
#endif
/* if we are in fbdev mode we don't bother saving fonts */
if ((fd = open ("/dev/fb0",O_RDWR)) != -1) {
close (fd);
return TRUE;
}
if (!getfont(&width, &height, &charcount, NULL)) {
xf86Msg(X_WARNING,
"lnx_savefont: cannot obtain font info\n");
goto error;
} else if (charcount == 2048) {
xf86Msg(X_WARNING, "lnx_savefont: "
"kernel bug: kernel doesn't report font info\n");
return FALSE;
}
size = (width + 7)/8 * 32 * charcount;
fontdata = (unsigned char *)xnfalloc(size);
if (!fontdata) {
xf86Msg(X_WARNING,
"lnx_savefont: cannot allocate memory to save font\n");
goto error;
}
if (!getfont(&width, &height, &charcount, fontdata)) {
xf86Msg(X_WARNING,"lnx_savefont: cannot read font data\n");
goto error;
}
lnxfont.width = width;
lnxfont.height = height;
lnxfont.charcount = charcount;
lnxfont.data = fontdata;
return TRUE;
error:
return FALSE;
}
static Bool
setfont(int width, int height,
int charcount, unsigned char *data)
{
struct console_font_op op;
struct consolefontdesc ds;
int result;
op.op = KD_FONT_OP_SET;
op.flags = 0;
op.charcount = charcount;
op.width = width;
op.height = height;
op.data = data;
SYSCALL(result = ioctl(xf86Info.consoleFd, KDFONTOP, &op));
if (!result)
return TRUE;
if (errno != ENOSYS && errno != EINVAL)
return FALSE;
/* PIO_FONTX fallback */
if (width != 8)
return FALSE;
ds.charcount = charcount;
ds.chardata = (char *)data;
ds.charheight = height;
SYSCALL(result = ioctl(xf86Info.consoleFd, PIO_FONTX, &ds));
if (!result)
return TRUE;
if (errno != ENOSYS && errno != EINVAL)
return FALSE;
/* PIO_FONT fallback */
SYSCALL(result = ioctl(xf86Info.consoleFd, PIO_FONT, data));
if (!result)
return TRUE;
return FALSE;
}
Bool
lnx_restorefont(void)
{
if (lnxfont.data == NULL)
return FALSE;
#ifdef DEBUG
ErrorF("RESTORE font\n");
#endif
#if 0
/* must wack the height to make the kernel reprogram the VGA registers */
if (!setfont(lnxfont.width, lnxfont.height + 1, lnxfont.charcount,
lnxfont.data)) {
xf86Msg(X_WARNING,"lnx_fontretore: cannot write font data\n");
return FALSE;
}
#endif
if (!setfont(lnxfont.width, lnxfont.height, lnxfont.charcount,
lnxfont.data)) {
xf86Msg(X_WARNING,"lnx_restorefont: cannot write font data\n");
return FALSE;
}
return TRUE;
}
Bool
lnx_switchaway(void)
{
Bool ret;
/* temporarily switch to text mode */
ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT);
ret = lnx_restorefont();
ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS);
return ret;
}
void
lnx_freefontdata(void)
{
if (lnxfont.data == NULL)
return;
xfree(lnxfont.data);
lnxfont.data = NULL;
lnxfont.width = lnxfont.height = lnxfont.charcount = 0;
}

View File

@ -1,3 +1,4 @@
/* $XdotOrg: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c,v 1.2 2004/04/23 19:54:08 eich Exp $ */
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_init.c,v 3.14 2001/10/31 22:50:30 tsi Exp $ */
/*
* Copyright 1992 by Orest Zborowski <obz@Kodak.com>
@ -35,6 +36,8 @@
#include "xf86_OSlib.h"
#include "lnx.h"
#include <sys/stat.h>
#ifdef USE_DEV_FB
extern char *getenv(const char *);
#include <linux/fb.h>
@ -45,13 +48,44 @@ static Bool KeepTty = FALSE;
static int VTnum = -1;
static int activeVT = -1;
static int vtPermSave[4];
static char vtname[11];
static int
saveVtPerms(void)
{
/* We need to use stat to get permissions. */
struct stat svtp;
/* Do them numerically ordered, hard coded tty0 first. */
if (stat("/dev/tty0", &svtp) != 0)
return 0;
vtPermSave[0] = (int)svtp.st_uid;
vtPermSave[1] = (int)svtp.st_gid;
/* Now check the console we are dealing with. */
if (stat(vtname, &svtp) != 0)
return 0;
vtPermSave[2] = (int)svtp.st_uid;
vtPermSave[3] = (int)svtp.st_gid;
return 1;
}
static void
restoreVtPerms(void)
{
/* Set the terminal permissions back to before we started. */
chown("/dev/tty0", vtPermSave[0], vtPermSave[1]);
chown(vtname, vtPermSave[2], vtPermSave[3]);
}
void
xf86OpenConsole(void)
{
int i, fd = -1;
int result;
struct vt_mode VT;
char vtname[11];
struct vt_stat vts;
MessageType from = X_PROBED;
#ifdef USE_DEV_FB
@ -124,6 +158,15 @@ xf86OpenConsole(void)
xf86Info.vtno, strerror(errno));
}
/*
* Grab the vt ownership before we overwrite it.
* Hard coded /dev/tty0 into this function as well for below.
*/
if (!saveVtPerms()){
xf86Msg(X_WARNING,
"xf86OpenConsole: Could not save ownership of VT\n");
}
/* change ownership of the vt */
chown(vtname, getuid(), getgid());
@ -170,6 +213,9 @@ xf86OpenConsole(void)
{
xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
}
#if defined(DO_OS_FONTRESTORE)
lnx_savefont();
#endif
SYSCALL(result = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
if (result < 0)
{
@ -227,17 +273,25 @@ void
xf86CloseConsole()
{
struct vt_mode VT;
#if defined(DO_OS_FONTRESTORE)
struct vt_stat vts;
int vtno = -1;
if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts) == 0)
vtno = vts.v_active;
#endif
#if 0
ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno);
ioctl(xf86Info.consoleFd, VT_WAITACTIVE, 0);
#endif
ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */
if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
{
VT.mode = VT_AUTO;
ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */
}
/*
* Perform a switch back to the active VT when we were started
*/
@ -246,7 +300,15 @@ xf86CloseConsole()
ioctl(xf86Info.consoleFd, VT_ACTIVATE, activeVT);
activeVT = -1;
}
#if defined(DO_OS_FONTRESTORE)
if (xf86Info.vtno == vtno)
lnx_restorefont();
lnx_freefontdata();
#endif
close(xf86Info.consoleFd); /* make the vt-manager happy */
restoreVtPerms(); /* restore the permissions */
return;
}

View File

@ -21,6 +21,9 @@
#include "xf86Xinput.h"
#include "xf86OSKbd.h"
#include "atKeynames.h"
#if defined(DO_OS_FONTRESTORE)
#include "lnx.h"
#endif
#include "lnx_kbd.h"
#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */

View File

@ -1,4 +1,4 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_usl.c,v 3.4 2002/09/16 18:06:14 eich Exp $ */
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/VTsw_usl.c,v 3.1.4.1 1998/06/05 16:23:21 dawes Exp $ */
/*
* Copyright 1993 by David Wexelblat <dwex@XFree86.org>
*
@ -29,6 +29,10 @@
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#ifdef OSHEADER
# include OSHEADER
#endif
/*
* Handle the VT-switching interface for OSs that use USL-style ioctl()s
* (the sysv, sco, and linux subdirs).
@ -62,6 +66,9 @@ xf86VTSwitchAway()
}
else
{
#ifdef OSSWITCHAWAY
OSSWITCHAWAY;
#endif
return(TRUE);
}
}

View File

@ -25,7 +25,7 @@
#include "xf86cmap.h"
#ifndef SAVE_FONT1
#define SAVE_FONT1
#define SAVE_FONT1 1
#endif
/*
@ -36,10 +36,10 @@
#define NEED_SAVED_CMAP
#endif
#ifndef SAVE_TEXT
#define SAVE_TEXT
#define SAVE_TEXT 1
#endif
#ifndef SAVE_FONT2
#define SAVE_FONT2
#define SAVE_FONT2 1
#endif
/* bytes per plane to save for text */
@ -51,11 +51,11 @@
#if 0
/* Override all of these for now */
#undef SAVE_FONT1
#define SAVE_FONT1
#define SAVE_FONT1 1
#undef SAVE_FONT2
#define SAVE_FONT2
#define SAVE_FONT2 1
#undef SAVE_TEST
#define SAVE_TEST
#define SAVE_TEST 1
#undef FONT_AMOUNT
#define FONT_AMOUNT 65536
#undef TEXT_AMOUNT
@ -720,13 +720,12 @@ vgaHWSeqReset(vgaHWPtr hwp, Bool start)
void
vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
{
#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
vgaHWPtr hwp = VGAHWPTR(scrninfp);
int savedIOBase;
unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
Bool doMap = FALSE;
#if defined(SAVE_TEXT) || defined(SAVE_FONT1) || defined(SAVE_FONT2)
/* If nothing to do, return now */
if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
return;
@ -782,7 +781,7 @@ vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
hwp->writeGr(hwp, 0x01, 0x00); /* all planes come from CPU */
}
#ifdef SAVE_FONT1
#if SAVE_FONT1
if (hwp->FontInfo1) {
hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */
@ -790,7 +789,7 @@ vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
}
#endif
#ifdef SAVE_FONT2
#if SAVE_FONT2
if (hwp->FontInfo2) {
hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */
@ -798,7 +797,7 @@ vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
}
#endif
#ifdef SAVE_TEXT
#if SAVE_TEXT
if (hwp->TextInfo) {
hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */
@ -828,7 +827,7 @@ vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
if (doMap)
vgaHWUnmapMem(scrninfp);
#endif /* defined(SAVE_TEXT) || defined(SAVE_FONT1) || defined(SAVE_FONT2) */
#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
}
@ -906,13 +905,12 @@ vgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags)
void
vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
{
#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
vgaHWPtr hwp = VGAHWPTR(scrninfp);
int savedIOBase;
unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
Bool doMap = FALSE;
#if defined(SAVE_TEXT) || defined(SAVE_FONT1) || defined(SAVE_FONT2)
if (hwp->Base == NULL) {
doMap = TRUE;
if (!vgaHWMapMem(scrninfp)) {
@ -961,21 +959,21 @@ vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */
hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */
#ifdef SAVE_FONT1
#if SAVE_FONT1
if (hwp->FontInfo1 || (hwp->FontInfo1 = xalloc(FONT_AMOUNT))) {
hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */
slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
}
#endif /* SAVE_FONT1 */
#ifdef SAVE_FONT2
#if SAVE_FONT2
if (hwp->FontInfo2 || (hwp->FontInfo2 = xalloc(FONT_AMOUNT))) {
hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */
slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
}
#endif /* SAVE_FONT2 */
#ifdef SAVE_TEXT
#if SAVE_TEXT
if (hwp->TextInfo || (hwp->TextInfo = xalloc(2 * TEXT_AMOUNT))) {
hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */
@ -1002,7 +1000,7 @@ vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
if (doMap)
vgaHWUnmapMem(scrninfp);
#endif /* defined(SAVE_TEXT) || defined(SAVE_FONT1) || defined(SAVE_FONT2) */
#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
}
void