diff options
Diffstat (limited to 'hw/kdrive/vesa/vesa.c')
-rw-r--r-- | hw/kdrive/vesa/vesa.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/hw/kdrive/vesa/vesa.c b/hw/kdrive/vesa/vesa.c new file mode 100644 index 000000000..cb72ea74d --- /dev/null +++ b/hw/kdrive/vesa/vesa.c @@ -0,0 +1,313 @@ +/* +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. +*/ +/* $XFree86$ */ + +#include "vesa.h" + +#define DEFAULT_MODE 0x115 + +int vesa_video_mode = DEFAULT_MODE; +Bool vesa_force_mode = FALSE; + +static Bool +vesaModeSupported(VbeInfoPtr vi, VbeModeInfoBlock *vmib, Bool complain) +{ + if((vmib->ModeAttributes & 0x10) == 0) { + if(complain) + ErrorF("Text mode specified.\n"); + return FALSE; + } + if(vmib->MemoryModel != 0x06 && vmib->MemoryModel != 0x04) { + if(complain) + ErrorF("Unsupported memory model 0x%X\n", vmib->MemoryModel); + return FALSE; + } + if((vmib->ModeAttributes & 0x80) == 0) { + if(complain) + ErrorF("No linear framebuffer available in this mode\n"); + return FALSE; + } + if(!(vmib->ModeAttributes&1)) { + if(complain) + ErrorF("Mode not supported on this hardware\n"); + return FALSE; + } + return TRUE; +} + +Bool +vesaListModes() +{ + int code; + VbeInfoPtr vi = NULL; + VbeInfoBlock *vib; + VbeModeInfoBlock *vmib; + unsigned i; + + vi = VbeSetup(); + if(!vi) + goto fail; + + vib = VbeGetInfo(vi); + if(!vib) + goto fail; + + VbeReportInfo(vi, vib); + i = MAKE_POINTER_1(vib->VideoModePtr); + + while(VbeMemoryW(vi, i) != 0xFFFF) { + vmib = VbeGetModeInfo(vi, VbeMemoryW(vi, i)); + if(!vmib) + goto fail; + if(vesa_force_mode || vesaModeSupported(vi, vmib, FALSE)) + VbeReportModeInfo(vi, VbeMemoryW(vi, i), vmib); + i+=2; + } + + VbeCleanup(vi); + return TRUE; + + fail: + VbeCleanup(vi); + return FALSE; +} + +Bool +vesaCardInit(KdCardInfo *card) +{ + VesaPrivPtr priv; + int code; + + priv = xalloc(sizeof(VesaPrivRec)); + if(!priv) + goto fail; + + priv->mode = vesa_video_mode; + + priv->vi = VbeSetup(); + if(!priv->vi) + goto fail; + + priv->vib = VbeGetInfo(priv->vi); + if(!priv->vib) + goto fail; + + priv->vmib = VbeGetModeInfo(priv->vi, priv->mode); + if(!priv->vmib) + goto fail; + + if(!vesa_force_mode && !vesaModeSupported(priv->vi, priv->vmib, TRUE)) + goto fail; + + code = VbeSetupStateBuffer(priv->vi); + if(code < 0) + goto fail; + + code = VbeSaveState(priv->vi); + if(code<0) + goto fail; + + priv->fb = VbeMapFramebuffer(priv->vi); + if(!priv->vi) + goto fail; + + card->driver = priv; + + return TRUE; + + fail: + if(priv) { + if(priv->vi) + VbeCleanup(priv->vi); + xfree(priv); + } + return FALSE; +} + +Bool +vesaScreenInit(KdScreenInfo *screen) +{ + VesaPrivPtr priv = screen->card->driver; + Pixel allbits; + int depth; + + screen->width = priv->vmib->XResolution; + screen->height = priv->vmib->YResolution; + screen->fb[0].depth = priv->vmib->BitsPerPixel; + screen->fb[0].bitsPerPixel = priv->vmib->BitsPerPixel; + screen->fb[0].byteStride = priv->vmib->BytesPerScanLine; + screen->fb[0].pixelStride = + (priv->vmib->BytesPerScanLine * 8) / priv->vmib->BitsPerPixel; + + if(priv->vmib->MemoryModel == 0x06) { + /* TrueColor or DirectColor */ + screen->fb[0].visuals = (1 << TrueColor); + screen->fb[0].redMask = + FbStipMask(priv->vmib->RedFieldPosition, priv->vmib->RedMaskSize); + screen->fb[0].greenMask = + FbStipMask(priv->vmib->GreenFieldPosition, priv->vmib->GreenMaskSize); + screen->fb[0].blueMask = + FbStipMask(priv->vmib->BlueFieldPosition, priv->vmib->BlueMaskSize); + allbits = + screen->fb[0].redMask | + screen->fb[0].greenMask | + screen->fb[0].blueMask; + depth = 32; + while (depth && !(allbits & (1 << (depth - 1)))) + depth--; + screen->fb[0].depth = depth; + } else if (priv->vmib->MemoryModel == 0x04) { + /* 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; + } else { + ErrorF("Unsupported VESA MemoryModel 0x%02X\n", + priv->vmib->MemoryModel); + return FALSE; + } + + screen->rate = 72; + screen->fb[0].frameBuffer = (CARD8 *)(priv->fb); + + return TRUE; +} + +Bool +vesaInitScreen(ScreenPtr pScreen) +{ + return TRUE; +} + +void +vesaEnable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + VesaPrivPtr priv = pScreenPriv->card->driver; + int code; + int palette_wait = 0, palette_hi = 0; + + code = VbeSetMode(priv->vi, priv->mode); + if(code < 0) + FatalError("Couldn't set mode\n"); + + if(priv->vib->Capabilities[0] & 1) + palette_hi = 1; + if(priv->vib->Capabilities[0] & 4) + palette_wait = 1; + if(palette_hi || palette_wait) + VbeSetPaletteOptions(priv->vi, palette_hi?8:6, palette_wait); + + return; +} + +void +vesaDisable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + VesaPrivPtr priv = pScreenPriv->card->driver; + +} + +void +vesaPreserve(KdCardInfo *card) +{ + VesaPrivPtr priv = card->driver; + int code; + + code = VbeSaveState(priv->vi); + if(code < 0) + FatalError("Couldn't save state\n"); + + return; +} + +void +vesaRestore(KdCardInfo *card) +{ + VesaPrivPtr priv = card->driver; + VbeRestoreState(priv->vi); + return; +} + +void +vesaCardFini(KdCardInfo *card) +{ + VesaPrivPtr priv = card->driver; + VbeUnmapFramebuffer(priv->vi); + VbeCleanup(priv->vi); + return; +} + +void +vesaScreenFini(KdScreenInfo *screen) +{ + return; +} + +void +vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + VesaPrivPtr priv = pScreenPriv->card->driver; + int i, j, k; + CARD8 scratch[4*256]; + + i = 0; + while(i < n) { + j = i + 1; + /* For some reason, doing more than one entry at a time breaks */ + while(j < n && pdefs[j].pixel == pdefs[j-1].pixel + 1 && j - i < 1) + j++; + for(k=0; k<(j - i); k++) { + /* The opposite of what the spec says? */ + scratch[k+3] = 0; + scratch[k+2] = pdefs[i+k].red >> 8; + scratch[k+1] = pdefs[i+k].green >> 8; + scratch[k+0] = pdefs[i+k].blue >> 8; + } + VbeSetPalette(priv->vi, pdefs[i].pixel, j - i, scratch); + i = j; + } +} + +void +vesaGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + VesaPrivPtr priv = pScreenPriv->card->driver; + int first, i, j, k; + CARD8 scratch[4]; + + for(i = 0; i<n; i++) { + VbeGetPalette(priv->vi, pdefs[i].pixel, 1, scratch); + pdefs[i].red = scratch[2]<<8; + pdefs[i].green = scratch[1]<<8; + pdefs[i].blue = scratch[0]<<8; + } +} |