From f74555e94264e6f703d399a5e0475c7283e20a88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Oct 2003 06:36:26 +0000 Subject: [PATCH] Add xfixes, fix smi driver to use either fbdev or vesa. Add hole mapping to vesa server by default --- hw/kdrive/Makefile.am | 3 +- hw/kdrive/fbdev/Makefile.am | 6 +- hw/kdrive/mach64/Makefile.am | 2 + hw/kdrive/mga/Makefile.am | 2 + hw/kdrive/nvidia/Makefile.am | 49 ++ hw/kdrive/nvidia/fourcc.h | 134 +++++ hw/kdrive/nvidia/nvidia.c | 367 ++++++++++++ hw/kdrive/nvidia/nvidia.h | 250 ++++++++ hw/kdrive/nvidia/nvidiacurs.c | 392 ++++++++++++ hw/kdrive/nvidia/nvidiadraw.c | 243 ++++++++ hw/kdrive/nvidia/nvidiadraw.h | 72 +++ hw/kdrive/nvidia/nvidiastub.c | 59 ++ hw/kdrive/nvidia/nvidiavideo.c | 1018 ++++++++++++++++++++++++++++++++ hw/kdrive/vesa/Makefile.am | 2 + hw/kdrive/vesa/Xvesa.man | 21 +- hw/kdrive/vesa/vesa.c | 13 +- hw/kdrive/vesa/vm86.c | 57 +- hw/kdrive/vesa/vm86.h | 9 +- 18 files changed, 2677 insertions(+), 22 deletions(-) create mode 100644 hw/kdrive/nvidia/Makefile.am create mode 100644 hw/kdrive/nvidia/fourcc.h create mode 100644 hw/kdrive/nvidia/nvidia.c create mode 100644 hw/kdrive/nvidia/nvidia.h create mode 100644 hw/kdrive/nvidia/nvidiacurs.c create mode 100644 hw/kdrive/nvidia/nvidiadraw.c create mode 100644 hw/kdrive/nvidia/nvidiadraw.h create mode 100644 hw/kdrive/nvidia/nvidiastub.c create mode 100644 hw/kdrive/nvidia/nvidiavideo.c diff --git a/hw/kdrive/Makefile.am b/hw/kdrive/Makefile.am index 877a6ca34..f3e73470c 100644 --- a/hw/kdrive/Makefile.am +++ b/hw/kdrive/Makefile.am @@ -1,9 +1,10 @@ if KDRIVEVESA -VESA_SUBDIRS = vesa mach64 mga smi +VESA_SUBDIRS = vesa mach64 mga nvidia endif SUBDIRS = \ src \ linux \ fbdev \ + smi \ $(VESA_SUBDIRS) diff --git a/hw/kdrive/fbdev/Makefile.am b/hw/kdrive/fbdev/Makefile.am index fc4ab67f6..a9dda001c 100644 --- a/hw/kdrive/fbdev/Makefile.am +++ b/hw/kdrive/fbdev/Makefile.am @@ -8,10 +8,10 @@ INCLUDES = \ -I$(top_srcdir)/render \ $(XSERVER_CFLAGS) -bin_PROGRAMS = Xfbdev - noinst_LIBRARIES = libfbdev.a +bin_PROGRAMS = Xfbdev + libfbdev_a_SOURCES = \ fbdev.c @@ -28,11 +28,13 @@ Xfbdev_LDADD = \ $(top_builddir)/miext/shadow/libshadow.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/fb/libfb.a \ $(top_builddir)/mi/libmi.a \ $(top_builddir)/Xext/libXext.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/dix/libxpstubs.a \ $(XSERVER_LIBS) \ -lm -lz diff --git a/hw/kdrive/mach64/Makefile.am b/hw/kdrive/mach64/Makefile.am index cfc377762..7ccd748ae 100644 --- a/hw/kdrive/mach64/Makefile.am +++ b/hw/kdrive/mach64/Makefile.am @@ -36,11 +36,13 @@ Xmach64_LDADD = \ $(top_builddir)/miext/shadow/libshadow.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/fb/libfb.a \ $(top_builddir)/mi/libmi.a \ $(top_builddir)/Xext/libXext.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/dix/libxpstubs.a \ $(XSERVER_LIBS) \ -lm -lz diff --git a/hw/kdrive/mga/Makefile.am b/hw/kdrive/mga/Makefile.am index 2e6403660..d7a908e5a 100644 --- a/hw/kdrive/mga/Makefile.am +++ b/hw/kdrive/mga/Makefile.am @@ -33,11 +33,13 @@ Xmga_LDADD = \ $(top_builddir)/miext/shadow/libshadow.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/fb/libfb.a \ $(top_builddir)/mi/libmi.a \ $(top_builddir)/Xext/libXext.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/dix/libxpstubs.a \ $(XSERVER_LIBS) \ -lm -lz diff --git a/hw/kdrive/nvidia/Makefile.am b/hw/kdrive/nvidia/Makefile.am new file mode 100644 index 000000000..4ecdab0de --- /dev/null +++ b/hw/kdrive/nvidia/Makefile.am @@ -0,0 +1,49 @@ +INCLUDES = \ + -I$(top_srcdir)/fb \ + -I$(top_srcdir)/hw/kdrive/src \ + -I$(top_srcdir)/hw/kdrive/vesa \ + -I$(top_srcdir)/mi \ + -I$(top_srcdir)/miext/layer \ + -I$(top_srcdir)/miext/shadow \ + -I$(top_srcdir)/randr \ + -I$(top_srcdir)/render \ + $(XSERVER_CFLAGS) + +bin_PROGRAMS = Xnvidia + +noinst_LIBRARIES = libnvidia.a + +# nvidiavideo.c + +libnvidia_a_SOURCES = \ + nvidia.c \ + nvidiadraw.c \ + fourcc.h \ + nvidia.h \ + nvidiadraw.h + + +Xnvidia_SOURCES = \ + nvidiastub.c + +Xnvidia_LDADD = \ + $(top_builddir)/hw/kdrive/nvidia/libnvidia.a \ + $(top_builddir)/hw/kdrive/vesa/libvesa.a \ + $(top_builddir)/dix/libdix.a \ + $(top_builddir)/os/libos.a \ + $(top_builddir)/miext/layer/liblayer.a \ + $(top_builddir)/hw/kdrive/src/libkdrive.a \ + $(top_builddir)/hw/kdrive/linux/liblinux.a \ + $(top_builddir)/miext/shadow/libshadow.a \ + $(top_builddir)/randr/librandr.a \ + $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ + $(top_builddir)/fb/libfb.a \ + $(top_builddir)/mi/libmi.a \ + $(top_builddir)/Xext/libXext.a \ + $(top_builddir)/randr/librandr.a \ + $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ + $(top_builddir)/dix/libxpstubs.a \ + $(XSERVER_LIBS) \ + -lm -lz diff --git a/hw/kdrive/nvidia/fourcc.h b/hw/kdrive/nvidia/fourcc.h new file mode 100644 index 000000000..b19f5decc --- /dev/null +++ b/hw/kdrive/nvidia/fourcc.h @@ -0,0 +1,134 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/fourcc.h,v 1.4 2003/04/23 21:51:24 tsi Exp $ */ + +/* + This header file contains listings of STANDARD guids for video formats. + Please do not place non-registered, or incomplete entries in this file. + A list of some popular fourcc's are at: http://www.webartz.com/fourcc/ + For an explanation of fourcc <-> guid mappings see RFC2361. +*/ + +#ifndef _XF86_FOURCC_H_ +#define _XF86_FOURCC_H_ 1 + +#define FOURCC_YUY2 0x32595559 +#define XVIMAGE_YUY2 \ + { \ + FOURCC_YUY2, \ + XvYUV, \ + LSBFirst, \ + {'Y','U','Y','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 1, 1, \ + {'Y','U','Y','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_YV12 0x32315659 +#define XVIMAGE_YV12 \ + { \ + FOURCC_YV12, \ + XvYUV, \ + LSBFirst, \ + {'Y','V','1','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 3, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','V','U', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_I420 0x30323449 +#define XVIMAGE_I420 \ + { \ + FOURCC_I420, \ + XvYUV, \ + LSBFirst, \ + {'I','4','2','0', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 3, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','U','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + + +#define FOURCC_UYVY 0x59565955 +#define XVIMAGE_UYVY \ + { \ + FOURCC_UYVY, \ + XvYUV, \ + LSBFirst, \ + {'U','Y','V','Y', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 1, 1, \ + {'U','Y','V','Y', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_IA44 0x34344149 +#define XVIMAGE_IA44 \ + { \ + FOURCC_IA44, \ + XvYUV, \ + LSBFirst, \ + {'I','A','4','4', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 8, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 1, 1, \ + 1, 1, 1, \ + {'A','I', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_AI44 0x34344941 +#define XVIMAGE_AI44 \ + { \ + FOURCC_AI44, \ + XvYUV, \ + LSBFirst, \ + {'A','I','4','4', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 8, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 1, 1, \ + 1, 1, 1, \ + {'I','A', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#endif /* _XF86_FOURCC_H_ */ diff --git a/hw/kdrive/nvidia/nvidia.c b/hw/kdrive/nvidia/nvidia.c new file mode 100644 index 000000000..c74daf7a0 --- /dev/null +++ b/hw/kdrive/nvidia/nvidia.c @@ -0,0 +1,367 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "nvidia.h" +#include + +Bool +nvidiaCardInit (KdCardInfo *card) +{ + NvidiaCardInfo *nvidiac; + + nvidiac = (NvidiaCardInfo *) xalloc (sizeof (NvidiaCardInfo)); + if (!nvidiac) + return FALSE; + + (void) nvidiaMapReg (card, nvidiac); + + if (!vesaInitialize (card, &nvidiac->vesa)) + { + xfree (nvidiac); + return FALSE; + } + + card->driver = nvidiac; + + return TRUE; +} + +Bool +nvidiaScreenInit (KdScreenInfo *screen) +{ + NvidiaCardInfo *nvidiac = screen->card->driver; + NvidiaScreenInfo *nvidias; + int screen_size, memory; + + nvidias = (NvidiaScreenInfo *) xalloc (sizeof (NvidiaScreenInfo)); + if (!nvidias) + return FALSE; + memset (nvidias, '\0', sizeof (NvidiaScreenInfo)); + if (!vesaScreenInitialize (screen, &nvidias->vesa)) + { + xfree (nvidias); + return FALSE; + } + if (!nvidiac->reg_base) + screen->dumb = TRUE; + if (nvidias->vesa.mapping != VESA_LINEAR) + screen->dumb = TRUE; + nvidias->screen = nvidias->vesa.fb; + memory = nvidias->vesa.fb_size; + screen_size = screen->fb[0].byteStride * screen->height; + if (nvidias->screen && memory >= screen_size + 2048) + { + memory -= 2048; + nvidias->cursor_base = nvidias->screen + memory - 2048; + } + else + nvidias->cursor_base = 0; + screen->softCursor = TRUE; /* XXX for now */ + memory -= screen_size; + if (memory > screen->fb[0].byteStride) + { + nvidias->off_screen = nvidias->screen + screen_size; + nvidias->off_screen_size = memory; + } + else + { + nvidias->off_screen = 0; + nvidias->off_screen_size = 0; + } + screen->driver = nvidias; + return TRUE; +} + +Bool +nvidiaInitScreen (ScreenPtr pScreen) +{ +#if 0 +#ifdef XV + KdScreenPriv(pScreen); + NvidiaCardInfo *nvidiac = pScreenPriv->screen->card->driver; + if (nvidiac->media_reg && nvidiac->reg) + nvidiaInitVideo(pScreen); +#endif +#endif + return vesaInitScreen (pScreen); +} + +#ifdef RANDR +nvidiaRandRSetConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + KdScreenPriv(pScreen); + + KdCheckSync (pScreen); + + if (!vesaRandRSetConfig (pScreen, rotation, rate, pSize)) + return FALSE; + + return TRUE; +} + +void +nvidiaRandRInit (ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + pScrPriv->rrSetConfig = nvidiaRandRSetConfig; +} +#endif + +Bool +nvidiaFinishInitScreen (ScreenPtr pScreen) +{ + Bool ret; + ret = vesaFinishInitScreen (pScreen); +#ifdef RANDR + nvidiaRandRInit (pScreen); +#endif + return ret; +} + +void +nvidiaPreserve (KdCardInfo *card) +{ + NvidiaCardInfo *nvidiac = card->driver; + + vesaPreserve(card); +} + +void +nvidiaOutb (NvidiaCardInfo *nvidiac, CARD16 port, CARD8 val) +{ + asm volatile ("outb %b0,%w1" : : "a" (val), "d" (port)); +} + +CARD8 +nvidiaInb (NvidiaCardInfo *nvidiac, CARD16 port) +{ + CARD8 v; + asm volatile ("inb %w1,%b0" : "=a" (v) : "d" (port)); + return v; +} + +CARD8 +nvidiaGetIndex (NvidiaCardInfo *nvidiac, CARD16 addr, CARD16 data, CARD8 id) +{ + CARD8 ret; + DBGOUT ("nvidiaGetIndex(0x%x,0x%x)\n", addr, id); + nvidiaOutb (nvidiac, addr, id); + ret = nvidiaInb (nvidiac, data); + DBGOUT (" -> 0x%x\n", ret); + return ret; +} + +void +nvidiaSetIndex (NvidiaCardInfo *nvidiac, CARD16 addr, CARD16 data, CARD8 id, CARD8 val) +{ + DBGOUT ("nvidiaSetIndex(0x%x,0x%x) = 0x%x\n", addr, id, val); + nvidiaOutb (nvidiac, addr, id); + nvidiaOutb (nvidiac, data, val); +} + +static void vgaLockUnlock (NvidiaCardInfo *nvidiac, Bool lock) +{ + CARD8 cr11; + ENTER (); + cr11 = nvidiaGetIndex (nvidiac, 0x3d4, 0x3d5, 0x11); + if (lock) cr11 |= 0x80; + else cr11 &= ~0x80; + nvidiaSetIndex (nvidiac, 0x3d4, 0x3d5, 0x11, cr11); + LEAVE (); +} + +void nvidiaLockUnlock (NvidiaCardInfo *nvidiac, Bool lock) +{ + if (NVIDIA_IS_3(nvidiac)) + nvidiaSetIndex (nvidiac, 0x3c4, 0x3c5, 0x06, lock ? 0x99 : 0x57); + else + nvidiaSetIndex (nvidiac, 0x3c4, 0x3c5, 0x1f, lock ? 0x99 : 0x57); + vgaLockUnlock(nvidiac, lock); +} + +Bool +nvidiaMapReg (KdCardInfo *card, NvidiaCardInfo *nvidiac) +{ + nvidiac->reg_base = (CARD8 *) KdMapDevice (NVIDIA_REG_BASE(card), + NVIDIA_REG_SIZE(card)); + + if (!nvidiac->reg_base) + { + nvidiac->mmio = 0; + nvidiac->rop = 0; + nvidiac->blt = 0; + nvidiac->rect = 0; + return FALSE; + } + + nvidiac->mmio = (CARD8 *) (nvidiac->reg_base + NVIDIA_MMIO_OFF(card)); + nvidiac->rop = (NvidiaRop *) (nvidiac->reg_base + NVIDIA_ROP_OFF(card)); + nvidiac->rect = (NvidiaRectangle *) (nvidiac->reg_base + NVIDIA_RECTANGLE_OFF(card)); + nvidiac->blt = (NvidiaScreenBlt *) (nvidiac->reg_base + NVIDIA_BLT_OFF(card)); + nvidiac->busy = (NvidiaBusy *) (nvidiac->reg_base + NVIDIA_BUSY_OFF(card)); + KdSetMappedMode (NVIDIA_REG_BASE(card), + NVIDIA_REG_SIZE(card), + KD_MAPPED_MODE_REGISTERS); + return TRUE; +} + +void +nvidiaUnmapReg (KdCardInfo *card, NvidiaCardInfo *nvidiac) +{ + if (nvidiac->reg_base) + { + KdResetMappedMode (NVIDIA_REG_BASE(card), + NVIDIA_REG_SIZE(card), + KD_MAPPED_MODE_REGISTERS); + KdUnmapDevice ((void *) nvidiac->reg_base, NVIDIA_REG_SIZE(card)); + nvidiac->reg_base = 0; + nvidiac->rop = 0; + nvidiac->blt = 0; + nvidiac->rect = 0; + } +} + +void +nvidiaSetMMIO (KdCardInfo *card, NvidiaCardInfo *nvidiac) +{ + if (!nvidiac->reg_base) + nvidiaMapReg (card, nvidiac); + nvidiaLockUnlock (nvidiac, FALSE); + nvidiac->fifo_free = 0; + nvidiac->fifo_size = nvidiac->rop->FifoFree.FifoFree; +} + +void +nvidiaResetMMIO (KdCardInfo *card, NvidiaCardInfo *nvidiac) +{ + nvidiaUnmapReg (card, nvidiac); + nvidiaLockUnlock (nvidiac, TRUE); +} + +Bool +nvidiaEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + NvidiaCardInfo *nvidiac = pScreenPriv->card->driver; + + if (!vesaEnable (pScreen)) + return FALSE; + + nvidiaSetMMIO (pScreenPriv->card, nvidiac); + nvidiaDPMS (pScreen, KD_DPMS_NORMAL); +#ifdef XV + KdXVEnable (pScreen); +#endif + return TRUE; +} + +void +nvidiaDisable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + NvidiaCardInfo *nvidiac = pScreenPriv->card->driver; + +#ifdef XV + KdXVDisable (pScreen); +#endif + nvidiaResetMMIO (pScreenPriv->card, nvidiac); + vesaDisable (pScreen); +} + +Bool +nvidiaDPMS (ScreenPtr pScreen, int mode) +{ + return vesaDPMS (pScreen, mode); +} + +void +nvidiaRestore (KdCardInfo *card) +{ + NvidiaCardInfo *nvidiac = card->driver; + + nvidiaResetMMIO (card, nvidiac); + vesaRestore (card); +} + +void +nvidiaScreenFini (KdScreenInfo *screen) +{ + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + + vesaScreenFini (screen); + xfree (nvidias); + screen->driver = 0; +} + +void +nvidiaCardFini (KdCardInfo *card) +{ + NvidiaCardInfo *nvidiac = card->driver; + + nvidiaUnmapReg (card, nvidiac); + vesaCardFini (card); +} + +#define nvidiaCursorInit 0 /* initCursor */ +#define nvidiaCursorEnable 0 /* enableCursor */ +#define nvidiaCursorDisable 0 /* disableCursor */ +#define nvidiaCursorFini 0 /* finiCursor */ +#define nvidiaRecolorCursor 0 /* recolorCursor */ + +KdCardFuncs nvidiaFuncs = { + nvidiaCardInit, /* cardinit */ + nvidiaScreenInit, /* scrinit */ + nvidiaInitScreen, /* initScreen */ + nvidiaPreserve, /* preserve */ + nvidiaEnable, /* enable */ + nvidiaDPMS, /* dpms */ + nvidiaDisable, /* disable */ + nvidiaRestore, /* restore */ + nvidiaScreenFini, /* scrfini */ + nvidiaCardFini, /* cardfini */ + + nvidiaCursorInit, /* initCursor */ + nvidiaCursorEnable, /* enableCursor */ + nvidiaCursorDisable, /* disableCursor */ + nvidiaCursorFini, /* finiCursor */ + nvidiaRecolorCursor, /* recolorCursor */ + + nvidiaDrawInit, /* initAccel */ + nvidiaDrawEnable, /* enableAccel */ + nvidiaDrawSync, /* syncAccel */ + nvidiaDrawDisable, /* disableAccel */ + nvidiaDrawFini, /* finiAccel */ + + vesaGetColors, /* getColors */ + vesaPutColors, /* putColors */ + + nvidiaFinishInitScreen, /* finishInitScreen */ +}; diff --git a/hw/kdrive/nvidia/nvidia.h b/hw/kdrive/nvidia/nvidia.h new file mode 100644 index 000000000..b1ba3b3ad --- /dev/null +++ b/hw/kdrive/nvidia/nvidia.h @@ -0,0 +1,250 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _NVIDIA_H_ +#define _NVIDIA_H_ +#include +#include "kxv.h" + +/* + * offset from ioport beginning + */ + +#define DEBUG +#ifdef DEBUG +#define DBGOUT(fmt,a...) fprintf (stderr, fmt, ##a) +#else +#define DBGOUT(fmt,a...) +#endif + +#define ENTER() DBGOUT("Enter %s\n", __FUNCTION__) +#define LEAVE() DBGOUT("Leave %s\n", __FUNCTION__) + +#define NVIDIA_REG_BASE(c) ((c)->attr.address[0]) +#define NVIDIA_REG_SIZE(c) (16 * 1024 * 1024) + +#define NVIDIA_PCIO_OFF(c) (0x601000) +#define NVIDIA_MMIO_OFF(c) (NVIDIA_PCIO_OFF(c) + 0) +#define NVIDIA_FIFO_OFF(c) (0x800000) +#define NVIDIA_ROP_OFF(c) (NVIDIA_FIFO_OFF(c) + 0) +#define NVIDIA_CLIP_OFF(c) (NVIDIA_FIFO_OFF(c) + 0x2000) +#define NVIDIA_PATT_OFF(c) (NVIDIA_FIFO_OFF(c) + 0x4000) +#define NVIDIA_PIXMAP_OFF(c) (NVIDIA_FIFO_OFF(c) + 0x6000) +#define NVIDIA_BLT_OFF(c) (NVIDIA_FIFO_OFF(c) + 0x8000) +#define NVIDIA_RECTANGLE_OFF(c) (NVIDIA_FIFO_OFF(c) + 0xa000) +#define NVIDIA_LINE_OFF(c) (NVIDIA_FIFO_OFF(c) + 0xc000) +#define NVIDIA_IS_3(c) (0) +#define NVIDIA_BUSY(c) (NVIDIA_IS_3(c) ? 0x6b0 : 0x700) +#define NVIDIA_BUSY_OFF(c) (0x400000 + NVIDIA_BUSY(c)) + +typedef volatile CARD8 VOL8; +typedef volatile CARD16 VOL16; +typedef volatile CARD32 VOL32; + +#define NVIDIA_XY(x,y) ((x) | ((y) << 16)) + +typedef struct { +#if X_BYTE_ORDER == X_BIG_ENDIAN + VOL32 FifoFree; +#else + VOL16 FifoFree; + VOL16 Nop; +#endif +} NvidiaFifoFree; + +/* + * Raster OPeration. Windows style ROP3. + */ +typedef struct { + VOL32 reserved00[4]; + NvidiaFifoFree FifoFree; + VOL32 reserved01[0x0BB]; + VOL32 Rop3; +} NvidiaRop; + +/* + * 2D filled rectangle. + */ +typedef struct { + VOL32 reserved00[4]; + NvidiaFifoFree FifoFree; + VOL32 reserved01[0x0BB]; + VOL32 reserved03[(0x040)-1]; + VOL32 Color1A; + VOL32 TopLeft; + VOL32 WidthHeight; +} NvidiaRectangle; + +/* + * 2D screen-screen BLT. + */ +typedef struct { + VOL32 reserved00[4]; + NvidiaFifoFree FifoFree; + VOL32 reserved01[0x0BB]; + VOL32 TopLeftSrc; + VOL32 TopLeftDst; + VOL32 WidthHeight; +} NvidiaScreenBlt; + +typedef struct { + VOL32 busy; +} NvidiaBusy; + +typedef struct _nvidiaCardInfo { + VesaCardPrivRec vesa; + CARD8 *reg_base; + int fifo_free; + int fifo_size; + CARD8 *mmio; + NvidiaRop *rop; + NvidiaRectangle *rect; + NvidiaScreenBlt *blt; + NvidiaBusy *busy; +} NvidiaCardInfo; + +#define getNvidiaCardInfo(kd) ((NvidiaCardInfo *) ((kd)->card->driver)) +#define nvidiaCardInfo(kd) NvidiaCardInfo *nvidiac = getNvidiaCardInfo(kd) + +/* + * Xv information, optional + */ +typedef struct _nvidiaPortPriv { + CARD32 YBuf0Offset; + + CARD32 YBuf1Offset; + + CARD8 currentBuf; + + int brightness; + int saturation; + + RegionRec clip; + CARD32 colorKey; + + Bool videoOn; + Time offTime; + Time freeTime; + CARD32 size; + CARD32 offset; +} NvidiaPortPrivRec, *NvidiaPortPrivPtr; + +Bool nvidiaInitVideo(ScreenPtr pScreen); + +typedef struct _nvidiaScreenInfo { + VesaScreenPrivRec vesa; + CARD8 *cursor_base; + CARD8 *screen; + CARD8 *off_screen; + int off_screen_size; + KdVideoAdaptorPtr pAdaptor; +} NvidiaScreenInfo; + +#define getNvidiaScreenInfo(kd) ((NvidiaScreenInfo *) ((kd)->screen->driver)) +#define nvidiaScreenInfo(kd) NvidiaScreenInfo *nvidias = getNvidiaScreenInfo(kd) + +void +nvidiaPreserve (KdCardInfo *card); + +void +nvidiaOutb (NvidiaCardInfo *nvidiac, CARD16 port, CARD8 val); + +CARD8 +nvidiaInb (NvidiaCardInfo *nvidiac, CARD16 port); + +CARD8 +nvidiaGetIndex (NvidiaCardInfo *nvidiac, CARD16 addr, CARD16 data, CARD8 id); + +void +nvidiaSetIndex (NvidiaCardInfo *nvidiac, CARD16 addr, CARD16 data, CARD8 id, CARD8 val); + +Bool +nvidiaMapReg (KdCardInfo *card, NvidiaCardInfo *nvidiac); + +void +nvidiaUnmapReg (KdCardInfo *card, NvidiaCardInfo *nvidiac); + +void +nvidiaSetMMIO (KdCardInfo *card, NvidiaCardInfo *nvidiac); + +void +nvidiaResetMMIO (KdCardInfo *card, NvidiaCardInfo *nvidiac); + +Bool +nvidiaEnable (ScreenPtr pScreen); + +void +nvidiaDisable (ScreenPtr pScreen); + +void +nvidiaWait (NvidiaCardInfo *card, NvidiaFifoFree *free, int n); + +void +nvidiaWaitIdle (NvidiaCardInfo *card); + +Bool +nvidiaDrawSetup (ScreenPtr pScreen); + +Bool +nvidiaDrawInit (ScreenPtr pScreen); + +void +nvidiaDrawReinit (ScreenPtr pScreen); + +void +nvidiaDrawEnable (ScreenPtr pScreen); + +void +nvidiaDrawSync (ScreenPtr pScreen); + +void +nvidiaDrawDisable (ScreenPtr pScreen); + +void +nvidiaDrawFini (ScreenPtr pScreen); + +CARD8 +nvidiaReadIndex (NvidiaCardInfo *nvidiac, CARD16 port, CARD8 index); + +void +nvidiaWriteIndex (NvidiaCardInfo *nvidiac, CARD16 port, CARD8 index, CARD8 value); + +Bool +nvidiaCursorInit (ScreenPtr pScreen); + +void +nvidiaCursorEnable (ScreenPtr pScreen); + +void +nvidiaCursorDisable (ScreenPtr pScreen); + +void +nvidiaCursorFini (ScreenPtr pScreen); + +void +nvidiaRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef); + +extern KdCardFuncs nvidiaFuncs; + +#endif /* _NVIDIA_H_ */ diff --git a/hw/kdrive/nvidia/nvidiacurs.c b/hw/kdrive/nvidia/nvidiacurs.c new file mode 100644 index 000000000..b5d7cd16c --- /dev/null +++ b/hw/kdrive/nvidia/nvidiacurs.c @@ -0,0 +1,392 @@ +/* + * Id: tridentcurs.c,v 1.1 1999/11/02 03:54:47 keithp Exp $ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $RCSId: xc/programs/Xserver/hw/kdrive/trident/tridentcurs.c,v 1.6 2000/09/03 05:11:20 keithp Exp $ */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "trident.h" +#include "cursorstr.h" + +#define SetupCursor(s) KdScreenPriv(s); \ + tridentCardInfo(pScreenPriv); \ + tridentScreenInfo(pScreenPriv); \ + TridentCursor *pCurPriv = &tridents->cursor + +static void +_tridentMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CARD8 xlow, xhigh, ylow, yhigh; + CARD8 xoff, yoff; + + x -= pCurPriv->xhot; + xoff = 0; + if (x < 0) + { + xoff = -x; + x = 0; + } + y -= pCurPriv->yhot; + yoff = 0; + if (y < 0) + { + yoff = -y; + y = 0; + } + xlow = (CARD8) x; + xhigh = (CARD8) (x >> 8); + ylow = (CARD8) y; + yhigh = (CARD8) (y >> 8); + + + /* This is the recommended order to move the cursor */ + + tridentWriteIndex (tridentc, 0x3d4, 0x41, xhigh); + tridentWriteIndex (tridentc, 0x3d4, 0x40, xlow); + tridentWriteIndex (tridentc, 0x3d4, 0x42, ylow); + tridentWriteIndex (tridentc, 0x3d4, 0x46, xoff); + tridentWriteIndex (tridentc, 0x3d4, 0x47, yoff); + tridentWriteIndex (tridentc, 0x3d4, 0x43, yhigh); +} + +static void +tridentMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor (pScreen); + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + _tridentMoveCursor (pScreen, x, y); +} + +static void +tridentAllocCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + + KdAllocateCursorPixels (pScreen, 0, pCursor, + &pCurPriv->source, &pCurPriv->mask); + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 4: + pCurPriv->source |= pCurPriv->source << 4; + pCurPriv->mask |= pCurPriv->mask << 4; + case 8: + pCurPriv->source |= pCurPriv->source << 8; + pCurPriv->mask |= pCurPriv->mask << 8; + case 16: + pCurPriv->source |= pCurPriv->source << 16; + pCurPriv->mask |= pCurPriv->mask << 16; + } +} + +static void +tridentSetCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CARD32 fg, bg; + + fg = pCurPriv->source; + bg = pCurPriv->mask; + tridentWriteIndex (tridentc, 0x3d4, 0x48, fg); + tridentWriteIndex (tridentc, 0x3d4, 0x49, fg >> 8); + tridentWriteIndex (tridentc, 0x3d4, 0x4a, fg >> 16); + + tridentWriteIndex (tridentc, 0x3d4, 0x4c, bg); + tridentWriteIndex (tridentc, 0x3d4, 0x4d, bg >> 8); + tridentWriteIndex (tridentc, 0x3d4, 0x4e, bg >> 16); +} + +void +tridentRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + xColorItem sourceColor, maskColor; + + if (!pCurPriv->has_cursor || !pCursor) + return; + + if (!pScreenPriv->enabled) + return; + + if (pdef) + { + while (ndef) + { + if (pdef->pixel == pCurPriv->source || + pdef->pixel == pCurPriv->mask) + break; + ndef--; + } + if (!ndef) + return; + } + tridentAllocCursorColors (pScreen); + tridentSetCursorColors (pScreen); +} + +#define InvertBits32(v) { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} + +static void +tridentLoadCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int w, h; + CARD32 *ram, *msk, *mskLine, *src, *srcLine; + int i, j; + int cursor_address; + int lwsrc; + unsigned char ramdac_control_; + CARD32 offset; + + /* + * Allocate new colors + */ + tridentAllocCursorColors (pScreen); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* + * Stick new image into cursor memory + */ + ram = (CARD32 *) tridents->cursor_base; + mskLine = (CARD32 *) bits->mask; + srcLine = (CARD32 *) bits->source; + + h = bits->height; + if (h > TRIDENT_CURSOR_HEIGHT) + h = TRIDENT_CURSOR_HEIGHT; + + lwsrc = BitmapBytePad(bits->width) / 4; /* words per line */ + + for (i = 0; i < TRIDENT_CURSOR_HEIGHT; i++) { + msk = mskLine; + src = srcLine; + mskLine += lwsrc; + srcLine += lwsrc; + for (j = 0; j < TRIDENT_CURSOR_WIDTH / 32; j++) { + + CARD32 m, s; + +#if 1 + if (i < h && j < lwsrc) + { + m = *msk++; + s = *src++; + InvertBits32(m); + InvertBits32(s); + } + else + { + m = 0; + s = 0; + } +#endif + *ram++ = m; + *ram++ = s; + } + } + + /* Set address for cursor bits */ + offset = tridents->cursor_base - (CARD8 *) tridents->screen; + offset >>= 10; + tridentWriteIndex (tridentc, 0x3d4, 0x44, (CARD8) (offset & 0xff)); + tridentWriteIndex (tridentc, 0x3d4, 0x45, (CARD8) (offset >> 8)); + + /* Set new color */ + tridentSetCursorColors (pScreen); + + /* Enable the cursor */ + tridentWriteIndex (tridentc, 0x3d4, 0x50, 0xc1); + + /* Move to new position */ + tridentMoveCursor (pScreen, x, y); +} + +static void +tridentUnloadCursor (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + /* Disable cursor */ + tridentWriteIndex (tridentc, 0x3d4, 0x50, 0); +} + +static Bool +tridentRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupCursor(pScreen); + + if (!pScreenPriv->enabled) + return TRUE; + + /* miRecolorCursor does this */ + if (pCurPriv->pCursor == pCursor) + { + if (pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + tridentLoadCursor (pScreen, x, y); + } + } + return TRUE; +} + +static Bool +tridentUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +tridentSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + SetupCursor(pScreen); + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + tridentLoadCursor (pScreen, x, y); + else + tridentUnloadCursor (pScreen); +} + +miPointerSpriteFuncRec tridentPointerSpriteFuncs = { + tridentRealizeCursor, + tridentUnrealizeCursor, + tridentSetCursor, + tridentMoveCursor, +}; + +static void +tridentQueryBestSize (int class, + unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + switch (class) + { + case CursorShape: + if (*pwidth > pCurPriv->width) + *pwidth = pCurPriv->width; + if (*pheight > pCurPriv->height) + *pheight = pCurPriv->height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + fbQueryBestSize (class, pwidth, pheight, pScreen); + break; + } +} + +Bool +tridentCursorInit (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!tridents->cursor_base) + { + pCurPriv->has_cursor = FALSE; + return FALSE; + } + + pCurPriv->width = TRIDENT_CURSOR_WIDTH; + pCurPriv->height= TRIDENT_CURSOR_HEIGHT; + pScreen->QueryBestSize = tridentQueryBestSize; + miPointerInitialize (pScreen, + &tridentPointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +tridentCursorEnable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + tridentLoadCursor (pScreen, x, y); + } + else + tridentUnloadCursor (pScreen); + } +} + +void +tridentCursorDisable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pScreenPriv->enabled) + return; + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + tridentUnloadCursor (pScreen); + } + } +} + +void +tridentCursorFini (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + pCurPriv->pCursor = NULL; +} diff --git a/hw/kdrive/nvidia/nvidiadraw.c b/hw/kdrive/nvidia/nvidiadraw.c new file mode 100644 index 000000000..c523562e2 --- /dev/null +++ b/hw/kdrive/nvidia/nvidiadraw.c @@ -0,0 +1,243 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "nvidia.h" +#include "nvidiadraw.h" + +#include +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "mistruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "fb.h" +#include "migc.h" +#include "miline.h" +#include "picturestr.h" + +CARD8 nvidiaRop[16] = { + /* GXclear */ 0x01, /* 0 */ + /* GXand */ 0x0c, /* src AND dst */ + /* GXandReverse */ 0x0d, /* src AND NOT dst */ + /* GXcopy */ 0x07, /* src */ + /* GXandInverted*/ 0x0e, /* NOT src AND dst */ + /* GXnoop */ 0x03, /* dst */ + /* GXxor */ 0x05, /* src XOR dst */ + /* GXor */ 0x0b, /* src OR dst */ + /* GXnor */ 0x0f, /* NOT src AND NOT dst */ + /* GXequiv */ 0x06, /* NOT src XOR dst */ + /* GXinvert */ 0x00, /* NOT dst */ + /* GXorReverse */ 0x0a, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x04, /* NOT src */ + /* GXorInverted */ 0x09, /* NOT src OR dst */ + /* GXnand */ 0x08, /* NOT src OR NOT dst */ + /* GXset */ 0x02, /* 1 */ +}; + +static NvidiaCardInfo *card; + +void +nvidiaWait (NvidiaCardInfo *card, NvidiaFifoFree *free, int n) +{ + while (card->fifo_free < n) + { + card->fifo_free = free->FifoFree >> 2; + } + card->fifo_free -= n; +} + +void +nvidiaWaitIdle (NvidiaCardInfo *card) +{ + while (card->fifo_free < card->fifo_size || (card->busy->busy & 1)) + { + card->fifo_free = card->rop->FifoFree.FifoFree >> 2; + } +} + +Bool +nvidiaPrepareSolid (DrawablePtr pDrawable, + int alu, + Pixel pm, + Pixel fg) +{ + ScreenPtr pScreen = pDrawable->pScreen; + KdScreenPriv(pScreen); + nvidiaScreenInfo(pScreenPriv); + nvidiaCardInfo(pScreenPriv); + + card = nvidiac; + if (~pm & FbFullMask(pDrawable->depth)) + return FALSE; + nvidiaWait (nvidiac, &nvidiac->rop->FifoFree, 1); + nvidiac->rop->Rop3 = nvidiaRop[alu]; + nvidiaWait (nvidiac, &nvidiac->rect->FifoFree, 1); + nvidiac->rect->Color1A = fg; + return TRUE; +} + +void +nvidiaSolid (int x1, int y1, int x2, int y2) +{ + nvidiaWait (card, &card->rect->FifoFree, 2); + card->rect->TopLeft = NVIDIA_XY(x1,y1); + card->rect->WidthHeight = NVIDIA_XY(x2-x1,y2-y1); +} + +void +nvidiaDoneSolid (void) +{ +} + + +Bool +nvidiaPrepareCopy (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + int dx, + int dy, + int alu, + Pixel pm) +{ + ScreenPtr pScreen = pDstDrawable->pScreen; + KdScreenPriv(pScreen); + nvidiaScreenInfo(pScreenPriv); + nvidiaCardInfo(pScreenPriv); + + card = nvidiac; + if (~pm & FbFullMask(pDstDrawable->depth)) + return FALSE; + nvidiaWait (nvidiac, &card->rop->FifoFree, 1); + nvidiac->rop->Rop3 = nvidiaRop[alu]; + return TRUE; +} + +void +nvidiaCopy (int srcX, + int srcY, + int dstX, + int dstY, + int w, + int h) +{ + nvidiaWait (card, &card->blt->FifoFree, 3); + card->blt->TopLeftSrc = NVIDIA_XY(srcX, srcY); + card->blt->TopLeftDst = NVIDIA_XY(dstX, dstY); + card->blt->WidthHeight = NVIDIA_XY(w, h); +} + +void +nvidiaDoneCopy (void) +{ +} + +KaaScreenPrivRec nvidiaKaa = { + nvidiaPrepareSolid, + nvidiaSolid, + nvidiaDoneSolid, + + nvidiaPrepareCopy, + nvidiaCopy, + nvidiaDoneCopy, +}; + +Bool +nvidiaDrawInit (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + nvidiaScreenInfo(pScreenPriv); + nvidiaCardInfo(pScreenPriv); + Bool ret; + + ENTER (); + if (pScreenPriv->screen->fb[0].depth == 4) + ret = FALSE; + + if (ret && !nvidiac->rop) + { + ErrorF ("Failed to map fifo registers\n"); + ret = FALSE; + } + if (ret && !nvidiac->rop->FifoFree.FifoFree) + { + ErrorF ("Fifo appears broken\n"); + ret = FALSE; + } + if (ret && !kaaDrawInit (pScreen, &nvidiaKaa)) + { + ErrorF ("kaaDrawInit failed\n"); + ret = FALSE; + } + + LEAVE (); + return ret; +} + +#define PIX_FORMAT_MONO 0 +#define PIX_FORMAT_PSEUDO_8 2 +#define PIX_FORMAT_TRUE_1555 3 +#define PIX_FORMAT_TRUE_565 4 +#define PIX_FORMAT_TRUE_8888 6 +#define PIX_FORMAT_TRUE_332 7 +#define PIX_FORMAT_GRAY_8 8 +#define PIX_FORMAT_YUV_422 0xb +#define PIX_FORMAT_YUV_444 0xe +#define PIX_FORMAT_TRUE_4444 0xf + +void +nvidiaDrawEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + nvidiaScreenInfo(pScreenPriv); + nvidiaCardInfo(pScreenPriv); + + ENTER (); + nvidiac->fifo_size = nvidiac->rop->FifoFree.FifoFree; + nvidiac->fifo_free = 0; + KdMarkSync (pScreen); + LEAVE (); +} + +void +nvidiaDrawDisable (ScreenPtr pScreen) +{ +} + +void +nvidiaDrawFini (ScreenPtr pScreen) +{ +} + +void +nvidiaDrawSync (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + nvidiaCardInfo(pScreenPriv); + + nvidiaWaitIdle (nvidiac); +} diff --git a/hw/kdrive/nvidia/nvidiadraw.h b/hw/kdrive/nvidia/nvidiadraw.h new file mode 100644 index 000000000..b7053ae49 --- /dev/null +++ b/hw/kdrive/nvidia/nvidiadraw.h @@ -0,0 +1,72 @@ +/* + * Id: tridentdraw.h,v 1.1 1999/11/02 03:54:47 keithp Exp $ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $RCSId: xc/programs/Xserver/hw/kdrive/trident/tridentdraw.h,v 1.4 2000/10/11 06:04:40 keithp Exp $ */ + +#ifndef _TRIDENTDRAW_H_ +#define _TRIDENTDRAW_H_ + +#define SetupTrident(s) KdScreenPriv(s); \ + tridentCardInfo(pScreenPriv); \ + Cop *cop = tridentc->cop + +#define TridentAlpha (COP_MULTI_ALPHA|COP_ALPHA_WRITE_ENABLE) + +#define _tridentInit(cop,tridentc) { \ + if ((cop)->status == 0xffffffff) tridentSetMMIO(tridentc); \ + (cop)->multi = (tridentc)->cop_depth; \ + (cop)->multi = (tridentc)->cop_stride; \ + (cop)->multi = TridentAlpha; \ +} \ + +#define _tridentSetSolidRect(cop,pix,alu,cmd) {\ + cop->multi = COP_MULTI_PATTERN; \ + cop->multi = COP_MULTI_ROP | tridentRop[alu]; \ + cop->fg = (pix); \ + cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FG; \ +} + +#define _tridentRect(cop,x1,y1,x2,y2,cmd) { \ + (cop)->dst_start_xy = TRI_XY (x1,y1); \ + (cop)->dst_end_xy = TRI_XY(x2,y2); \ + _tridentWaitDone(cop); \ + (cop)->command = (cmd); \ +} + +#define COP_STATUS_BUSY (COP_STATUS_BE_BUSY | \ + COP_STATUS_DPE_BUSY | \ + COP_STATUS_MI_BUSY) + +#define _tridentWaitDone(cop) { \ + int __q__ = 500000; \ + while (__q__-- && (cop)->status & COP_STATUS_BUSY) \ + ; \ + if (!__q__) \ + (cop)->status = 0; \ +} + +#define _tridentWaitIdleEmpty(cop) _tridentWaitDone(cop) + +#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) + +#endif diff --git a/hw/kdrive/nvidia/nvidiastub.c b/hw/kdrive/nvidia/nvidiastub.c new file mode 100644 index 000000000..285a73844 --- /dev/null +++ b/hw/kdrive/nvidia/nvidiastub.c @@ -0,0 +1,59 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "nvidia.h" + +void +InitCard (char *name) +{ + KdCardAttr attr; + + if (LinuxFindPci (0x10de, 0x0112, 0, &attr)) + KdCardInfoAdd (&nvidiaFuncs, &attr, 0); +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdInitInput (&LinuxMouseFuncs, &LinuxKeyboardFuncs); +} + +int +ddxProcessArgument (int argc, char **argv, int i) +{ + int ret; + + if (!(ret = vesaProcessArgument (argc, argv, i))) + ret = KdProcessArgument(argc, argv, i); + return ret; +} diff --git a/hw/kdrive/nvidia/nvidiavideo.c b/hw/kdrive/nvidia/nvidiavideo.c new file mode 100644 index 000000000..04cc8044c --- /dev/null +++ b/hw/kdrive/nvidia/nvidiavideo.c @@ -0,0 +1,1018 @@ +/* + * $Id$ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "nvidia.h" + +#include +#include "fourcc.h" + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvSaturation, xvColorKey; + +#define IMAGE_MAX_WIDTH 720 +#define IMAGE_MAX_HEIGHT 576 + +static void +nvidiaStopVideo(KdScreenInfo *screen, pointer data, Bool exit) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + NvidiaPortPrivPtr pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr; + Reg *reg = nvidiac->reg; + MediaReg *media = nvidiac->media_reg; + + REGION_EMPTY(screen->pScreen, &pPortPriv->clip); + + if (!media) + return; + + if(pPortPriv->videoOn) + { + nvidiaWaitIdle (reg); + /* wait for buffer to be displayed */ + while (((media->TRIG_CNTL >> 5) & 1) != pPortPriv->currentBuf) + ; + /* wait for buffer to be finished */ + while (((media->TRIG_CNTL >> 6) & 1) != 0) + ; + nvidiaWaitAvail (reg, 1); + media->OVERLAY_SCALE_CNTL = 0; + pPortPriv->videoOn = FALSE; + nvidiaWaitIdle (reg); + } +} + +static int +nvidiaSetPortAttribute(KdScreenInfo *screen, + Atom attribute, + int value, + pointer data) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + NvidiaPortPrivPtr pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr; + MediaReg *media = nvidiac->media_reg; + + if(attribute == xvBrightness) + { + if(value < -1000) + value = -1000; + if (value > 1000) + value = 1000; + pPortPriv->brightness = value; + } + else if(attribute == xvSaturation) + { + if (value < -1000) + value = -1000; + if (value > 1000) + value = 1000; + pPortPriv->saturation = value; + } + else if(attribute == xvColorKey) + { + if (pPortPriv->colorKey != value) + { + pPortPriv->colorKey = value; + REGION_EMPTY(screen->pScreen, &pPortPriv->clip); + } + } + else + return BadMatch; + + return Success; +} + +static int +nvidiaGetPortAttribute(KdScreenInfo *screen, + Atom attribute, + int *value, + pointer data) +{ + NvidiaPortPrivPtr pPortPriv = (NvidiaPortPrivPtr)data; + + if(attribute == xvBrightness) + *value = pPortPriv->brightness; + else if(attribute == xvSaturation) + *value = pPortPriv->saturation; + else if(attribute == xvColorKey) + *value = pPortPriv->colorKey; + else + return BadMatch; + + return Success; +} + +static void +nvidiaQueryBestSize(KdScreenInfo *screen, + Bool motion, + short vid_w, + short vid_h, + short drw_w, + short drw_h, + unsigned int *p_w, + unsigned int *p_h, + pointer data) +{ + *p_w = drw_w; + *p_h = drw_h; +} + + +static void +nvidiaCopyPackedData(KdScreenInfo *screen, + unsigned char *buf, + int randr, + int srcPitch, + int dstPitch, + int srcW, + int srcH, + int top, + int left, + int h, + int w) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + NvidiaPortPrivPtr pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr; + CARD8 *src, *dst; + int srcDown, srcRight, srcNext; + int p; + + switch (randr & RR_Rotate_All) { + case RR_Rotate_0: + src = buf; + srcDown = srcPitch; + srcRight = 2; + break; + case RR_Rotate_90: + src = buf + (srcH - 1) * 2; + srcDown = -2; + srcRight = srcPitch; + break; + case RR_Rotate_180: + src = buf + srcPitch * (srcH - 1) + (srcW - 1) * 2; + srcDown = -srcPitch; + srcRight = -2; + break; + case RR_Rotate_270: + src = buf + srcPitch * (srcW - 1); + srcDown = 2; + srcRight = -srcPitch; + break; + } + + src = src + top*srcDown + left*srcRight; + + if (pPortPriv->currentBuf == 0) + dst = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf0Offset; + else + dst = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf1Offset; + + w >>= 1; + srcRight >>= 1; + srcNext = srcRight >> 1; + while(h--) + { + CARD16 *s = (CARD16 *) src; + CARD32 *d = (CARD32 *) dst; + p = w; + while (p--) + { + *d++ = s[0] | (s[srcNext] << 16); + s += srcRight; + } + src += srcPitch; + dst += dstPitch; + } +} + +static void +nvidiaCopyPlanarData(KdScreenInfo *screen, + unsigned char *buf, + int randr, + int srcPitch, + int srcPitch2, + int dstPitch, /* of chroma */ + int srcW, + int srcH, + int height, + int top, + int left, + int h, + int w, + int id) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + NvidiaPortPrivPtr pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr; + int i, j; + CARD8 *src1, *src2, *src3, *dst1; + int srcDown, srcDown2, srcRight, srcRight2, srcNext; + + /* compute source data pointers */ + src1 = buf; + src2 = src1 + height * srcPitch; + src3 = src2 + (height >> 1) * srcPitch2; + switch (randr & RR_Rotate_All) { + case RR_Rotate_0: + srcDown = srcPitch; + srcDown2 = srcPitch2; + srcRight = 2; + srcRight2 = 1; + srcNext = 1; + break; + case RR_Rotate_90: + src1 = src1 + srcH - 1; + src2 = src2 + (srcH >> 1) - 1; + src3 = src3 + (srcH >> 1) - 1; + srcDown = -1; + srcDown2 = -1; + srcRight = srcPitch * 2; + srcRight2 = srcPitch2; + srcNext = srcPitch; + break; + case RR_Rotate_180: + src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1); + src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); + src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); + srcDown = -srcPitch; + srcDown2 = -srcPitch2; + srcRight = -2; + srcRight2 = -1; + srcNext = -1; + break; + case RR_Rotate_270: + src1 = src1 + srcPitch * (srcW - 1); + src2 = src2 + srcPitch2 * ((srcW >> 1) - 1); + src3 = src3 + srcPitch2 * ((srcW >> 1) - 1); + srcDown = 1; + srcDown2 = 1; + srcRight = -srcPitch * 2; + srcRight2 = -srcPitch2; + srcNext = -srcPitch; + break; + } + + /* adjust for origin */ + src1 += top * srcDown + left * srcNext; + src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; + src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; + + if (id == FOURCC_I420) + { + CARD8 *srct = src2; + src2 = src3; + src3 = srct; + } + + if (pPortPriv->currentBuf == 0) + dst1 = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf0Offset; + else + dst1 = (CARD8 *) nvidias->vesa.fb + pPortPriv->YBuf1Offset; + + w >>= 1; + for (j = 0; j < h; j++) + { + CARD32 *dst = (CARD32 *) dst1; + CARD8 *s1l = src1; + CARD8 *s1r = src1 + srcNext; + CARD8 *s2 = src2; + CARD8 *s3 = src3; + + for (i = 0; i < w; i++) + { + *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24); + s1l += srcRight; + s1r += srcRight; + s2 += srcRight2; + s3 += srcRight2; + } + src1 += srcDown; + dst1 += dstPitch; + if (j & 1) + { + src2 += srcDown2; + src3 += srcDown2; + } + } +} + +static void +nvidiaPaintRegion (ScreenPtr pScreen, RegionPtr pRgn, Pixel fg) +{ + WindowPtr pRoot = WindowTable[pScreen->myNum]; + GCPtr pGC; + CARD32 val[2]; + xRectangle *rects, *r; + BoxPtr pBox = REGION_RECTS (pRgn); + int nBox = REGION_NUM_RECTS (pRgn); + + rects = ALLOCATE_LOCAL (nBox * sizeof (xRectangle)); + if (!rects) + goto bail0; + r = rects; + while (nBox--) + { + r->x = pBox->x1; + r->y = pBox->y1; + r->width = pBox->x2 - pBox->x1; + r->height = pBox->y2 - pBox->y1; + r++; + pBox++; + } + + pGC = GetScratchGC (pRoot->drawable.depth, pScreen); + if (!pGC) + goto bail1; + + val[0] = fg; + val[1] = IncludeInferiors; + ChangeGC (pGC, GCForeground|GCSubwindowMode, val); + + ValidateGC (&pRoot->drawable, pGC); + + (*pGC->ops->PolyFillRect) (&pRoot->drawable, pGC, + REGION_NUM_RECTS (pRgn), rects); + + FreeScratchGC (pGC); +bail1: + DEALLOCATE_LOCAL (rects); +bail0: + ; +} + +/* NvidiaClipVideo - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +static void +NvidiaClipVideo(BoxPtr dst, + INT32 *x1, + INT32 *x2, + INT32 *y1, + INT32 *y2, + BoxPtr extents, /* extents of the clip region */ + INT32 width, + INT32 height) +{ + INT32 vscale, hscale, delta; + int diff; + + hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); + vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); + + *x1 <<= 16; *x2 <<= 16; + *y1 <<= 16; *y2 <<= 16; + + diff = extents->x1 - dst->x1; + if(diff > 0) { + dst->x1 = extents->x1; + *x1 += diff * hscale; + } + diff = dst->x2 - extents->x2; + if(diff > 0) { + dst->x2 = extents->x2; + *x2 -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if(diff > 0) { + dst->y1 = extents->y1; + *y1 += diff * vscale; + } + diff = dst->y2 - extents->y2; + if(diff > 0) { + dst->y2 = extents->y2; + *y2 -= diff * vscale; + } + + if(*x1 < 0) { + diff = (- *x1 + hscale - 1)/ hscale; + dst->x1 += diff; + *x1 += diff * hscale; + } + delta = *x2 - (width << 16); + if(delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *x2 -= diff * hscale; + } + if(*y1 < 0) { + diff = (- *y1 + vscale - 1)/ vscale; + dst->y1 += diff; + *y1 += diff * vscale; + } + delta = *y2 - (height << 16); + if(delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *y2 -= diff * vscale; + } +} + +static void +nvidiaDisplayVideo(KdScreenInfo *screen, + int id, + int dstPitch, /* of chroma for 4:2:0 */ + int x1, + int y1, + int x2, + int y2, + int dst_x1, + int dst_y1, + int dst_x2, + int dst_y2, + short src_w, + short src_h, + short drw_w, + short drw_h) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + NvidiaPortPrivPtr pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr; + Reg *reg = nvidiac->reg; + MediaReg *media = nvidiac->media_reg; + int xscaleInt, xscaleFract, yscaleInt, yscaleFract; + int xscaleIntUV = 0, xscaleFractUV = 0; + int yscaleIntUV = 0, yscaleFractUV = 0; + int randr = nvidias->vesa.randr; + int HORZ_INC, VERT_INC; + CARD32 SCALER_IN; + CARD32 OVERLAY_SCALE_CNTL; + int tmp; + int left; + int bright; + int sat; + + if (id == FOURCC_UYVY) + SCALER_IN = SCALER_IN_YVYU422; + else + SCALER_IN = SCALER_IN_VYUY422; + + nvidiaWaitAvail (reg, 4); + + media->VIDEO_FORMAT = SCALER_IN | VIDEO_IN_VYUY422; + + /* color key */ + media->OVERLAY_GRAPHICS_KEY_MSK = (1 << screen->fb[0].depth) - 1; + media->OVERLAY_GRAPHICS_KEY_CLR = pPortPriv->colorKey; + /* set key control to obey only graphics color key */ + media->OVERLAY_KEY_CNTL = 0x50; + + nvidiaWaitAvail (reg, 9); + media->CAPTURE_DEBUG = 0; + /* no exclusive video region */ + media->OVERLAY_EXCLUSIVE_HORZ = 0; + media->OVERLAY_EXCLUSIVE_VERT = 0; + /* scaling coefficients */ + media->SCALER_H_COEFF0 = 0x00002000; + media->SCALER_H_COEFF1 = 0x0D06200D; + media->SCALER_H_COEFF2 = 0x0D0A1C0D; + media->SCALER_H_COEFF3 = 0x0C0E1A0C; + media->SCALER_H_COEFF4 = 0x0C14140C; + media->SCALER_TEST = 0; + + nvidiaWaitAvail (reg, 2); + media->OVERLAY_SCALE_CNTL = (SCALE_PIX_EXPAND | + SCALE_GAMMA_BRIGHT | + SCALE_BANDWIDTH | + SCALE_OVERLAY_EN | + SCALE_EN); + + bright = (pPortPriv->brightness * 64 / 1000); + if (bright < -0x40) + bright = -0x40; + if (bright > 0x3f) + bright = 0x3f; + bright = bright & 0x7f; + sat = ((pPortPriv->saturation * 31 + 31000) / 2000); + if (sat > 0x1f) + sat = 0x1f; + if (sat < 0) + sat = 0; + + media->SCALER_COLOUR_CNTL = ((bright << 0) | /* BRIGHTNESS */ + (sat << 8) | /* SATURATION_U */ + (sat << 16) | /* SATURATION_V */ + (0 << 21) | /* SCALER_VERT_ADJ_UV */ + (0 << 28)); /* SCALER_HORZ_ADJ_UV */ + + VERT_INC = (src_h << 12) / drw_h; + HORZ_INC = (src_w << 12) / drw_w; + + nvidiaWaitAvail (reg, 13); + + /* lock registers to prevent non-atomic update */ + media->OVERLAY_Y_X_START = 0x80000000 | NVIDIA_YX (dst_x1, dst_y1); + /* ending screen coordinate */ + media->OVERLAY_Y_X_END = 0x80000000 | NVIDIA_YX (dst_x2, dst_y2); + + media->OVERLAY_SCALE_INC = NVIDIA_YX(HORZ_INC, VERT_INC); + + media->SCALER_BUF0_OFFSET = pPortPriv->YBuf0Offset; + media->SCALER_BUF1_OFFSET = pPortPriv->YBuf1Offset; + + media->SCALER_BUF0_OFFSET_U = pPortPriv->YBuf0Offset; + media->SCALER_BUF1_OFFSET_U = pPortPriv->YBuf1Offset; + + media->SCALER_BUF0_OFFSET_V = pPortPriv->YBuf0Offset; + media->SCALER_BUF1_OFFSET_V = pPortPriv->YBuf1Offset; + + media->SCALER_BUF_PITCH = dstPitch >> 1; + media->SCALER_HEIGHT_WIDTH = NVIDIA_YX(src_w - (x1 >> 16), src_h - (y1 >> 16)); + + media->CAPTURE_CONFIG = pPortPriv->currentBuf << 28; + + /* set XY location and unlock */ + media->OVERLAY_Y_X_START = NVIDIA_YX (dst_x1, dst_y1); +} + +static int +nvidiaPutImage(KdScreenInfo *screen, + short src_x, + short src_y, + short drw_x, + short drw_y, + short src_w, + short src_h, + short drw_w, + short drw_h, + int id, + unsigned char *buf, + short width, + short height, + Bool sync, + RegionPtr clipBoxes, + pointer data) +{ + KdCardInfo *card = screen->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + NvidiaPortPrivPtr pPortPriv = (NvidiaPortPrivPtr)data; + Reg *reg = nvidiac->reg; + MediaReg *media = nvidiac->media_reg; + INT32 x1, x2, y1, y2; + int randr = nvidias->vesa.randr; + int srcPitch, srcPitch2, dstPitch; + int top, left, npixels, nlines, size; + BoxRec dstBox; + int dst_width = width, dst_height = height; + int rot_x1, rot_y1, rot_x2, rot_y2; + int dst_x1, dst_y1, dst_x2, dst_y2; + int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + NvidiaClipVideo(&dstBox, &x1, &x2, &y1, &y2, + REGION_EXTENTS(pScreen, clipBoxes), width, height); + + if((x1 >= x2) || (y1 >= y2)) + return Success; + + if (!media) + return BadAlloc; + + if (randr & (RR_Rotate_0|RR_Rotate_180)) + { + dst_width = width; + dst_height = height; + rot_src_w = src_w; + rot_src_h = src_h; + rot_drw_w = drw_w; + rot_drw_h = drw_h; + } + else + { + dst_width = height; + dst_height = width; + rot_src_w = src_h; + rot_src_h = src_w; + rot_drw_w = drw_h; + rot_drw_h = drw_w; + } + + switch (randr & RR_Rotate_All) { + case RR_Rotate_0: + dst_x1 = dstBox.x1; + dst_y1 = dstBox.y1; + dst_x2 = dstBox.x2; + dst_y2 = dstBox.y2; + rot_x1 = x1; + rot_y1 = y1; + rot_x2 = x2; + rot_y2 = y2; + break; + case RR_Rotate_90: + dst_x1 = dstBox.y1; + dst_y1 = screen->height - dstBox.x2; + dst_x2 = dstBox.y2; + dst_y2 = screen->height - dstBox.x1; + + rot_x1 = y1; + rot_y1 = (src_w << 16) - x2; + rot_x2 = y2; + rot_y2 = (src_w << 16) - x1; + break; + case RR_Rotate_180: + dst_x1 = screen->width - dstBox.x2; + dst_y1 = screen->height - dstBox.y2; + dst_x2 = screen->width - dstBox.x1; + dst_y2 = screen->height - dstBox.y1; + rot_x1 = (src_w << 16) - x2; + rot_y1 = (src_h << 16) - y2; + rot_x2 = (src_w << 16) - x1; + rot_y2 = (src_h << 16) - y1; + break; + case RR_Rotate_270: + dst_x1 = screen->width - dstBox.y2; + dst_y1 = dstBox.x1; + dst_x2 = screen->width - dstBox.y1; + dst_y2 = dstBox.x2; + rot_x1 = (src_h << 16) - y2; + rot_y1 = x1; + rot_x2 = (src_h << 16) - y1; + rot_y2 = x2; + break; + } + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + dstPitch = ((dst_width << 1) + 15) & ~15; + srcPitch = (width + 3) & ~3; + srcPitch2 = ((width >> 1) + 3) & ~3; + size = dstPitch * (int) dst_height; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + dstPitch = ((dst_width << 1) + 15) & ~15; + srcPitch = (width << 1); + size = dstPitch * (int) dst_height; + break; + } + + pPortPriv->offset = nvidias->off_screen - (CARD8 *) nvidias->vesa.fb; + /* fixup pointers */ + + pPortPriv->YBuf0Offset = pPortPriv->offset; + pPortPriv->YBuf1Offset = pPortPriv->offset + size; + +#if 0 + nvidiaWaitIdle (reg); + + if (pPortPriv->videoOn) + { + /* wait for buffer to be displayed */ + while (((media->TRIG_CNTL >> 5) & 1) != pPortPriv->currentBuf) + ; + } +#endif + /* + * Use the other buffer + */ + pPortPriv->currentBuf = 1 - pPortPriv->currentBuf; + + /* copy data */ + top = rot_y1 >> 16; + left = (rot_x1 >> 16) & ~1; + npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top; + nvidiaCopyPlanarData(screen, buf, randr, + srcPitch, srcPitch2, dstPitch, + rot_src_w, rot_src_h, height, + top, left, nlines, npixels, id); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + nlines = ((rot_y2 + 0xffff) >> 16) - top; + nvidiaCopyPackedData(screen, buf, randr, + srcPitch, dstPitch, + rot_src_w, rot_src_h, + top, left, nlines, + npixels); + break; + } + + nvidiaDisplayVideo(screen, id, dstPitch, + rot_x1, rot_y1, rot_x2, rot_y2, + dst_x1, dst_y1, + dst_x2, dst_y2, + rot_src_w, rot_src_h, rot_drw_w, rot_drw_h); + + /* update cliplist */ + if (!REGION_EQUAL (screen->pScreen, &pPortPriv->clip, clipBoxes)) + { + REGION_COPY (screen->pScreen, &pPortPriv->clip, clipBoxes); + nvidiaPaintRegion (screen->pScreen, &pPortPriv->clip, pPortPriv->colorKey); + } + + pPortPriv->videoOn = TRUE; + + return Success; +} + +static int +nvidiaQueryImageAttributes(KdScreenInfo *screen, + int id, + unsigned short *w, + unsigned short *h, + int *pitches, + int *offsets) +{ + int size, tmp; + + if(*w > IMAGE_MAX_WIDTH) + *w = IMAGE_MAX_WIDTH; + if(*h > IMAGE_MAX_HEIGHT) + *h = IMAGE_MAX_HEIGHT; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) + pitches[0] = size; + size *= *h; + if(offsets) + offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) + pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) + offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if(pitches) + pitches[0] = size; + size *= *h; + break; + } + + return size; +} + + +/* client libraries expect an encoding */ +static KdVideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} + } +}; + +#define NUM_FORMATS 3 + +static KdVideoFormatRec Formats[NUM_FORMATS] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 3 + +static KdAttributeRec Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"}, + {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"} +}; + +#define NUM_IMAGES 4 + +static KdImageRec Images[NUM_IMAGES] = +{ + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_UYVY +}; + +static void nvidiaResetVideo(KdScreenInfo *screen) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + NvidiaPortPrivPtr pPortPriv = nvidias->pAdaptor->pPortPrivates[0].ptr; + MediaReg *media = nvidiac->media_reg; + + /* + * Default to maximum image size in YV12 + */ + +} + +static int +nvidiaReputImage (KdScreenInfo *screen, + short drw_x, + short drw_y, + RegionPtr clipBoxes, + pointer data) +{ + ScreenPtr pScreen = screen->pScreen; + NvidiaPortPrivPtr pPortPriv = (NvidiaPortPrivPtr)data; + BoxPtr pOldExtents = REGION_EXTENTS (pScreen, &pPortPriv->clip); + BoxPtr pNewExtents = REGION_EXTENTS (pScreen, clipBoxes); + + if (pOldExtents->x1 == pNewExtents->x1 && + pOldExtents->x2 == pNewExtents->x2 && + pOldExtents->y1 == pNewExtents->y1 && + pOldExtents->y2 == pNewExtents->y2) + { + /* update cliplist */ + if (!REGION_EQUAL (screen->pScreen, &pPortPriv->clip, clipBoxes)) + { + REGION_COPY (screen->pScreen, &pPortPriv->clip, clipBoxes); + nvidiaPaintRegion (screen->pScreen, &pPortPriv->clip, pPortPriv->colorKey); + } + return Success; + } + return BadMatch; +} + +static KdVideoAdaptorPtr +nvidiaSetupImageVideo(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + nvidiaCardInfo(pScreenPriv); + nvidiaScreenInfo(pScreenPriv); + KdScreenInfo *screen = pScreenPriv->screen; + KdCardInfo *card = pScreenPriv->card; + KdVideoAdaptorPtr adapt; + NvidiaPortPrivPtr pPortPriv; + + if(!(adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) + + sizeof(NvidiaPortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "Nvidia Video Overlay"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + + pPortPriv = (NvidiaPortPrivPtr)(&adapt->pPortPrivates[1]); + + adapt->pPortPrivates[0].ptr = (pointer)(pPortPriv); + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = nvidiaStopVideo; + adapt->SetPortAttribute = nvidiaSetPortAttribute; + adapt->GetPortAttribute = nvidiaGetPortAttribute; + adapt->QueryBestSize = nvidiaQueryBestSize; + adapt->PutImage = nvidiaPutImage; + adapt->ReputImage = nvidiaReputImage; + adapt->QueryImageAttributes = nvidiaQueryImageAttributes; + + pPortPriv->colorKey = nvidias->colorKey; + pPortPriv->videoOn = FALSE; + pPortPriv->brightness = 0; + pPortPriv->saturation = 0; + pPortPriv->currentBuf = 0; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0); + + nvidias->pAdaptor = adapt; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + + nvidiaResetVideo(screen); + + return adapt; +} + +Bool nvidiaInitVideo(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL; + KdVideoAdaptorPtr newAdaptor = NULL; + int num_adaptors; + KdCardInfo *card = pScreenPriv->card; + NvidiaScreenInfo *nvidias = (NvidiaScreenInfo *) screen->driver; + NvidiaCardInfo *nvidiac = (NvidiaCardInfo *) card->driver; + + if (!nvidiac->media_reg) + return FALSE; + + newAdaptor = nvidiaSetupImageVideo(pScreen); + + num_adaptors = KdXVListGenericAdaptors(screen, &adaptors); + + if(newAdaptor) + { + if(!num_adaptors) + { + num_adaptors = 1; + adaptors = &newAdaptor; + } + else + { + newAdaptors = xalloc((num_adaptors + 1) * + sizeof(KdVideoAdaptorPtr*)); + if(newAdaptors) + { + memcpy(newAdaptors, adaptors, + num_adaptors * sizeof(KdVideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + KdXVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); + return TRUE; +} diff --git a/hw/kdrive/vesa/Makefile.am b/hw/kdrive/vesa/Makefile.am index 2338672a8..8bfb8a919 100644 --- a/hw/kdrive/vesa/Makefile.am +++ b/hw/kdrive/vesa/Makefile.am @@ -31,10 +31,12 @@ Xvesa_LDADD = \ $(top_builddir)/miext/shadow/libshadow.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/fb/libfb.a \ $(top_builddir)/mi/libmi.a \ $(top_builddir)/Xext/libXext.a \ $(top_builddir)/randr/librandr.a \ $(top_builddir)/render/librender.a \ + $(top_builddir)/xfixes/libxfixes.a \ $(top_builddir)/dix/libxpstubs.a \ $(XSERVER_LIBS) diff --git a/hw/kdrive/vesa/Xvesa.man b/hw/kdrive/vesa/Xvesa.man index c09defdb6..fdac902ca 100644 --- a/hw/kdrive/vesa/Xvesa.man +++ b/hw/kdrive/vesa/Xvesa.man @@ -15,6 +15,7 @@ running the video BIOS in VM86 mode. .B Xvesa can use both standard VGA BIOS modes and any modes advertised by a VESA BIOS if available. + .B Xvesa runs untrusted code with full privileges, and is therefore a fairly insecure X server. @@ -29,8 +30,8 @@ specifies the VESA video mode to use. If mode .I n is not supported by your BIOS and hardware, .B Xvesa -will fail, hang your system, or cause your monitor to explode; you are -on your own. This option overrides any +will fail, hang your system, damage your hardware, or cause a global +thermonuclear war; you are on your own. This option overrides any .B -screen options. .TP 8 @@ -60,10 +61,24 @@ want to use this option. pass RGB values in the order that works on broken BIOSes. Use this if the colours are wrong in PseudoColor and 16 colour modes. .TP 8 +.B -map-holes +use a contiguous (hole-less) memory map. This fixes a segmentation +violation with some rare BIOSes that violate the VESA specification, +but may cause slightly higher memory usage on systems that overcommit +memory. +.TP 8 .B -verbose emit diagnostic messages during BIOS initialization and teardown. .SH KEYBOARD -To be written. +Multiple key presses recognized directly by +.B Xvesa +are: +.TP 8 +.B Ctrl+Alt+Backspace +Immediately kill the server. +.TP 8 +.B Ctrl+Alt+F1...F12 +Switch to virtual console 1 through 12. .SH BUGS .B Xvesa opens all IO ports and runs your VESA BIOS, which may be assumed to be diff --git a/hw/kdrive/vesa/vesa.c b/hw/kdrive/vesa/vesa.c index 4913dbd79..52cc3bcfa 100644 --- a/hw/kdrive/vesa/vesa.c +++ b/hw/kdrive/vesa/vesa.c @@ -38,6 +38,7 @@ Bool vesa_restore = FALSE; Bool vesa_verbose = FALSE; Bool vesa_force_text = FALSE; Bool vesa_restore_font = TRUE; +Bool vesa_map_holes = TRUE; #define VesaPriv(scr) ((VesaScreenPrivPtr) (scr)->driver) @@ -202,7 +203,7 @@ vesaInitialize (KdCardInfo *card, VesaCardPrivPtr priv) { int code; - priv->vi = Vm86Setup(); + priv->vi = Vm86Setup(vesa_map_holes); if(!priv->vi) goto fail; @@ -231,7 +232,7 @@ vesaListModes (void) int nmode; int n; - vi = Vm86Setup (); + vi = Vm86Setup (vesa_map_holes); if (!vi) { ErrorF ("Can't setup vm86\n"); @@ -267,7 +268,7 @@ vesaTestMode (void) int nmode; int n; - vi = Vm86Setup (); + vi = Vm86Setup (vesa_map_holes); if (!vi) { ErrorF ("Can't setup vm86\n"); @@ -1854,6 +1855,12 @@ vesaProcessArgument (int argc, char **argv, int i) } 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; diff --git a/hw/kdrive/vesa/vm86.c b/hw/kdrive/vesa/vm86.c index b5a3983ea..da85b83a9 100644 --- a/hw/kdrive/vesa/vm86.c +++ b/hw/kdrive/vesa/vm86.c @@ -66,10 +66,11 @@ static const U8 retcode_data[2] = { 0xCD, 0xFF }; Vm86InfoPtr -Vm86Setup(void) +Vm86Setup(int mapHoles) { int devmem = -1, devzero = -1; void *magicMem, *loMem, *hiMem; + void *hole1, *hole2; U32 stack_base, ret_code; Vm86InfoPtr vi = NULL; @@ -85,6 +86,12 @@ Vm86Setup(void) goto fail; } + magicMem = MAP_FAILED; + loMem = MAP_FAILED; + hiMem = MAP_FAILED; + hole1 = MAP_FAILED; + hole2 = MAP_FAILED; + magicMem = mmap((void*)MAGICMEM_BASE, MAGICMEM_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, @@ -92,7 +99,18 @@ Vm86Setup(void) if(magicMem == MAP_FAILED) { ErrorF("Couldn't map magic memory\n"); - goto fail; + goto unmapfail; + } + + if(mapHoles) { + hole1 = mmap((void*)HOLE1_BASE, HOLE1_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_FIXED, devzero, HOLE1_BASE); + + if(hole1 == MAP_FAILED) { + ErrorF("Couldn't map first hole\n"); + goto unmapfail; + } } loMem = mmap((void*)LOMEM_BASE, LOMEM_SIZE, @@ -101,7 +119,18 @@ Vm86Setup(void) if(loMem == MAP_FAILED) { ErrorF("Couldn't map low memory\n"); munmap(magicMem, MAGICMEM_SIZE); - goto fail; + goto unmapfail; + } + + if(mapHoles) { + hole2 = mmap((void*)HOLE2_BASE, HOLE2_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_FIXED, devzero, HOLE2_BASE); + + if(hole2 == MAP_FAILED) { + ErrorF("Couldn't map first hole\n"); + goto unmapfail; + } } hiMem = mmap((void*)HIMEM_BASE, HIMEM_SIZE, @@ -110,9 +139,7 @@ Vm86Setup(void) devmem, HIMEM_BASE); if(hiMem == MAP_FAILED) { ErrorF("Couldn't map high memory\n"); - munmap(magicMem, MAGICMEM_SIZE); - munmap(loMem, LOMEM_SIZE); - goto fail; + goto unmapfail; } vi = xalloc(sizeof(Vm86InfoRec)); @@ -120,7 +147,9 @@ Vm86Setup(void) goto unmapfail; vi->magicMem = magicMem; + vi->hole1 = hole1; vi->loMem = loMem; + vi->hole2 = hole2; vi->hiMem = hiMem; vi->brk = LOMEM_BASE; @@ -150,9 +179,11 @@ Vm86Setup(void) return vi; unmapfail: - munmap(magicMem, MAGICMEM_SIZE); - munmap(loMem, LOMEM_SIZE); - munmap(hiMem, HIMEM_SIZE); + if(magicMem != MAP_FAILED) munmap(magicMem, MAGICMEM_SIZE); + if(hole1 != MAP_FAILED) munmap(magicMem, HOLE1_SIZE); + if(loMem != MAP_FAILED) munmap(loMem, LOMEM_SIZE); + if(hole2 != MAP_FAILED) munmap(magicMem, HOLE2_SIZE); + if(hiMem != MAP_FAILED) munmap(hiMem, HIMEM_SIZE); fail: if(devmem >= 0) close(devmem); @@ -166,9 +197,11 @@ fail: void Vm86Cleanup(Vm86InfoPtr vi) { - munmap(vi->magicMem, MAGICMEM_SIZE); - munmap(vi->loMem, LOMEM_SIZE); - munmap(vi->hiMem, HIMEM_SIZE); + if(vi->magicMem != MAP_FAILED) munmap(vi->magicMem, MAGICMEM_SIZE); + if(vi->hole1 != MAP_FAILED) munmap(vi->magicMem, HOLE1_SIZE); + if(vi->loMem != MAP_FAILED) munmap(vi->loMem, LOMEM_SIZE); + if(vi->hole2 != MAP_FAILED) munmap(vi->magicMem, HOLE2_SIZE); + if(vi->hiMem != MAP_FAILED) munmap(vi->hiMem, HIMEM_SIZE); xfree(vi); } diff --git a/hw/kdrive/vesa/vm86.h b/hw/kdrive/vesa/vm86.h index e37cd7f28..dce777b39 100644 --- a/hw/kdrive/vesa/vm86.h +++ b/hw/kdrive/vesa/vm86.h @@ -91,6 +91,12 @@ typedef unsigned int U32; #define HIMEM_BASE 0xA0000 #define HIMEM_SIZE (SYSMEM_BASE + SYSMEM_SIZE - HIMEM_BASE) +#define HOLE1_BASE (MAGICMEM_BASE + MAGICMEM_SIZE) +#define HOLE1_SIZE (LOMEM_BASE - HOLE1_BASE) + +#define HOLE2_BASE (LOMEM_BASE + LOMEM_SIZE) +#define HOLE2_SIZE (HIMEM_BASE - HOLE2_BASE) + /* The BIOS ROM */ #define ROM_BASE 0xC0000 #define ROM_SIZE 0x30000 @@ -105,6 +111,7 @@ typedef unsigned int U32; typedef struct _Vm86InfoRec { void *magicMem, *loMem, *hiMem; + void *hole1, *hole2; U32 brk; struct vm86_struct vms; U32 ret_code, stack_base; @@ -121,7 +128,7 @@ typedef struct _Vm86InfoRec { #define HML(vi,i) (*(U32*)(&MM(vi,i))) Vm86InfoPtr -Vm86Setup(void); +Vm86Setup(int); void Vm86Cleanup(Vm86InfoPtr vi);