summaryrefslogtreecommitdiff
path: root/hw/kdrive/vesa/vesa.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/kdrive/vesa/vesa.c')
-rw-r--r--hw/kdrive/vesa/vesa.c313
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;
+ }
+}