1825 lines
41 KiB
C
1825 lines
41 KiB
C
/*
|
|
Copyright (c) 2000 by Juliusz Chroboczek
|
|
|
|
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 THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
/* $Id: vesa.c,v 1.1.1.1 2006/11/26 18:22:04 matthieu Exp $ */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <kdrive-config.h>
|
|
#endif
|
|
#include "vesa.h"
|
|
#include "vga.h"
|
|
#include "vbe.h"
|
|
#ifdef RANDR
|
|
#include <randrstr.h>
|
|
#endif
|
|
|
|
int vesa_video_mode = 0;
|
|
Bool vesa_force_mode = FALSE;
|
|
Bool vesa_swap_rgb = FALSE;
|
|
Bool vesa_shadow = FALSE;
|
|
Bool vesa_linear_fb = TRUE;
|
|
Bool vesa_restore = FALSE;
|
|
Bool vesa_verbose = FALSE;
|
|
Bool vesa_force_text = FALSE;
|
|
Bool vesa_restore_font = TRUE;
|
|
Bool vesa_map_holes = TRUE;
|
|
Bool vesa_boot = FALSE;
|
|
|
|
#define VesaPriv(scr) ((VesaScreenPrivPtr) (scr)->driver)
|
|
|
|
#define vesaWidth(scr,vmib) ((vmib)->XResolution)
|
|
#define vesaHeight(scr,vmib) ((vmib)->YResolution)
|
|
|
|
static Bool
|
|
vesaComputeFramebufferMapping (KdScreenInfo *screen);
|
|
|
|
static Bool
|
|
vesaMapFramebuffer (KdScreenInfo *screen);
|
|
|
|
static Bool
|
|
vesaModeSupportable (VesaModePtr mode, Bool complain)
|
|
{
|
|
if((mode->ModeAttributes & 0x10) == 0) {
|
|
if(complain)
|
|
ErrorF("Text mode specified.\n");
|
|
return FALSE;
|
|
}
|
|
if(mode->MemoryModel != 0x06 && mode->MemoryModel != 0x04 && mode->MemoryModel != 0x03) {
|
|
if(complain)
|
|
ErrorF("Unsupported memory model 0x%X\n", mode->MemoryModel);
|
|
return FALSE;
|
|
}
|
|
if((mode->ModeAttributes & 0x80) == 0) {
|
|
if ((mode->ModeAttributes & 0x40) != 0) {
|
|
if(complain)
|
|
ErrorF("Neither linear nor windowed framebuffer available in this mode\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
if(!(mode->ModeAttributes & 1)) {
|
|
if(complain)
|
|
ErrorF("Mode not supported on this hardware\n");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
vesaModeSupported (VesaCardPrivPtr priv, VesaModePtr mode, Bool complain)
|
|
{
|
|
if (!priv->vbeInfo && mode->vbe) {
|
|
if (complain)
|
|
ErrorF("VBE bios mode not usable.\n");
|
|
return FALSE;
|
|
}
|
|
return vesaModeSupportable (mode, complain);
|
|
}
|
|
|
|
void
|
|
vesaReportMode (VesaModePtr mode)
|
|
{
|
|
int supported = (mode->ModeAttributes&MODE_SUPPORTED)?1:0;
|
|
int colour = (mode->ModeAttributes&MODE_COLOUR)?1:0;
|
|
int graphics = (mode->ModeAttributes&MODE_GRAPHICS)?1:0;
|
|
int vga_compatible = !((mode->ModeAttributes&MODE_VGA)?1:0);
|
|
int linear_fb = (mode->ModeAttributes&MODE_LINEAR)?1:0;
|
|
|
|
ErrorF("0x%04X: %dx%dx%d%s%s",
|
|
(unsigned)mode->mode,
|
|
(int)mode->XResolution, (int)mode->YResolution,
|
|
vesaDepth (mode),
|
|
colour?"":" (monochrome)",
|
|
graphics?"":" (graphics)",
|
|
vga_compatible?"":" (vga compatible)",
|
|
linear_fb?"":" (linear frame buffer)");
|
|
switch(mode->MemoryModel) {
|
|
case MEMORY_TEXT:
|
|
ErrorF(" text mode");
|
|
break;
|
|
case MEMORY_CGA:
|
|
ErrorF(" CGA graphics");
|
|
break;
|
|
case MEMORY_HERCULES:
|
|
ErrorF(" Hercules graphics");
|
|
break;
|
|
case MEMORY_PLANAR:
|
|
ErrorF(" Planar (%d planes)", mode->NumberOfPlanes);
|
|
break;
|
|
case MEMORY_PSEUDO:
|
|
ErrorF(" PseudoColor");
|
|
break;
|
|
case MEMORY_NONCHAIN:
|
|
ErrorF(" Non-chain 4, 256 colour");
|
|
break;
|
|
case MEMORY_DIRECT:
|
|
if(mode->DirectColorModeInfo & MODE_DIRECT)
|
|
ErrorF(" DirectColor");
|
|
else
|
|
ErrorF(" TrueColor");
|
|
ErrorF(" [%d:%d:%d:%d]",
|
|
mode->RedMaskSize, mode->GreenMaskSize, mode->BlueMaskSize,
|
|
mode->RsvdMaskSize);
|
|
if(mode->DirectColorModeInfo & 2)
|
|
ErrorF(" (reserved bits are reserved)");
|
|
break;
|
|
case MEMORY_YUV:
|
|
ErrorF("YUV");
|
|
break;
|
|
default:
|
|
ErrorF("unknown MemoryModel 0x%X ", mode->MemoryModel);
|
|
}
|
|
if(!supported)
|
|
ErrorF(" (unsupported)");
|
|
else if(!linear_fb)
|
|
ErrorF(" (no linear framebuffer)");
|
|
ErrorF("\n");
|
|
}
|
|
|
|
VesaModePtr
|
|
vesaGetModes (Vm86InfoPtr vi, int *ret_nmode)
|
|
{
|
|
VesaModePtr modes;
|
|
int nmode, nmodeVbe, nmodeVga;
|
|
int code;
|
|
|
|
code = VgaGetNmode (vi);
|
|
if (code <= 0)
|
|
nmodeVga = 0;
|
|
else
|
|
nmodeVga = code;
|
|
|
|
code = VbeGetNmode (vi);
|
|
if (code <= 0)
|
|
nmodeVbe = 0;
|
|
else
|
|
nmodeVbe = code;
|
|
|
|
nmode = nmodeVga + nmodeVbe;
|
|
if (nmode <= 0)
|
|
return 0;
|
|
|
|
modes = xalloc (nmode * sizeof (VesaModeRec));
|
|
|
|
memset (modes, '\0', nmode * sizeof (VesaModeRec));
|
|
|
|
if (nmodeVga)
|
|
{
|
|
code = VgaGetModes (vi, modes, nmodeVga);
|
|
if (code <= 0)
|
|
nmodeVga = 0;
|
|
else
|
|
nmodeVga = code;
|
|
}
|
|
|
|
if (nmodeVbe)
|
|
{
|
|
code = VbeGetModes (vi, modes + nmodeVga, nmodeVbe);
|
|
if (code <= 0)
|
|
nmodeVbe = 0;
|
|
else
|
|
nmodeVbe = code;
|
|
}
|
|
|
|
nmode = nmodeVga + nmodeVbe;
|
|
|
|
if (nmode == 0)
|
|
{
|
|
xfree (modes);
|
|
modes = 0;
|
|
return 0;
|
|
}
|
|
*ret_nmode = nmode;
|
|
return modes;
|
|
}
|
|
|
|
Bool
|
|
vesaInitialize (KdCardInfo *card, VesaCardPrivPtr priv)
|
|
{
|
|
priv->vi = Vm86Setup(vesa_map_holes);
|
|
if(!priv->vi)
|
|
goto fail;
|
|
|
|
if (vesa_boot)
|
|
VbeBoot (priv->vi);
|
|
|
|
priv->modes = vesaGetModes (priv->vi, &priv->nmode);
|
|
|
|
if (!priv->modes)
|
|
goto fail;
|
|
|
|
priv->vbeInfo = VbeInit (priv->vi);
|
|
|
|
card->driver = priv;
|
|
|
|
return TRUE;
|
|
|
|
fail:
|
|
if(priv->vi)
|
|
Vm86Cleanup(priv->vi);
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
vesaListModes (void)
|
|
{
|
|
Vm86InfoPtr vi;
|
|
VesaModePtr modes;
|
|
int nmode;
|
|
int n;
|
|
|
|
vi = Vm86Setup (vesa_map_holes);
|
|
if (!vi)
|
|
{
|
|
ErrorF ("Can't setup vm86\n");
|
|
}
|
|
else
|
|
{
|
|
modes = vesaGetModes (vi, &nmode);
|
|
if (!modes)
|
|
{
|
|
ErrorF ("No modes available\n");
|
|
}
|
|
else
|
|
{
|
|
VbeReportInfo (vi);
|
|
for (n = 0; n < nmode; n++)
|
|
{
|
|
if (vesa_force_mode || vesaModeSupportable (modes+n, 0))
|
|
vesaReportMode (modes+n);
|
|
}
|
|
xfree (modes);
|
|
}
|
|
Vm86Cleanup (vi);
|
|
}
|
|
}
|
|
|
|
void
|
|
vesaTestMode (void)
|
|
{
|
|
Vm86InfoPtr vi;
|
|
VesaModePtr modes;
|
|
VesaModePtr mode;
|
|
VbeInfoPtr vbeInfo;
|
|
int nmode;
|
|
int n;
|
|
|
|
vi = Vm86Setup (vesa_map_holes);
|
|
if (!vi)
|
|
{
|
|
ErrorF ("Can't setup vm86\n");
|
|
return;
|
|
}
|
|
modes = vesaGetModes (vi, &nmode);
|
|
if (!modes)
|
|
{
|
|
ErrorF ("No modes available\n");
|
|
return;
|
|
}
|
|
VbeReportInfo (vi);
|
|
vbeInfo = VbeInit (vi);
|
|
for (n = 0; n < nmode; n++)
|
|
{
|
|
if (modes[n].mode == vesa_video_mode)
|
|
break;
|
|
}
|
|
if (n == nmode)
|
|
{
|
|
ErrorF ("no mode specified\n");
|
|
return;
|
|
}
|
|
mode = &modes[n];
|
|
if (mode->vbe)
|
|
{
|
|
ErrorF ("Enable VBE mode 0x%x\n", mode->mode);
|
|
VbeSetMode(vi, vbeInfo, mode->mode, FALSE, FALSE);
|
|
}
|
|
else
|
|
{
|
|
ErrorF ("Enable BIOS mode 0x%x\n", mode->mode);
|
|
VgaSetMode (vi, mode->mode);
|
|
}
|
|
sleep (2);
|
|
ErrorF ("Restore BIOS mode 0x%x\n", 3);
|
|
VgaSetMode (vi, 3);
|
|
xfree (modes);
|
|
Vm86Cleanup (vi);
|
|
}
|
|
|
|
Bool
|
|
vesaCardInit(KdCardInfo *card)
|
|
{
|
|
VesaCardPrivPtr priv;
|
|
|
|
priv = xalloc(sizeof(VesaCardPrivRec));
|
|
if(!priv)
|
|
return FALSE;
|
|
|
|
if (!vesaInitialize (card, priv))
|
|
{
|
|
xfree(priv);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int
|
|
vesaDepth (VesaModePtr mode)
|
|
{
|
|
if (mode->MemoryModel == MEMORY_DIRECT)
|
|
return (mode->RedMaskSize +
|
|
mode->GreenMaskSize +
|
|
mode->BlueMaskSize);
|
|
else
|
|
return mode->BitsPerPixel;
|
|
}
|
|
|
|
Bool
|
|
vesaModeGood (KdScreenInfo *screen,
|
|
VesaModePtr a)
|
|
{
|
|
if (vesaWidth(screen,a) <= screen->width &&
|
|
vesaHeight(screen,a) <= screen->height &&
|
|
vesaDepth (a) >= screen->fb[0].depth)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
#define vabs(a) ((a) >= 0 ? (a) : -(a))
|
|
|
|
int
|
|
vesaSizeError (KdScreenInfo *screen,
|
|
VesaModePtr a)
|
|
{
|
|
int xdist, ydist;
|
|
xdist = vabs (screen->width - vesaWidth(screen,a));
|
|
ydist = vabs (screen->height - vesaHeight(screen,a));
|
|
return xdist * xdist + ydist * ydist;
|
|
}
|
|
|
|
Bool
|
|
vesaModeBetter (KdScreenInfo *screen,
|
|
VesaModePtr a,
|
|
VesaModePtr b)
|
|
{
|
|
int aerr, berr;
|
|
|
|
if (vesaModeGood (screen, a))
|
|
{
|
|
if (!vesaModeGood (screen, b))
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (vesaModeGood (screen, b))
|
|
return FALSE;
|
|
}
|
|
aerr = vesaSizeError (screen, a);
|
|
berr = vesaSizeError (screen, b);
|
|
if (aerr < berr)
|
|
return TRUE;
|
|
if (berr < aerr)
|
|
return FALSE;
|
|
if (vabs (screen->fb[0].depth - vesaDepth (a)) <
|
|
vabs (screen->fb[0].depth - vesaDepth (b)))
|
|
return TRUE;
|
|
if (a->BitsPerPixel == 32 && b->BitsPerPixel == 24)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
VesaModePtr
|
|
vesaSelectMode (KdScreenInfo *screen)
|
|
{
|
|
VesaCardPrivPtr priv = screen->card->driver;
|
|
int i, best;
|
|
|
|
if (vesa_video_mode)
|
|
{
|
|
for (best = 0; best < priv->nmode; best++)
|
|
if (priv->modes[best].mode == vesa_video_mode &&
|
|
(vesaModeSupported (priv, &priv->modes[best], FALSE) ||
|
|
vesa_force_mode))
|
|
return &priv->modes[best];
|
|
}
|
|
for (best = 0; best < priv->nmode; best++)
|
|
{
|
|
if (vesaModeSupported (priv, &priv->modes[best], FALSE))
|
|
break;
|
|
}
|
|
if (best == priv->nmode)
|
|
return 0;
|
|
for (i = best + 1; i < priv->nmode; i++)
|
|
if (vesaModeSupported (priv, &priv->modes[i], FALSE) &&
|
|
vesaModeBetter (screen, &priv->modes[i],
|
|
&priv->modes[best]))
|
|
best = i;
|
|
return &priv->modes[best];
|
|
}
|
|
|
|
Bool
|
|
vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr)
|
|
{
|
|
VesaModePtr mode;
|
|
|
|
screen->driver = pscr;
|
|
|
|
if (!screen->width || !screen->height)
|
|
{
|
|
screen->width = 640;
|
|
screen->height = 480;
|
|
}
|
|
if (!screen->fb[0].depth)
|
|
screen->fb[0].depth = 4;
|
|
|
|
if (vesa_verbose)
|
|
ErrorF ("Mode requested %dx%dx%d\n",
|
|
screen->width, screen->height, screen->fb[0].depth);
|
|
|
|
mode = vesaSelectMode (screen);
|
|
|
|
if (!mode)
|
|
{
|
|
if (vesa_verbose)
|
|
ErrorF ("No selectable mode\n");
|
|
return FALSE;
|
|
}
|
|
pscr->mode = *mode;
|
|
|
|
if (vesa_verbose)
|
|
{
|
|
ErrorF ("\t");
|
|
vesaReportMode (&pscr->mode);
|
|
}
|
|
|
|
pscr->randr = screen->randr;
|
|
pscr->shadow = vesa_shadow;
|
|
pscr->origDepth = screen->fb[0].depth;
|
|
/*
|
|
* Compute visual support for the selected depth
|
|
*/
|
|
|
|
switch (pscr->mode.MemoryModel) {
|
|
case MEMORY_DIRECT:
|
|
/* TrueColor or DirectColor */
|
|
screen->fb[0].visuals = (1 << TrueColor);
|
|
screen->fb[0].redMask =
|
|
FbStipMask(pscr->mode.RedFieldPosition, pscr->mode.RedMaskSize);
|
|
screen->fb[0].greenMask =
|
|
FbStipMask(pscr->mode.GreenFieldPosition, pscr->mode.GreenMaskSize);
|
|
screen->fb[0].blueMask =
|
|
FbStipMask(pscr->mode.BlueFieldPosition, pscr->mode.BlueMaskSize);
|
|
break;
|
|
case MEMORY_PSEUDO:
|
|
/* PseudoColor */
|
|
screen->fb[0].visuals = ((1 << StaticGray) |
|
|
(1 << GrayScale) |
|
|
(1 << StaticColor) |
|
|
(1 << PseudoColor) |
|
|
(1 << TrueColor) |
|
|
(1 << DirectColor));
|
|
screen->fb[0].blueMask = 0x00;
|
|
screen->fb[0].greenMask = 0x00;
|
|
screen->fb[0].redMask = 0x00;
|
|
break;
|
|
case MEMORY_PLANAR:
|
|
/* 4 plane planar */
|
|
if (pscr->mode.ModeAttributes & MODE_COLOUR)
|
|
screen->fb[0].visuals = (1 << StaticColor);
|
|
else
|
|
screen->fb[0].visuals = (1 << StaticGray);
|
|
screen->fb[0].blueMask = 0x00;
|
|
screen->fb[0].greenMask = 0x00;
|
|
screen->fb[0].redMask = 0x00;
|
|
break;
|
|
default:
|
|
ErrorF("Unsupported VESA MemoryModel 0x%02X\n",
|
|
pscr->mode.MemoryModel);
|
|
return FALSE;
|
|
}
|
|
screen->rate = 72;
|
|
|
|
if (!vesaComputeFramebufferMapping (screen))
|
|
return FALSE;
|
|
if (!vesaMapFramebuffer (screen))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
vesaScreenInit(KdScreenInfo *screen)
|
|
{
|
|
VesaScreenPrivPtr pscr;
|
|
|
|
pscr = xcalloc (1, sizeof (VesaScreenPrivRec));
|
|
if (!pscr)
|
|
return FALSE;
|
|
if (!vesaScreenInitialize (screen, pscr))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
void *
|
|
vesaSetWindowPlanar(ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
static int plane;
|
|
int winSize;
|
|
void *base;
|
|
|
|
plane = offset & 3;
|
|
VgaSetWritePlaneMask (priv->vi, (1 << plane));
|
|
offset = offset >> 2;
|
|
if (pscr->mode.vbe)
|
|
{
|
|
base = VbeSetWindow (priv->vi,
|
|
priv->vbeInfo,
|
|
pscr->mode.BytesPerScanLine * row + offset,
|
|
mode,
|
|
&winSize);
|
|
}
|
|
else
|
|
{
|
|
base = VgaSetWindow (priv->vi,
|
|
pscr->mode.mode,
|
|
pscr->mode.BytesPerScanLine * row + offset,
|
|
mode,
|
|
&winSize);
|
|
}
|
|
*size = (CARD32) winSize;
|
|
return base;
|
|
}
|
|
|
|
void *
|
|
vesaSetWindowLinear (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
|
|
*size = pscr->mode.BytesPerScanLine;
|
|
return (CARD8 *) pscr->fb + row * pscr->mode.BytesPerScanLine + offset;
|
|
}
|
|
|
|
void *
|
|
vesaSetWindowWindowed (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
int winSize;
|
|
void *base;
|
|
|
|
if (pscr->mode.vbe)
|
|
{
|
|
base = VbeSetWindow (priv->vi,
|
|
priv->vbeInfo,
|
|
pscr->mode.BytesPerScanLine * row + offset,
|
|
mode,
|
|
&winSize);
|
|
}
|
|
else
|
|
{
|
|
base = VgaSetWindow (priv->vi,
|
|
pscr->mode.mode,
|
|
pscr->mode.BytesPerScanLine * row + offset,
|
|
mode,
|
|
&winSize);
|
|
}
|
|
*size = (CARD32) winSize;
|
|
return base;
|
|
}
|
|
|
|
void *
|
|
vesaWindowPlanar (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size,
|
|
void *closure)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
|
|
if (!pScreenPriv->enabled)
|
|
return 0;
|
|
return vesaSetWindowPlanar (pScreen, row, offset, mode, size);
|
|
}
|
|
|
|
void *
|
|
vesaWindowLinear (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size,
|
|
void *closure)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
|
|
if (!pScreenPriv->enabled)
|
|
return 0;
|
|
return vesaSetWindowLinear (pScreen, row, offset, mode, size);
|
|
}
|
|
|
|
void *
|
|
vesaWindowWindowed (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size,
|
|
void *closure)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
|
|
if (!pScreenPriv->enabled)
|
|
return 0;
|
|
return vesaSetWindowWindowed (pScreen, row, offset, mode, size);
|
|
}
|
|
|
|
#define vesaInvertBits32(v) { \
|
|
v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \
|
|
v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \
|
|
v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \
|
|
}
|
|
|
|
void *
|
|
vesaWindowCga (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size,
|
|
void *closure)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
int line;
|
|
|
|
if (!pScreenPriv->enabled)
|
|
return 0;
|
|
*size = pscr->mode.BytesPerScanLine;
|
|
line = ((row & 1) << 13) + (row >> 1) * pscr->mode.BytesPerScanLine;
|
|
return (CARD8 *) pscr->fb + line + offset;
|
|
}
|
|
|
|
void
|
|
vesaUpdateMono (ScreenPtr pScreen,
|
|
shadowBufPtr pBuf)
|
|
{
|
|
RegionPtr damage = shadowDamage(pBuf);
|
|
PixmapPtr pShadow = pBuf->pPixmap;
|
|
int nbox = REGION_NUM_RECTS (damage);
|
|
BoxPtr pbox = REGION_RECTS (damage);
|
|
FbBits *shaBase, *shaLine, *sha;
|
|
FbStride shaStride;
|
|
int scrBase, scrLine, scr;
|
|
int shaBpp;
|
|
int shaXoff, shaYoff; /* XXX assumed to be zero */
|
|
int x, y, w, h, width;
|
|
int i;
|
|
FbBits *winBase = 0, *win;
|
|
CARD32 winSize;
|
|
FbBits bits;
|
|
|
|
fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff);
|
|
while (nbox--)
|
|
{
|
|
x = pbox->x1 * shaBpp;
|
|
y = pbox->y1;
|
|
w = (pbox->x2 - pbox->x1) * shaBpp;
|
|
h = pbox->y2 - pbox->y1;
|
|
|
|
scrLine = (x >> FB_SHIFT);
|
|
shaLine = shaBase + y * shaStride + (x >> FB_SHIFT);
|
|
|
|
x &= FB_MASK;
|
|
w = (w + x + FB_MASK) >> FB_SHIFT;
|
|
|
|
while (h--)
|
|
{
|
|
winSize = 0;
|
|
scrBase = 0;
|
|
width = w;
|
|
scr = scrLine;
|
|
sha = shaLine;
|
|
while (width) {
|
|
/* how much remains in this window */
|
|
i = scrBase + winSize - scr;
|
|
if (i <= 0 || scr < scrBase)
|
|
{
|
|
winBase = (FbBits *) (*pBuf->window) (pScreen,
|
|
y,
|
|
scr * sizeof (FbBits),
|
|
SHADOW_WINDOW_WRITE,
|
|
&winSize,
|
|
pBuf->closure);
|
|
if(!winBase)
|
|
return;
|
|
scrBase = scr;
|
|
winSize /= sizeof (FbBits);
|
|
i = winSize;
|
|
}
|
|
win = winBase + (scr - scrBase);
|
|
if (i > width)
|
|
i = width;
|
|
width -= i;
|
|
scr += i;
|
|
while (i--)
|
|
{
|
|
bits = *sha++;
|
|
vesaInvertBits32(bits);
|
|
*win++ = bits;
|
|
}
|
|
}
|
|
shaLine += shaStride;
|
|
y++;
|
|
}
|
|
pbox++;
|
|
}
|
|
}
|
|
|
|
static const CARD16 vga16Colors[16][3] = {
|
|
{ 0, 0, 0, }, /* 0 */
|
|
{ 0, 0, 0xAA,}, /* 1 */
|
|
{ 0, 0xAA,0, }, /* 2 */
|
|
{ 0, 0xAA,0xAA,}, /* 3 */
|
|
{ 0xAA,0, 0, }, /* 4 */
|
|
{ 0xAA,0, 0xAA,}, /* 5 */
|
|
{ 0xAA,0x55,0, }, /* 6 */
|
|
{ 0xAA,0xAA,0xAA,}, /* 7 */
|
|
{ 0x55,0x55,0x55,}, /* 8 */
|
|
{ 0x55,0x55,0xFF,}, /* 9 */
|
|
{ 0x55,0xFF,0x55,}, /* 10 */
|
|
{ 0x55,0xFF,0xFF,}, /* 11 */
|
|
{ 0xFF,0x55,0x55,}, /* 12 */
|
|
{ 0xFF,0x55,0xFF,}, /* 13 */
|
|
{ 0xFF,0xFF,0x55,}, /* 14 */
|
|
{ 0xFF,0xFF,0xFF,}, /* 15 */
|
|
};
|
|
|
|
Bool
|
|
vesaCreateColormap16 (ColormapPtr pmap)
|
|
{
|
|
int i, j;
|
|
|
|
if (pmap->pVisual->ColormapEntries == 16)
|
|
for (i = 0; i < pmap->pVisual->ColormapEntries; i++)
|
|
{
|
|
j = i & 0xf;
|
|
pmap->red[i].co.local.red = (vga16Colors[j][0]<<8)|vga16Colors[j][0];
|
|
pmap->red[i].co.local.green = (vga16Colors[j][1]<<8)|vga16Colors[j][1];
|
|
pmap->red[i].co.local.blue = (vga16Colors[j][2]<<8)|vga16Colors[j][2];
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
vesaSetScreenSizes (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
VesaScreenPrivPtr pscr = screen->driver;
|
|
|
|
if (pscr->randr & (RR_Rotate_0|RR_Rotate_180))
|
|
{
|
|
pScreen->width = pscr->mode.XResolution;
|
|
pScreen->height = pscr->mode.YResolution;
|
|
pScreen->mmWidth = screen->width_mm;
|
|
pScreen->mmHeight = screen->height_mm;
|
|
}
|
|
else
|
|
{
|
|
pScreen->width = pscr->mode.YResolution;
|
|
pScreen->height = pscr->mode.XResolution;
|
|
pScreen->mmWidth = screen->height_mm;
|
|
pScreen->mmHeight = screen->width_mm;
|
|
}
|
|
}
|
|
|
|
Bool
|
|
vesaSetShadow (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
ShadowUpdateProc update;
|
|
ShadowWindowProc window = 0;
|
|
|
|
if (pscr->randr != RR_Rotate_0)
|
|
update = shadowUpdateRotatePacked;
|
|
else
|
|
update = shadowUpdatePacked;
|
|
switch (pscr->mapping) {
|
|
case VESA_LINEAR:
|
|
window = vesaWindowLinear;
|
|
break;
|
|
case VESA_WINDOWED:
|
|
window = vesaWindowWindowed;
|
|
break;
|
|
case VESA_PLANAR:
|
|
if (pScreenPriv->screen->fb[0].bitsPerPixel == 8)
|
|
update = shadowUpdatePlanar4x8;
|
|
else
|
|
update = shadowUpdatePlanar4;
|
|
window = vesaWindowPlanar;
|
|
break;
|
|
case VESA_MONO:
|
|
update = vesaUpdateMono;
|
|
if (pscr->mode.mode < 8)
|
|
window = vesaWindowCga;
|
|
else
|
|
window = vesaWindowLinear;
|
|
break;
|
|
}
|
|
|
|
return KdShadowSet (pScreen, pscr->randr, update, window);
|
|
}
|
|
|
|
static Bool
|
|
vesaComputeFramebufferMapping (KdScreenInfo *screen)
|
|
{
|
|
VesaScreenPrivPtr pscr = screen->driver;
|
|
int depth, bpp, fbbpp;
|
|
Pixel allbits;
|
|
KdMouseMatrix m;
|
|
|
|
if (vesa_linear_fb)
|
|
{
|
|
pscr->mapping = VESA_LINEAR;
|
|
pscr->shadow = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pscr->mapping = VESA_WINDOWED;
|
|
pscr->shadow = TRUE;
|
|
}
|
|
|
|
depth = vesaDepth (&pscr->mode);
|
|
bpp = pscr->mode.BitsPerPixel;
|
|
|
|
if (bpp > 24)
|
|
bpp = 32;
|
|
else if (bpp > 16)
|
|
bpp = 24;
|
|
else if (bpp > 8)
|
|
bpp = 16;
|
|
else if (bpp > 4)
|
|
bpp = 8;
|
|
else if (bpp > 1)
|
|
bpp = 4;
|
|
else
|
|
bpp = 1;
|
|
fbbpp = bpp;
|
|
|
|
switch (pscr->mode.MemoryModel) {
|
|
case MEMORY_DIRECT:
|
|
allbits = (screen->fb[0].redMask |
|
|
screen->fb[0].greenMask |
|
|
screen->fb[0].blueMask);
|
|
depth = 32;
|
|
while (depth && !(allbits & (1 << (depth - 1))))
|
|
depth--;
|
|
if (vesa_verbose)
|
|
ErrorF ("\tTrue Color %d/%d red 0x%x green 0x%x blue 0x%x\n",
|
|
bpp, depth,
|
|
screen->fb[0].redMask,
|
|
screen->fb[0].greenMask,
|
|
screen->fb[0].blueMask);
|
|
break;
|
|
case MEMORY_PSEUDO:
|
|
if (vesa_verbose)
|
|
ErrorF ("\tPseudo Color bpp %d depth %d\n",
|
|
bpp, depth);
|
|
break;
|
|
case MEMORY_PLANAR:
|
|
if (bpp == 4)
|
|
{
|
|
bpp = screen->fb[0].bitsPerPixel;
|
|
if (bpp != 8)
|
|
bpp = 4;
|
|
depth = bpp;
|
|
}
|
|
if (bpp == 1)
|
|
{
|
|
pscr->mapping = VESA_MONO;
|
|
if (vesa_verbose)
|
|
ErrorF ("\tMonochrome\n");
|
|
}
|
|
else
|
|
{
|
|
pscr->mapping = VESA_PLANAR;
|
|
if (vesa_verbose)
|
|
ErrorF ("\tStatic color bpp %d depth %d\n",
|
|
bpp, depth);
|
|
}
|
|
pscr->randr = RR_Rotate_0;
|
|
pscr->shadow = TRUE;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
switch (fbbpp) {
|
|
case 8:
|
|
case 16:
|
|
case 32:
|
|
break;
|
|
default:
|
|
pscr->randr = RR_Rotate_0;
|
|
break;
|
|
}
|
|
|
|
if (pscr->randr != RR_Rotate_0)
|
|
pscr->shadow = TRUE;
|
|
|
|
if (vesa_shadow)
|
|
pscr->shadow = vesa_shadow;
|
|
|
|
if (pscr->mapping == VESA_LINEAR && !(pscr->mode.ModeAttributes & MODE_LINEAR))
|
|
{
|
|
pscr->mapping = VESA_WINDOWED;
|
|
pscr->shadow = TRUE;
|
|
}
|
|
KdComputeMouseMatrix (&m, pscr->randr,
|
|
pscr->mode.XResolution, pscr->mode.YResolution);
|
|
|
|
KdSetMouseMatrix (&m);
|
|
|
|
screen->width = pscr->mode.XResolution;
|
|
screen->height = pscr->mode.YResolution;
|
|
screen->fb[0].depth = depth;
|
|
screen->fb[0].bitsPerPixel = bpp;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
vesaMapFramebuffer (KdScreenInfo *screen)
|
|
{
|
|
VesaCardPrivPtr priv = screen->card->driver;
|
|
VesaScreenPrivPtr pscr = screen->driver;
|
|
|
|
if (pscr->mapped)
|
|
return TRUE;
|
|
switch (pscr->mapping) {
|
|
case VESA_MONO:
|
|
case VESA_LINEAR:
|
|
if (pscr->mode.vbe)
|
|
pscr->fb = VbeMapFramebuffer(priv->vi, priv->vbeInfo,
|
|
pscr->mode.mode,
|
|
&pscr->fb_size,
|
|
&pscr->fb_phys);
|
|
else
|
|
pscr->fb = VgaMapFramebuffer (priv->vi,
|
|
pscr->mode.mode,
|
|
&pscr->fb_size,
|
|
&pscr->fb_phys);
|
|
if (!pscr->fb)
|
|
return FALSE;
|
|
break;
|
|
case VESA_WINDOWED:
|
|
pscr->fb = NULL;
|
|
break;
|
|
case VESA_PLANAR:
|
|
pscr->fb = NULL;
|
|
break;
|
|
}
|
|
|
|
screen->memory_base = pscr->fb;
|
|
screen->memory_size = pscr->fb_size;
|
|
|
|
if (pscr->shadow)
|
|
{
|
|
if (!KdShadowFbAlloc (screen, 0,
|
|
pscr->randr & (RR_Rotate_90|RR_Rotate_270)))
|
|
return FALSE;
|
|
screen->off_screen_base = screen->memory_size;
|
|
}
|
|
else
|
|
{
|
|
screen->fb[0].frameBuffer = (CARD8 *) (pscr->fb);
|
|
screen->fb[0].byteStride = pscr->mode.BytesPerScanLine;
|
|
screen->fb[0].pixelStride = ((pscr->mode.BytesPerScanLine * 8) /
|
|
screen->fb[0].bitsPerPixel);
|
|
screen->off_screen_base = screen->fb[0].byteStride * screen->height;
|
|
}
|
|
pscr->mapped = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
vesaUnmapFramebuffer (KdScreenInfo *screen)
|
|
{
|
|
VesaCardPrivPtr priv = screen->card->driver;
|
|
VesaScreenPrivPtr pscr = screen->driver;
|
|
|
|
if (!pscr->mapped)
|
|
return;
|
|
|
|
pscr->mapped = FALSE;
|
|
KdShadowFbFree (screen, 0);
|
|
if (pscr->fb)
|
|
{
|
|
if (pscr->mode.vbe)
|
|
VbeUnmapFramebuffer(priv->vi, priv->vbeInfo, pscr->mode.mode, pscr->fb);
|
|
else
|
|
VgaUnmapFramebuffer (priv->vi);
|
|
pscr->fb = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef RANDR
|
|
Bool
|
|
vesaRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaModePtr modes, mode;
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
int nmode;
|
|
int n;
|
|
RRScreenSizePtr pSize;
|
|
|
|
*rotations = (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270|
|
|
RR_Reflect_X|RR_Reflect_Y);
|
|
/*
|
|
* Get mode information from BIOS -- every time in case
|
|
* something changes, like an external monitor is plugged in
|
|
*/
|
|
modes = vesaGetModes (priv->vi, &nmode);
|
|
if (!modes)
|
|
return FALSE;
|
|
if (priv->modes)
|
|
xfree (priv->modes);
|
|
priv->modes = modes;
|
|
priv->nmode = nmode;
|
|
for (n = 0; n < nmode; n++)
|
|
{
|
|
mode = &priv->modes[n];
|
|
if (vesaModeSupported (priv, mode, FALSE))
|
|
{
|
|
/*
|
|
* XXX limit reported modes to those matching the current
|
|
* format
|
|
*/
|
|
if (mode->NumberOfPlanes == pscr->mode.NumberOfPlanes &&
|
|
mode->BitsPerPixel == pscr->mode.BitsPerPixel &&
|
|
mode->MemoryModel == pscr->mode.MemoryModel &&
|
|
mode->RedMaskSize == pscr->mode.RedMaskSize &&
|
|
mode->RedFieldPosition == pscr->mode.RedFieldPosition &&
|
|
mode->GreenMaskSize == pscr->mode.GreenMaskSize &&
|
|
mode->GreenFieldPosition == pscr->mode.GreenFieldPosition &&
|
|
mode->BlueMaskSize == pscr->mode.BlueMaskSize &&
|
|
mode->BlueFieldPosition == pscr->mode.BlueFieldPosition)
|
|
{
|
|
int width, height, width_mm, height_mm;
|
|
if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
|
|
{
|
|
width = mode->XResolution;
|
|
height = mode->YResolution;
|
|
width_mm = screen->width_mm;
|
|
height_mm = screen->height_mm;
|
|
}
|
|
else
|
|
{
|
|
width = mode->YResolution;
|
|
height = mode->XResolution;
|
|
width_mm = screen->height_mm;
|
|
height_mm = screen->width_mm;
|
|
}
|
|
pSize = RRRegisterSize (pScreen,
|
|
width, height,
|
|
width_mm, height_mm);
|
|
if (mode->XResolution == screen->width &&
|
|
mode->YResolution == screen->height)
|
|
{
|
|
int randr = KdSubRotation (pscr->randr, screen->randr);
|
|
RRSetCurrentConfig (pScreen, randr, 0, pSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
vesaRandRSetConfig (ScreenPtr pScreen,
|
|
Rotation randr,
|
|
int rate,
|
|
RRScreenSizePtr pSize)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaModePtr mode = 0;
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
int n;
|
|
Bool wasEnabled = pScreenPriv->enabled;
|
|
Bool ret = FALSE;
|
|
VesaScreenPrivRec oldscr;
|
|
int oldwidth;
|
|
int oldheight;
|
|
int oldmmwidth;
|
|
int oldmmheight;
|
|
int newwidth, newheight;
|
|
|
|
if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
|
|
{
|
|
newwidth = pSize->width;
|
|
newheight = pSize->height;
|
|
}
|
|
else
|
|
{
|
|
newwidth = pSize->height;
|
|
newheight = pSize->width;
|
|
}
|
|
for (n = 0; n < priv->nmode; n++)
|
|
{
|
|
mode = &priv->modes[n];
|
|
if (vesaModeSupported (priv, mode, FALSE))
|
|
{
|
|
/*
|
|
* XXX all we have to match is the size
|
|
*/
|
|
if (mode->XResolution == newwidth &&
|
|
mode->YResolution == newheight &&
|
|
mode->NumberOfPlanes == pscr->mode.NumberOfPlanes &&
|
|
mode->BitsPerPixel == pscr->mode.BitsPerPixel &&
|
|
mode->RedMaskSize == pscr->mode.RedMaskSize &&
|
|
mode->RedFieldPosition == pscr->mode.RedFieldPosition &&
|
|
mode->GreenMaskSize == pscr->mode.GreenMaskSize &&
|
|
mode->GreenFieldPosition == pscr->mode.GreenFieldPosition &&
|
|
mode->BlueMaskSize == pscr->mode.BlueMaskSize &&
|
|
mode->BlueFieldPosition == pscr->mode.BlueFieldPosition)
|
|
break;
|
|
}
|
|
}
|
|
if (n == priv->nmode)
|
|
goto bail0;
|
|
|
|
if (wasEnabled)
|
|
KdDisableScreen (pScreen);
|
|
|
|
if (mode->mode != pscr->mode.mode)
|
|
{
|
|
ret = vesaSetMode (pScreen, mode);
|
|
if (!ret)
|
|
goto bail1;
|
|
}
|
|
|
|
oldscr = *pscr;
|
|
|
|
oldwidth = screen->width;
|
|
oldheight = screen->height;
|
|
oldmmwidth = pScreen->mmWidth;
|
|
oldmmheight = pScreen->mmHeight;
|
|
|
|
/*
|
|
* Set new configuration
|
|
*/
|
|
|
|
pscr->mode = *mode;
|
|
pscr->randr = KdAddRotation (screen->randr, randr);
|
|
|
|
/*
|
|
* Can't rotate some formats
|
|
*/
|
|
switch (screen->fb[0].bitsPerPixel) {
|
|
case 8:
|
|
case 16:
|
|
case 32:
|
|
break;
|
|
default:
|
|
if (pscr->randr)
|
|
goto bail2;
|
|
break;
|
|
}
|
|
|
|
KdOffscreenSwapOut (screen->pScreen);
|
|
|
|
vesaUnmapFramebuffer (screen);
|
|
|
|
if (!vesaComputeFramebufferMapping (screen))
|
|
goto bail3;
|
|
|
|
if (!vesaMapFramebuffer (screen))
|
|
goto bail3;
|
|
|
|
vesaSetScreenSizes (screen->pScreen);
|
|
|
|
if (!vesaSetShadow (screen->pScreen))
|
|
goto bail4;
|
|
|
|
/*
|
|
* Set frame buffer mapping
|
|
*/
|
|
(*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
|
|
pScreen->width,
|
|
pScreen->height,
|
|
screen->fb[0].depth,
|
|
screen->fb[0].bitsPerPixel,
|
|
screen->fb[0].byteStride,
|
|
screen->fb[0].frameBuffer);
|
|
|
|
/* set the subpixel order */
|
|
KdSetSubpixelOrder (pScreen, pscr->randr);
|
|
|
|
if (wasEnabled)
|
|
KdEnableScreen (pScreen);
|
|
|
|
return TRUE;
|
|
|
|
bail4:
|
|
vesaUnmapFramebuffer (screen);
|
|
*pscr = oldscr;
|
|
(void) vesaComputeFramebufferMapping (screen);
|
|
(void) vesaMapFramebuffer (screen);
|
|
|
|
bail3:
|
|
pScreen->width = oldwidth;
|
|
pScreen->height = oldheight;
|
|
pScreen->mmWidth = oldmmwidth;
|
|
pScreen->mmHeight = oldmmheight;
|
|
|
|
bail2:
|
|
*pscr = oldscr;
|
|
|
|
(void) vesaSetMode (pScreen, &pscr->mode);
|
|
bail1:
|
|
if (wasEnabled)
|
|
KdEnableScreen (pScreen);
|
|
bail0:
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
Bool
|
|
vesaRandRInit (ScreenPtr pScreen)
|
|
{
|
|
rrScrPrivPtr pScrPriv;
|
|
|
|
if (!RRScreenInit (pScreen))
|
|
return FALSE;
|
|
|
|
pScrPriv = rrGetScrPriv(pScreen);
|
|
pScrPriv->rrGetInfo = vesaRandRGetInfo;
|
|
pScrPriv->rrSetConfig = vesaRandRSetConfig;
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
Bool
|
|
vesaInitScreen(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
switch (pscr->mapping) {
|
|
case VESA_PLANAR:
|
|
pScreen->CreateColormap = vesaCreateColormap16;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
vesaFinishInitScreen (ScreenPtr pScreen)
|
|
{
|
|
if (!shadowSetup (pScreen))
|
|
return FALSE;
|
|
|
|
#ifdef RANDR
|
|
if (!vesaRandRInit (pScreen))
|
|
return FALSE;
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
vesaCreateResources (ScreenPtr pScreen)
|
|
{
|
|
return vesaSetShadow (pScreen);
|
|
}
|
|
|
|
Bool
|
|
vesaSetMode (ScreenPtr pScreen,
|
|
VesaModePtr mode)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
int code;
|
|
|
|
if (mode->vbe)
|
|
{
|
|
if (vesa_verbose)
|
|
ErrorF ("Enable VBE mode 0x%x\n", mode->mode);
|
|
code = VbeSetMode(priv->vi, priv->vbeInfo, mode->mode,
|
|
pscr->mapping == VESA_LINEAR,
|
|
mode->MemoryModel == MEMORY_DIRECT);
|
|
}
|
|
else
|
|
{
|
|
if (vesa_verbose)
|
|
ErrorF ("Enable BIOS mode 0x%x\n", mode->mode);
|
|
code = VgaSetMode (priv->vi, mode->mode);
|
|
}
|
|
|
|
if(code < 0)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
vesaEnable(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
int i;
|
|
CARD32 size;
|
|
char *p;
|
|
Bool was_mapped = pscr->mapped;
|
|
|
|
if (!vesaMapFramebuffer (screen))
|
|
return FALSE;
|
|
|
|
if (!vesaSetMode (pScreen, &pscr->mode))
|
|
return FALSE;
|
|
|
|
switch (pscr->mapping) {
|
|
case VESA_MONO:
|
|
VgaSetWritePlaneMask (priv->vi, 0x1);
|
|
case VESA_LINEAR:
|
|
if (vesa_restore_font)
|
|
memcpy (priv->text, pscr->fb, VESA_TEXT_SAVE);
|
|
break;
|
|
case VESA_WINDOWED:
|
|
if (vesa_restore_font)
|
|
{
|
|
for (i = 0; i < VESA_TEXT_SAVE;)
|
|
{
|
|
p = vesaSetWindowWindowed (pScreen, 0, i, VBE_WINDOW_READ, &size);
|
|
if(!p) {
|
|
ErrorF("Couldn't set window for saving VGA font\n");
|
|
break;
|
|
}
|
|
if(i + size > VESA_TEXT_SAVE)
|
|
size = VESA_TEXT_SAVE - i;
|
|
memcpy(((char*)priv->text) + i, p, size);
|
|
i += size;
|
|
}
|
|
}
|
|
break;
|
|
case VESA_PLANAR:
|
|
if (vesa_restore_font)
|
|
{
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
p = vesaSetWindowPlanar (pScreen, 0, i, VBE_WINDOW_READ, &size);
|
|
memcpy (((char *)priv->text) + i * (VESA_TEXT_SAVE/4), p,
|
|
(VESA_TEXT_SAVE/4));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (!was_mapped)
|
|
{
|
|
(*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
|
|
pScreen->width,
|
|
pScreen->height,
|
|
screen->fb[0].depth,
|
|
screen->fb[0].bitsPerPixel,
|
|
screen->fb[0].byteStride,
|
|
screen->fb[0].frameBuffer);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#ifndef TOSHIBA_SMM
|
|
|
|
# ifdef linux
|
|
# define TOSHIBA_SMM 1
|
|
# endif
|
|
|
|
# ifndef TOSHIBA_SMM
|
|
# define TOSHIBA_SMM 0
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if TOSHIBA_SMM
|
|
/*
|
|
* Toshiba laptops use a special interface to operate the backlight
|
|
*/
|
|
#include <sys/ioctl.h>
|
|
#define TOSH_PROC "/proc/toshiba"
|
|
#define TOSH_DEVICE "/dev/toshiba"
|
|
#define TOSH_SMM _IOWR('t', 0x90, SMMRegisters)
|
|
|
|
typedef struct {
|
|
unsigned int eax;
|
|
unsigned int ebx __attribute__ ((packed));
|
|
unsigned int ecx __attribute__ ((packed));
|
|
unsigned int edx __attribute__ ((packed));
|
|
unsigned int esi __attribute__ ((packed));
|
|
unsigned int edi __attribute__ ((packed));
|
|
} SMMRegisters;
|
|
|
|
#define HCI_BACKLIGHT 0x0002
|
|
#define HCI_DISABLE 0x0000
|
|
#define HCI_ENABLE 0x0001
|
|
#define HCI_GET 0xfe00,
|
|
#define HCI_SET 0xff00
|
|
|
|
Bool
|
|
toshibaDPMS (ScreenPtr pScreen, int mode)
|
|
{
|
|
SMMRegisters regs;
|
|
static int fd;
|
|
|
|
if (!fd)
|
|
fd = open (TOSH_DEVICE, 2);
|
|
if (fd < 0)
|
|
return FALSE;
|
|
regs.eax = HCI_SET;
|
|
regs.ebx = HCI_BACKLIGHT;
|
|
regs.ecx = mode ? HCI_DISABLE : HCI_ENABLE;
|
|
if (ioctl (fd, TOSH_SMM, ®s) < 0)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
#endif /* TOSHIBA_SMM */
|
|
|
|
Bool
|
|
vesaDPMS (ScreenPtr pScreen, int mode)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
|
|
#if TOSHIBA_SMM
|
|
if (toshibaDPMS (pScreen, mode))
|
|
return TRUE;
|
|
#endif
|
|
if (pscr->mode.vbe)
|
|
return VbeDPMS (priv->vi, mode);
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
vesaDisable(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
VesaScreenPrivPtr pscr = screen->driver;
|
|
int i=0;
|
|
CARD32 size;
|
|
char *p;
|
|
|
|
if (vesa_restore_font) {
|
|
switch (pscr->mapping) {
|
|
case VESA_LINEAR:
|
|
case VESA_MONO:
|
|
memcpy(pscr->fb, priv->text, VESA_TEXT_SAVE);
|
|
break;
|
|
case VESA_WINDOWED:
|
|
while(i < VESA_TEXT_SAVE) {
|
|
p = vesaSetWindowWindowed (pScreen, 0, i, VBE_WINDOW_WRITE, &size);
|
|
if(!p) {
|
|
ErrorF("Couldn't set window for restoring VGA font\n");
|
|
break;
|
|
}
|
|
if(i + size > VESA_TEXT_SAVE)
|
|
size = VESA_TEXT_SAVE - i;
|
|
memcpy(p, ((char*)priv->text) + i, size);
|
|
i += size;
|
|
}
|
|
break;
|
|
case VESA_PLANAR:
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
p = vesaSetWindowPlanar (pScreen, 0, i, VBE_WINDOW_WRITE, &size);
|
|
memcpy (p,
|
|
((char *)priv->text) + i * (VESA_TEXT_SAVE/4),
|
|
(VESA_TEXT_SAVE/4));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
vesaUnmapFramebuffer (screen);
|
|
}
|
|
|
|
void
|
|
vesaPreserve(KdCardInfo *card)
|
|
{
|
|
VesaCardPrivPtr priv = card->driver;
|
|
|
|
/* The framebuffer might not be valid at this point, so we cannot
|
|
save the VGA fonts now; we do it in vesaEnable. */
|
|
|
|
if (VbeGetMode (priv->vi, &priv->old_vbe_mode) < 0)
|
|
priv->old_vbe_mode = -1;
|
|
|
|
if (VgaGetMode (priv->vi, &priv->old_vga_mode) < 0)
|
|
priv->old_vga_mode = -1;
|
|
|
|
if (vesa_verbose)
|
|
ErrorF ("Previous modes: VBE 0x%x BIOS 0x%x\n",
|
|
priv->old_vbe_mode, priv->old_vga_mode);
|
|
}
|
|
|
|
void
|
|
vesaRestore(KdCardInfo *card)
|
|
{
|
|
VesaCardPrivPtr priv = card->driver;
|
|
int n;
|
|
|
|
if (vesa_force_text)
|
|
{
|
|
if (vesa_verbose)
|
|
ErrorF ("Forcing switch back to mode 3 text\n");
|
|
priv->old_vbe_mode = -1;
|
|
priv->old_vga_mode = 3;
|
|
}
|
|
for (n = 0; n < priv->nmode; n++)
|
|
if (priv->modes[n].vbe && priv->modes[n].mode == (priv->old_vbe_mode&0x3fff))
|
|
break;
|
|
|
|
if (n < priv->nmode)
|
|
{
|
|
if (vesa_verbose)
|
|
ErrorF ("Restore VBE mode 0x%x\n", priv->old_vbe_mode);
|
|
VbeSetMode (priv->vi, priv->vbeInfo, priv->old_vbe_mode, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
if (vesa_verbose)
|
|
ErrorF ("Restore BIOS mode 0x%x\n", priv->old_vga_mode);
|
|
VgaSetMode (priv->vi, priv->old_vga_mode);
|
|
}
|
|
}
|
|
|
|
void
|
|
vesaCardFini(KdCardInfo *card)
|
|
{
|
|
VesaCardPrivPtr priv = card->driver;
|
|
|
|
if (priv->vbeInfo)
|
|
VbeCleanup (priv->vi, priv->vbeInfo);
|
|
if (priv->modes)
|
|
xfree (priv->modes);
|
|
Vm86Cleanup(priv->vi);
|
|
}
|
|
|
|
void
|
|
vesaScreenFini(KdScreenInfo *screen)
|
|
{
|
|
VesaScreenPrivPtr pscr = screen->driver;
|
|
|
|
KdShadowFbFree (screen, 0);
|
|
vesaUnmapFramebuffer (screen);
|
|
screen->fb[0].depth = pscr->origDepth;
|
|
}
|
|
|
|
int
|
|
vesaSetPalette(VesaCardPrivPtr priv, int first, int number, U8 *entries)
|
|
{
|
|
if (priv->vga_palette)
|
|
return VgaSetPalette (priv->vi, first, number, entries);
|
|
else
|
|
return VbeSetPalette (priv->vi, priv->vbeInfo, first, number, entries);
|
|
}
|
|
|
|
|
|
int
|
|
vesaGetPalette(VesaCardPrivPtr priv, int first, int number, U8 *entries)
|
|
{
|
|
int code;
|
|
|
|
if (priv->vga_palette)
|
|
code = VgaGetPalette (priv->vi, first, number, entries);
|
|
else
|
|
{
|
|
code = VbeGetPalette (priv->vi, priv->vbeInfo, first, number, entries);
|
|
if (code < 0)
|
|
{
|
|
priv->vga_palette = 1;
|
|
code = VgaGetPalette (priv->vi, first, number, entries);
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
void
|
|
vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
int p;
|
|
CARD8 *scratch;
|
|
int red, green, blue;
|
|
int min, max;
|
|
|
|
if (vesa_swap_rgb)
|
|
{
|
|
red = 2;
|
|
green = 1;
|
|
blue = 0;
|
|
}
|
|
else
|
|
{
|
|
red = 0;
|
|
green = 1;
|
|
blue = 2;
|
|
}
|
|
|
|
min = 256;
|
|
max = 0;
|
|
while (n--)
|
|
{
|
|
p = pdefs->pixel;
|
|
if (p < min)
|
|
min = p;
|
|
if (p > max)
|
|
max = p;
|
|
scratch = priv->cmap + (p * 4);
|
|
scratch[red] = pdefs->red >> 8;
|
|
scratch[green] = pdefs->green >> 8;
|
|
scratch[blue] = pdefs->blue >> 8;
|
|
scratch[3] = 0;
|
|
pdefs++;
|
|
if (pscr->mapping == VESA_PLANAR)
|
|
{
|
|
/*
|
|
* VGA modes are strange; this code covers all
|
|
* possible modes by duplicating the color information
|
|
* however the attribute registers might be set
|
|
*/
|
|
if (p < 16)
|
|
{
|
|
vesaSetPalette (priv, p, 1, scratch);
|
|
if (p >= 8)
|
|
vesaSetPalette (priv, p+0x30, 1, scratch);
|
|
else if (p == 6)
|
|
vesaSetPalette (priv, 0x14, 1, scratch);
|
|
}
|
|
}
|
|
}
|
|
if (pscr->mapping != VESA_PLANAR)
|
|
vesaSetPalette (priv, min, max-min+1, priv->cmap + min * 4);
|
|
}
|
|
|
|
void
|
|
vesaGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
VesaScreenPrivPtr pscr = pScreenPriv->screen->driver;
|
|
VesaCardPrivPtr priv = pScreenPriv->card->driver;
|
|
int i;
|
|
int red, green, blue;
|
|
int min, max;
|
|
int p;
|
|
CARD8 *scratch;
|
|
|
|
if (vesa_swap_rgb)
|
|
{
|
|
red = 2;
|
|
green = 1;
|
|
blue = 0;
|
|
}
|
|
else
|
|
{
|
|
red = 0;
|
|
green = 1;
|
|
blue = 2;
|
|
}
|
|
|
|
min = 256;
|
|
max = 0;
|
|
for(i = 0; i < n; i++)
|
|
{
|
|
p = pdefs[i].pixel;
|
|
if (p < min)
|
|
min = p;
|
|
if (p > max)
|
|
max = p;
|
|
if (pscr->mapping == VESA_PLANAR)
|
|
vesaGetPalette (priv, p, 1, priv->cmap + p * 4);
|
|
}
|
|
if (pscr->mapping != VESA_PLANAR)
|
|
vesaGetPalette (priv, min, max - min + 1, priv->cmap + min * 4);
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
p = pdefs[i].pixel;
|
|
scratch = priv->cmap + p * 4;
|
|
pdefs[i].red = scratch[red]<<8;
|
|
pdefs[i].green = scratch[green]<<8;
|
|
pdefs[i].blue = scratch[blue]<<8;
|
|
}
|
|
}
|
|
|
|
void
|
|
vesaUseMsg (void)
|
|
{
|
|
ErrorF("\nTinyX VESA Usage:\n");
|
|
ErrorF("-mode VESA video mode to use (Be careful!)\n");
|
|
ErrorF("-listmodes List supported video modes\n");
|
|
ErrorF("-force Attempt even unsupported modes\n");
|
|
ErrorF("-shadow Always use shadow framebuffer (May increase performance)\n");
|
|
ErrorF("-nolinear Never use linear framebuffer (Not useful)\n");
|
|
ErrorF("-swaprgb Use if colors are wrong in PseudoColor and 16 color modes\n");
|
|
ErrorF("-map-holes Use contiguous memory map (For seg fault with rare BIOS)\n");
|
|
ErrorF("-verbose Emit diagnostic messages during BIOS initialization\n");
|
|
ErrorF("-force-text Always use standard 25x80 text mode on server exit or VT switch\n");
|
|
ErrorF("-boot Soft boot video card\n");
|
|
/* XXX: usage for -vesatest, -no-map-holes (don't need?),
|
|
* XXX: and -trash-font. Also in man page. */
|
|
}
|
|
|
|
int
|
|
vesaProcessArgument (int argc, char **argv, int i)
|
|
{
|
|
if(!strcmp(argv[i], "-mode")) {
|
|
if(i+1 < argc) {
|
|
vesa_video_mode = strtol(argv[i+1], NULL, 0);
|
|
} else
|
|
UseMsg();
|
|
return 2;
|
|
} else if(!strcmp(argv[i], "-force")) {
|
|
vesa_force_mode = TRUE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-listmodes")) {
|
|
vesaListModes();
|
|
exit(0);
|
|
} else if(!strcmp(argv[i], "-vesatest")) {
|
|
vesaTestMode();
|
|
exit (0);
|
|
} else if(!strcmp(argv[i], "-swaprgb")) {
|
|
vesa_swap_rgb = TRUE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-shadow")) {
|
|
vesa_shadow = TRUE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-nolinear")) {
|
|
vesa_linear_fb = FALSE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-verbose")) {
|
|
vesa_verbose = TRUE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-force-text")) {
|
|
vesa_force_text = TRUE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-map-holes")) {
|
|
vesa_map_holes = TRUE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-no-map-holes")) {
|
|
vesa_map_holes = FALSE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-trash-font")) {
|
|
vesa_restore_font = FALSE;
|
|
return 1;
|
|
} else if(!strcmp(argv[i], "-boot")) {
|
|
vesa_boot = TRUE;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|