diff options
Diffstat (limited to 'hw/kdrive/vesa/vesa.c')
-rw-r--r-- | hw/kdrive/vesa/vesa.c | 880 |
1 files changed, 590 insertions, 290 deletions
diff --git a/hw/kdrive/vesa/vesa.c b/hw/kdrive/vesa/vesa.c index fa5bfc62d..5f7f44237 100644 --- a/hw/kdrive/vesa/vesa.c +++ b/hw/kdrive/vesa/vesa.c @@ -30,6 +30,7 @@ Bool vesa_shadow = FALSE; Bool vesa_linear_fb = TRUE; Bool vesa_restore = FALSE; Bool vesa_rotate = FALSE; +Bool vesa_verbose = FALSE; #define VesaPriv(scr) ((VesaScreenPrivPtr) (scr)->driver) @@ -38,166 +39,216 @@ Bool vesa_rotate = FALSE; #define vesaHeight(scr,vmib) (ScreenRotated(scr) ? vmib->XResolution : vmib->YResolution) static Bool -vesaModeSupported(VbeInfoPtr vi, VbeModeInfoBlock *vmib, Bool complain) +vesaModeSupportable (VesaModePtr mode, Bool complain) { - if((vmib->ModeAttributes & 0x10) == 0) { - if(complain) - ErrorF("Text mode specified.\n"); - return FALSE; + if((mode->ModeAttributes & 0x10) == 0) { + if(complain) + ErrorF("Text mode specified.\n"); + return FALSE; } - if(vmib->MemoryModel != 0x06 && vmib->MemoryModel != 0x04 && vmib->MemoryModel != 0x03) { - if(complain) - ErrorF("Unsupported memory model 0x%X\n", vmib->MemoryModel); - 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((vmib->ModeAttributes & 0x80) == 0) { - if ((vmib->WinAAttributes & 0x5) != 0x5) { + 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(!(vmib->ModeAttributes & 1)) { - if(complain) - ErrorF("Mode not supported on this hardware\n"); - return FALSE; + if(!(mode->ModeAttributes & 1)) { + if(complain) + ErrorF("Mode not supported on this hardware\n"); + return FALSE; } return TRUE; } -Bool -vesaListModes() +static Bool +vesaModeSupported (VesaCardPrivPtr priv, VesaModePtr mode, Bool complain) { - int code; - VbeInfoPtr vi = NULL; - VbeInfoBlock *vib; - VbeModeInfoBlock *vmib; - unsigned p, num_modes, i; - CARD16 *modes_list = NULL; - - vi = VbeSetup(); - if(!vi) - goto fail; - - vib = VbeGetInfo(vi); - if(!vib) - goto fail; - - VbeReportInfo(vi, vib); - /* The spec says you need to copy the list */ - p = MAKE_POINTER_1(vib->VideoModePtr); - num_modes = 0; - while(VbeMemoryW(vi, p) != 0xFFFF) { - num_modes++; - p+=2; - } - modes_list = ALLOCATE_LOCAL(num_modes * sizeof(CARD16)); - if(!modes_list) - goto fail; - p = MAKE_POINTER_1(vib->VideoModePtr); - for(i=0; i<num_modes; i++) { - modes_list[i] = VbeMemoryW(vi, p); - p += 2; - } - - for(i=0; i<num_modes; i++) { - vmib = VbeGetModeInfo(vi, modes_list[i]); - if(!vmib) - goto fail; - if(vesa_force_mode || vesaModeSupported(vi, vmib, FALSE)) - VbeReportModeInfo(vi, modes_list[i], vmib); - } - - if(modes_list) - DEALLOCATE_LOCAL(modes_list); - VbeCleanup(vi); - return TRUE; - - fail: - if(modes_list) - DEALLOCATE_LOCAL(modes_list); - VbeCleanup(vi); - return FALSE; + if (!priv->vbeInfo && mode->vbe) { + if (complain) + ErrorF("VBE bios mode not usable.\n"); + return FALSE; + } + return vesaModeSupportable (mode, complain); } -Bool -vesaGetModes (KdCardInfo *card, VesaCardPrivPtr priv) +void +vesaReportMode (VesaModePtr mode) { - VesaModePtr mode; - int nmode; - unsigned int i; - VbeInfoPtr vi = priv->vi; - VbeInfoBlock *vib = priv->vib; - VbeModeInfoBlock *vmib; - - /* The spec says you need to copy the list */ - i = MAKE_POINTER_1(vib->VideoModePtr); - nmode = 0; - while(VbeMemoryW(vi, i) != 0xFFFF) { - nmode++; - i+=2; - } - if (!nmode) - return FALSE; - priv->modes = xalloc (nmode * sizeof (VesaModeRec)); - if (!priv->modes) - return FALSE; - priv->nmode = nmode; - i = MAKE_POINTER_1(vib->VideoModePtr); - nmode = 0; - while(nmode < priv->nmode) { - priv->modes[nmode].mode = VbeMemoryW(vi, i); - nmode++; - i+=2; - } - i = MAKE_POINTER_1(vib->VideoModePtr); - nmode = 0; - while(nmode < priv->nmode) { - vmib = VbeGetModeInfo(vi, priv->modes[nmode].mode); - if(!vmib) - break; - priv->modes[nmode].vmib = *vmib; - i += 2; - nmode++; + 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", + (unsigned)mode->mode, + (int)mode->XResolution, (int)mode->YResolution, + vesaDepth (mode), + colour?"":" (monochrome)"); + 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); } - return TRUE; + 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)); + + 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) { int code; - - priv->vi = VbeSetup(); - if(!priv->vi) - goto fail; - - priv->vib = VbeGetInfo(priv->vi); - if(!priv->vib) - goto fail; - code = VbeSetupStateBuffer(priv->vi); - if(code < 0) - goto fail; - - code = VbeSaveState(priv->vi); - if(code<0) - goto fail; + priv->vi = Vm86Setup(); + if(!priv->vi) + goto fail; - if (!vesaGetModes (card, priv)) + priv->modes = vesaGetModes (priv->vi, &priv->nmode); + + if (!priv->modes) goto fail; + + priv->vbeInfo = VbeInit (priv->vi); card->driver = priv; return TRUE; - fail: +fail: if(priv->vi) - VbeCleanup(priv->vi); + Vm86Cleanup(priv->vi); return FALSE; } +void +vesaListModes (void) +{ + Vm86InfoPtr vi; + VesaModePtr modes; + int nmode; + int n; + + vi = Vm86Setup (); + 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); + } +} + Bool vesaCardInit(KdCardInfo *card) { @@ -217,19 +268,19 @@ vesaCardInit(KdCardInfo *card) } int -vesaDepth (VbeModeInfoBlock *m) +vesaDepth (VesaModePtr mode) { - if (m->MemoryModel == 0x06) - return (m->RedMaskSize + - m->GreenMaskSize + - m->BlueMaskSize); + if (mode->MemoryModel == MEMORY_DIRECT) + return (mode->RedMaskSize + + mode->GreenMaskSize + + mode->BlueMaskSize); else - return m->BitsPerPixel; + return mode->BitsPerPixel; } Bool -vesaModeGood (KdScreenInfo *screen, - VbeModeInfoBlock *a) +vesaModeGood (KdScreenInfo *screen, + VesaModePtr a) { if (vesaWidth(screen,a) <= screen->width && vesaHeight(screen,a) <= screen->height && @@ -242,8 +293,8 @@ vesaModeGood (KdScreenInfo *screen, #define vabs(a) ((a) >= 0 ? (a) : -(a)) int -vesaSizeError (KdScreenInfo *screen, - VbeModeInfoBlock *a) +vesaSizeError (KdScreenInfo *screen, + VesaModePtr a) { int xdist, ydist; xdist = vabs (screen->width - vesaWidth(screen,a)); @@ -252,9 +303,9 @@ vesaSizeError (KdScreenInfo *screen, } Bool -vesaModeBetter (KdScreenInfo *screen, - VbeModeInfoBlock *a, - VbeModeInfoBlock *b) +vesaModeBetter (KdScreenInfo *screen, + VesaModePtr a, + VesaModePtr b) { int aerr, berr; @@ -290,21 +341,21 @@ vesaSelectMode (KdScreenInfo *screen) { for (best = 0; best < priv->nmode; best++) if (priv->modes[best].mode == vesa_video_mode && - (vesaModeSupported (priv->vi, &priv->modes[best].vmib, FALSE) || + (vesaModeSupported (priv, &priv->modes[best], FALSE) || vesa_force_mode)) return &priv->modes[best]; } for (best = 0; best < priv->nmode; best++) { - if (vesaModeSupported (priv->vi, &priv->modes[best].vmib, FALSE)) + 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->vi, &priv->modes[i].vmib, FALSE) && - vesaModeBetter (screen, &priv->modes[i].vmib, - &priv->modes[best].vmib)) + if (vesaModeSupported (priv, &priv->modes[i], FALSE) && + vesaModeBetter (screen, &priv->modes[i], + &priv->modes[best])) best = i; return &priv->modes[best]; } @@ -313,19 +364,43 @@ Bool vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr) { VesaCardPrivPtr priv = screen->card->driver; - VbeModeInfoBlock *vmib; + VesaModePtr mode; Pixel allbits; int depth; - int bpp; + int bpp, fbbpp; screen->driver = pscr; pscr->rotate = FALSE; if (screen->width < screen->height) pscr->rotate = TRUE; + + 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); + pscr->mode = vesaSelectMode (screen); + if (!pscr->mode) + { + if (vesa_verbose) + ErrorF ("No selectable mode\n"); return FALSE; + } + if (vesa_verbose) + { + ErrorF ("\t"); + vesaReportMode (pscr->mode); + } + pscr->shadow = vesa_shadow; pscr->origDepth = screen->fb[0].depth; if (vesa_linear_fb) @@ -333,21 +408,35 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr) else pscr->mapping = VESA_WINDOWED; - vmib = &pscr->mode->vmib; + mode = pscr->mode; - depth = vesaDepth (vmib); - bpp = vmib->BitsPerPixel; + depth = vesaDepth (mode); + bpp = mode->BitsPerPixel; - switch (vmib->MemoryModel) { - case 0x06: + 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 (mode->MemoryModel) { + case MEMORY_DIRECT: /* TrueColor or DirectColor */ screen->fb[0].visuals = (1 << TrueColor); screen->fb[0].redMask = - FbStipMask(vmib->RedFieldPosition, vmib->RedMaskSize); + FbStipMask(mode->RedFieldPosition, mode->RedMaskSize); screen->fb[0].greenMask = - FbStipMask(vmib->GreenFieldPosition, vmib->GreenMaskSize); + FbStipMask(mode->GreenFieldPosition, mode->GreenMaskSize); screen->fb[0].blueMask = - FbStipMask(vmib->BlueFieldPosition, vmib->BlueMaskSize); + FbStipMask(mode->BlueFieldPosition, mode->BlueMaskSize); allbits = screen->fb[0].redMask | screen->fb[0].greenMask | @@ -355,8 +444,14 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr) depth = 32; while (depth && !(allbits & (1 << (depth - 1)))) depth--; + if (vesa_verbose) + ErrorF ("\tTrue Color bpp %d depth %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 0x04: + case MEMORY_PSEUDO: /* PseudoColor */ screen->fb[0].visuals = ((1 << StaticGray) | (1 << GrayScale) | @@ -367,43 +462,73 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr) screen->fb[0].blueMask = 0x00; screen->fb[0].greenMask = 0x00; screen->fb[0].redMask = 0x00; + if (vesa_verbose) + ErrorF ("\tPseudo Color bpp %d depth %d\n", + bpp, depth); break; - case 0x03: + case MEMORY_PLANAR: /* 4 plane planar */ - screen->fb[0].visuals = (1 << StaticColor); + if (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; - bpp = screen->fb[0].bitsPerPixel; - if (bpp != 8) - bpp = 4; - depth = bpp; - pscr->mapping = VESA_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->rotate = FALSE; break; default: ErrorF("Unsupported VESA MemoryModel 0x%02X\n", - vmib->MemoryModel); + mode->MemoryModel); return FALSE; } - screen->width = vesaWidth(screen, vmib); - screen->height = vesaHeight(screen, vmib); + screen->width = vesaWidth(screen, mode); + screen->height = vesaHeight(screen, mode); screen->fb[0].depth = depth; screen->fb[0].bitsPerPixel = bpp; - screen->fb[0].byteStride = vmib->BytesPerScanLine; - screen->fb[0].pixelStride = ((vmib->BytesPerScanLine * 8) / - vmib->BitsPerPixel); + screen->fb[0].byteStride = mode->BytesPerScanLine; + screen->fb[0].pixelStride = ((mode->BytesPerScanLine * 8) / fbbpp); - if (pscr->mapping == VESA_LINEAR && !(vmib->ModeAttributes & 0x80)) + if (pscr->mapping == VESA_LINEAR && !(mode->ModeAttributes & MODE_LINEAR)) pscr->mapping = VESA_WINDOWED; if (pscr->rotate) pscr->shadow = TRUE; switch (pscr->mapping) { + case VESA_MONO: + pscr->shadow = TRUE; + /* fall through */ case VESA_LINEAR: - pscr->fb = VbeMapFramebuffer(priv->vi, vmib); + if (mode->vbe) + pscr->fb = VbeMapFramebuffer(priv->vi, priv->vbeInfo, + pscr->mode->mode, + &pscr->fb_size); + else + pscr->fb = VgaMapFramebuffer (priv->vi, + pscr->mode->mode, + &pscr->fb_size); break; case VESA_WINDOWED: pscr->fb = NULL; @@ -424,6 +549,10 @@ vesaScreenInitialize (KdScreenInfo *screen, VesaScreenPrivPtr pscr) if (pscr->shadow) return KdShadowScreenInit (screen); + if (vesa_verbose) + ErrorF ("Mode selected %dx%dx%d\n", + screen->width, screen->height, screen->fb[0].depth); + return TRUE; } @@ -441,7 +570,7 @@ vesaScreenInit(KdScreenInfo *screen) } void * -vesaWindowPlanar (ScreenPtr pScreen, +vesaSetWindowPlanar(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, @@ -450,25 +579,96 @@ vesaWindowPlanar (ScreenPtr pScreen, KdScreenPriv(pScreen); VesaCardPrivPtr priv = pScreenPriv->card->driver; VesaScreenPrivPtr pscr = pScreenPriv->screen->driver; - VbeModeInfoBlock *vmib = &pscr->mode->vmib; static int plane; int winSize; void *base; - if (!pScreenPriv->enabled) - return 0; plane = offset & 3; - VbeSetWritePlaneMask (priv->vi, (1 << plane)); + VgaSetWritePlaneMask (priv->vi, (1 << plane)); offset = offset >> 2; - base = VbeSetWindow (priv->vi, - vmib->BytesPerScanLine * row + offset, - mode, - &winSize); + 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); + VesaCardPrivPtr priv = pScreenPriv->card->driver; + 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) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->enabled) + return 0; + return vesaSetWindowPlanar (pScreen, row, offset, mode, size); +} + +void * vesaWindowLinear (ScreenPtr pScreen, CARD32 row, CARD32 offset, @@ -476,14 +676,10 @@ vesaWindowLinear (ScreenPtr pScreen, CARD32 *size) { KdScreenPriv(pScreen); - VesaCardPrivPtr priv = pScreenPriv->card->driver; - VesaScreenPrivPtr pscr = pScreenPriv->screen->driver; - VbeModeInfoBlock *vmib = &pscr->mode->vmib; if (!pScreenPriv->enabled) return 0; - *size = vmib->BytesPerScanLine; - return (CARD8 *) pscr->fb + row * vmib->BytesPerScanLine + offset; + return vesaSetWindowLinear (pScreen, row, offset, mode, size); } void * @@ -494,41 +690,114 @@ vesaWindowWindowed (ScreenPtr pScreen, CARD32 *size) { 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) +{ + KdScreenPriv(pScreen); VesaCardPrivPtr priv = pScreenPriv->card->driver; VesaScreenPrivPtr pscr = pScreenPriv->screen->driver; - VbeModeInfoBlock *vmib = &pscr->mode->vmib; - int winSize; - void *base; - + int line; + if (!pScreenPriv->enabled) return 0; - base = VbeSetWindow (priv->vi, - vmib->BytesPerScanLine * row + offset, - mode, - &winSize); - *size = (CARD32) winSize; - return base; + *size = pscr->mode->BytesPerScanLine; + line = ((row & 1) << 13) + (row >> 1) * pscr->mode->BytesPerScanLine; + return (CARD8 *) pscr->fb + line + offset; } -static CARD16 vga16Colors[16][3] = { -#if 0 - { 0, 0, 0, }, /* 0 */ - { 0, 0, 0x80,}, /* 1 */ - { 0, 0x80,0, }, /* 2 */ - { 0, 0x80,0x80,}, /* 3 */ - { 0x80,0, 0, }, /* 4 */ - { 0x80,0, 0x80,}, /* 5 */ - { 0x80,0x80,0, }, /* 6 */ - { 0xC0,0xC0,0xC0,}, /* 7 */ - { 0x80,0x80,0x80,}, /* 8 */ - { 0, 0, 0xFF,}, /* 9 */ - { 0, 0xFF,0 ,}, /* 10 */ - { 0, 0xFF,0xFF,}, /* 11 */ - { 0xFF,0, 0 ,}, /* 12 */ - { 0xFF,0, 0xFF,}, /* 13 */ - { 0xFF,0xFF,0 ,}, /* 14 */ - { 0xFF,0xFF,0xFF,}, /* 15 */ -#else +void +vesaUpdateMono (ScreenPtr pScreen, + PixmapPtr pShadow, + RegionPtr damage) +{ + shadowScrPriv(pScreen); + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + FbBits *shaBase, *shaLine, *sha; + FbBits s; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int x, y, w, h, width; + int i; + FbBits *winBase, *winLine, *win; + CARD32 winSize; + FbBits bits; + int plane; + + fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp); + 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 *) (*pScrPriv->window) (pScreen, + y, + scr * sizeof (FbBits), + SHADOW_WINDOW_WRITE, + &winSize); + 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 */ @@ -545,7 +814,6 @@ static CARD16 vga16Colors[16][3] = { { 0xFF,0x55,0xFF,}, /* 13 */ { 0xFF,0xFF,0x55,}, /* 14 */ { 0xFF,0xFF,0xFF,}, /* 15 */ -#endif }; Bool @@ -586,26 +854,20 @@ vesaInitScreen(ScreenPtr pScreen) case VESA_PLANAR: pScreen->CreateColormap = vesaCreateColormap16; if (pScreenPriv->screen->fb[0].bitsPerPixel == 8) - { -#if 0 - int i; - - for (i = 0; i < pScreen->numVisuals; i++) - { - if (pScreen->visuals[i].nplanes == - pScreenPriv->screen->fb[0].depth) - { - pScreen->visuals[i].ColormapEntries = 16; - } - } -#endif update = shadowUpdatePlanar4x8; - } else update = shadowUpdatePlanar4; window = vesaWindowPlanar; pscr->rotate = FALSE; break; + case VESA_MONO: + update = vesaUpdateMono; + if (pscr->mode->mode < 8) + window = vesaWindowCga; + else + window = vesaWindowLinear; + pscr->rotate = FALSE; + break; } if (pscr->rotate) { @@ -629,55 +891,41 @@ Bool vesaEnable(ScreenPtr pScreen) { KdScreenPriv(pScreen); - VesaCardPrivPtr priv = pScreenPriv->card->driver; + VesaCardPrivPtr priv = pScreenPriv->card->driver; VesaScreenPrivPtr pscr = pScreenPriv->screen->driver; - int code; - int palette_wait = 0, palette_hi = 0; - int i; - int size; - char *p; + int code; + int i; + CARD32 size; + char *p; KdMouseMatrix m; - code = VbeSetMode(priv->vi, pscr->mode->mode, pscr->mapping == VESA_LINEAR); - if(code < 0) - return FALSE; - + if (pscr->mode->vbe) { - int p; - CARD8 scratch[4] = {0x40,0x40,0x40,0}; - for (p = 0; p < 256; p++) - { - if (20 <= p && p < 21) - { - scratch[0] = 255; - scratch[1] = 255; - scratch[2] = 255; - } - else - { - scratch[0] = 0; - scratch[1] = 0; - scratch[2] = 0; - } - VbeSetPalette(priv->vi, p, 1, scratch); - } + if (vesa_verbose) + ErrorF ("Enable VBE mode 0x%x\n", pscr->mode->mode); + code = VbeSetMode(priv->vi, priv->vbeInfo, pscr->mode->mode, + pscr->mapping == VESA_LINEAR); + } + else + { + if (vesa_verbose) + ErrorF ("Enable BIOS mode 0x%x\n", pscr->mode->mode); + code = VgaSetMode (priv->vi, pscr->mode->mode); } - 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); - + if(code < 0) + return FALSE; + switch (pscr->mapping) { + case VESA_MONO: + VgaSetWritePlaneMask (priv->vi, 0x1); case VESA_LINEAR: memcpy (priv->text, pscr->fb, VESA_TEXT_SAVE); break; case VESA_WINDOWED: for (i = 0; i < VESA_TEXT_SAVE;) { - p = VbeSetWindow(priv->vi, i, VBE_WINDOW_READ, &size); + p = vesaSetWindowWindowed (pScreen, 0, i, VBE_WINDOW_READ, &size); if(!p) { ErrorF("Couldn't set window for saving VGA font\n"); break; @@ -689,10 +937,9 @@ vesaEnable(ScreenPtr pScreen) } break; case VESA_PLANAR: - p = VbeSetWindow (priv->vi, 0, VBE_WINDOW_READ, &size); for (i = 0; i < 4; i++) { - VbeSetReadPlaneMap (priv->vi, i); + p = vesaSetWindowPlanar (pScreen, 0, i, VBE_WINDOW_READ, &size); memcpy (((char *)priv->text) + i * (VESA_TEXT_SAVE/4), p, (VESA_TEXT_SAVE/4)); } @@ -716,19 +963,20 @@ void vesaDisable(ScreenPtr pScreen) { KdScreenPriv(pScreen); - VesaCardPrivPtr priv = pScreenPriv->card->driver; + VesaCardPrivPtr priv = pScreenPriv->card->driver; VesaScreenPrivPtr pscr = pScreenPriv->screen->driver; - int i=0; - int size; - char *p; + int i=0; + CARD32 size; + char *p; 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 = VbeSetWindow(priv->vi, i, VBE_WINDOW_WRITE, &size); + p = vesaSetWindowWindowed (pScreen, 0, i, VBE_WINDOW_WRITE, &size); if(!p) { ErrorF("Couldn't set window for restoring VGA font\n"); break; @@ -740,10 +988,9 @@ vesaDisable(ScreenPtr pScreen) } break; case VESA_PLANAR: - p = VbeSetWindow (priv->vi, 0, VBE_WINDOW_WRITE, &size); for (i = 0; i < 4; i++) { - VbeSetWritePlaneMask (priv->vi, 1 << i); + p = vesaSetWindowPlanar (pScreen, 0, i, VBE_WINDOW_WRITE, &size); memcpy (p, ((char *)priv->text) + i * (VESA_TEXT_SAVE/4), (VESA_TEXT_SAVE/4)); @@ -761,29 +1008,49 @@ vesaPreserve(KdCardInfo *card) /* The framebuffer might not be valid at this point, so we cannot save the VGA fonts now; we do it in vesaEnable. */ - code = VbeSaveState(priv->vi); - if(code < 0) - FatalError("Couldn't save state\n"); + if (VbeGetMode (priv->vi, &priv->old_vbe_mode) < 0) + priv->old_vbe_mode = -1; - return; + 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; - VbeRestoreState(priv->vi); - return; + int n; + + 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); + } + 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 (vesa_restore) - VbeSetTextMode(priv->vi,3); - VbeCleanup(priv->vi); - return; + + if (priv->vbeInfo) + VbeCleanup (priv->vi, priv->vbeInfo); + Vm86Cleanup(priv->vi); } void @@ -793,14 +1060,47 @@ vesaScreenFini(KdScreenInfo *screen) VesaCardPrivPtr priv = screen->card->driver; if (pscr->fb) - VbeUnmapFramebuffer(priv->vi, &pscr->mode->vmib, pscr->fb); + { + if (pscr->mode->vbe) + VbeUnmapFramebuffer(priv->vi, priv->vbeInfo, pscr->mode->mode, pscr->fb); + else + VgaUnmapFramebuffer (priv->vi); + } if (pscr->shadow) KdShadowScreenFini (screen); screen->fb[0].depth = pscr->origDepth; - return; } +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) { @@ -841,15 +1141,15 @@ vesaPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) */ if (p < 16) { - VbeSetPalette (priv->vi, p, 1, scratch); + vesaSetPalette (priv, p, 1, scratch); if (p >= 8) - VbeSetPalette (priv->vi, p+0x30, 1, scratch); + vesaSetPalette (priv, p+0x30, 1, scratch); else if (p == 6) - VbeSetPalette (priv->vi, 0x14, 1, scratch); + vesaSetPalette (priv, 0x14, 1, scratch); } } else - VbeSetPalette(priv->vi, p, 1, scratch); + vesaSetPalette(priv, p, 1, scratch); } } @@ -876,7 +1176,7 @@ vesaGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) } for(i = 0; i<n; i++) { - VbeGetPalette(priv->vi, pdefs[i].pixel, 1, scratch); + vesaGetPalette(priv, pdefs[i].pixel, 1, scratch); pdefs[i].red = scratch[red]<<8; pdefs[i].green = scratch[green]<<8; pdefs[i].blue = scratch[blue]<<8; @@ -907,8 +1207,8 @@ vesaProcessArgument (int argc, char **argv, int i) } else if(!strcmp(argv[i], "-nolinear")) { vesa_linear_fb = FALSE; return 1; - } else if(!strcmp(argv[i], "-restore")) { - vesa_restore = TRUE; + } else if(!strcmp(argv[i], "-verbose")) { + vesa_verbose = TRUE; return 1; } |