summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2001-03-30 02:18:41 +0000
committerKeith Packard <keithp@keithp.com>2001-03-30 02:18:41 +0000
commiteb3da37564593b7c9fb574af824e2f5e0cc6bb24 (patch)
tree76013708fc6c1027221b5d05858fe34cc9152d19
parentf39a62d122b6e63e2971d8593bf6b24933f66ec8 (diff)
Add files for Xmuu and i810 driver
-rw-r--r--hw/kdrive/i810/Imakefile21
-rw-r--r--hw/kdrive/i810/i810.c2096
-rw-r--r--hw/kdrive/i810/i810.h503
-rw-r--r--hw/kdrive/i810/i810_cursor.c409
-rw-r--r--hw/kdrive/i810/i810_reg.h696
-rw-r--r--hw/kdrive/i810/i810_video.c1165
-rw-r--r--hw/kdrive/i810/i810draw.c603
-rw-r--r--hw/kdrive/i810/i810draw.h46
-rw-r--r--hw/kdrive/i810/i810stub.c80
-rw-r--r--hw/kdrive/linux/agp.c348
-rw-r--r--hw/kdrive/linux/agp.h70
-rw-r--r--hw/kdrive/src/kxv.c1784
-rw-r--r--hw/kdrive/src/kxv.h302
13 files changed, 8123 insertions, 0 deletions
diff --git a/hw/kdrive/i810/Imakefile b/hw/kdrive/i810/Imakefile
new file mode 100644
index 000000000..d967f197b
--- /dev/null
+++ b/hw/kdrive/i810/Imakefile
@@ -0,0 +1,21 @@
+XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $
+XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/i810/Imakefile,v 1.6 2000/10/20 00:19:51 keithp Exp $
+KDRIVE=..
+#include "../Kdrive.tmpl"
+
+#if BuildXvExt
+XVSRCS = i810_video.c
+XVOBJS = i810_video.o
+#endif
+
+SRCS = i810.c i810stub.c i810draw.c i810_cursor.c $(XVSRCS)
+
+OBJS = i810.o i810stub.o i810draw.o i810_cursor.o $(XVOBJS)
+
+DEFINES = XvExtensionDefines /* -DI810CFG_SHOW_OVERSCAN */
+
+INCLUDES = -I. $(KDINCS)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(i810,$(OBJS))
+DependTarget()
diff --git a/hw/kdrive/i810/i810.c b/hw/kdrive/i810/i810.c
new file mode 100644
index 000000000..bb9cc5ad4
--- /dev/null
+++ b/hw/kdrive/i810/i810.c
@@ -0,0 +1,2096 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+
+/* $XFree86$ */
+
+/*
+ * i810.c - KDrive driver for the i810 chipset
+ *
+ * Authors:
+ * Pontus Lidman <pontus.lidman@nokia.com>
+ *
+ */
+
+#include "kdrive.h"
+#include "kxv.h"
+
+#include "i810.h"
+#include "linux/agp.h"
+
+#include "i810draw.h"
+
+Bool i810InitVideo(ScreenPtr pScreen);
+
+#ifndef I810_DEBUG
+int I810_DEBUG = (0
+/* | DEBUG_ALWAYS_SYNC */
+/* | DEBUG_VERBOSE_ACCEL */
+/* | DEBUG_VERBOSE_SYNC */
+/* | DEBUG_VERBOSE_VGA */
+/* | DEBUG_VERBOSE_RING */
+/* | DEBUG_VERBOSE_OUTREG */
+/* | DEBUG_VERBOSE_MEMORY */
+/* | DEBUG_VERBOSE_CURSOR */
+ );
+#endif
+
+
+static Bool
+i810ModeInit(KdScreenInfo *screen, const KdMonitorTiming *t);
+
+static void
+i810PrintMode( vgaRegPtr vgaReg, I810RegPtr mode );
+
+Bool
+i810CardInit (KdCardInfo *card)
+{
+ int i;
+
+ I810CardInfo *i810c;
+
+/* fprintf(stderr,"i810CardInit\n"); */
+
+ i810c = (I810CardInfo *) xalloc (sizeof (I810CardInfo));
+
+ if (!i810c)
+ return FALSE;
+
+ /* 2MB Video RAM */
+ i810c->videoRam=2048;
+
+ /* Find FB address */
+
+ if (card->attr.address[1] != 0) {
+ i810c->LinearAddr = card->attr.address[0] & 0xFF000000;
+
+ if (!i810c->LinearAddr) {
+ fprintf(stderr,"No valid FB address in PCI config space(1)\n");
+ xfree(i810c);
+ return FALSE;
+ } else {
+/* fprintf(stderr,"Linear framebuffer at %lx\n",i810c->LinearAddr); */
+ }
+ } else {
+ fprintf(stderr,"No valid FB address in PCI config space(2)\n");
+ xfree(i810c);
+ return FALSE;
+ }
+
+ if (card->attr.address[1]) {
+
+ i810c->MMIOAddr = card->attr.address[1] & 0xFFF80000;
+
+ i810c->MMIOBase =
+ KdMapDevice (i810c->MMIOAddr, I810_REG_SIZE);
+ if (!i810c->MMIOBase) {
+ fprintf(stderr,"No valid MMIO address in PCI config space(1)\n");
+ xfree(i810c);
+ return FALSE;
+ } else {
+
+ }
+ } else {
+ fprintf(stderr,"No valid MMIO address in PCI config space(2)\n");
+ xfree(i810c);
+ return FALSE;
+ }
+
+/* fprintf(stderr,"Mapped 0x%x bytes of MMIO regs at phys 0x%lx virt %p\n", */
+/* I810_REG_SIZE,i810c->MMIOAddr,i810c->MMIOBase); */
+
+ /* Find out memory bus frequency.
+ */
+
+ {
+ unsigned long *p;
+ unsigned char *LinuxGetPciCfg(KdCardAttr *attr);
+
+
+ if (!(p= (unsigned long *) LinuxGetPciCfg(&card->attr)))
+ return FALSE;
+
+/* fprintf(stderr,"Frequency long %lx\n",p[WHTCFG_PAMR_DRP]); */
+
+ if ( (p[WHTCFG_PAMR_DRP] & LM_FREQ_MASK) == LM_FREQ_133 )
+ i810c->LmFreqSel = 133;
+ else
+ i810c->LmFreqSel = 100;
+
+ xfree(p);
+
+/* fprintf(stderr,"Selected frequency %d\n",i810c->LmFreqSel); */
+ }
+
+/* fprintf(stderr,"Will alloc AGP framebuffer: %d kByte\n",i810c->videoRam); */
+
+ /* Since we always want write combining on first 32 mb of framebuffer
+ * we pass a mapsize of 32 mb */
+ i810c->FbMapSize = 32*1024*1024;
+
+ for (i = 2 ; i < i810c->FbMapSize ; i <<= 1);
+ i810c->FbMapSize = i;
+
+ i810c->FbBase =
+ KdMapDevice (i810c->LinearAddr, i810c->FbMapSize);
+
+ if (!i810c->FbBase) return FALSE;
+/* fprintf(stderr,"Mapped 0x%lx bytes of framebuffer at %p\n", */
+/* i810c->FbMapSize,i810c->FbBase); */
+
+ card->driver=i810c;
+
+ return TRUE;
+}
+
+void
+i810ScreenFini (KdScreenInfo *screen)
+{
+ I810ScreenInfo *i810s = (I810ScreenInfo *) screen->driver;
+
+ xfree (i810s);
+ screen->driver = 0;
+}
+
+Bool
+i810InitScreen (ScreenPtr pScreen) {
+
+#ifdef XV
+ i810InitVideo(pScreen);
+#endif
+ return TRUE;
+}
+
+void
+i810CardFini (KdCardInfo *card)
+{
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ KdUnmapDevice (i810c->FbBase, i810c->FbMapSize);
+ KdUnmapDevice (i810c->MMIOBase, I810_REG_SIZE);
+ xfree (i810c);
+ card->driver = 0;
+}
+
+struct wm_info {
+ double freq;
+ unsigned int wm;
+};
+
+struct wm_info i810_wm_8_100[] = {
+ { 0, 0x22003000 },
+ { 25.2, 0x22003000 },
+ { 28.0, 0x22003000 },
+ { 31.5, 0x22003000 },
+ { 36.0, 0x22007000 },
+ { 40.0, 0x22007000 },
+ { 45.0, 0x22007000 },
+ { 49.5, 0x22008000 },
+ { 50.0, 0x22008000 },
+ { 56.3, 0x22008000 },
+ { 65.0, 0x22008000 },
+ { 75.0, 0x22008000 },
+ { 78.8, 0x22008000 },
+ { 80.0, 0x22008000 },
+ { 94.0, 0x22008000 },
+ { 96.0, 0x22107000 },
+ { 99.0, 0x22107000 },
+ { 108.0, 0x22107000 },
+ { 121.0, 0x22107000 },
+ { 128.9, 0x22107000 },
+ { 132.0, 0x22109000 },
+ { 135.0, 0x22109000 },
+ { 157.5, 0x2210b000 },
+ { 162.0, 0x2210b000 },
+ { 175.5, 0x2210b000 },
+ { 189.0, 0x2220e000 },
+ { 202.5, 0x2220e000 }
+};
+
+struct wm_info i810_wm_16_100[] = {
+ { 0, 0x22004000 },
+ { 25.2, 0x22006000 },
+ { 28.0, 0x22006000 },
+ { 31.5, 0x22007000 },
+ { 36.0, 0x22007000 },
+ { 40.0, 0x22007000 },
+ { 45.0, 0x22007000 },
+ { 49.5, 0x22009000 },
+ { 50.0, 0x22009000 },
+ { 56.3, 0x22108000 },
+ { 65.0, 0x2210e000 },
+ { 75.0, 0x2210e000 },
+ { 78.8, 0x2210e000 },
+ { 80.0, 0x22210000 },
+ { 94.5, 0x22210000 },
+ { 96.0, 0x22210000 },
+ { 99.0, 0x22210000 },
+ { 108.0, 0x22210000 },
+ { 121.0, 0x22210000 },
+ { 128.9, 0x22210000 },
+ { 132.0, 0x22314000 },
+ { 135.0, 0x22314000 },
+ { 157.5, 0x22415000 },
+ { 162.0, 0x22416000 },
+ { 175.5, 0x22416000 },
+ { 189.0, 0x22416000 },
+ { 195.0, 0x22416000 },
+ { 202.5, 0x22416000 }
+};
+
+
+struct wm_info i810_wm_24_100[] = {
+ { 0, 0x22006000 },
+ { 25.2, 0x22009000 },
+ { 28.0, 0x22009000 },
+ { 31.5, 0x2200a000 },
+ { 36.0, 0x2210c000 },
+ { 40.0, 0x2210c000 },
+ { 45.0, 0x2210c000 },
+ { 49.5, 0x22111000 },
+ { 50.0, 0x22111000 },
+ { 56.3, 0x22111000 },
+ { 65.0, 0x22214000 },
+ { 75.0, 0x22214000 },
+ { 78.8, 0x22215000 },
+ { 80.0, 0x22216000 },
+ { 94.5, 0x22218000 },
+ { 96.0, 0x22418000 },
+ { 99.0, 0x22418000 },
+ { 108.0, 0x22418000 },
+ { 121.0, 0x22418000 },
+ { 128.9, 0x22419000 },
+ { 132.0, 0x22519000 },
+ { 135.0, 0x4441d000 },
+ { 157.5, 0x44419000 },
+ { 162.0, 0x44419000 },
+ { 175.5, 0x44419000 },
+ { 189.0, 0x44419000 },
+ { 195.0, 0x44419000 },
+ { 202.5, 0x44419000 }
+};
+
+struct wm_info i810_wm_32_100[] = {
+ { 0, 0x2210b000 },
+ { 60, 0x22415000 }, /* 0x314000 works too */
+ { 80, 0x22419000 } /* 0x518000 works too */
+};
+
+
+struct wm_info i810_wm_8_133[] = {
+ { 0, 0x22003000 },
+ { 25.2, 0x22003000 },
+ { 28.0, 0x22003000 },
+ { 31.5, 0x22003000 },
+ { 36.0, 0x22007000 },
+ { 40.0, 0x22007000 },
+ { 45.0, 0x22007000 },
+ { 49.5, 0x22008000 },
+ { 50.0, 0x22008000 },
+ { 56.3, 0x22008000 },
+ { 65.0, 0x22008000 },
+ { 75.0, 0x22008000 },
+ { 78.8, 0x22008000 },
+ { 80.0, 0x22008000 },
+ { 94.0, 0x22008000 },
+ { 96.0, 0x22107000 },
+ { 99.0, 0x22107000 },
+ { 108.0, 0x22107000 },
+ { 121.0, 0x22107000 },
+ { 128.9, 0x22107000 },
+ { 132.0, 0x22109000 },
+ { 135.0, 0x22109000 },
+ { 157.5, 0x2210b000 },
+ { 162.0, 0x2210b000 },
+ { 175.5, 0x2210b000 },
+ { 189.0, 0x2220e000 },
+ { 202.5, 0x2220e000 }
+};
+
+
+struct wm_info i810_wm_16_133[] = {
+ { 0, 0x22004000 },
+ { 25.2, 0x22006000 },
+ { 28.0, 0x22006000 },
+ { 31.5, 0x22007000 },
+ { 36.0, 0x22007000 },
+ { 40.0, 0x22007000 },
+ { 45.0, 0x22007000 },
+ { 49.5, 0x22009000 },
+ { 50.0, 0x22009000 },
+ { 56.3, 0x22108000 },
+ { 65.0, 0x2210e000 },
+ { 75.0, 0x2210e000 },
+ { 78.8, 0x2210e000 },
+ { 80.0, 0x22210000 },
+ { 94.5, 0x22210000 },
+ { 96.0, 0x22210000 },
+ { 99.0, 0x22210000 },
+ { 108.0, 0x22210000 },
+ { 121.0, 0x22210000 },
+ { 128.9, 0x22210000 },
+ { 132.0, 0x22314000 },
+ { 135.0, 0x22314000 },
+ { 157.5, 0x22415000 },
+ { 162.0, 0x22416000 },
+ { 175.5, 0x22416000 },
+ { 189.0, 0x22416000 },
+ { 195.0, 0x22416000 },
+ { 202.5, 0x22416000 }
+};
+
+struct wm_info i810_wm_24_133[] = {
+ { 0, 0x22006000 },
+ { 25.2, 0x22009000 },
+ { 28.0, 0x22009000 },
+ { 31.5, 0x2200a000 },
+ { 36.0, 0x2210c000 },
+ { 40.0, 0x2210c000 },
+ { 45.0, 0x2210c000 },
+ { 49.5, 0x22111000 },
+ { 50.0, 0x22111000 },
+ { 56.3, 0x22111000 },
+ { 65.0, 0x22214000 },
+ { 75.0, 0x22214000 },
+ { 78.8, 0x22215000 },
+ { 80.0, 0x22216000 },
+ { 94.5, 0x22218000 },
+ { 96.0, 0x22418000 },
+ { 99.0, 0x22418000 },
+ { 108.0, 0x22418000 },
+ { 121.0, 0x22418000 },
+ { 128.9, 0x22419000 },
+ { 132.0, 0x22519000 },
+ { 135.0, 0x4441d000 },
+ { 157.5, 0x44419000 },
+ { 162.0, 0x44419000 },
+ { 175.5, 0x44419000 },
+ { 189.0, 0x44419000 },
+ { 195.0, 0x44419000 },
+ { 202.5, 0x44419000 }
+};
+
+static void
+i810WriteControlMMIO(I810CardInfo *i810c, int addr, CARD8 index, CARD8 val) {
+ moutb(addr, index);
+ moutb(addr+1, val);
+}
+
+static CARD8
+i810ReadControlMMIO(I810CardInfo *i810c, int addr, CARD8 index) {
+ moutb(addr, index);
+ return minb(addr+1);
+}
+
+Bool
+i810ModeSupported (KdScreenInfo *screen, const KdMonitorTiming *t)
+{
+ /* This is just a guess. */
+ if (t->horizontal > 1600 || t->horizontal < 640) return FALSE;
+ if (t->vertical > 1200 || t->horizontal < 350) return FALSE;
+ return TRUE;
+}
+
+Bool
+i810ModeUsable (KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ int byte_width, pixel_width, screen_size;
+
+/* fprintf(stderr,"i810ModeUsable\n"); */
+
+ if (screen->fb[0].depth >= 24)
+ {
+ screen->fb[0].depth = 24;
+ screen->fb[0].bitsPerPixel = 24;
+ screen->dumb = TRUE;
+ }
+ else if (screen->fb[0].depth >= 16)
+ {
+ screen->fb[0].depth = 16;
+ screen->fb[0].bitsPerPixel = 16;
+ }
+ else if (screen->fb[0].depth >= 15)
+ {
+ screen->fb[0].depth = 15;
+ screen->fb[0].bitsPerPixel = 16;
+ }
+ else
+ {
+ screen->fb[0].depth = 8;
+ screen->fb[0].bitsPerPixel = 8;
+ }
+ byte_width = screen->width * (screen->fb[0].bitsPerPixel >> 3);
+ pixel_width = screen->width;
+
+ screen->fb[0].pixelStride = pixel_width;
+ screen->fb[0].byteStride = byte_width;
+
+ screen_size = byte_width * screen->height;
+
+ return screen_size <= (i810c->videoRam * 1024);
+}
+
+int i810AllocateGARTMemory( KdScreenInfo *screen )
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ unsigned long size = i810c->videoRam * 1024;
+
+ int key;
+ long tom = 0;
+ unsigned long physical;
+
+ if (!KdAgpGARTSupported())
+ return FALSE;
+
+ if (!KdAcquireGART(screen->mynum))
+ return FALSE;
+
+ /* This allows the 2d only Xserver to regen */
+ i810c->agpAcquired2d = TRUE;
+
+ /* Treat the gart like video memory - we assume we own all that is
+ * there, so ignore EBUSY errors. Don't try to remove it on
+ * failure, either, as other X server may be using it.
+ */
+
+ if ((key = KdAllocateGARTMemory(screen->mynum, size, 0, NULL)) == -1)
+ return FALSE;
+
+ i810c->VramOffset = 0;
+ i810c->VramKey = key;
+
+ if (!KdBindGARTMemory(screen->mynum, key, 0))
+ return FALSE;
+
+
+ i810c->SysMem.Start = 0;
+ i810c->SysMem.Size = size;
+ i810c->SysMem.End = size;
+ i810c->SavedSysMem = i810c->SysMem;
+
+ tom = i810c->SysMem.End;
+
+ i810c->DcacheMem.Start = 0;
+ i810c->DcacheMem.End = 0;
+ i810c->DcacheMem.Size = 0;
+ i810c->CursorPhysical = 0;
+
+ /* Dcache - half the speed of normal ram, so not really useful for
+ * a 2d server. Don't bother reporting its presence. This is
+ * mapped in addition to the requested amount of system ram.
+ */
+ size = 1024 * 4096;
+
+ /* Keep it 512K aligned for the sake of tiled regions.
+ */
+ tom += 0x7ffff;
+ tom &= ~0x7ffff;
+
+ if ((key = KdAllocateGARTMemory(screen->mynum, size, AGP_DCACHE_MEMORY, NULL)) != -1) {
+ i810c->DcacheOffset= tom;
+ i810c->DcacheKey = key;
+ if (!KdBindGARTMemory(screen->mynum, key, tom)) {
+ fprintf(stderr,"Allocation of %ld bytes for DCACHE failed\n", size);
+ i810c->DcacheKey = -1;
+ } else {
+ i810c->DcacheMem.Start = tom;
+ i810c->DcacheMem.Size = size;
+ i810c->DcacheMem.End = i810c->DcacheMem.Start + i810c->DcacheMem.Size;
+ tom = i810c->DcacheMem.End;
+ }
+ } else {
+ fprintf(stderr,
+ "No physical memory available for %ld bytes of DCACHE\n",
+ size);
+ i810c->DcacheKey = -1;
+ }
+
+ /* Mouse cursor -- The i810 (crazy) needs a physical address in
+ * system memory from which to upload the cursor. We get this from
+ * the agpgart module using a special memory type.
+ */
+
+ /* 4k for the cursor is excessive, I'm going to steal 3k for
+ * overlay registers later
+ */
+
+ size = 4096;
+
+ if ((key = KdAllocateGARTMemory(screen->mynum, size, AGP_PHYS_MEMORY,
+ &physical)) == -1) {
+ fprintf(stderr,
+ "No physical memory available for HW cursor\n");
+ i810c->HwcursKey = -1;
+ } else {
+ i810c->HwcursOffset= tom;
+ i810c->HwcursKey = key;
+ if (!KdBindGARTMemory(screen->mynum, key, tom)) {
+ fprintf(stderr,
+ "Allocation of %ld bytes for HW cursor failed\n",
+ size);
+ i810c->HwcursKey = -1;
+ } else {
+ i810c->CursorPhysical = physical;
+ i810c->CursorStart = tom;
+ tom += size;
+ }
+ }
+
+ /* Overlay register buffer -- Just like the cursor, the i810 needs a
+ * physical address in system memory from which to upload the overlay
+ * registers.
+ */
+ if (i810c->CursorStart != 0) {
+ i810c->OverlayPhysical = i810c->CursorPhysical + 1024;
+ i810c->OverlayStart = i810c->CursorStart + 1024;
+ }
+
+
+ i810c->GttBound = 1;
+
+ return TRUE;
+}
+
+/* Allocate from a memrange, returns success */
+
+int i810AllocLow( I810MemRange *result, I810MemRange *pool, int size )
+{
+ if (size > pool->Size) return FALSE;
+
+ pool->Size -= size;
+ result->Size = size;
+ result->Start = pool->Start;
+ result->End = pool->Start += size;
+ return TRUE;
+}
+
+int i810AllocHigh( I810MemRange *result, I810MemRange *pool, int size )
+{
+ if (size > pool->Size) return 0;
+
+ pool->Size -= size;
+ result->Size = size;
+ result->End = pool->End;
+ result->Start = pool->End -= size;
+ return 1;
+}
+
+Bool
+i810AllocateFront(KdScreenInfo *screen) {
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ int cache_lines = -1;
+
+ if(i810c->DoneFrontAlloc)
+ return TRUE;
+
+ memset(&(i810c->FbMemBox), 0, sizeof(BoxRec));
+ /* Alloc FrontBuffer/Ring/Accel memory */
+ i810c->FbMemBox.x1=0;
+ i810c->FbMemBox.x2=screen->width;
+ i810c->FbMemBox.y1=0;
+ i810c->FbMemBox.y2=screen->height;
+
+ /* This could be made a command line option */
+ cache_lines = 0;
+
+ if(cache_lines >= 0)
+ i810c->FbMemBox.y2 += cache_lines;
+ else {
+ /* make sure there is enough for two DVD sized YUV buffers */
+ i810c->FbMemBox.y2 += (screen->fb[0].depth == 24) ? 256 : 384;
+ if (screen->width <= 1024)
+ i810c->FbMemBox.y2 += (screen->fb[0].depth == 24) ? 256 : 384;
+ cache_lines = i810c->FbMemBox.y2 - screen->height;
+ }
+
+ if (I810_DEBUG)
+ ErrorF("Adding %i scanlines for pixmap caching\n", cache_lines);
+
+ /* Reserve room for the framebuffer and pixcache. Put at the top
+ * of memory so we can have nice alignment for the tiled regions at
+ * the start of memory.
+ */
+ i810AllocLow( &(i810c->FrontBuffer),
+ &(i810c->SysMem),
+ ((i810c->FbMemBox.x2 *
+ i810c->FbMemBox.y2 *
+ i810c->cpp) + 4095) & ~4095);
+
+ memset( &(i810c->LpRing), 0, sizeof( I810RingBuffer ) );
+ if(i810AllocLow( &(i810c->LpRing.mem), &(i810c->SysMem), 16*4096 )) {
+ if (I810_DEBUG & DEBUG_VERBOSE_MEMORY)
+ ErrorF( "ring buffer at local %lx\n",
+ i810c->LpRing.mem.Start);
+
+ i810c->LpRing.tail_mask = i810c->LpRing.mem.Size - 1;
+ i810c->LpRing.virtual_start = i810c->FbBase + i810c->LpRing.mem.Start;
+ i810c->LpRing.head = 0;
+ i810c->LpRing.tail = 0;
+ i810c->LpRing.space = 0;
+ }
+
+ if ( i810AllocLow( &i810c->Scratch, &(i810c->SysMem), 64*1024 ) ||
+ i810AllocLow( &i810c->Scratch, &(i810c->SysMem), 16*1024 ) ) {
+ if (I810_DEBUG & DEBUG_VERBOSE_MEMORY)
+ ErrorF("Allocated Scratch Memory\n");
+ }
+
+#ifdef XV
+ /* 720x720 is just how much memory the mpeg player needs for overlays */
+
+ if ( i810AllocHigh( &i810c->XvMem, &(i810c->SysMem), 720*720*2 )) {
+ if (I810_DEBUG & DEBUG_VERBOSE_MEMORY)
+ ErrorF("Allocated overlay Memory\n");
+ }
+#endif
+
+ i810c->DoneFrontAlloc = TRUE;
+ return TRUE;
+}
+
+static Bool
+i810MapMem(KdScreenInfo *screen)
+{
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ i810c->LpRing.virtual_start = i810c->FbBase + i810c->LpRing.mem.Start;
+
+ return TRUE;
+}
+
+
+Bool
+i810ScreenInit (KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ I810ScreenInfo *i810s;
+
+ int i;
+
+ const KdMonitorTiming *t;
+
+/* fprintf(stderr,"i810ScreenInit\n"); */
+
+ i810s = (I810ScreenInfo *) xalloc (sizeof (I810ScreenInfo));
+ if (!i810s)
+ return FALSE;
+
+ memset (i810s, '\0', sizeof (I810ScreenInfo));
+
+ /* Default dimensions */
+ if (!screen->width || !screen->height)
+ {
+ screen->width = 720;
+ screen->height = 576;
+ screen->rate = 52;
+#if 0
+ screen->width = 1024;
+ screen->height = 768;
+ screen->rate = 72;
+#endif
+ }
+
+ if (!screen->fb[0].depth)
+ screen->fb[0].depth = 16;
+
+ t = KdFindMode (screen, i810ModeSupported);
+
+ screen->rate = t->rate;
+ screen->width = t->horizontal;
+ screen->height = t->vertical;
+
+ if (!KdTuneMode (screen, i810ModeUsable, i810ModeSupported))
+ {
+ xfree (i810c);
+ return FALSE;
+ }
+
+/* fprintf(stderr,"Screen rate %d horiz %d vert %d\n",t->rate,t->horizontal,t->vertical); */
+
+ switch (screen->fb[0].depth) {
+ case 8:
+ screen->fb[0].visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ screen->fb[0].blueMask = 0x00;
+ screen->fb[0].greenMask = 0x00;
+ screen->fb[0].redMask = 0x00;
+ break;
+ case 15:
+ screen->fb[0].visuals = (1 << TrueColor);
+ screen->fb[0].blueMask = 0x001f;
+ screen->fb[0].greenMask = 0x03e0;
+ screen->fb[0].redMask = 0x7c00;
+
+ i810c->colorKey = 0x043f;
+
+ break;
+ case 16:
+ screen->fb[0].visuals = (1 << TrueColor);
+ screen->fb[0].blueMask = 0x001f;
+ screen->fb[0].greenMask = 0x07e0;
+ screen->fb[0].redMask = 0xf800;
+
+ i810c->colorKey = 0x083f;
+
+ break;
+ case 24:
+ screen->fb[0].visuals = (1 << TrueColor);
+ screen->fb[0].blueMask = 0x0000ff;
+ screen->fb[0].greenMask = 0x00ff00;
+ screen->fb[0].redMask = 0xff0000;
+
+ i810c->colorKey = 0x0101ff;
+
+ break;
+ default:
+ fprintf(stderr,"Unsupported depth %d\n",screen->fb[0].depth);
+ return FALSE;
+ }
+
+
+
+ /* Set all colours to black */
+ for (i=0; i<768; i++) i810c->vga.ModeReg.DAC[i] = 0x00;
+
+ /* ... and the overscan */
+ if (screen->fb[0].depth >= 4)
+ i810c->vga.ModeReg.Attribute[OVERSCAN] = 0xFF;
+
+ /* Could be made a command-line option */
+
+#ifdef I810CFG_SHOW_OVERSCAN
+ i810c->vga.ModeReg.DAC[765] = 0x3F;
+ i810c->vga.ModeReg.DAC[766] = 0x00;
+ i810c->vga.ModeReg.DAC[767] = 0x3F;
+ i810c->vga.ModeReg.Attribute[OVERSCAN] = 0xFF;
+ i810c->vga.ShowOverscan = TRUE;
+#else
+ i810c->vga.ShowOverscan = FALSE;
+#endif
+
+ i810c->vga.paletteEnabled = FALSE;
+ i810c->vga.cmapSaved = FALSE;
+ i810c->vga.MMIOBase = i810c->MMIOBase;
+
+ i810c->cpp = screen->fb[0].bitsPerPixel/8;
+
+ /* move to initscreen? */
+
+ switch (screen->fb[0].bitsPerPixel) {
+ case 8:
+ i810c->MaxClock = 203000;
+ break;
+ case 16:
+ i810c->MaxClock = 163000;
+ break;
+ case 24:
+ i810c->MaxClock = 136000;
+ break;
+ case 32: /* not supported */
+ i810c->MaxClock = 86000;
+ default:
+ fprintf(stderr,"Unsupported bpp %d\n",screen->fb[0].bitsPerPixel);
+ return FALSE;
+ }
+
+ if (!i810AllocateGARTMemory( screen )) {
+ return FALSE;
+ }
+
+ i810AllocateFront(screen);
+
+ /* Map LpRing memory */
+ if (!i810MapMem(screen)) return FALSE;
+
+ screen->fb[0].frameBuffer = i810c->FbBase;
+
+ screen->driver = i810s;
+
+ return TRUE;
+}
+
+/*
+ * I810Save --
+ *
+ * This function saves the video state. It reads all of the SVGA registers
+ * into the vgaI810Rec data structure. There is in general no need to
+ * mask out bits here - just read the registers.
+ */
+static void
+DoSave(KdCardInfo *card, vgaRegPtr vgaReg, I810RegPtr i810Reg, Bool saveFonts)
+{
+
+ I810CardInfo *i810c = card->driver;
+ i810VGAPtr vgap = &i810c->vga;
+
+ int i;
+
+ /* Save VGA registers */
+
+ vgaReg->MiscOutReg = mmioReadMiscOut(vgap);
+ if (vgaReg->MiscOutReg & 0x01)
+ vgap->IOBase = VGA_IOBASE_COLOR;
+ else
+ vgap->IOBase = VGA_IOBASE_MONO;
+
+ for (i = 0; i < VGA_NUM_CRTC; i++) {
+ vgaReg->CRTC[i] = mmioReadCrtc(vgap, i);
+ }
+
+ mmioEnablePalette(vgap);
+ for (i = 0; i < VGA_NUM_ATTR; i++) {
+ vgaReg->Attribute[i] = mmioReadAttr(vgap, i);
+ }
+ mmioDisablePalette(vgap);
+
+ for (i = 0; i < VGA_NUM_GFX; i++) {
+ vgaReg->Graphics[i] = mmioReadGr(vgap, i);
+ }
+
+ for (i = 1; i < VGA_NUM_SEQ; i++) {
+ vgaReg->Sequencer[i] = mmioReadSeq(vgap, i);
+ }
+
+ /*
+ * The port I/O code necessary to read in the extended registers
+ * into the fields of the I810Rec structure goes here.
+ */
+ i810Reg->IOControl = mmioReadCrtc(vgap, IO_CTNL);
+ i810Reg->AddressMapping = i810ReadControlMMIO(i810c, GRX, ADDRESS_MAPPING);
+ i810Reg->BitBLTControl = INREG8(BITBLT_CNTL);
+ i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M);
+ i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N);
+ i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL);
+
+ i810Reg->ExtVertTotal=mmioReadCrtc(vgap, EXT_VERT_TOTAL);
+ i810Reg->ExtVertDispEnd=mmioReadCrtc(vgap, EXT_VERT_DISPLAY);
+ i810Reg->ExtVertSyncStart=mmioReadCrtc(vgap, EXT_VERT_SYNC_START);
+ i810Reg->ExtVertBlankStart=mmioReadCrtc(vgap, EXT_VERT_BLANK_START);
+ i810Reg->ExtHorizTotal=mmioReadCrtc(vgap, EXT_HORIZ_TOTAL);
+ i810Reg->ExtHorizBlank=mmioReadCrtc(vgap, EXT_HORIZ_BLANK);
+ i810Reg->ExtOffset=mmioReadCrtc(vgap, EXT_OFFSET);
+ i810Reg->InterlaceControl=mmioReadCrtc(vgap, INTERLACE_CNTL);
+
+ i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0);
+ i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1);
+ i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2);
+ i810Reg->DisplayControl = INREG8(DISPLAY_CNTL);
+ i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
+
+ for (i = 0 ; i < 8 ; i++)
+ i810Reg->Fence[i] = INREG(FENCE+i*4);
+
+ i810Reg->LprbTail = INREG(LP_RING + RING_TAIL);
+ i810Reg->LprbHead = INREG(LP_RING + RING_HEAD);
+ i810Reg->LprbStart = INREG(LP_RING + RING_START);
+ i810Reg->LprbLen = INREG(LP_RING + RING_LEN);
+
+ if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) &&
+ i810Reg->LprbLen & RING_VALID) {
+ i810PrintErrorState( card );
+ FatalError( "Active ring not flushed\n");
+ }
+
+ if (I810_DEBUG) {
+ fprintf(stderr,"Got mode in I810Save:\n");
+ i810PrintMode( vgaReg, i810Reg );
+ }
+}
+
+void i810Preserve(KdCardInfo *card) {
+ I810CardInfo *i810c = card->driver;
+ i810VGAPtr vgap = &i810c->vga;
+
+/* fprintf(stderr,"i810Preserve\n"); */
+ DoSave(card, &vgap->SavedReg, &i810c->SavedReg, TRUE);
+}
+
+/* Famous last words
+ */
+void
+i810PrintErrorState(KdCardInfo *card)
+{
+
+ I810CardInfo *i810c = card->driver;
+
+ fprintf(stderr, "pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
+ INREG(PGETBL_CTL),
+ INREG(PGE_ERR));
+
+ fprintf(stderr, "ipeir: %lx iphdr: %lx\n",
+ INREG(IPEIR),
+ INREG(IPEHR));
+
+ fprintf(stderr, "LP ring tail: %lx head: %lx len: %lx start %lx\n",
+ INREG(LP_RING + RING_TAIL),
+ INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+ INREG(LP_RING + RING_LEN),
+ INREG(LP_RING + RING_START));
+
+ fprintf(stderr, "eir: %x esr: %x emr: %x\n",
+ INREG16(EIR),
+ INREG16(ESR),
+ INREG16(EMR));
+
+ fprintf(stderr, "instdone: %x instpm: %x\n",
+ INREG16(INST_DONE),
+ INREG8(INST_PM));
+
+ fprintf(stderr, "memmode: %lx instps: %lx\n",
+ INREG(MEMMODE),
+ INREG(INST_PS));
+
+ fprintf(stderr, "hwstam: %x ier: %x imr: %x iir: %x\n",
+ INREG16(HWSTAM),
+ INREG16(IER),
+ INREG16(IMR),
+ INREG16(IIR));
+}
+
+Bool
+i810BindGARTMemory( KdScreenInfo *screen )
+{
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+
+ if (!i810c->GttBound) {
+ if (!KdAcquireGART(screen->mynum))
+ return FALSE;
+ if (!KdBindGARTMemory(screen->mynum, i810c->VramKey,
+ i810c->VramOffset))
+
+ return FALSE;
+ if (i810c->DcacheKey != -1) {
+ if (!KdBindGARTMemory(screen->mynum, i810c->DcacheKey,
+ i810c->DcacheOffset))
+ return FALSE;
+ }
+ if (i810c->HwcursKey != -1) {
+ if (!KdBindGARTMemory(screen->mynum, i810c->HwcursKey,
+ i810c->HwcursOffset))
+ return FALSE;
+ }
+ i810c->GttBound = 1;
+ }
+ return TRUE;
+}
+
+Bool
+i810UnbindGARTMemory(KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+
+
+ if (KdAgpGARTSupported() && i810c->GttBound) {
+ if (!KdUnbindGARTMemory(screen->mynum, i810c->VramKey))
+ return FALSE;
+ if (i810c->DcacheKey != -1) {
+ if (!KdUnbindGARTMemory(screen->mynum, i810c->DcacheKey))
+ return FALSE;
+ }
+ if (i810c->HwcursKey != -1) {
+ if (!KdUnbindGARTMemory(screen->mynum, i810c->HwcursKey))
+ return FALSE;
+ }
+ if (!KdReleaseGART(screen->mynum))
+ return FALSE;
+ i810c->GttBound = 0;
+ }
+ return TRUE;
+}
+
+/*
+ * I810CalcVCLK --
+ *
+ * Determine the closest clock frequency to the one requested.
+ */
+
+#define MAX_VCO_FREQ 600.0
+#define TARGET_MAX_N 30
+#define REF_FREQ 24.0
+
+#define CALC_VCLK(m,n,p) \
+ (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
+
+static void
+i810CalcVCLK( KdScreenInfo *screen, double freq )
+{
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+ I810RegPtr i810Reg = &i810c->ModeReg;
+
+ int m, n, p;
+ double f_out, f_best;
+ double f_err;
+ double f_vco;
+ int m_best = 0, n_best = 0, p_best = 0;
+ double f_target = freq;
+ double err_max = 0.005;
+ double err_target = 0.001;
+ double err_best = 999999.0;
+
+ p_best = p = log(MAX_VCO_FREQ/f_target)/log((double)2);
+ f_vco = f_target * (1 << p);
+
+ n = 2;
+ do {
+ n++;
+ m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
+ if (m < 3) m = 3;
+ f_out = CALC_VCLK(m,n,p);
+ f_err = 1.0 - (f_target/f_out);
+ if (fabs(f_err) < err_max) {
+ m_best = m;
+ n_best = n;
+ f_best = f_out;
+ err_best = f_err;
+ }
+ } while ((fabs(f_err) >= err_target) &&
+ ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
+
+ if (fabs(f_err) < err_target) {
+ m_best = m;
+ n_best = n;
+ }
+
+ i810Reg->VideoClk2_M = (m_best-2) & 0x3FF;
+ i810Reg->VideoClk2_N = (n_best-2) & 0x3FF;
+ i810Reg->VideoClk2_DivisorSel = (p_best << 4);
+
+/* fprintf(stderr, "Setting dot clock to %.1f MHz " */
+/* "[ 0x%x 0x%x 0x%x ] " */
+/* "[ %d %d %d ]\n", */
+/* CALC_VCLK(m_best,n_best,p_best), */
+/* i810Reg->VideoClk2_M, */
+/* i810Reg->VideoClk2_N, */
+/* i810Reg->VideoClk2_DivisorSel, */
+/* m_best, n_best, p_best); */
+}
+
+/*
+ * I810CalcFIFO --
+ *
+ * Calculate burst length and FIFO watermark.
+ */
+
+#define Elements(x) (sizeof(x)/sizeof(*x))
+
+unsigned int
+i810CalcWatermark( KdScreenInfo *screen, double freq, Bool dcache )
+{
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+
+
+ struct wm_info *tab;
+ int nr;
+ int i;
+
+ if (i810c->LmFreqSel == 100) {
+ switch(screen->fb[0].bitsPerPixel) {
+ case 8:
+ tab = i810_wm_8_100;
+ nr = Elements(i810_wm_8_100);
+ break;
+ case 16:
+ tab = i810_wm_16_100;
+ nr = Elements(i810_wm_16_100);
+ break;
+ case 24:
+ tab = i810_wm_24_100;
+ nr = Elements(i810_wm_24_100);
+ break;
+ default:
+ return 0;
+ }
+ } else {
+ switch(screen->fb[0].bitsPerPixel) {
+ case 8:
+ tab = i810_wm_8_133;
+ nr = Elements(i810_wm_8_133);
+ break;
+ case 16:
+ tab = i810_wm_16_133;
+ nr = Elements(i810_wm_16_133);
+ break;
+ case 24:
+ tab = i810_wm_24_133;
+ nr = Elements(i810_wm_24_133);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ for (i = 0 ; i < nr && tab[i].freq < freq ; i++);
+
+ if (i == nr)
+ i--;
+
+/* fprintf(stderr,"chose watermark 0x%x: (tab.freq %.1f)\n", */
+/* tab[i].wm, tab[i].freq); */
+
+ /* None of these values (sourced from intel) have watermarks for
+ * the dcache memory. Fake it for now by using the same watermark
+ * for both...
+ *
+ * Update: this is probably because dcache isn't real useful as
+ * framebuffer memory, so intel's drivers don't need watermarks
+ * for that memory because they never use it to feed the ramdacs.
+ * We do use it in the fallback mode, so keep the watermarks for
+ * now.
+ */
+ if (dcache)
+ return (tab[i].wm & ~0xffffff) | ((tab[i].wm>>12) & 0xfff);
+ else
+ return tab[i].wm;
+}
+
+static void i810PrintMode( vgaRegPtr vgaReg, I810RegPtr mode )
+{
+ int i;
+
+ fprintf(stderr," MiscOut: %x\n", vgaReg->MiscOutReg);
+
+
+ fprintf(stderr,"SEQ: ");
+ for (i = 0 ; i < VGA_NUM_SEQ ; i++) {
+ if ((i&7)==0) fprintf(stderr,"\n");
+ fprintf(stderr," %d: %x", i, vgaReg->Sequencer[i]);
+ }
+ fprintf(stderr,"\n");
+
+ fprintf(stderr,"CRTC: ");
+ for (i = 0 ; i < VGA_NUM_CRTC ; i++) {
+ if ((i&3)==0) fprintf(stderr,"\n");
+ fprintf(stderr," CR%02x: %2x", i, vgaReg->CRTC[i]);
+ }
+ fprintf(stderr,"\n");
+
+ fprintf(stderr,"GFX: ");
+ for (i = 0 ; i < VGA_NUM_GFX ; i++) {
+ if ((i&3)==0) fprintf(stderr,"\n");
+ fprintf(stderr," GR%02x: %02x", i, vgaReg->Graphics[i]);
+ }
+ fprintf(stderr,"\n");
+
+ fprintf(stderr,"ATTR: ");
+ for (i = 0 ; i < VGA_NUM_ATTR ; i++) {
+ if ((i&7)==0) fprintf(stderr,"\n");
+ fprintf(stderr," %d: %x", i, vgaReg->Attribute[i]);
+ }
+ fprintf(stderr,"\n");
+
+
+ fprintf(stderr," DisplayControl: %x\n", mode->DisplayControl);
+ fprintf(stderr," PixelPipeCfg0: %x\n", mode->PixelPipeCfg0);
+ fprintf(stderr," PixelPipeCfg1: %x\n", mode->PixelPipeCfg1);
+ fprintf(stderr," PixelPipeCfg2: %x\n", mode->PixelPipeCfg2);
+ fprintf(stderr," VideoClk2_M: %x\n", mode->VideoClk2_M);
+ fprintf(stderr," VideoClk2_N: %x\n", mode->VideoClk2_N);
+ fprintf(stderr," VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel);
+ fprintf(stderr," AddressMapping: %x\n", mode->AddressMapping);
+ fprintf(stderr," IOControl: %x\n", mode->IOControl);
+ fprintf(stderr," BitBLTControl: %x\n", mode->BitBLTControl);
+ fprintf(stderr," ExtVertTotal: %x\n", mode->ExtVertTotal);
+ fprintf(stderr," ExtVertDispEnd: %x\n", mode->ExtVertDispEnd);
+ fprintf(stderr," ExtVertSyncStart: %x\n", mode->ExtVertSyncStart);
+ fprintf(stderr," ExtVertBlankStart: %x\n", mode->ExtVertBlankStart);
+ fprintf(stderr," ExtHorizTotal: %x\n", mode->ExtHorizTotal);
+ fprintf(stderr," ExtHorizBlank: %x\n", mode->ExtHorizBlank);
+ fprintf(stderr," ExtOffset: %x\n", mode->ExtOffset);
+ fprintf(stderr," InterlaceControl: %x\n", mode->InterlaceControl);
+ fprintf(stderr," LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark);
+ fprintf(stderr," LprbTail: %x\n", mode->LprbTail);
+ fprintf(stderr," LprbHead: %x\n", mode->LprbHead);
+ fprintf(stderr," LprbStart: %x\n", mode->LprbStart);
+ fprintf(stderr," LprbLen: %x\n", mode->LprbLen);
+ fprintf(stderr," OverlayActiveStart: %x\n", mode->OverlayActiveStart);
+ fprintf(stderr," OverlayActiveEnd: %x\n", mode->OverlayActiveEnd);
+}
+
+
+/*
+ * i810VGASeqReset
+ * perform a sequencer reset.
+ *
+ * The i815 documentation states that these bits are not used by the
+ * HW, but still warns about not programming them...
+ */
+
+void
+i810VGASeqReset(i810VGAPtr vgap, Bool start)
+{
+ if (start)
+ {
+ mmioWriteSeq(vgap, 0x00, 0x01); /* Synchronous Reset */
+ }
+ else
+ {
+ mmioWriteSeq(vgap, 0x00, 0x03); /* End Reset */
+ }
+}
+
+void
+i810VGAProtect(KdCardInfo *card, Bool on)
+{
+
+ I810CardInfo *i810c = card->driver;
+ i810VGAPtr vgap = &i810c->vga;
+
+ unsigned char tmp;
+
+ if (on) {
+ /*
+ * Turn off screen and disable sequencer.
+ */
+ tmp = mmioReadSeq(vgap, 0x01);
+
+ i810VGASeqReset(vgap, TRUE); /* start synchronous reset */
+ mmioWriteSeq(vgap, 0x01, tmp | 0x20); /* disable the display */
+
+ mmioEnablePalette(vgap);
+ } else {
+ /*
+ * Reenable sequencer, then turn on screen.
+ */
+
+ tmp = mmioReadSeq(vgap, 0x01);
+
+ mmioWriteSeq(vgap, 0x01, tmp & ~0x20); /* reenable display */
+ i810VGASeqReset(vgap, FALSE); /* clear synchronousreset */
+
+ mmioDisablePalette(vgap);
+ }
+}
+
+/*
+ * i810VGABlankScreen -- blank the screen.
+ */
+
+void
+i810VGABlankScreen(KdCardInfo *card, Bool on)
+{
+ I810CardInfo *i810c = card->driver;
+ i810VGAPtr vgap = &i810c->vga;
+
+ unsigned char scrn;
+
+ scrn = mmioReadSeq(vgap, 0x01);
+
+ if (on) {
+ scrn &= ~0x20; /* enable screen */
+ } else {
+ scrn |= 0x20; /* blank screen */
+ }
+
+ mmioWriteSeq(vgap,0x00,0x01);
+ mmioWriteSeq(vgap, 0x01, scrn); /* change mode */
+ mmioWriteSeq(vgap,0x00,0x03);
+}
+
+/* Restore hardware state */
+
+static void
+DoRestore(KdCardInfo *card, vgaRegPtr vgaReg, I810RegPtr i810Reg,
+ Bool restoreFonts) {
+
+
+ I810CardInfo *i810c = card->driver;
+
+ i810VGAPtr vgap = &i810c->vga;
+
+ unsigned char temp;
+ unsigned int itemp;
+ int i;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
+ fprintf(stderr,"Setting mode in DoRestore:\n");
+ i810PrintMode( vgaReg, i810Reg );
+ }
+
+ /* Blank screen (i810vgaprotect) */
+ i810VGAProtect(card, TRUE);
+
+ /* Should wait for at least two hsync and no more than two vsync
+ before writing PIXCONF and turning the display on (?) */
+ usleep(50000);
+
+ /* Turn off DRAM Refresh */
+ temp = INREG8( DRAM_ROW_CNTL_HI );
+ temp &= ~DRAM_REFRESH_RATE;
+ temp |= DRAM_REFRESH_DISABLE;
+ OUTREG8( DRAM_ROW_CNTL_HI, temp );
+
+ usleep(1000); /* Wait 1 ms */
+
+ /* Write the M, N and P values */
+ OUTREG16( VCLK2_VCO_M, i810Reg->VideoClk2_M);
+ OUTREG16( VCLK2_VCO_N, i810Reg->VideoClk2_N);
+ OUTREG8( VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel);
+
+ /*
+ * Turn on 8 bit dac mode, if requested. This is needed to make
+ * sure that vgaHWRestore writes the values into the DAC properly.
+ * The problem occurs if 8 bit dac mode is requested and the HW is
+ * in 6 bit dac mode. If this happens, all the values are
+ * automatically shifted left twice by the HW and incorrect colors
+ * will be displayed on the screen. The only time this can happen
+ * is at server startup time and when switching back from a VT.
+ */
+ temp = INREG8(PIXPIPE_CONFIG_0);
+ temp &= 0x7F; /* Save all but the 8 bit dac mode bit */
+ temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);
+ OUTREG8( PIXPIPE_CONFIG_0, temp );
+
+ /*
+ * Code to restore any SVGA registers that have been saved/modified
+ * goes here. Note that it is allowable, and often correct, to
+ * only modify certain bits in a register by a read/modify/write cycle.
+ *
+ * A special case - when using an external clock-setting program,
+ * this function must not change bits associated with the clock
+ * selection. This condition can be checked by the condition:
+ *
+ * if (i810Reg->std.NoClock >= 0)
+ * restore clock-select bits.
+ */
+
+ /* VGA restore */
+ if (vgaReg->MiscOutReg & 0x01)
+ vgap->IOBase = VGA_IOBASE_COLOR;
+ else
+ vgap->IOBase = VGA_IOBASE_MONO;
+
+ mmioWriteMiscOut(vgap, vgaReg->MiscOutReg);
+
+ for (i = 1; i < VGA_NUM_SEQ; i++)
+ mmioWriteSeq(vgap, i, vgaReg->Sequencer[i]);
+
+ /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
+ /* = CR11 */
+ mmioWriteCrtc(vgap, 17, vgaReg->CRTC[17] & ~0x80);
+
+ for (i = 0; i < VGA_NUM_CRTC; i++) {
+ mmioWriteCrtc(vgap, i, vgaReg->CRTC[i]);
+ }
+
+ for (i = 0; i < VGA_NUM_GFX; i++)
+ mmioWriteGr(vgap, i, vgaReg->Graphics[i]);
+
+ mmioEnablePalette(vgap);
+ for (i = 0; i < VGA_NUM_ATTR; i++)
+ mmioWriteAttr(vgap, i, vgaReg->Attribute[i]);
+ mmioDisablePalette(vgap);
+
+
+ mmioWriteCrtc(vgap, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);
+ mmioWriteCrtc(vgap, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);
+ mmioWriteCrtc(vgap, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);
+ mmioWriteCrtc(vgap, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);
+ mmioWriteCrtc(vgap, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);
+ mmioWriteCrtc(vgap, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);
+
+ /* write CR40, CR42 first etc to get CR13 written as described in PRM */
+
+ mmioWriteCrtc(vgap, EXT_START_ADDR_HI, 0);
+ mmioWriteCrtc(vgap, EXT_START_ADDR, EXT_START_ADDR_ENABLE);
+
+ mmioWriteCrtc(vgap, EXT_OFFSET, i810Reg->ExtOffset);
+ mmioWriteCrtc(vgap, 0x13, vgaReg->CRTC[0x13]);
+
+ temp=mmioReadCrtc(vgap, INTERLACE_CNTL);
+ temp &= ~INTERLACE_ENABLE;
+ temp |= i810Reg->InterlaceControl;
+ mmioWriteCrtc(vgap, INTERLACE_CNTL, temp);
+
+ temp=i810ReadControlMMIO(i810c, GRX, ADDRESS_MAPPING);
+ temp &= 0xE0; /* Save reserved bits 7:5 */
+ temp |= i810Reg->AddressMapping;
+ i810WriteControlMMIO(i810c, GRX, ADDRESS_MAPPING, temp);
+
+ /* Setting the OVRACT Register for video overlay*/
+ OUTREG(0x6001C, (i810Reg->OverlayActiveEnd << 16) | i810Reg->OverlayActiveStart);
+
+ /* Turn on DRAM Refresh */
+ temp = INREG8( DRAM_ROW_CNTL_HI );
+ temp &= ~DRAM_REFRESH_RATE;
+ temp |= DRAM_REFRESH_60HZ;
+ OUTREG8( DRAM_ROW_CNTL_HI, temp );
+
+ temp = INREG8( BITBLT_CNTL );
+ temp &= ~COLEXP_MODE;
+ temp |= i810Reg->BitBLTControl;
+ OUTREG8( BITBLT_CNTL, temp );
+
+ temp = INREG8( DISPLAY_CNTL );
+ temp &= ~(VGA_WRAP_MODE | GUI_MODE);
+ temp |= i810Reg->DisplayControl;
+ OUTREG8( DISPLAY_CNTL, temp );
+
+
+ temp = INREG8( PIXPIPE_CONFIG_0 );
+ temp &= 0x64; /* Save reserved bits 6:5,2 */
+ temp |= i810Reg->PixelPipeCfg0;
+ OUTREG8( PIXPIPE_CONFIG_0, temp );
+
+ temp = INREG8( PIXPIPE_CONFIG_2 );
+ temp &= 0xF3; /* Save reserved bits 7:4,1:0 */
+ temp |= i810Reg->PixelPipeCfg2;
+ OUTREG8( PIXPIPE_CONFIG_2, temp );
+
+ temp = INREG8( PIXPIPE_CONFIG_1 );
+ temp &= ~DISPLAY_COLOR_MODE;
+ temp &= 0xEF; /* Restore the CRT control bit */
+ temp |= i810Reg->PixelPipeCfg1;
+ OUTREG8( PIXPIPE_CONFIG_1, temp );
+
+ OUTREG16(EIR, 0);
+
+ itemp = INREG(FWATER_BLC);
+ itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
+ MM_BURST_LENGTH | MM_FIFO_WATERMARK );
+ itemp |= i810Reg->LMI_FIFO_Watermark;
+ OUTREG(FWATER_BLC, itemp);
+
+
+ for (i = 0 ; i < 8 ; i++) {
+ OUTREG( FENCE+i*4, i810Reg->Fence[i] );
+ if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+ fprintf(stderr,"Fence Register : %x\n", i810Reg->Fence[i]);
+ }
+
+ /* First disable the ring buffer (Need to wait for empty first?, if so
+ * should probably do it before entering this section)
+ */
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~RING_VALID_MASK;
+ OUTREG(LP_RING + RING_LEN, itemp );
+
+ /* Set up the low priority ring buffer.
+ */
+ OUTREG(LP_RING + RING_TAIL, 0 );
+ OUTREG(LP_RING + RING_HEAD, 0 );
+
+ i810c->LpRing.head = 0;
+ i810c->LpRing.tail = 0;
+
+ itemp = INREG(LP_RING + RING_START);
+ itemp &= ~(START_ADDR);
+ itemp |= i810Reg->LprbStart;
+ OUTREG(LP_RING + RING_START, itemp );
+
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
+ itemp |= i810Reg->LprbLen;
+ OUTREG(LP_RING + RING_LEN, itemp );
+
+ i810VGAProtect(card, FALSE);
+
+ temp=mmioReadCrtc(vgap, IO_CTNL);
+ temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+ temp |= i810Reg->IOControl;
+ mmioWriteCrtc(vgap, IO_CTNL, temp);
+ /* Protect CRTC[0-7] */
+ mmioWriteCrtc(vgap, 0x11, mmioReadCrtc(vgap, 0x11) | 0x80);
+}
+
+
+static Bool
+i810SetMode(KdScreenInfo *screen, const KdMonitorTiming *t)
+{
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+ i810VGAPtr vgap = &i810c->vga;
+
+ I810RegPtr i810Reg = &i810c->ModeReg;
+ vgaRegPtr pVga = &vgap->ModeReg;
+
+ double dclk = t->clock/1000.0;
+
+ switch (screen->fb[0].bitsPerPixel) {
+ case 8:
+ pVga->CRTC[0x13] = screen->width >> 3;
+ i810Reg->ExtOffset = screen->width >> 11;
+ i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
+ i810Reg->BitBLTControl = COLEXP_8BPP;
+ break;
+ case 16:
+ i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
+ pVga->CRTC[0x13] = screen->width >> 2;
+ i810Reg->ExtOffset = screen->width >> 10;
+ i810Reg->BitBLTControl = COLEXP_16BPP;
+ break;
+ case 24:
+ pVga->CRTC[0x13] = (screen->width * 3) >> 3;
+ i810Reg->ExtOffset = (screen->width * 3) >> 11;
+
+ i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
+ i810Reg->BitBLTControl = COLEXP_24BPP;
+ break;
+ default:
+ break;
+ }
+
+ i810Reg->PixelPipeCfg0 = DAC_8_BIT;
+
+ /* Do not delay CRT Blank: needed for video overlay */
+ i810Reg->PixelPipeCfg1 |= 0x10;
+
+ /* Turn on Extended VGA Interpretation */
+ i810Reg->IOControl = EXTENDED_CRTC_CNTL;
+
+ /* Turn on linear and page mapping */
+ i810Reg->AddressMapping = (LINEAR_MODE_ENABLE |
+ GTT_MEM_MAP_ENABLE);
+
+ /* Turn on GUI mode */
+ i810Reg->DisplayControl = HIRES_MODE;
+
+ i810Reg->OverlayActiveStart = t->horizontal + t->hblank - 32;
+ i810Reg->OverlayActiveEnd = t->horizontal - 32;
+
+ /* Turn on interlaced mode if necessary (it's not) */
+ i810Reg->InterlaceControl = INTERLACE_DISABLE;
+
+ /*
+ * Set the overscan color to 0.
+ * NOTE: This only affects >8bpp mode.
+ */
+ pVga->Attribute[0x11] = 0;
+
+ /*
+ * Calculate the VCLK that most closely matches the requested dot
+ * clock.
+ */
+ i810CalcVCLK(screen, dclk);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ pVga->MiscOutReg |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ i810Reg->LMI_FIFO_Watermark = i810CalcWatermark(screen, dclk, FALSE);
+
+ /* Setup the ring buffer */
+ i810Reg->LprbTail = 0;
+ i810Reg->LprbHead = 0;
+ i810Reg->LprbStart = i810c->LpRing.mem.Start;
+
+ if (i810Reg->LprbStart)
+ i810Reg->LprbLen = ((i810c->LpRing.mem.Size-4096) |
+ RING_NO_REPORT | RING_VALID);
+ else
+ i810Reg->LprbLen = RING_INVALID;
+
+ return TRUE;
+}
+
+static Bool
+i810ModeInit(KdScreenInfo *screen, const KdMonitorTiming *t)
+{
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+ i810VGAPtr vgap = &i810c->vga;
+ vgaRegPtr pVga;
+
+/* fprintf(stderr,"i810ModeInit\n"); */
+
+ i810VGAUnlock(vgap);
+
+ if (!i810VGAInit(screen, t)) return FALSE;
+ pVga = &vgap->ModeReg;
+
+ if (!i810SetMode(screen, t)) return FALSE;
+
+ DoRestore(screen->card, &vgap->ModeReg, &i810c->ModeReg, FALSE);
+
+ return TRUE;
+}
+
+Bool
+i810VGAInit(KdScreenInfo *screen, const KdMonitorTiming *t)
+{
+ unsigned int i;
+
+ int hactive, hblank, hbp, hfp;
+ int vactive, vblank, vbp, vfp;
+ int h_screen_off, h_adjust, h_total, h_display_end, h_blank_start;
+ int h_blank_end, h_sync_start, h_sync_end, v_total, v_retrace_start;
+ int v_retrace_end, v_display_end, v_blank_start, v_blank_end;
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+
+ i810VGAPtr vgap = &i810c->vga;
+ I810RegPtr ireg = &i810c->ModeReg;
+
+
+ vgaRegPtr regp;
+ int depth = screen->fb[0].depth;
+
+ regp = &vgap->ModeReg;
+
+ /*
+ * compute correct Hsync & Vsync polarity
+ */
+
+ regp->MiscOutReg = 0x23;
+ if (t->vpol == KdSyncNegative) regp->MiscOutReg |= 0x40;
+ if (t->hpol == KdSyncNegative) regp->MiscOutReg |= 0x80;
+
+ /*
+ * Time Sequencer
+ */
+ if (depth == 4)
+ regp->Sequencer[0] = 0x02;
+ else
+ regp->Sequencer[0] = 0x00;
+ /* No support for 320 or 360 x resolution */
+ regp->Sequencer[1] = 0x01;
+
+ if (depth == 1)
+ regp->Sequencer[2] = 1 << BIT_PLANE;
+ else
+ regp->Sequencer[2] = 0x0F;
+
+ regp->Sequencer[3] = 0x00; /* Font select */
+
+ if (depth < 8)
+ regp->Sequencer[4] = 0x06; /* Misc */
+ else
+ regp->Sequencer[4] = 0x0E; /* Misc */
+
+ hactive = t->horizontal;
+ hblank = t->hblank;
+ hbp = t->hbp;
+ hfp = t->hfp;
+
+ vactive = t->vertical;
+ vblank = t->vblank;
+ vbp = t->vbp;
+ vfp = t->vfp;
+
+ switch (screen->fb[0].bitsPerPixel) {
+ case 8:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+ h_screen_off = hactive;
+ h_adjust = 1;
+ break;
+ case 16:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+
+ h_screen_off = hactive * 2;
+ h_adjust = 1;
+ break;
+ case 24:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+
+ h_screen_off = hactive * 3;
+ h_adjust = 1;
+ break;
+ case 32:
+ hactive /= 8;
+ hblank /= 8;
+ hfp /= 8;
+ hbp /= 8;
+
+ h_screen_off = hactive * 4;
+ h_adjust = 1;
+ break;
+ }
+
+ /*
+ * Compute horizontal register values from timings
+ */
+ h_total = hactive + hblank - 5;
+ h_display_end = hactive - 1;
+ h_blank_start = h_display_end;
+ h_blank_end = h_blank_start + hblank;
+
+ h_sync_start = hactive + hfp + h_adjust;
+ h_sync_end = h_sync_start + hblank - hbp - hfp;
+
+ /* Set CRTC regs for horizontal timings */
+ regp->CRTC[0x0] = h_total;
+ ireg->ExtHorizTotal=(h_total & 0x100) >> 8;
+
+ regp->CRTC[0x1] = h_display_end;
+
+ regp->CRTC[0x2] = h_blank_start;
+
+ regp->CRTC[0x3] = 0x80 | (h_blank_end & 0x1f);
+ regp->CRTC[0x5] = (h_blank_end & 0x20) << 2;
+
+ regp->CRTC[0x4] = h_sync_start;
+
+ regp->CRTC[0x5] |= h_sync_end & 0x1f;
+
+ regp->CRTC[0x13] = h_screen_off;
+ ireg->ExtOffset = h_screen_off >> 8;
+
+ /* Compute vertical timings */
+ v_total = vactive + vblank - 2;
+ v_retrace_start = vactive + vfp - 1;
+ v_retrace_end = v_retrace_start + vblank - vbp - vfp;
+ v_display_end = vactive - 1;
+ v_blank_start = vactive - 1;
+ v_blank_end = v_blank_start + vblank /* - 1 */;
+
+ regp->CRTC[0x6] = v_total;
+ ireg->ExtVertTotal = v_total >> 8;
+
+ regp->CRTC[0x10] = v_retrace_start;
+ ireg->ExtVertSyncStart = v_retrace_start >> 8;
+
+ regp->CRTC[0x11] = v_retrace_end;
+
+ regp->CRTC[0x12] = v_display_end;
+ ireg->ExtVertDispEnd = v_display_end >> 8;
+
+ regp->CRTC[0x15] = v_blank_start;
+ ireg->ExtVertBlankStart = v_blank_start >> 8;
+
+ regp->CRTC[0x16] = v_blank_end;
+
+ if (depth < 8)
+ regp->CRTC[23] = 0xE3;
+ else
+ regp->CRTC[23] = 0xC3;
+ regp->CRTC[24] = 0xFF;
+
+ /*
+ * Graphics Display Controller
+ */
+ regp->Graphics[0] = 0x00;
+ regp->Graphics[1] = 0x00;
+ regp->Graphics[2] = 0x00;
+ regp->Graphics[3] = 0x00;
+ if (depth == 1) {
+ regp->Graphics[4] = BIT_PLANE;
+ regp->Graphics[5] = 0x00;
+ } else {
+ regp->Graphics[4] = 0x00;
+ if (depth == 4)
+ regp->Graphics[5] = 0x02;
+ else
+ regp->Graphics[5] = 0x40;
+ }
+ regp->Graphics[6] = 0x05;
+ regp->Graphics[7] = 0x0F;
+ regp->Graphics[8] = 0xFF;
+
+ if (depth == 1) {
+ /* Initialise the Mono map according to which bit-plane gets used */
+
+ Bool flipPixels = FALSE; /* maybe support this in the future? */
+
+ for (i=0; i<16; i++)
+ if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
+ regp->Attribute[i] = WHITE_VALUE;
+ else
+ regp->Attribute[i] = BLACK_VALUE;
+
+ regp->Attribute[16] = 0x01; /* -VGA2- */
+ if (!vgap->ShowOverscan)
+ regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
+ } else {
+ regp->Attribute[0] = 0x00; /* standard colormap translation */
+ regp->Attribute[1] = 0x01;
+ regp->Attribute[2] = 0x02;
+ regp->Attribute[3] = 0x03;
+ regp->Attribute[4] = 0x04;
+ regp->Attribute[5] = 0x05;
+ regp->Attribute[6] = 0x06;
+ regp->Attribute[7] = 0x07;
+ regp->Attribute[8] = 0x08;
+ regp->Attribute[9] = 0x09;
+ regp->Attribute[10] = 0x0A;
+ regp->Attribute[11] = 0x0B;
+ regp->Attribute[12] = 0x0C;
+ regp->Attribute[13] = 0x0D;
+ regp->Attribute[14] = 0x0E;
+ regp->Attribute[15] = 0x0F;
+ if (depth == 4)
+ regp->Attribute[16] = 0x81;
+ else
+ regp->Attribute[16] = 0x41;
+ /* Attribute[17] (overscan) was initialised earlier */
+ }
+ regp->Attribute[18] = 0x0F;
+ regp->Attribute[19] = 0x00;
+ regp->Attribute[20] = 0x00;
+
+ return(TRUE);
+}
+
+void
+i810VGALock(i810VGAPtr vgap)
+{
+ /* Protect CRTC[0-7] */
+ mmioWriteCrtc(vgap, 0x11, mmioReadCrtc(vgap, 0x11) & ~0x80);
+}
+
+void
+i810VGAUnlock(i810VGAPtr vgap)
+{
+ /* Unprotect CRTC[0-7] */
+ mmioWriteCrtc(vgap, 0x11, mmioReadCrtc(vgap, 0x11) | 0x80);
+}
+
+static void
+i810Restore(KdCardInfo *card) {
+
+ I810CardInfo *i810c = card->driver;
+
+ i810VGAPtr vgap = &i810c->vga;
+
+ if (I810_DEBUG)
+ fprintf(stderr,"i810Restore\n");
+
+ DoRestore(card, &vgap->SavedReg, &i810c->SavedReg, TRUE);
+}
+
+Bool
+i810Enable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = pScreenPriv->card;
+ I810CardInfo *i810c = card->driver;
+ i810VGAPtr vgap = &i810c->vga;
+ const KdMonitorTiming *t;
+
+ if (I810_DEBUG)
+ fprintf(stderr,"i810Enable\n");
+
+ vgap->IOBase = (mmioReadMiscOut(vgap) & 0x01) ?
+ VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
+
+ {
+ I810RegPtr i810Reg = &i810c->ModeReg;
+ int i;
+
+ for (i = 0 ; i < 8 ; i++)
+ i810Reg->Fence[i] = 0;
+ }
+
+ t = KdFindMode (screen, i810ModeSupported);
+
+ if (!i810BindGARTMemory(screen))
+ return FALSE;
+
+ if (!i810ModeInit(screen, t)) return FALSE;
+
+ {
+ /* DPMS power on state */
+
+ unsigned char SEQ01=0;
+ int DPMSSyncSelect=0;
+
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+
+ SEQ01 |= i810ReadControlMMIO(i810c, SRX, 0x01) & ~0x20;
+ i810WriteControlMMIO(i810c, SRX, 0x01, SEQ01);
+
+ /* Set the DPMS mode */
+ OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
+ }
+
+ return TRUE;
+}
+
+
+void
+i810Disable(ScreenPtr pScreen) {
+
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = pScreenPriv->card;
+ I810CardInfo *i810c = card->driver;
+
+ i810VGAPtr vgap = &i810c->vga;
+
+ if (I810_DEBUG)
+ fprintf(stderr,"i810Disable\n");
+
+ i810Restore(screen->card);
+
+ if (!i810UnbindGARTMemory(screen))
+ return;
+
+ i810VGALock(vgap);
+}
+
+
+static Bool
+i810DPMS(ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ I810CardInfo *i810c = card->driver;
+
+ unsigned char SEQ01=0;
+ int DPMSSyncSelect=0;
+
+ if (I810_DEBUG)
+ fprintf(stderr,"i810DPMS: %d\n",mode);
+
+ switch (mode) {
+ case KD_DPMS_NORMAL:
+ /* Screen: On; HSync: On, VSync: On */
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+ break;
+ case KD_DPMS_STANDBY:
+ /* Screen: Off; HSync: Off, VSync: On */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+ break;
+ case KD_DPMS_SUSPEND:
+ /* Screen: Off; HSync: On, VSync: Off */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+ break;
+ case KD_DPMS_POWERDOWN:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+ break;
+ }
+
+ /* Turn the screen on/off */
+ SEQ01 |= i810ReadControlMMIO(i810c, SRX, 0x01) & ~0x20;
+ i810WriteControlMMIO(i810c, SRX, 0x01, SEQ01);
+
+ /* Set the DPMS mode */
+ OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
+ return TRUE;
+}
+
+
+void i810GetColors (ScreenPtr pScreen, int fb, int ndefs, xColorItem *c) {
+
+ if (I810_DEBUG)
+ fprintf(stderr,"i810GetColors (NOT IMPLEMENTED)\n");
+}
+
+#define DACDelay(hw) \
+ do { \
+ unsigned char temp = Vminb((hw)->IOBase + VGA_IN_STAT_1_OFFSET); \
+ temp = Vminb((hw)->IOBase + VGA_IN_STAT_1_OFFSET); \
+ } while (0)
+
+void i810PutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs) {
+
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ i810VGAPtr vgap = &i810c->vga;
+
+ if (I810_DEBUG)
+ fprintf(stderr,"i810PutColors\n");
+
+ while (ndef--)
+ {
+ mmioWriteDacWriteAddr(vgap, pdefs->pixel);
+ DACDelay(vgap);
+ mmioWriteDacData(vgap, pdefs->red);
+ DACDelay(vgap);
+ mmioWriteDacData(vgap, pdefs->green);
+ DACDelay(vgap);
+ mmioWriteDacData(vgap, pdefs->blue);
+ DACDelay(vgap);
+
+ pdefs++;
+ }
+}
+
+
+KdCardFuncs i810Funcs = {
+ i810CardInit, /* cardinit */
+ i810ScreenInit, /* scrinit */
+ i810InitScreen, /* initScreen */
+ i810Preserve, /* preserve */
+ i810Enable, /* enable */
+ i810DPMS, /* dpms */
+ i810Disable, /* disable */
+ i810Restore, /* restore */
+ i810ScreenFini, /* scrfini */
+ i810CardFini, /* cardfini */
+
+ i810CursorInit, /* initCursor */
+ i810CursorEnable, /* enableCursor */
+ i810CursorDisable, /* disableCursor */
+ i810CursorFini, /* finiCursor */
+ NULL, /* recolorCursor */
+
+ i810InitAccel, /* initAccel */
+ i810EnableAccel, /* enableAccel */
+ i810SyncAccel, /* syncAccel */
+ i810DisableAccel, /* disableAccel */
+ i810FiniAccel, /* finiAccel */
+
+ i810GetColors, /* getColors */
+ i810PutColors, /* putColors */
+};
diff --git a/hw/kdrive/i810/i810.h b/hw/kdrive/i810/i810.h
new file mode 100644
index 000000000..bd4ff9711
--- /dev/null
+++ b/hw/kdrive/i810/i810.h
@@ -0,0 +1,503 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/* $XFree86$ */
+
+/*
+ * Author:
+ * Pontus Lidman <pontus.lidman@nokia.com>
+ */
+
+#ifndef _I810_H_
+#define _I810_H_
+
+#include "i810_reg.h"
+
+/* Globals */
+
+typedef struct _I810Rec *I810Ptr;
+
+/* Linear region allocated in framebuffer.
+ */
+typedef struct {
+ unsigned long Start;
+ unsigned long End;
+ unsigned long Size;
+} I810MemRange;
+
+typedef struct {
+ int tail_mask;
+ I810MemRange mem;
+ unsigned char *virtual_start;
+ int head;
+ int tail;
+ int space;
+} I810RingBuffer;
+
+typedef struct {
+ unsigned char DisplayControl;
+ unsigned char PixelPipeCfg0;
+ unsigned char PixelPipeCfg1;
+ unsigned char PixelPipeCfg2;
+ unsigned short VideoClk2_M;
+ unsigned short VideoClk2_N;
+ unsigned char VideoClk2_DivisorSel;
+ unsigned char AddressMapping;
+ unsigned char IOControl;
+ unsigned char BitBLTControl;
+ unsigned char ExtVertTotal;
+ unsigned char ExtVertDispEnd;
+ unsigned char ExtVertSyncStart;
+ unsigned char ExtVertBlankStart;
+ unsigned char ExtHorizTotal;
+ unsigned char ExtHorizBlank;
+ unsigned char ExtOffset;
+ unsigned char InterlaceControl;
+ unsigned int LMI_FIFO_Watermark;
+
+ unsigned int LprbTail;
+ unsigned int LprbHead;
+ unsigned int LprbStart;
+ unsigned int LprbLen;
+
+ unsigned int Fence[8];
+
+ unsigned short OverlayActiveStart;
+ unsigned short OverlayActiveEnd;
+
+
+} I810RegRec, *I810RegPtr;
+
+#define minb(p) *(volatile CARD8 *)(i810c->MMIOBase + (p))
+#define moutb(p,v) *(volatile CARD8 *)(i810c->MMIOBase + (p)) = (v)
+
+#define OUT_RING(n) { \
+ if (I810_DEBUG & DEBUG_VERBOSE_RING) \
+ ErrorF( "OUT_RING %x: %x\n", outring, n); \
+ *(volatile unsigned int *)(virt + outring) = n; \
+ outring += 4; \
+ outring &= ringmask; \
+}
+
+#define ADVANCE_LP_RING() { \
+ i810c->LpRing.tail = outring; \
+ OUTREG(LP_RING + RING_TAIL, outring); \
+}
+
+#ifdef __GNUC__
+#define LP_RING_MESSAGE(n) \
+ ErrorF("BEGIN_LP_RING %d in %s\n", n, __FUNCTION__)
+#else
+#define LP_RING_MESSAGE(n) \
+ ErrorF("BEGIN_LP_RING %d in %s:%d\n", n, __FILE__, __LINE__)
+#endif
+
+#define BEGIN_LP_RING(n) \
+ unsigned int outring, ringmask; \
+ volatile unsigned char *virt; \
+ if (n>2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC)) i810Sync( screen ); \
+ if (i810c->LpRing.space < n*4) i810WaitLpRing( screen, n*4, 0); \
+ i810c->LpRing.space -= n*4; \
+ if (I810_DEBUG & DEBUG_VERBOSE_RING) \
+ LP_RING_MESSAGE(n); \
+ outring = i810c->LpRing.tail; \
+ ringmask = i810c->LpRing.tail_mask; \
+ virt = i810c->LpRing.virtual_start;
+
+/* Memory mapped register access macros */
+#define INREG8(addr) *(volatile CARD8 *)(i810c->MMIOBase + (addr))
+#define INREG16(addr) *(volatile CARD16 *)(i810c->MMIOBase + (addr))
+#define INREG(addr) *(volatile CARD32 *)(i810c->MMIOBase + (addr))
+
+#define OUTREG8(addr, val) do { \
+ *(volatile CARD8 *)(i810c->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) \
+ ErrorF( "OUTREG8(%x, %x)\n", addr, val); \
+} while (0)
+
+#define OUTREG16(addr, val) do { \
+ *(volatile CARD16 *)(i810c->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) \
+ ErrorF( "OUTREG16(%x, %x)\n", addr, val); \
+} while (0)
+
+#define OUTREG(addr, val) do { \
+ *(volatile CARD32 *)(i810c->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) \
+ ErrorF( "OUTREG(%x, %x)\n", addr, val); \
+} while (0)
+
+/* To remove all debugging, make sure I810_DEBUG is defined as a
+ * preprocessor symbol, and equal to zero.
+ */
+
+#define I810_DEBUG 0
+
+#ifndef I810_DEBUG
+#warning "Debugging enabled - expect reduced performance"
+extern int I810_DEBUG;
+#endif
+
+#define DEBUG_VERBOSE_ACCEL 0x1
+#define DEBUG_VERBOSE_SYNC 0x2
+#define DEBUG_VERBOSE_VGA 0x4
+#define DEBUG_VERBOSE_RING 0x8
+#define DEBUG_VERBOSE_OUTREG 0x10
+#define DEBUG_VERBOSE_MEMORY 0x20
+#define DEBUG_VERBOSE_CURSOR 0x40
+#define DEBUG_ALWAYS_SYNC 0x80
+#define DEBUG_VERBOSE_DRI 0x100
+
+
+/* Size of the mmio region.
+ */
+#define I810_REG_SIZE 0x80000
+
+/* PCI identifiers */
+#ifndef PCI_CHIP_I810
+#define PCI_CHIP_I810 0x7121
+#define PCI_CHIP_I810_DC100 0x7123
+#define PCI_CHIP_I810_E 0x7125
+#define PCI_CHIP_I815 0x1132
+#define PCI_CHIP_I810_BRIDGE 0x7120
+#define PCI_CHIP_I810_DC100_BRIDGE 0x7122
+#define PCI_CHIP_I810_E_BRIDGE 0x7124
+#define PCI_CHIP_I815_BRIDGE 0x1130
+#endif
+
+
+#define IS_I810(i810c) (i810c->PciInfo->chipType == PCI_CHIP_I810 || \
+ i810c->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
+ i810c->PciInfo->chipType == PCI_CHIP_I810_E)
+#define IS_I815(i810c) (i810c->PciInfo->chipType == PCI_CHIP_I815)
+
+
+/* default number of VGA registers stored internally */
+#define VGA_NUM_CRTC 25 /* 0x19 */
+#define VGA_NUM_SEQ 5
+#define VGA_NUM_GFX 9
+#define VGA_NUM_ATTR 21
+
+/*
+ * Settings of standard VGA registers.
+ */
+typedef struct {
+ unsigned char MiscOutReg; /* */
+ unsigned char CRTC[VGA_NUM_CRTC]; /* Crtc Controller */
+ unsigned char Sequencer[VGA_NUM_SEQ]; /* Video Sequencer */
+ unsigned char Graphics[VGA_NUM_GFX]; /* Video Graphics */
+ unsigned char Attribute[VGA_NUM_ATTR]; /* Video Atribute */
+ unsigned char DAC[768]; /* Internal Colorlookuptable */
+} vgaRegRec, *vgaRegPtr;
+
+
+typedef struct _i810VGARec *i810VGAPtr;
+
+/* VGA registers */
+typedef struct _i810VGARec {
+ int IOBase; /* I/O Base address */
+ CARD8 * MMIOBase; /* Pointer to MMIO start */
+ vgaRegRec SavedReg; /* saved registers */
+ vgaRegRec ModeReg; /* register settings for
+ current mode */
+ Bool ShowOverscan;
+ Bool paletteEnabled;
+ Bool cmapSaved;
+} i810VGARec;
+
+typedef struct _i810CardInfo {
+ int videoRam;
+ int MaxClock;
+ long FbMapSize;
+ int cpp; /* chars per pixel */
+
+ unsigned long LinearAddr;
+ unsigned long MMIOAddr;
+
+ unsigned char *MMIOBase;
+ unsigned char *FbBase;
+
+ Bool GttBound;
+ Bool agpAcquired2d;
+ int VramKey;
+ unsigned long VramOffset;
+ int DcacheKey;
+ unsigned long DcacheOffset;
+ int HwcursKey;
+ unsigned long HwcursOffset;
+
+ I810MemRange DcacheMem;
+ I810MemRange SysMem;
+
+ I810MemRange SavedDcacheMem;
+ I810MemRange SavedSysMem;
+
+ unsigned int bufferOffset; /* for I810SelectBuffer */
+ Bool DoneFrontAlloc;
+ BoxRec FbMemBox;
+ I810MemRange FrontBuffer;
+ I810MemRange Scratch;
+ I810MemRange XvMem;
+
+ int LmFreqSel;
+
+ i810VGARec vga;
+
+ I810RegRec SavedReg;
+ I810RegRec ModeReg;
+ I810RingBuffer LpRing;
+
+ unsigned int BR[20];
+
+ int CursorOffset;
+ unsigned long CursorPhysical;
+ unsigned long CursorStart;
+ unsigned long OverlayPhysical;
+ unsigned long OverlayStart;
+ int colorKey;
+
+ Bool NeedToSync; /* Need to sync accel stuff */
+
+ int nextColorExpandBuf;
+
+ ScreenBlockHandlerProcPtr BlockHandler;
+
+#ifdef XV
+ KdVideoAdaptorPtr adaptor;
+#endif
+
+} I810CardInfo;
+
+#define getI810CardInfo(kd) ((I810CardInfo *) ((kd)->card->driver))
+#define i810CardInfo(kd) I810CardInfo *i810c = getI810CardInfo(kd)
+
+#define getI810ScreenInfo(kd) ((I810ScreenInfo *) ((kd)->screen->driver))
+#define i810ScreenInfo(kd) I810ScreenInfo *i810s = getI810ScreenInfo(kd)
+
+typedef struct _i810Cursor {
+ int width, height;
+ int xhot, yhot;
+ Bool has_cursor;
+ CursorPtr pCursor;
+} i810Cursor, *i810CursorPtr;
+
+typedef struct _i810ScreenInfo {
+ i810Cursor cursor;
+} I810ScreenInfo;
+
+#define I810_CURSOR_HEIGHT 64
+#define I810_CURSOR_WIDTH 64
+
+/* init functions (i810.c) */
+
+Bool
+i810CardInit (KdCardInfo *card);
+
+Bool
+i810ScreenInit (KdScreenInfo *screen);
+
+/* The cursor functions (i810_cursor.c) */
+
+Bool
+i810CursorInit(ScreenPtr pScreen);
+
+void
+i810CursorEnable (ScreenPtr pScreen);
+
+void
+i810CursorDisable (ScreenPtr pScreen);
+
+void
+i810CursorFini (ScreenPtr pScreen);
+
+/* Accel functions (i810draw.c) */
+
+Bool
+i810InitAccel(ScreenPtr);
+
+void
+i810EnableAccel (ScreenPtr);
+
+void
+i810SyncAccel (ScreenPtr);
+
+void
+i810DisableAccel (ScreenPtr);
+
+void
+i810FiniAccel (ScreenPtr);
+
+void
+i810FillBoxSolid (KdScreenInfo *screen, int nBox, BoxPtr pBox,
+ unsigned long pixel, int alu, unsigned long planemask);
+
+
+extern KdCardFuncs i810Funcs;
+
+/* Standard VGA registers */
+
+#define VGA_ATTR_INDEX 0x3C0
+#define VGA_ATTR_DATA_W 0x3C0
+#define VGA_ATTR_DATA_R 0x3C1
+#define VGA_IN_STAT_0 0x3C2 /* read */
+#define VGA_MISC_OUT_W 0x3C2 /* write */
+#define VGA_ENABLE 0x3C3
+#define VGA_SEQ_INDEX 0x3C4
+#define VGA_SEQ_DATA 0x3C5
+#define VGA_DAC_MASK 0x3C6
+#define VGA_DAC_READ_ADDR 0x3C7
+#define VGA_DAC_WRITE_ADDR 0x3C8
+#define VGA_DAC_DATA 0x3C9
+#define VGA_FEATURE_R 0x3CA /* read */
+#define VGA_MISC_OUT_R 0x3CC /* read */
+#define VGA_GRAPH_INDEX 0x3CE
+#define VGA_GRAPH_DATA 0x3CF
+
+#define VGA_IOBASE_MONO 0x3B0
+#define VGA_IOBASE_COLOR 0x3D0
+
+#define VGA_CRTC_INDEX_OFFSET 0x04
+#define VGA_CRTC_DATA_OFFSET 0x05
+#define VGA_IN_STAT_1_OFFSET 0x0A /* read */
+#define VGA_FEATURE_W_OFFSET 0x0A /* write */
+
+/* VGA stuff */
+#define BIT_PLANE 3 /* Which plane we write to in mono mode */
+
+/* DAC indices for white and black */
+#define WHITE_VALUE 0x3F
+#define BLACK_VALUE 0x00
+#define OVERSCAN_VALUE 0x01
+
+#define OVERSCAN 0x11 /* Index of OverScan register */
+
+void
+i810VGAUnlock(i810VGAPtr vgap);
+
+void
+i810VGALock(i810VGAPtr vgap);
+
+Bool
+i810VGAInit(KdScreenInfo *scrninfp, const KdMonitorTiming *t);
+
+void
+i810VGABlankScreen(KdCardInfo *card, Bool on);
+
+void
+i810AdjustFrame(KdScreenInfo *screen, int x, int y, int flags);
+
+Bool
+i810VGAMapMem(KdCardInfo *card);
+
+void
+i810VGASave(KdCardInfo *card, vgaRegPtr save, int flags);
+
+void
+i810PrintErrorState(KdCardInfo *card);
+
+void
+i810VGAGetIOBase(i810VGAPtr vgap);
+
+/*
+ * MMIO versions of the register access functions. These require
+ * hwp->MemBase to be set in such a way that when the standard VGA port
+ * address is added the correct memory address results.
+ */
+
+#define Vminb(p) ( *(volatile CARD8 *)(vgap->MMIOBase + (p)))
+#define Vmoutb(p,v) ( *(volatile CARD8 *)(vgap->MMIOBase + (p)) = (v))
+
+#define mmioWriteCrtc(vgap, index, value) { \
+ Vmoutb(vgap->IOBase + VGA_CRTC_INDEX_OFFSET, index); \
+ Vmoutb(vgap->IOBase + VGA_CRTC_DATA_OFFSET, value); \
+}
+
+#define mmioReadCrtc(vgap, index) ( \
+ Vmoutb(vgap->IOBase + VGA_CRTC_INDEX_OFFSET, index), \
+ Vminb(vgap->IOBase + VGA_CRTC_DATA_OFFSET) \
+)
+
+#define mmioWriteGr(vgap, index, value) { \
+ Vmoutb(VGA_GRAPH_INDEX, index); \
+ Vmoutb(VGA_GRAPH_DATA, value); \
+}
+
+#define mmioReadGr(vgap, index) ( \
+ Vmoutb(VGA_GRAPH_INDEX, index), \
+ Vminb(VGA_GRAPH_DATA) \
+)
+
+#define mmioWriteSeq(vgap, index, value) {\
+ Vmoutb(VGA_SEQ_INDEX, index); \
+ Vmoutb(VGA_SEQ_DATA, value); \
+}
+
+#define mmioReadSeq(vgap, index) ( \
+ Vmoutb(VGA_SEQ_INDEX, index), \
+ Vminb(VGA_SEQ_DATA) \
+)
+
+#define mmioWriteAttr(vgap, index, value) { \
+ (void) Vminb(vgap->IOBase + VGA_IN_STAT_1_OFFSET); \
+ Vmoutb(VGA_ATTR_INDEX, index); \
+ Vmoutb(VGA_ATTR_DATA_W, value); \
+}
+
+#define mmioReadAttr(vgap, index) ( \
+ (void) Vminb(vgap->IOBase + VGA_IN_STAT_1_OFFSET), \
+ Vmoutb(VGA_ATTR_INDEX, index), \
+ Vminb(VGA_ATTR_DATA_R) \
+)
+
+#define mmioWriteMiscOut(vgap, value) Vmoutb(VGA_MISC_OUT_W, value)
+
+
+#define mmioReadMiscOut(vgap) Vminb(VGA_MISC_OUT_R)
+
+#define mmioEnablePalette(vgap) { \
+ (void) Vminb(vgap->IOBase + VGA_IN_STAT_1_OFFSET); \
+ Vmoutb(VGA_ATTR_INDEX, 0x00); \
+ vgap->paletteEnabled = TRUE; \
+}
+
+#define mmioDisablePalette(vgap) { \
+ (void) Vminb(vgap->IOBase + VGA_IN_STAT_1_OFFSET); \
+ Vmoutb(VGA_ATTR_INDEX, 0x20); \
+ vgap->paletteEnabled = FALSE; \
+}
+
+#define mmioWriteDacWriteAddr(vgap, value) Vmoutb(VGA_DAC_WRITE_ADDR, value)
+
+#define mmioWriteDacData(vgap, value) Vmoutb(VGA_DAC_DATA, value)
+
+#endif /* _I810_H_ */
diff --git a/hw/kdrive/i810/i810_cursor.c b/hw/kdrive/i810/i810_cursor.c
new file mode 100644
index 000000000..9136ce748
--- /dev/null
+++ b/hw/kdrive/i810/i810_cursor.c
@@ -0,0 +1,409 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+
+/* $XFree86$ */
+
+/* i810_cursor.c: KDrive hardware cursor routines for the i810 chipset */
+
+/*
+ * Authors:
+ * Keith Whitwell <keithw@precisioninsight.com>
+ * Pontus Lidman <pontus.lidman@nokia.com>
+ *
+ */
+
+#include "kdrive.h"
+#include "kxv.h"
+#include "i810.h"
+#include "cursorstr.h"
+
+#define SetupCursor(s) KdScreenPriv(s); \
+ i810CardInfo(pScreenPriv); \
+ i810ScreenInfo(pScreenPriv); \
+ i810Cursor *pCurPriv = &i810s->cursor
+
+
+static void
+writeStandardMMIO(I810CardInfo *i810c, int addr, CARD8 val) {
+ moutb(addr, val);
+}
+
+void
+_i810MoveCursor(ScreenPtr pScreen, int x, int y) {
+ SetupCursor(pScreen);
+ int flag;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
+ ErrorF( "I810SetCursorPosition %d %d\n", x, y);
+
+ x += i810c->CursorOffset;
+
+ if (x >= 0) flag = CURSOR_X_POS;
+ else {
+ flag = CURSOR_X_NEG;
+ x=-x;
+ }
+
+ OUTREG8( CURSOR_X_LO, x&0xFF);
+ OUTREG8( CURSOR_X_HI, (((x >> 8) & 0x07) | flag));
+
+ if (y >= 0) flag = CURSOR_Y_POS;
+ else {
+ flag = CURSOR_Y_NEG;
+ y=-y;
+ }
+ OUTREG8( CURSOR_Y_LO, y&0xFF);
+ OUTREG8( CURSOR_Y_HI, (((y >> 8) & 0x07) | flag));
+
+ /* Enable cursor */
+ OUTREG( CURSOR_BASEADDR, i810c->CursorPhysical);
+ OUTREG8( CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_3C);
+
+}
+
+static void i810LoadCursor(ScreenPtr pScreen, int x, int y);
+
+static void
+i810MoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ SetupCursor (pScreen);
+
+ if (!pCurPriv->has_cursor)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ _i810MoveCursor (pScreen, x, y);
+
+ i810LoadCursor(pScreen, x, y);
+}
+
+static void
+_i810SetCursorColors(ScreenPtr pScreen) { /* int bg, int fg */
+
+ SetupCursor(pScreen);
+ int tmp;
+
+ int bg = 0xffffff;
+ int fg = 0x000000;
+
+ tmp=INREG8(PIXPIPE_CONFIG_0);
+ tmp |= EXTENDED_PALETTE;
+ OUTREG8( PIXPIPE_CONFIG_0, tmp);
+
+ writeStandardMMIO(i810c, DACMASK, 0xFF);
+ writeStandardMMIO(i810c, DACWX, 0x04);
+
+ writeStandardMMIO(i810c, DACDATA, (bg & 0x00FF0000) >> 16);
+ writeStandardMMIO(i810c, DACDATA, (bg & 0x0000FF00) >> 8);
+ writeStandardMMIO(i810c, DACDATA, (bg & 0x000000FF));
+
+ writeStandardMMIO(i810c, DACDATA, (fg & 0x00FF0000) >> 16);
+ writeStandardMMIO(i810c, DACDATA, (fg & 0x0000FF00) >> 8);
+ writeStandardMMIO(i810c, DACDATA, (fg & 0x000000FF));
+
+ tmp=INREG8( PIXPIPE_CONFIG_0 );
+ tmp &= ~EXTENDED_PALETTE;
+ OUTREG8( PIXPIPE_CONFIG_0, tmp );
+}
+
+static void i810LoadCursor(ScreenPtr pScreen, int x, int y) {
+
+ SetupCursor(pScreen);
+
+ int w, h;
+ unsigned short r;
+ unsigned char *msk, *mskLine, *src, *srcLine;
+
+ int i, j;
+ int src_stride, src_width;
+
+ CursorPtr pCursor = pCurPriv->pCursor;
+ CursorBitsPtr bits = pCursor->bits;
+ CARD8 tmp;
+ unsigned char *ram, *ramLine;
+
+ pCurPriv->pCursor = pCursor;
+ pCurPriv->xhot = pCursor->bits->xhot;
+ pCurPriv->yhot = pCursor->bits->yhot;
+
+ ramLine = (unsigned char *)(i810c->FbBase + i810c->CursorStart);
+ mskLine = (unsigned char *) bits->mask;
+ srcLine = (unsigned char *) bits->source;
+
+ h = bits->height;
+ if (h > I810_CURSOR_HEIGHT)
+ h = I810_CURSOR_HEIGHT;
+
+
+ src_stride = BitmapBytePad(bits->width); /* bytes per line */
+ src_width = (bits->width + 7) >> 3;
+
+ for (i = 0; i < I810_CURSOR_HEIGHT; i++) {
+ msk = mskLine;
+ src = srcLine;
+ ram = ramLine;
+ mskLine += src_stride;
+ srcLine += src_stride;
+ ramLine += I810_CURSOR_WIDTH / 4;
+
+ for (j = 0; j < I810_CURSOR_WIDTH / 8; j++) {
+
+ unsigned short m, s, b1, b2;
+
+ if (i < h && j < src_width)
+ {
+ m = *msk++;
+ s = *src++ & m;
+ m = ~m;
+ /* mask off right side */
+ if (j == src_width - 1 && (bits->width & 7))
+ {
+ m |= 0xff << (bits->width & 7);
+ }
+ }
+ else
+ {
+ m = 0xff;
+ s = 0x00;
+ }
+
+ /* The i810 stores the cursor in an interleaved bitmap format,
+ in reverse byte order */
+ /* Not tested with cursors bigger than 16x16 !!! */
+
+ ram[8+(j ^ 1)] = s; /* b2 */
+ ram[0+(j ^ 1)] = m; /* b1 */
+ }
+ }
+ /* Set new color */
+ _i810SetCursorColors (pScreen);
+
+ /* Move to new position */
+ _i810MoveCursor (pScreen, x, y);
+
+ /* Enable cursor */
+ OUTREG( CURSOR_BASEADDR, i810c->CursorPhysical);
+ OUTREG8( CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_3C);
+
+ tmp = INREG8( PIXPIPE_CONFIG_0 );
+ tmp |= HW_CURSOR_ENABLE;
+ OUTREG8( PIXPIPE_CONFIG_0, tmp);
+}
+
+static void
+i810UnloadCursor(ScreenPtr pScreen) {
+
+ SetupCursor(pScreen);
+
+ unsigned char tmp;
+
+ tmp=INREG8( PIXPIPE_CONFIG_0 );
+ tmp &= ~HW_CURSOR_ENABLE;
+ OUTREG8( PIXPIPE_CONFIG_0, tmp);
+}
+
+
+static Bool
+i810RealizeCursor (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);
+ i810LoadCursor (pScreen, x, y);
+ }
+ }
+ return TRUE;
+}
+
+static Bool
+i810UnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+static void
+i810SetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ SetupCursor(pScreen);
+
+ pCurPriv->pCursor = pCursor;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCursor)
+ i810LoadCursor (pScreen, x, y);
+ else
+ i810UnloadCursor (pScreen);
+}
+
+miPointerSpriteFuncRec i810PointerSpriteFuncs = {
+ i810RealizeCursor,
+ i810UnrealizeCursor,
+ i810SetCursor,
+ i810MoveCursor,
+};
+
+static void
+i810QueryBestSize (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
+i810CursorInit(ScreenPtr pScreen)
+{
+
+ SetupCursor(pScreen);
+
+ if (!i810c->CursorStart) {
+ pCurPriv->has_cursor = FALSE;
+ return FALSE;
+ }
+
+ pCurPriv->width = I810_CURSOR_WIDTH;
+ pCurPriv->height= I810_CURSOR_HEIGHT;
+ pScreen->QueryBestSize = i810QueryBestSize;
+ miPointerInitialize (pScreen,
+ &i810PointerSpriteFuncs,
+ &kdPointerScreenFuncs,
+ FALSE);
+ pCurPriv->has_cursor = TRUE;
+ pCurPriv->pCursor = NULL;
+ return TRUE;
+}
+
+void
+i810CursorEnable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ int x, y;
+
+ miPointerPosition (&x, &y);
+ i810LoadCursor (pScreen, x, y);
+ }
+ else
+ i810UnloadCursor (pScreen);
+ }
+}
+
+void
+i810CursorDisable (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (pCurPriv->has_cursor)
+ {
+ if (pCurPriv->pCursor)
+ {
+ i810UnloadCursor (pScreen);
+ }
+ }
+}
+
+void
+i810CursorFini (ScreenPtr pScreen)
+{
+ SetupCursor (pScreen);
+
+ pCurPriv->pCursor = NULL;
+}
+
diff --git a/hw/kdrive/i810/i810_reg.h b/hw/kdrive/i810/i810_reg.h
new file mode 100644
index 000000000..2f8e67f63
--- /dev/null
+++ b/hw/kdrive/i810/i810_reg.h
@@ -0,0 +1,696 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_reg.h,v 1.4 2000/09/26 15:57:12 tsi Exp $ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keithw@precisioninsight.com>
+ * Pontus Lidman <pontus.lidman@nokia.com>
+ *
+ * based on the i740 driver by
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ *
+ */
+
+/* I/O register offsets
+ */
+#define SRX 0x3C4 /* p208 */
+#define GRX 0x3CE /* p213 */
+#define ARX 0x3C0 /* p224 */
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6 /* p232 */
+#define DACSTATE 0x3C7 /* p232 */
+#define DACRX 0x3C7 /* p233 */
+#define DACWX 0x3C8 /* p233 */
+#define DACDATA 0x3C9 /* p233 */
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C /* p246 */
+#define START_ADDR_LO 0x0D /* p247 */
+#define VERT_SYNC_END 0x11 /* p249 */
+#define EXT_VERT_TOTAL 0x30 /* p257 */
+#define EXT_VERT_DISPLAY 0x31 /* p258 */
+#define EXT_VERT_SYNC_START 0x32 /* p259 */
+#define EXT_VERT_BLANK_START 0x33 /* p260 */
+#define EXT_HORIZ_TOTAL 0x35 /* p261 */
+#define EXT_HORIZ_BLANK 0x39 /* p261 */
+#define EXT_START_ADDR 0x40 /* p262 */
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41 /* p263 */
+#define EXT_START_ADDR_HI 0x42 /* p263 */
+#define INTERLACE_CNTL 0x70 /* p264 */
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register
+ */
+#define MSR_R 0x3CC /* p207 */
+#define MSR_W 0x3C2 /* p207 */
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0 /* p207 */
+#define CGA_BASE 0x3D0 /* p207 */
+
+/* CR80 - IO Control, p264
+ */
+#define IO_CTNL 0x80
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+/* GR10 - Address mapping, p221
+ */
+#define ADDRESS_MAPPING 0x10
+#define PAGE_TO_LOCAL_MEM_ENABLE 0x10
+#define GTT_MEM_MAP_ENABLE 0x08
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+/* Blitter control, p378
+ */
+#define BITBLT_CNTL 0x7000c
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define BITBLT_STATUS 0x01
+
+/* p375.
+ */
+#define DISPLAY_CNTL 0x70008
+#define VGA_WRAP_MODE 0x02
+#define VGA_WRAP_AT_256KB 0x00
+#define VGA_NO_WRAP 0x02
+#define GUI_MODE 0x01
+#define STANDARD_VGA_MODE 0x00
+#define HIRES_MODE 0x01
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_0 0x70009
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_1 0x7000a
+#define DISPLAY_COLOR_MODE 0x0F
+#define DISPLAY_VGA_MODE 0x00
+#define DISPLAY_8BPP_MODE 0x02
+#define DISPLAY_15BPP_MODE 0x04
+#define DISPLAY_16BPP_MODE 0x05
+#define DISPLAY_24BPP_MODE 0x06
+#define DISPLAY_32BPP_MODE 0x07
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_2 0x7000b
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+
+/* p380
+ */
+#define DISPLAY_BASE 0x70020
+#define DISPLAY_BASE_MASK 0x03fffffc
+
+
+/* Cursor control registers, pp383-384
+ */
+#define CURSOR_CONTROL 0x70080
+#define CURSOR_ORIGIN_SCREEN 0x00
+#define CURSOR_ORIGIN_DISPLAY 0x10
+#define CURSOR_MODE 0x07
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_RESERVED 0x07
+#define CURSOR_BASEADDR 0x70084
+#define CURSOR_BASEADDR_MASK 0x1FFFFF00
+#define CURSOR_X_LO 0x70088
+#define CURSOR_X_HI 0x70089
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0x7008A
+#define CURSOR_Y_HI 0x7008B
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+
+
+/* Similar registers exist in Device 0 on the i810 (pp55-65), but I'm
+ * not sure they refer to local (graphics) memory.
+ *
+ * These details are for the local memory control registers,
+ * (pp301-310). The test machines are not equiped with local memory,
+ * so nothing is tested. Only a single row seems to be supported.
+ */
+#define DRAM_ROW_TYPE 0x3000
+#define DRAM_ROW_0 0x01
+#define DRAM_ROW_0_SDRAM 0x01
+#define DRAM_ROW_0_EMPTY 0x00
+#define DRAM_ROW_CNTL_LO 0x3001
+#define DRAM_PAGE_MODE_CTRL 0x10
+#define DRAM_RAS_TO_CAS_OVRIDE 0x08
+#define DRAM_CAS_LATENCY 0x04
+#define DRAM_RAS_TIMING 0x02
+#define DRAM_RAS_PRECHARGE 0x01
+#define DRAM_ROW_CNTL_HI 0x3002
+#define DRAM_REFRESH_RATE 0x18
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x08
+#define DRAM_REFRESH_FAST_TEST 0x10
+#define DRAM_REFRESH_RESERVED 0x18
+#define DRAM_SMS 0x07
+#define DRAM_SMS_NORMAL 0x00
+#define DRAM_SMS_NOP_ENABLE 0x01
+#define DRAM_SMS_ABPCE 0x02
+#define DRAM_SMS_MRCE 0x03
+#define DRAM_SMS_CBRCE 0x04
+
+/* p307
+ */
+#define DPMS_SYNC_SELECT 0x5002
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+
+
+/* p317, 319
+ */
+#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */
+#define VCLK2_VCO_N 0x600a
+#define VCLK2_VCO_DIV_SEL 0x6012
+#define POST_DIV_SELECT 0x70
+#define POST_DIV_1 0x00
+#define POST_DIV_2 0x10
+#define POST_DIV_4 0x20
+#define POST_DIV_8 0x30
+#define POST_DIV_16 0x40
+#define POST_DIV_32 0x50
+#define VCO_LOOP_DIV_BY_4M 0x00
+#define VCO_LOOP_DIV_BY_16M 0x04
+
+
+/* Instruction Parser Mode Register
+ * - p281
+ * - 2 new bits.
+ */
+#define INST_PM 0x20c0
+#define AGP_SYNC_PACKET_FLUSH_ENABLE 0x20 /* reserved */
+#define SYNC_PACKET_FLUSH_ENABLE 0x10
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+
+#define INST_DONE 0x2090
+#define INST_PS 0x20c4
+
+#define MEMMODE 0x20dc
+
+
+/* Instruction parser error register. p279
+ */
+#define IPEIR 0x2088
+#define IPEHR 0x208C
+
+
+/* General error reporting regs, p296
+ */
+#define EIR 0x20B0
+#define EMR 0x20B4
+#define ESR 0x20B8
+#define IP_ERR 0x0001
+#define ERROR_RESERVED 0xffc6
+
+
+/* Interrupt Control Registers
+ * - new bits for i810
+ * - new register hwstam (mask)
+ */
+#define HWSTAM 0x2098 /* p290 */
+#define IER 0x20a0 /* p291 */
+#define IIR 0x20a4 /* p292 */
+#define IMR 0x20a8 /* p293 */
+#define ISR 0x20ac /* p294 */
+#define HW_ERROR 0x8000
+#define SYNC_STATUS_TOGGLE 0x1000
+#define DPY_0_FLIP_PENDING 0x0800
+#define DPY_1_FLIP_PENDING 0x0400 /* not implemented on i810 */
+#define OVL_0_FLIP_PENDING 0x0200
+#define OVL_1_FLIP_PENDING 0x0100 /* not implemented on i810 */
+#define DPY_0_VBLANK 0x0080
+#define DPY_0_EVENT 0x0040
+#define DPY_1_VBLANK 0x0020 /* not implemented on i810 */
+#define DPY_1_EVENT 0x0010 /* not implemented on i810 */
+#define HOST_PORT_EVENT 0x0008 /* */
+#define CAPTURE_EVENT 0x0004 /* */
+#define USER_DEFINED 0x0002
+#define BREAKPOINT 0x0001
+
+
+#define INTR_RESERVED (0x6000 | \
+ DPY_1_FLIP_PENDING | \
+ OVL_1_FLIP_PENDING | \
+ DPY_1_VBLANK | \
+ DPY_1_EVENT | \
+ HOST_PORT_EVENT | \
+ CAPTURE_EVENT )
+
+/* FIFO Watermark and Burst Length Control Register
+ *
+ * - different offset and contents on i810 (p299) (fewer bits per field)
+ * - some overlay fields added
+ * - what does it all mean?
+ */
+#define FWATER_BLC 0x20d8
+#define MM_BURST_LENGTH 0x00700000
+#define MM_FIFO_WATERMARK 0x0001F000
+#define LM_BURST_LENGTH 0x00000700
+#define LM_FIFO_WATERMARK 0x0000001F
+
+
+/* Fence/Tiling ranges [0..7]
+ */
+#define FENCE 0x2000
+#define FENCE_NR 8
+
+#define FENCE_START_MASK 0x03F80000
+#define FENCE_X_MAJOR 0x00000000
+#define FENCE_Y_MAJOR 0x00001000
+#define FENCE_SIZE_MASK 0x00000700
+#define FENCE_SIZE_512K 0x00000000
+#define FENCE_SIZE_1M 0x00000100
+#define FENCE_SIZE_2M 0x00000200
+#define FENCE_SIZE_4M 0x00000300
+#define FENCE_SIZE_8M 0x00000400
+#define FENCE_SIZE_16M 0x00000500
+#define FENCE_SIZE_32M 0x00000600
+#define FENCE_PITCH_MASK 0x00000070
+#define FENCE_PITCH_1 0x00000000
+#define FENCE_PITCH_2 0x00000010
+#define FENCE_PITCH_4 0x00000020
+#define FENCE_PITCH_8 0x00000030
+#define FENCE_PITCH_16 0x00000040
+#define FENCE_PITCH_32 0x00000050
+#define FENCE_VALID 0x00000001
+
+
+/* Registers to control page table, p274
+ */
+#define PGETBL_CTL 0x2020
+#define PGETBL_ADDR_MASK 0xFFFFF000
+#define PGETBL_ENABLE_MASK 0x00000001
+#define PGETBL_ENABLED 0x00000001
+
+/* Register containing pge table error results, p276
+ */
+#define PGE_ERR 0x2024
+#define PGE_ERR_ADDR_MASK 0xFFFFF000
+#define PGE_ERR_ID_MASK 0x00000038
+#define PGE_ERR_CAPTURE 0x00000000
+#define PGE_ERR_OVERLAY 0x00000008
+#define PGE_ERR_DISPLAY 0x00000010
+#define PGE_ERR_HOST 0x00000018
+#define PGE_ERR_RENDER 0x00000020
+#define PGE_ERR_BLITTER 0x00000028
+#define PGE_ERR_MAPPING 0x00000030
+#define PGE_ERR_CMD_PARSER 0x00000038
+#define PGE_ERR_TYPE_MASK 0x00000007
+#define PGE_ERR_INV_TABLE 0x00000000
+#define PGE_ERR_INV_PTE 0x00000001
+#define PGE_ERR_MIXED_TYPES 0x00000002
+#define PGE_ERR_PAGE_MISS 0x00000003
+#define PGE_ERR_ILLEGAL_TRX 0x00000004
+#define PGE_ERR_LOCAL_MEM 0x00000005
+#define PGE_ERR_TILED 0x00000006
+
+
+
+/* Page table entries loaded via mmio region, p323
+ */
+#define PTE_BASE 0x10000
+#define PTE_ADDR_MASK 0x3FFFF000
+#define PTE_TYPE_MASK 0x00000006
+#define PTE_LOCAL 0x00000002
+#define PTE_MAIN_UNCACHED 0x00000000
+#define PTE_MAIN_CACHED 0x00000006
+#define PTE_VALID_MASK 0x00000001
+#define PTE_VALID 0x00000001
+
+
+/* Ring buffer registers, p277, overview p19
+ */
+#define LP_RING 0x2030
+#define HP_RING 0x2040
+
+#define RING_TAIL 0x00
+#define TAIL_ADDR 0x000FFFF8
+
+#define RING_HEAD 0x04
+#define HEAD_WRAP_COUNT 0xFFE00000
+#define HEAD_WRAP_ONE 0x00200000
+#define HEAD_ADDR 0x001FFFFC
+
+#define RING_START 0x08
+#define START_ADDR 0x00FFFFF8
+
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x000FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+
+
+
+/* BitBlt Instructions
+ *
+ * There are many more masks & ranges yet to add.
+ */
+#define BR00_BITBLT_CLIENT 0x40000000
+#define BR00_OP_COLOR_BLT 0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR00_OP_FULL_BLT 0x11400000
+#define BR00_OP_MONO_SRC_BLT 0x11800000
+#define BR00_OP_MONO_SRC_COPY_BLT 0x11000000
+#define BR00_OP_MONO_PAT_BLT 0x11C00000
+#define BR00_OP_MONO_SRC_COPY_IMMEDIATE_BLT (0x61 << 22)
+#define BR00_OP_TEXT_IMMEDIATE_BLT 0xc000000
+
+
+#define BR00_TPCY_DISABLE 0x00000000
+#define BR00_TPCY_ENABLE 0x00000010
+
+#define BR00_TPCY_ROP 0x00000000
+#define BR00_TPCY_NO_ROP 0x00000020
+#define BR00_TPCY_EQ 0x00000000
+#define BR00_TPCY_NOT_EQ 0x00000040
+
+#define BR00_PAT_MSB_FIRST 0x00000000 /* ? */
+
+#define BR00_PAT_VERT_ALIGN 0x000000e0
+
+#define BR00_LENGTH 0x0000000F
+
+#define BR09_DEST_ADDR 0x03FFFFFF
+
+#define BR11_SOURCE_PITCH 0x00003FFF
+
+#define BR12_SOURCE_ADDR 0x03FFFFFF
+
+#define BR13_SOLID_PATTERN 0x80000000
+#define BR13_RIGHT_TO_LEFT 0x40000000
+#define BR13_LEFT_TO_RIGHT 0x00000000
+#define BR13_MONO_TRANSPCY 0x20000000
+#define BR13_USE_DYN_DEPTH 0x04000000
+#define BR13_DYN_8BPP 0x00000000
+#define BR13_DYN_16BPP 0x01000000
+#define BR13_DYN_24BPP 0x02000000
+#define BR13_ROP_MASK 0x00FF0000
+#define BR13_DEST_PITCH 0x0000FFFF
+#define BR13_PITCH_SIGN_BIT 0x00008000
+
+#define BR14_DEST_HEIGHT 0xFFFF0000
+#define BR14_DEST_WIDTH 0x0000FFFF
+
+#define BR15_PATTERN_ADDR 0x03FFFFFF
+
+#define BR16_SOLID_PAT_COLOR 0x00FFFFFF
+#define BR16_BACKGND_PAT_CLR 0x00FFFFFF
+
+#define BR17_FGND_PAT_CLR 0x00FFFFFF
+
+#define BR18_SRC_BGND_CLR 0x00FFFFFF
+#define BR19_SRC_FGND_CLR 0x00FFFFFF
+
+
+/* Instruction parser instructions
+ */
+
+#define INST_PARSER_CLIENT 0x00000000
+#define INST_OP_FLUSH 0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+#define INST_DEST_BUFFER_INFO 0x06800000
+
+#define INST_FRONT_BUFFER_INFO 0x06000000
+#define FRONT_INFO_ASYNC_FLIP 1<<6
+#define FRONT_INFO_PITCH_B 8
+
+#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
+
+
+/* Registers in the i810 host-pci bridge pci config space which affect
+ * the i810 graphics operations.
+ */
+#define SMRAM_MISCC 0x70
+#define GMS 0x000000c0
+#define GMS_DISABLE 0x00000000
+#define GMS_ENABLE_BARE 0x00000040
+#define GMS_ENABLE_512K 0x00000080
+#define GMS_ENABLE_1M 0x000000c0
+#define USMM 0x00000030
+#define USMM_DISABLE 0x00000000
+#define USMM_TSEG_ZERO 0x00000010
+#define USMM_TSEG_512K 0x00000020
+#define USMM_TSEG_1M 0x00000030
+#define GFX_MEM_WIN_SIZE 0x00010000
+#define GFX_MEM_WIN_32M 0x00010000
+#define GFX_MEM_WIN_64M 0x00000000
+
+/* Overkill? I don't know. Need to figure out top of mem to make the
+ * SMRAM calculations come out. Linux seems to have problems
+ * detecting it all on its own, so this seems a reasonable double
+ * check to any user supplied 'mem=...' boot param.
+ *
+ * ... unfortunately this reg doesn't work according to spec on the
+ * test hardware.
+ */
+#define WHTCFG_PAMR_DRP 0x50
+#define SYS_DRAM_ROW_0_SHIFT 16
+#define SYS_DRAM_ROW_1_SHIFT 20
+#define DRAM_MASK 0x0f
+#define DRAM_VALUE_0 0
+#define DRAM_VALUE_1 8
+/* No 2 value defined */
+#define DRAM_VALUE_3 16
+#define DRAM_VALUE_4 16
+#define DRAM_VALUE_5 24
+#define DRAM_VALUE_6 32
+#define DRAM_VALUE_7 32
+#define DRAM_VALUE_8 48
+#define DRAM_VALUE_9 64
+#define DRAM_VALUE_A 64
+#define DRAM_VALUE_B 96
+#define DRAM_VALUE_C 128
+#define DRAM_VALUE_D 128
+#define DRAM_VALUE_E 192
+#define DRAM_VALUE_F 256 /* nice one, geezer */
+#define LM_FREQ_MASK 0x10
+#define LM_FREQ_133 0x10
+#define LM_FREQ_100 0x00
+
+
+
+
+/* These are 3d state registers, but the state is invarient, so we let
+ * the X server handle it:
+ */
+
+
+
+/* GFXRENDERSTATE_COLOR_CHROMA_KEY, p135
+ */
+#define GFX_OP_COLOR_CHROMA_KEY ((0x3<<29)|(0x1d<<24)|(0x2<<16)|0x1)
+#define CC1_UPDATE_KILL_WRITE (1<<28)
+#define CC1_ENABLE_KILL_WRITE (1<<27)
+#define CC1_DISABLE_KILL_WRITE 0
+#define CC1_UPDATE_COLOR_IDX (1<<26)
+#define CC1_UPDATE_CHROMA_LOW (1<<25)
+#define CC1_UPDATE_CHROMA_HI (1<<24)
+#define CC1_CHROMA_LOW_MASK ((1<<24)-1)
+#define CC2_COLOR_IDX_SHIFT 24
+#define CC2_COLOR_IDX_MASK (0xff<<24)
+#define CC2_CHROMA_HI_MASK ((1<<24)-1)
+
+
+#define GFX_CMD_CONTEXT_SEL ((0<<29)|(0x5<<23))
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_UPDATE_USE (1<<16)
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_LOAD_CTX0 0
+#define CS_LOAD_CTX1 (1<<8)
+#define CS_USE_CTX0 0
+#define CS_USE_CTX1 (1<<0)
+
+/* 3D Rendering Engine */
+
+#define RENDER_CLIENT 0x60000000
+
+/* Primitive rendering instruction */
+
+#define GFX_PRIMITIVE 0x1f000000
+#define PRIMITIVE_TRIANGLE 0 << 18
+#define PRIMITIVE_TRI_STRIP 1 << 18
+#define PRIMITIVE_TRI_REV_STRIP 2 << 18
+#define PRIMITIVE_TRI_FAN 3 << 18
+#define PRIMITIVE_POLYGON 4 << 18
+#define PRIMITIVE_LINE 5 << 18
+#define PRIMITIVE_LINE_STRIP 6 << 18
+#define PRIMITIVE_RECTANGLE 7 << 18
+
+/* Vertex format instruction */
+#define GFX_VERTEX_FORMAT 0x05000000
+#define VERTEX_0_TEXCOORDS 0 << 8
+#define VERTEX_1_TEXCOORDS 1 << 8
+#define VERTEX_2_TEXCOORDS 2 << 8
+#define VERTEX_SPECULAR_FOG 1 << 7
+#define VERTEX_DIFFUSE_ALPHA 1 << 6
+#define VERTEX_Z_OFFSET 1 << 5
+#define VERTEX_POS_XYZ 1 << 1
+#define VERTEX_POS_XYZ_RHW 2 << 1
+#define VERTEX_POS_XY 3 << 1
+#define VERTEX_POS_XY_RHW 4 << 1
+
+/* Drawing Rectangle Info instruction */
+
+#define GFX_DRAWING_RECTANGLE_INFO 0x1d800003
+#define GFX_DRAWING_CLIP_DISABLE 1<<31
+
+/* Boolean enable 1 */
+#define GFX_BOOLEAN_ENA_1 0x03000000
+#define BOOL1_ALPHA_SETUP_MASK 1<<17
+#define BOOL1_ALPHA_SETUP_BIT 1<<16
+#define BOOL1_FOG_ENABLE_MASK 1<<7
+#define BOOL1_FOG_ENABLE_BIT 1<<6
+#define BOOL1_ALPHA_TEST_MASK 1<<5
+#define BOOL1_ALPHA_TEST_BIT 1<<4
+#define BOOL1_BLEND_ENABLE_MASK 1<<3
+#define BOOL1_BLEND_ENABLE_BIT 1<<2
+#define BOOL1_Z_ENABLE_MASK 1<<1
+#define BOOL1_Z_ENABLE_BIT 1<<0
+
+/* Boolean enable 2 */
+#define GFX_BOOLEAN_ENA_2 0x04000000
+#define BOOL2_MAPPING_CACHE_MASK 1<<17
+#define BOOL2_MAPPING_CACHE_BIT 1<<16
+#define BOOL2_ALPHA_DITHER_MASK 1<<15
+#define BOOL2_ALPHA_DITHER_BIT 1<<14
+#define BOOL2_FOG_DITHER_MASK 1<<13
+#define BOOL2_FOG_DITHER_BIT 1<<12
+#define BOOL2_SPECULAR_DITHER_MASK 1<<11
+#define BOOL2_SPECULAR_DITHER_BIT 1<<10
+#define BOOL2_COLOR_DITHER_MASK 1<<9
+#define BOOL2_COLOR_DITHER_BIT 1<<8
+#define BOOL2_FB_WRITE_MASK 1<<3
+#define BOOL2_FB_WRITE_BIT 1<<2
+#define BOOL2_Z_WRITE_MASK 1<<1
+#define BOOL2_Z_WRITE_BIT 1<<0
+
+/* Dest buffer variables */
+
+#define GFX_DEST_BUFFER_VARIABLES 0x1d850000
+
+#define DEST_BUF_VAR_8BIT 0 << 8
+#define DEST_BUF_VAR_555 1 << 8
+#define DEST_BUF_VAR_565 2 << 8
+
+/* map color blend stages */
+
+#define GFX_MAP_COLOR_BLEND_STAGES 0
+
+#define MAP_BLEND_STAGE_B 20
+#define MAP_BLEND_ACC_SEL_MASK 1<<19
+#define MAP_BLEND_ACC_SEL_BIT 1<<18
+#define MAP_BLEND_ARG1_MASK 1<<17
+#define MAP_BLEND_ARG1_B 14
+#define MAP_BLEND_REPLICATE_ARG1 1<<13
+#define MAP_BLEND_INVERT_ARG1 1<<12
+
+#define MAP_BLEND_ARG2_MASK 1<<11
+#define MAP_BLEND_ARG2_B 8
+#define MAP_BLEND_REPLICATE_ARG2 1<<7
+#define MAP_BLEND_INVERT_ARG2 1<<6
+
+#define MAP_BLEND_COLOR_OP_MASK 1<<5
+#define MAP_BLEND_COLOR_OP_B 0
+
+#define GFX_SCISSOR_ENABLE 0x1c800000
+
+#define SCISSOR_ENABLE_MASK 1<<1
+#define SCISSOR_ENABLE_BIT 1<<0
diff --git a/hw/kdrive/i810/i810_video.c b/hw/kdrive/i810/i810_video.c
new file mode 100644
index 000000000..0d18e44d9
--- /dev/null
+++ b/hw/kdrive/i810/i810_video.c
@@ -0,0 +1,1165 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/***************************************************************************
+
+Copyright 2000 Intel Corporation. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+
+/* $XFree86$ */
+
+/*
+ * i810_video.c: i810 KDrive Xv driver.
+ * Based on the XFree86 i810 Xv driver by Jonathan Bian.
+ *
+ * Authors:
+ * Jonathan Bian <jonathan.bian@intel.com>
+ * Pontus Lidman <pontus.lidman@nokia.com>
+ *
+ */
+
+#include "kdrive.h"
+#include "kxv.h"
+#include "i810.h"
+
+#include "Xv.h"
+
+#include "../../xfree86/common/fourcc.h"
+
+typedef struct {
+ CARD32 size;
+ CARD32 offset;
+} FBLinearRec, *FBLinearPtr;
+
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+static KdVideoAdaptorPtr i810SetupImageVideo(ScreenPtr);
+static void i810StopVideo(KdScreenInfo *, pointer, Bool);
+static int i810SetPortAttribute(KdScreenInfo *, Atom, int, pointer);
+static int i810GetPortAttribute(KdScreenInfo *, Atom, int *, pointer);
+static void i810QueryBestSize(KdScreenInfo *, Bool,
+ short, short, short, short, unsigned int *, unsigned int *, pointer);
+static int i810PutImage( KdScreenInfo *,
+ short, short, short, short, short, short, short, short,
+ int, unsigned char*, short, short, Bool, RegionPtr, pointer);
+static int i810QueryImageAttributes(KdScreenInfo *,
+ int, unsigned short *, unsigned short *, int *, int *);
+
+static void i810BlockHandler(int, pointer, pointer, pointer);
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast, xvColorKey;
+
+#define IMAGE_MAX_WIDTH 720
+#define IMAGE_MAX_HEIGHT 576
+#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT)
+
+#define OVERLAY_UPDATE(p) OUTREG(0x30000, p | 0x80000000);
+
+/*
+ * OV0CMD - Overlay Command Register
+ */
+#define VERTICAL_CHROMINANCE_FILTER 0x70000000
+#define VC_SCALING_OFF 0x00000000
+#define VC_LINE_REPLICATION 0x10000000
+#define VC_UP_INTERPOLATION 0x20000000
+#define VC_PIXEL_DROPPING 0x50000000
+#define VC_DOWN_INTERPOLATION 0x60000000
+#define VERTICAL_LUMINANCE_FILTER 0x0E000000
+#define VL_SCALING_OFF 0x00000000
+#define VL_LINE_REPLICATION 0x02000000
+#define VL_UP_INTERPOLATION 0x04000000
+#define VL_PIXEL_DROPPING 0x0A000000
+#define VL_DOWN_INTERPOLATION 0x0C000000
+#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000
+#define HC_SCALING_OFF 0x00000000
+#define HC_LINE_REPLICATION 0x00400000
+#define HC_UP_INTERPOLATION 0x00800000
+#define HC_PIXEL_DROPPING 0x01400000
+#define HC_DOWN_INTERPOLATION 0x01800000
+#define HORIZONTAL_LUMINANCE_FILTER 0x00380000
+#define HL_SCALING_OFF 0x00000000
+#define HL_LINE_REPLICATION 0x00080000
+#define HL_UP_INTERPOLATION 0x00100000
+#define HL_PIXEL_DROPPING 0x00280000
+#define HL_DOWN_INTERPOLATION 0x00300000
+
+#define Y_ADJUST 0x00010000
+#define OV_BYTE_ORDER 0x0000C000
+#define UV_SWAP 0x00004000
+#define Y_SWAP 0x00008000
+#define Y_AND_UV_SWAP 0x0000C000
+#define SOURCE_FORMAT 0x00003C00
+#define RGB_555 0x00000800
+#define RGB_565 0x00000C00
+#define YUV_422 0x00002000
+#define YUV_411 0x00002400
+#define YUV_420 0x00003000
+#define YUV_410 0x00003800
+#define BUFFER_AND_FIELD 0x00000006
+#define BUFFER0_FIELD0 0x00000000
+#define BUFFER1_FIELD0 0x00000004
+#define OVERLAY_ENABLE 0x00000001
+
+/*
+ * DOV0STA - Display/Overlay 0 Status Register
+ */
+#define DOV0STA 0x30008
+
+#define MINUV_SCALE 0x1
+
+#define RGB16ToColorKey(c) \
+ (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+
+#define RGB15ToColorKey(c) \
+ (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
+
+Bool i810InitVideo(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ KdVideoAdaptorPtr newAdaptor = NULL;
+ int num_adaptors;
+
+/* fprintf(stderr,"i810InitVideo\n"); */
+
+ if (screen->fb[0].bitsPerPixel != 8)
+ {
+ newAdaptor = i810SetupImageVideo(pScreen);
+ }
+
+ num_adaptors = KdXVListGenericAdaptors(screen, &adaptors);
+
+ if(newAdaptor) {
+ if(!num_adaptors) {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ } else {
+ newAdaptors = /* need to free this someplace */
+ 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;
+}
+
+/* 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, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+
+#define NUM_IMAGES 4
+
+static KdImageRec Images[NUM_IMAGES] =
+{
+ XVIMAGE_YUY2,
+ XVIMAGE_YV12,
+ XVIMAGE_I420,
+ XVIMAGE_UYVY
+};
+
+typedef struct {
+ CARD32 OBUF_0Y;
+ CARD32 OBUF_1Y;
+ CARD32 OBUF_0U;
+ CARD32 OBUF_0V;
+ CARD32 OBUF_1U;
+ CARD32 OBUF_1V;
+ CARD32 OV0STRIDE;
+ CARD32 YRGB_VPH;
+ CARD32 UV_VPH;
+ CARD32 HORZ_PH;
+ CARD32 INIT_PH;
+ CARD32 DWINPOS;
+ CARD32 DWINSZ;
+ CARD32 SWID;
+ CARD32 SWIDQW;
+ CARD32 SHEIGHT;
+ CARD32 YRGBSCALE;
+ CARD32 UVSCALE;
+ CARD32 OV0CLRC0;
+ CARD32 OV0CLRC1;
+ CARD32 DCLRKV;
+ CARD32 DCLRKM;
+ CARD32 SCLRKVH;
+ CARD32 SCLRKVL;
+ CARD32 SCLRKM;
+ CARD32 OV0CONF;
+ CARD32 OV0CMD;
+} I810OverlayRegRec, *I810OverlayRegPtr;
+
+typedef struct {
+ CARD32 YBuf0offset;
+ CARD32 UBuf0offset;
+ CARD32 VBuf0offset;
+
+ CARD32 YBuf1offset;
+ CARD32 UBuf1offset;
+ CARD32 VBuf1offset;
+
+ unsigned char currentBuf;
+
+ unsigned char brightness;
+ unsigned char contrast;
+
+ RegionRec clip;
+ CARD32 colorKey;
+
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+ FBLinearPtr linear;
+} I810PortPrivRec, *I810PortPrivPtr;
+
+#define GET_PORT_PRIVATE(screen) \
+ (I810PortPrivPtr)(((I810CardInfo *) (screen->card->driver))->adaptor->pPortPrivates[0].ptr)
+
+static void i810ResetVideo(KdScreenInfo *screen)
+{
+ ScreenPtr pScreen = screen->pScreen;
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ I810PortPrivPtr pPriv = i810c->adaptor->pPortPrivates[0].ptr;
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (i810c->FbBase + i810c->OverlayStart);
+
+ /*
+ * Default to maximum image size in YV12
+ */
+
+ overlay->YRGB_VPH = 0;
+ overlay->UV_VPH = 0;
+ overlay->HORZ_PH = 0;
+ overlay->INIT_PH = 0;
+ overlay->DWINPOS = 0;
+ overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH;
+ overlay->SWID = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15);
+ overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12);
+ overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15);
+ overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */
+ overlay->UVSCALE = 0x80004000; /* scale factor 1 */
+ overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */
+ overlay->OV0CLRC1 = 0x80; /* saturation: bypass */
+
+ /*
+ * Enable destination color keying
+ */
+ switch(screen->fb[0].depth) {
+ case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+ overlay->DCLRKM = 0x80070307;
+ break;
+ case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+ overlay->DCLRKM = 0x80070707;
+ break;
+ default: overlay->DCLRKV = pPriv->colorKey;
+ overlay->DCLRKM = 0x80000000;
+ break;
+ }
+
+ overlay->SCLRKVH = 0;
+ overlay->SCLRKVL = 0;
+ overlay->SCLRKM = 0; /* source color key disable */
+ overlay->OV0CONF = 0; /* two 720 pixel line buffers */
+
+ overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
+ YUV_420;
+
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+}
+
+
+static KdVideoAdaptorPtr
+i810SetupImageVideo(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = pScreenPriv->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+
+ KdVideoAdaptorPtr adapt;
+ I810PortPrivPtr pPriv;
+
+/* fprintf(stderr,"i810SetupImageVideo\n"); */
+
+ if(!(adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) +
+ sizeof(I810PortPrivRec) +
+ sizeof(DevUnion))))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "I810 Video Overlay";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+
+ pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]);
+
+ adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
+ 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 = i810StopVideo;
+ adapt->SetPortAttribute = i810SetPortAttribute;
+ adapt->GetPortAttribute = i810GetPortAttribute;
+ adapt->QueryBestSize = i810QueryBestSize;
+ adapt->PutImage = i810PutImage;
+ adapt->QueryImageAttributes = i810QueryImageAttributes;
+
+ pPriv->colorKey = i810c->colorKey & ((1 << screen->fb[0].depth) - 1);
+ pPriv->videoStatus = 0;
+ pPriv->brightness = 0;
+ pPriv->contrast = 128;
+ pPriv->linear = NULL;
+ pPriv->currentBuf = 0;
+
+ /* gotta uninit this someplace */
+ REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
+
+ i810c->adaptor = adapt;
+
+ i810c->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = i810BlockHandler;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+
+ i810ResetVideo(screen);
+
+ return adapt;
+}
+
+
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (int*)REGION_RECTS(A);
+ dataB = (int*)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+
+/* I810ClipVideo -
+
+ 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
+I810ClipVideo(
+ 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
+i810StopVideo(KdScreenInfo *screen, pointer data, Bool exit)
+{
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (i810c->FbBase + i810c->OverlayStart);
+
+ REGION_EMPTY(screen->pScreen, &pPriv->clip);
+
+ if(exit) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ overlay->OV0CMD &= 0xFFFFFFFE;
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+ }
+ if(pPriv->linear) {
+ xfree(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ } else {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+
+}
+
+static int
+i810SetPortAttribute(
+ KdScreenInfo *screen,
+ Atom attribute,
+ int value,
+ pointer data
+){
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (i810c->FbBase + i810c->OverlayStart);
+
+ if(attribute == xvBrightness) {
+ if((value < -128) || (value > 127))
+ return BadValue;
+ pPriv->brightness = value;
+ overlay->OV0CLRC0 &= 0xFFFFFF00;
+ overlay->OV0CLRC0 |= value;
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+ } else
+ if(attribute == xvContrast) {
+ if((value < 0) || (value > 255))
+ return BadValue;
+ pPriv->contrast = value;
+ overlay->OV0CLRC0 &= 0xFFFE00FF;
+ overlay->OV0CLRC0 |= value << 9;
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+ } else
+ if(attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ switch(screen->fb[0].depth) {
+ case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+ break;
+ case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+ break;
+ default: overlay->DCLRKV = pPriv->colorKey;
+ break;
+ }
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+ REGION_EMPTY(screen->pScreen, &pPriv->clip);
+ } else return BadMatch;
+
+ return Success;
+}
+
+static int
+i810GetPortAttribute(
+ KdScreenInfo *screen,
+ Atom attribute,
+ int *value,
+ pointer data
+){
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+
+ if(attribute == xvBrightness) {
+ *value = pPriv->brightness;
+ } else
+ if(attribute == xvContrast) {
+ *value = pPriv->contrast;
+ } else
+ if(attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ } else return BadMatch;
+
+ return Success;
+}
+
+static void
+i810QueryBestSize(
+ 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
+I810CopyPackedData(
+ KdScreenInfo *screen,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch,
+ int top,
+ int left,
+ int h,
+ int w
+ )
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ I810PortPrivPtr pPriv = i810c->adaptor->pPortPrivates[0].ptr;
+ unsigned char *src, *dst;
+
+ src = buf + (top*srcPitch) + (left<<1);
+
+ if (pPriv->currentBuf == 0)
+ dst = i810c->FbBase + pPriv->YBuf0offset;
+ else
+ dst = i810c->FbBase + pPriv->YBuf1offset;
+
+ w <<= 1;
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+static void
+i810CopyPlanarData(
+ KdScreenInfo *screen,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch, /* of chroma */
+ int srcH,
+ int top,
+ int left,
+ int h,
+ int w,
+ int id
+ )
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ I810PortPrivPtr pPriv = i810c->adaptor->pPortPrivates[0].ptr;
+ int i;
+ unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
+
+ /* Copy Y data */
+ src1 = buf + (top*srcPitch) + left;
+ if (pPriv->currentBuf == 0)
+ dst1 = i810c->FbBase + pPriv->YBuf0offset;
+ else
+ dst1 = i810c->FbBase + pPriv->YBuf1offset;
+
+ for (i = 0; i < h; i++) {
+ memcpy(dst1, src1, w);
+ src1 += srcPitch;
+ dst1 += dstPitch << 1;
+ }
+
+ /* Copy V data for YV12, or U data for I420 */
+ src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst2 = i810c->FbBase + pPriv->UBuf0offset;
+ else
+ dst2 = i810c->FbBase + pPriv->VBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst2 = i810c->FbBase + pPriv->UBuf1offset;
+ else
+ dst2 = i810c->FbBase + pPriv->VBuf1offset;
+ }
+
+ for (i = 0; i < h/2; i++) {
+ memcpy(dst2, src2, w/2);
+ src2 += srcPitch>>1;
+ dst2 += dstPitch;
+ }
+
+ /* Copy U data for YV12, or V data for I420 */
+ src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst3 = i810c->FbBase + pPriv->VBuf0offset;
+ else
+ dst3 = i810c->FbBase + pPriv->UBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst3 = i810c->FbBase + pPriv->VBuf1offset;
+ else
+ dst3 = i810c->FbBase + pPriv->UBuf1offset;
+ }
+
+ for (i = 0; i < h/2; i++) {
+ memcpy(dst3, src3, w/2);
+ src3 += srcPitch>>1;
+ dst3 += dstPitch;
+ }
+}
+
+static void
+i810DisplayVideo(
+ KdScreenInfo *screen,
+ int id,
+ short width, short height,
+ int dstPitch, /* of chroma for 4:2:0 */
+ int x1, int y1, int x2, int y2,
+ BoxPtr dstBox,
+ short src_w, short src_h,
+ short drw_w, short drw_h
+){
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ I810PortPrivPtr pPriv = i810c->adaptor->pPortPrivates[0].ptr;
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (i810c->FbBase + i810c->OverlayStart);
+ int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+ int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0;
+ unsigned int swidth;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ swidth = (width + 7) & ~7;
+ overlay->SWID = (swidth << 15) | swidth;
+ overlay->SWIDQW = (swidth << 12) | (swidth >> 3);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ swidth = ((width + 3) & ~3) << 1;
+ overlay->SWID = swidth;
+ overlay->SWIDQW = swidth >> 3;
+ break;
+ }
+
+ overlay->SHEIGHT = height | (height << 15);
+ overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
+ overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
+ (dstBox->x2 - dstBox->x1);
+
+ /* buffer locations */
+ overlay->OBUF_0Y = pPriv->YBuf0offset;
+ overlay->OBUF_1Y = pPriv->YBuf1offset;
+ overlay->OBUF_0U = pPriv->UBuf0offset;
+ overlay->OBUF_0V = pPriv->VBuf0offset;
+ overlay->OBUF_1U = pPriv->UBuf1offset;
+ overlay->OBUF_1V = pPriv->VBuf1offset;
+
+ /*
+ * Calculate horizontal and vertical scaling factors, default to 1:1
+ */
+ overlay->YRGBSCALE = 0x80004000;
+ overlay->UVSCALE = 0x80004000;
+
+ /*
+ * Initially, YCbCr and Overlay Enable and
+ * vertical chrominance up interpolation and horozontal chrominance
+ * up interpolation
+ */
+ overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
+ OVERLAY_ENABLE;
+
+ if ((drw_w != src_w) || (drw_h != src_h))
+ {
+ xscaleInt = (src_w / drw_w) & 0x3;
+ xscaleFract = (src_w << 12) / drw_w;
+ yscaleInt = (src_h / drw_h) & 0x3;
+ yscaleFract = (src_h << 12) / drw_h;
+
+ overlay->YRGBSCALE = (xscaleInt << 15) |
+ ((xscaleFract & 0xFFF) << 3) |
+ (yscaleInt) |
+ ((yscaleFract & 0xFFF) << 20);
+
+ if (drw_w > src_w)
+ {
+ /* horizontal up-scaling */
+ overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
+ }
+
+ if (drw_h > src_h)
+ {
+ /* vertical up-scaling */
+ overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
+ }
+
+ if (drw_w < src_w)
+ {
+ /* horizontal down-scaling */
+ overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
+ }
+
+ if (drw_h < src_h)
+ {
+ /* vertical down-scaling */
+ overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
+ }
+
+ /* now calculate the UV scaling factor */
+
+ if (xscaleFract)
+ {
+ xscaleFractUV = xscaleFract >> MINUV_SCALE;
+ overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION;
+ overlay->OV0CMD |= HC_UP_INTERPOLATION;
+ }
+
+ if (xscaleInt)
+ {
+ xscaleIntUV = xscaleInt >> MINUV_SCALE;
+ if (xscaleIntUV)
+ {
+ overlay->OV0CMD &= ~HC_UP_INTERPOLATION;
+ }
+ }
+
+ if (yscaleFract)
+ {
+ yscaleFractUV = yscaleFract >> MINUV_SCALE;
+ overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION;
+ overlay->OV0CMD |= VC_UP_INTERPOLATION;
+ }
+
+ if (yscaleInt)
+ {
+ yscaleIntUV = yscaleInt >> MINUV_SCALE;
+ if (yscaleIntUV)
+ {
+ overlay->OV0CMD &= ~VC_UP_INTERPOLATION;
+ overlay->OV0CMD |= VC_DOWN_INTERPOLATION;
+ }
+ }
+
+ overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ }
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16);
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_420;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ overlay->OV0STRIDE = dstPitch;
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_422;
+ overlay->OV0CMD &= ~OV_BYTE_ORDER;
+ if (id == FOURCC_UYVY)
+ overlay->OV0CMD |= Y_SWAP;
+ break;
+ }
+
+ overlay->OV0CMD &= ~BUFFER_AND_FIELD;
+ if (pPriv->currentBuf == 0)
+ overlay->OV0CMD |= BUFFER0_FIELD0;
+ else
+ overlay->OV0CMD |= BUFFER1_FIELD0;
+
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+
+}
+
+static FBLinearPtr
+i810AllocateMemory(
+ KdScreenInfo *screen,
+ FBLinearPtr linear,
+ int size
+){
+ KdCardInfo *card=screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ FBLinearPtr new_linear;
+
+ if(linear) {
+ if(linear->size >= size)
+ return linear;
+ else
+ ErrorF("Ran out of memory for overlay buffer, requested size = %d\n",size);
+ }
+
+ new_linear = xalloc(sizeof(FBLinearRec));
+ new_linear->size = i810c->XvMem.Size;
+ new_linear->offset = i810c->XvMem.Start;
+
+/* fprintf(stderr,"Overlay mem offset %lx\n",new_linear->offset); */
+
+ return new_linear;
+}
+
+static int
+i810PutImage(
+ 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;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ INT32 x1, x2, y1, y2;
+ int srcPitch, dstPitch;
+ int top, left, npixels, nlines, size;
+ BoxRec dstBox;
+
+ /* 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;
+
+ I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(pScreen, clipBoxes), width, height);
+
+ if((x1 >= x2) || (y1 >= y2))
+ return Success;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ dstPitch = ((width >> 1) + 7) & ~7; /* of chroma */
+ size = dstPitch * height * 3;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = (width << 1);
+ dstPitch = (srcPitch + 7) & ~7;
+ size = dstPitch * height;
+ break;
+ }
+
+ if(!(pPriv->linear = i810AllocateMemory(screen, pPriv->linear,
+ (screen->fb[0].bitsPerPixel == 16) ? size : (size >> 1))))
+ return BadAlloc;
+
+ /* fixup pointers */
+ pPriv->YBuf0offset = pPriv->linear->offset;
+ pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
+ pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1);
+
+ pPriv->YBuf1offset = pPriv->linear->offset + size;
+ pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
+ pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1);
+
+ /* wait for the last rendered buffer to be flipped in */
+ while (((INREG(DOV0STA)&0x00100000)>>20) != pPriv->currentBuf);
+
+ /* buffer swap */
+ if (pPriv->currentBuf == 0)
+ pPriv->currentBuf = 1;
+ else
+ pPriv->currentBuf = 0;
+
+ /* copy data */
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+ i810CopyPlanarData(screen, buf, srcPitch, dstPitch, height, top, left,
+ nlines, npixels, id);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ I810CopyPackedData(screen, buf, srcPitch, dstPitch, top, left, nlines,
+ npixels);
+ break;
+ }
+
+ /* update cliplist */
+ if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ i810FillBoxSolid(screen, REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes),
+ pPriv->colorKey, GXcopy, ~0);
+ /*
+ XAAFillSolidRects(screen, pPriv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ */
+ }
+
+
+ i810DisplayVideo(screen, id, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ return Success;
+}
+
+
+static int
+i810QueryImageAttributes(
+ KdScreenInfo *screen,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+ int size, tmp;
+
+ if(*w > 720) *w = 720;
+ if(*h > 576) *h = 576;
+
+ *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;
+}
+
+static void
+i810BlockHandler (
+ int i,
+ pointer blockData,
+ pointer pTimeout,
+ pointer pReadmask
+){
+ ScreenPtr pScreen = screenInfo.screens[i];
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ I810PortPrivPtr pPriv = GET_PORT_PRIVATE(screen);
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (i810c->FbBase + i810c->OverlayStart);
+
+ pScreen->BlockHandler = i810c->BlockHandler;
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ pScreen->BlockHandler = i810BlockHandler;
+
+ if(pPriv->videoStatus & TIMER_MASK) {
+ UpdateCurrentTime();
+ if(pPriv->videoStatus & OFF_TIMER) {
+ if(pPriv->offTime < currentTime.milliseconds) {
+ /* Turn off the overlay */
+ overlay->OV0CMD &= 0xFFFFFFFE;
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+ } else { /* FREE_TIMER */
+ if(pPriv->freeTime < currentTime.milliseconds) {
+ if(pPriv->linear) {
+ xfree(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ }
+ }
+ }
+}
diff --git a/hw/kdrive/i810/i810draw.c b/hw/kdrive/i810/i810draw.c
new file mode 100644
index 000000000..3f8a836cf
--- /dev/null
+++ b/hw/kdrive/i810/i810draw.c
@@ -0,0 +1,603 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/* Hardware accelerated drawing for KDrive i810 driver.
+ Author: Pontus Lidman <pontus.lidman@nokia.com>
+*/
+
+#include "kdrive.h"
+#ifdef XV
+#include "kxv.h"
+#endif
+#include "i810.h"
+#include "i810_reg.h"
+
+#include "Xmd.h"
+#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"
+
+#define NUM_STACK_RECTS 1024
+
+void
+i810Sync( KdScreenInfo *screen );
+int
+i810WaitLpRing( KdScreenInfo *screen, int n, int timeout_millis );
+
+void
+i810EmitInvarientState(KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ BEGIN_LP_RING( 10 );
+
+ OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+ OUT_RING( GFX_CMD_CONTEXT_SEL | CS_UPDATE_USE | CS_USE_CTX0 );
+ OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING( 0 );
+
+
+ OUT_RING( GFX_OP_COLOR_CHROMA_KEY );
+ OUT_RING( CC1_UPDATE_KILL_WRITE |
+ CC1_DISABLE_KILL_WRITE |
+ CC1_UPDATE_COLOR_IDX |
+ CC1_UPDATE_CHROMA_LOW |
+ CC1_UPDATE_CHROMA_HI |
+ 0);
+ OUT_RING( 0 );
+ OUT_RING( 0 );
+
+ /* No depth buffer in KDrive yet */
+ /* OUT_RING( CMD_OP_Z_BUFFER_INFO ); */
+ /* OUT_RING( pI810->DepthBuffer.Start | pI810->auxPitchBits); */
+
+ ADVANCE_LP_RING();
+}
+
+static unsigned int i810PatternRop[16] = {
+ 0x00, /* GXclear */
+ 0xA0, /* GXand */
+ 0x50, /* GXandReverse */
+ 0xF0, /* GXcopy */
+ 0x0A, /* GXandInvert */
+ 0xAA, /* GXnoop */
+ 0x5A, /* GXxor */
+ 0xFA, /* GXor */
+ 0x05, /* GXnor */
+ 0xA5, /* GXequiv */
+ 0x55, /* GXinvert */
+ 0xF5, /* GXorReverse */
+ 0x0F, /* GXcopyInvert */
+ 0xAF, /* GXorInverted */
+ 0x5F, /* GXnand */
+ 0xFF /* GXset */
+};
+
+void
+i810SetupForSolidFill(KdScreenInfo *screen, int color, int rop,
+ unsigned int planemask)
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF( "i810SetupForFillRectSolid color: %x rop: %x mask: %x\n",
+ color, rop, planemask);
+
+ /* Color blit, p166 */
+ i810c->BR[13] = (BR13_SOLID_PATTERN |
+ (i810PatternRop[rop] << 16) |
+ (screen->width * i810c->cpp));
+ i810c->BR[16] = color;
+}
+
+
+void
+i810SubsequentSolidFillRect(KdScreenInfo *screen, int x, int y, int w, int h)
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF( "i810SubsequentFillRectSolid %d,%d %dx%d\n",
+ x,y,w,h);
+
+ {
+ BEGIN_LP_RING(6);
+
+ OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 );
+ OUT_RING( i810c->BR[13] );
+ OUT_RING( (h << 16) | (w * i810c->cpp));
+ OUT_RING( i810c->bufferOffset +
+ (y * screen->width + x) * i810c->cpp);
+
+ OUT_RING( i810c->BR[16]);
+ OUT_RING( 0 ); /* pad to quadword */
+
+ ADVANCE_LP_RING();
+ }
+}
+
+
+BOOL
+i810FillOk (GCPtr pGC)
+{
+ FbBits depthMask;
+
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ return TRUE;
+ /* More cases later... */
+ }
+ return FALSE;
+}
+
+void
+i810FillBoxSolid (KdScreenInfo *screen, int nBox, BoxPtr pBox,
+ unsigned long pixel, int alu, unsigned long planemask)
+{
+ i810SetupForSolidFill(screen, pixel, alu, planemask);
+ while (nBox--)
+ {
+ i810SubsequentSolidFillRect(screen, pBox->x1, pBox->y1,
+ pBox->x2-pBox->x1, pBox->y2-pBox->y1);
+ pBox++;
+ }
+ KdMarkSync(screen->pScreen);
+}
+
+
+void
+i810PolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit)
+{
+
+
+ xRectangle *prect;
+ RegionPtr prgnClip;
+ register BoxPtr pbox;
+ register BoxPtr pboxClipped;
+ BoxPtr pboxClippedBase;
+ BoxPtr pextent;
+ BoxRec stackRects[NUM_STACK_RECTS];
+ FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC);
+ int numRects;
+ int n;
+ int xorg, yorg;
+ int x, y;
+ KdScreenPriv(pDrawable->pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+
+ if (!i810FillOk (pGC))
+ {
+ KdCheckPolyFillRect (pDrawable, pGC, nrectFill, prectInit);
+ return;
+ }
+ prgnClip = fbGetCompositeClip(pGC);
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ if (xorg || yorg)
+ {
+ prect = prectInit;
+ n = nrectFill;
+ while(n--)
+ {
+ prect->x += xorg;
+ prect->y += yorg;
+ prect++;
+ }
+ }
+
+ prect = prectInit;
+
+ numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
+ if (numRects > NUM_STACK_RECTS)
+ {
+ pboxClippedBase = (BoxPtr)xalloc(numRects * sizeof(BoxRec));
+ if (!pboxClippedBase)
+ return;
+ }
+ else
+ pboxClippedBase = stackRects;
+
+ pboxClipped = pboxClippedBase;
+
+ if (REGION_NUM_RECTS(prgnClip) == 1)
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_RECTS(prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ if ((pboxClipped->x1 = prect->x) < x1)
+ pboxClipped->x1 = x1;
+
+ if ((pboxClipped->y1 = prect->y) < y1)
+ pboxClipped->y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ pboxClipped->x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ pboxClipped->y2 = by2;
+
+ prect++;
+ if ((pboxClipped->x1 < pboxClipped->x2) &&
+ (pboxClipped->y1 < pboxClipped->y2))
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ else
+ {
+ int x1, y1, x2, y2, bx2, by2;
+
+ pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
+ x1 = pextent->x1;
+ y1 = pextent->y1;
+ x2 = pextent->x2;
+ y2 = pextent->y2;
+ while (nrectFill--)
+ {
+ BoxRec box;
+
+ if ((box.x1 = prect->x) < x1)
+ box.x1 = x1;
+
+ if ((box.y1 = prect->y) < y1)
+ box.y1 = y1;
+
+ bx2 = (int) prect->x + (int) prect->width;
+ if (bx2 > x2)
+ bx2 = x2;
+ box.x2 = bx2;
+
+ by2 = (int) prect->y + (int) prect->height;
+ if (by2 > y2)
+ by2 = y2;
+ box.y2 = by2;
+
+ prect++;
+
+ if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
+ continue;
+
+ n = REGION_NUM_RECTS (prgnClip);
+ pbox = REGION_RECTS(prgnClip);
+
+ /* clip the rectangle to each box in the clip region
+ this is logically equivalent to calling Intersect()
+ */
+ while(n--)
+ {
+ pboxClipped->x1 = max(box.x1, pbox->x1);
+ pboxClipped->y1 = max(box.y1, pbox->y1);
+ pboxClipped->x2 = min(box.x2, pbox->x2);
+ pboxClipped->y2 = min(box.y2, pbox->y2);
+ pbox++;
+
+ /* see if clipping left anything */
+ if(pboxClipped->x1 < pboxClipped->x2 &&
+ pboxClipped->y1 < pboxClipped->y2)
+ {
+ pboxClipped++;
+ }
+ }
+ }
+ }
+ if (pboxClipped != pboxClippedBase)
+ {
+ switch (pGC->fillStyle) {
+ case FillSolid:
+ i810FillBoxSolid(screen,
+ pboxClipped-pboxClippedBase, pboxClippedBase,
+ pGC->fgPixel, pGC->alu, pGC->planemask);
+ break;
+ /* More cases later... */
+ }
+ }
+ if (pboxClippedBase != stackRects)
+ xfree(pboxClippedBase);
+}
+
+void
+i810RefreshRing(KdScreenInfo *screen)
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ i810c->LpRing.head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ i810c->LpRing.tail = INREG(LP_RING + RING_TAIL);
+ i810c->LpRing.space = i810c->LpRing.head - (i810c->LpRing.tail+8);
+ if (i810c->LpRing.space < 0)
+ i810c->LpRing.space += i810c->LpRing.mem.Size;
+
+ i810c->NeedToSync = TRUE;
+}
+
+int
+i810WaitLpRing( KdScreenInfo *screen, int n, int timeout_millis )
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+ I810RingBuffer *ring = &(i810c->LpRing);
+ int iters = 0;
+ int start = 0;
+ int now = 0;
+ int last_head = 0;
+ int first = 0;
+
+ /* If your system hasn't moved the head pointer in 2 seconds, I'm going to
+ * call it crashed.
+ */
+ if (timeout_millis == 0)
+ timeout_millis = 2000;
+
+ if (I810_DEBUG) {
+ fprintf(stderr, "i810WaitLpRing %d\n", n);
+ first = GetTimeInMillis();
+ }
+
+ while (ring->space < n)
+ {
+ int i;
+
+ ring->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->space = ring->head - (ring->tail+8);
+
+ if (ring->space < 0)
+ ring->space += ring->mem.Size;
+
+ iters++;
+ now = GetTimeInMillis();
+ if ( start == 0 || now < start || ring->head != last_head) {
+ if (I810_DEBUG)
+ if (now > start)
+ fprintf(stderr, "space: %d wanted %d\n", ring->space, n );
+ start = now;
+ last_head = ring->head;
+ } else if ( now - start > timeout_millis ) {
+
+ i810PrintErrorState( screen->card );
+ fprintf(stderr, "space: %d wanted %d\n", ring->space, n );
+ FatalError("lockup\n");
+ }
+
+ for (i = 0 ; i < 2000 ; i++)
+ ;
+ }
+
+ if (I810_DEBUG)
+ {
+ now = GetTimeInMillis();
+ if (now - first) {
+ fprintf(stderr,"Elapsed %d ms\n", now - first);
+ fprintf(stderr, "space: %d wanted %d\n", ring->space, n );
+ }
+ }
+
+ return iters;
+}
+
+void
+i810Sync( KdScreenInfo *screen )
+{
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = card->driver;
+
+ if (I810_DEBUG)
+ fprintf(stderr, "i810Sync\n");
+
+ /* Send a flush instruction and then wait till the ring is empty.
+ * This is stronger than waiting for the blitter to finish as it also
+ * flushes the internal graphics caches.
+ */
+ {
+ BEGIN_LP_RING(2);
+ OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+ OUT_RING( 0 ); /* pad to quadword */
+ ADVANCE_LP_RING();
+ }
+
+ i810WaitLpRing(screen, i810c->LpRing.mem.Size - 8, 0 );
+
+ i810c->LpRing.space = i810c->LpRing.mem.Size - 8;
+ i810c->nextColorExpandBuf = 0;
+}
+
+static const GCOps i810Ops = {
+ KdCheckFillSpans,
+ KdCheckSetSpans,
+ KdCheckPutImage,
+ KdCheckCopyArea,
+ KdCheckCopyPlane,
+ KdCheckPolyPoint,
+ KdCheckPolylines,
+ KdCheckPolySegment,
+ miPolyRectangle,
+ KdCheckPolyArc,
+ miFillPolygon,
+ i810PolyFillRect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ KdCheckImageGlyphBlt,
+ KdCheckPolyGlyphBlt,
+ KdCheckPushPixels,
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+void
+i810ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
+{
+ FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
+
+ fbValidateGC (pGC, changes, pDrawable);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ pGC->ops = (GCOps *) &i810Ops;
+ else
+ pGC->ops = (GCOps *) &kdAsyncPixmapGCOps;
+}
+
+GCFuncs i810GCFuncs = {
+ i810ValidateGC,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+int
+i810CreateGC (GCPtr pGC)
+{
+ if (!fbCreateGC (pGC))
+ return FALSE;
+
+ if (pGC->depth != 1)
+ pGC->funcs = &i810GCFuncs;
+
+ return TRUE;
+}
+
+static void
+i810SetRingRegs( KdScreenInfo *screen ) {
+ unsigned int itemp;
+
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+ OUTREG(LP_RING + RING_TAIL, 0 );
+ OUTREG(LP_RING + RING_HEAD, 0 );
+
+ itemp = INREG(LP_RING + RING_START);
+ itemp &= ~(START_ADDR);
+ itemp |= i810c->LpRing.mem.Start;
+ OUTREG(LP_RING + RING_START, itemp );
+
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
+ itemp |= ((i810c->LpRing.mem.Size-4096) | RING_NO_REPORT | RING_VALID);
+ OUTREG(LP_RING + RING_LEN, itemp );
+}
+
+Bool
+i810InitAccel(ScreenPtr pScreen)
+{
+
+/* fprintf(stderr,"i810InitAccel\n"); */
+
+ /*
+ * Hook up asynchronous drawing
+ */
+ KdScreenInitAsync (pScreen);
+ /*
+ * Replace various fb screen functions
+ */
+ pScreen->CreateGC = i810CreateGC;
+
+ return TRUE;
+}
+
+void
+i810EnableAccel(ScreenPtr pScreen)
+{
+
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = screen->card;
+ I810CardInfo *i810c = (I810CardInfo *) card->driver;
+
+/* fprintf(stderr,"i810EnableAccel\n"); */
+
+ if (i810c->LpRing.mem.Size == 0) {
+ ErrorF("No memory for LpRing!! Acceleration not functional!!\n");
+ }
+
+ i810SetRingRegs( screen );
+
+ KdMarkSync (pScreen);
+}
+
+
+void
+i810SyncAccel(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+
+ i810Sync(screen);
+}
+
+void
+i810DisableAccel(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+
+/* fprintf(stderr,"i810DisableAccel\n"); */
+ i810RefreshRing( screen );
+ i810Sync( screen );
+}
+
+void
+i810FiniAccel(ScreenPtr pScreen)
+{
+/* fprintf(stderr,"i810FiniAccel\n"); */
+
+}
diff --git a/hw/kdrive/i810/i810draw.h b/hw/kdrive/i810/i810draw.h
new file mode 100644
index 000000000..7c8c04489
--- /dev/null
+++ b/hw/kdrive/i810/i810draw.h
@@ -0,0 +1,46 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/* Hardware accelerated drawing for KDrive i810 driver, header file.
+ Author: Pontus Lidman <pontus.lidman@nokia.com>
+*/
+
+
+#ifndef _I810DRAW_H_
+#define _I810DRAW_H_
+
+void i810RefreshRing(KdScreenInfo *screen);
+int i810WaitLpRing( KdScreenInfo *screen, int n, int timeout_millis );
+void i810Sync( KdScreenInfo *screen );
+
+#endif /* _I810DRAW_H_ */
diff --git a/hw/kdrive/i810/i810stub.c b/hw/kdrive/i810/i810stub.c
new file mode 100644
index 000000000..f7097c7d8
--- /dev/null
+++ b/hw/kdrive/i810/i810stub.c
@@ -0,0 +1,80 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/* Stub functions for the i810 KDrive driver
+ Author: Pontus Lidman <pontus.lidman@nokia.com>
+*/
+
+#include "kdrive.h"
+#include "kxv.h"
+#include "i810.h"
+
+static const int i810Cards[]={ PCI_CHIP_I810, PCI_CHIP_I810_DC100, PCI_CHIP_I810_E };
+
+#define numI810Cards (sizeof(i810Cards) / sizeof(i810Cards[0]))
+
+void
+InitCard (char *name)
+{
+ KdCardAttr attr;
+ int i;
+
+ Bool LinuxFindPci(CARD16, CARD16, CARD32, KdCardAttr *);
+
+ for (i = 0; i < numI810Cards; i++)
+ if (LinuxFindPci (0x8086, i810Cards[i], 0, &attr))
+ KdCardInfoAdd (&i810Funcs, &attr, (void *) i810Cards[i]);
+}
+
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs);
+}
+
+int
+ddxProcessArgument (int argc, char **argv, int i)
+{
+ int ret;
+ int KdProcessArgument(int, char **, int);
+
+ ret = KdProcessArgument(argc, argv, i);
+ return ret;
+}
diff --git a/hw/kdrive/linux/agp.c b/hw/kdrive/linux/agp.c
new file mode 100644
index 000000000..c27e1b0af
--- /dev/null
+++ b/hw/kdrive/linux/agp.c
@@ -0,0 +1,348 @@
+/*
+ * Abstraction of the AGP GART interface.
+ *
+ * This version is for both Linux and FreeBSD.
+ *
+ * Copyright © 2000-2001 Nokia Home Communications
+ * Copyright © 2000 VA Linux Systems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_agp.c,v 3.4 2000/08/28 18:12:56 dawes Exp $ */
+
+/*
+ * Author: Pontus Lidman <pontus.lidman@nokia.com> (adaption to KDrive) and others
+ */
+
+#include "X.h"
+
+#include "Xdefs.h"
+#include "Xmd.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "agp.h"
+
+#if defined(linux)
+#include <asm/ioctl.h>
+
+#include "../../xfree86/os-support/linux/agpgart.h"
+
+#elif defined(__FreeBSD__)
+#include <sys/ioctl.h>
+#include <sys/agpio.h>
+#endif
+
+#ifndef AGP_DEVICE
+#define AGP_DEVICE "/dev/agpgart"
+#endif
+/* AGP page size is independent of the host page size. */
+#ifndef AGP_PAGE_SIZE
+#define AGP_PAGE_SIZE 4096
+#endif
+#define AGPGART_MAJOR_VERSION 0
+#define AGPGART_MINOR_VERSION 99
+
+static int gartFd = -1;
+static int acquiredScreen = -1;
+
+/*
+ * Open /dev/agpgart. Keep it open until server exit.
+ */
+
+static Bool
+GARTInit()
+{
+ static Bool initDone = FALSE;
+ struct _agp_info agpinf;
+
+ if (initDone)
+ return (gartFd != -1);
+
+ initDone = TRUE;
+
+ if (gartFd == -1)
+ gartFd = open(AGP_DEVICE, O_RDWR, 0);
+ else
+ return FALSE;
+
+ if (gartFd == -1) {
+ fprintf(stderr, "Unable to open " AGP_DEVICE " (%s)\n",
+ strerror(errno));
+ return FALSE;
+ }
+
+ KdAcquireGART(-1);
+ /* Check the kernel driver version. */
+ if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) {
+ fprintf(stderr, "GARTInit: AGPIOC_INFO failed (%s)\n",
+ strerror(errno));
+ close(gartFd);
+ gartFd = -1;
+ return FALSE;
+ }
+ KdReleaseGART(-1);
+
+#if defined(linux)
+ /* Should this look for version >= rather than version == ? */
+ if (agpinf.version.major != AGPGART_MAJOR_VERSION &&
+ agpinf.version.minor != AGPGART_MINOR_VERSION) {
+ fprintf(stderr,
+ "Kernel agpgart driver version is not current"
+ " (%d.%d vs %d.%d)\n",
+ agpinf.version.major, agpinf.version.minor,
+ AGPGART_MAJOR_VERSION, AGPGART_MINOR_VERSION);
+ close(gartFd);
+ gartFd = -1;
+ return FALSE;
+ }
+#endif
+
+ return TRUE;
+}
+
+Bool
+KdAgpGARTSupported()
+{
+ return GARTInit();
+}
+
+AgpInfoPtr
+KdGetAGPInfo(int screenNum)
+{
+ struct _agp_info agpinf;
+ AgpInfoPtr info;
+
+ if (!GARTInit())
+ return NULL;
+
+
+ if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) {
+ fprintf(stderr, "Failed to allocate AgpInfo\n");
+ return NULL;
+ }
+
+ if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) {
+ fprintf(stderr,
+ "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ info->bridgeId = agpinf.bridge_id;
+ info->agpMode = agpinf.agp_mode;
+ info->base = agpinf.aper_base;
+ info->size = agpinf.aper_size;
+ info->totalPages = agpinf.pg_total;
+ info->systemPages = agpinf.pg_system;
+ info->usedPages = agpinf.pg_used;
+
+ return info;
+}
+
+/*
+ * XXX If multiple screens can acquire the GART, should we have a reference
+ * count instead of using acquiredScreen?
+ */
+
+Bool
+KdAcquireGART(int screenNum)
+{
+ if (screenNum != -1 && !GARTInit())
+ return FALSE;
+
+ if (screenNum == -1 || acquiredScreen != screenNum) {
+ if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) {
+ fprintf(stderr,
+ "AGPIOC_ACQUIRE failed (%s)\n",
+ strerror(errno));
+ return FALSE;
+ }
+ acquiredScreen = screenNum;
+ }
+
+ return TRUE;
+}
+
+Bool
+KdReleaseGART(int screenNum)
+{
+ if (screenNum != -1 && !GARTInit())
+ return FALSE;
+
+ if (acquiredScreen == screenNum) {
+ if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) {
+ fprintf(stderr,
+ "AGPIOC_RELEASE failed (%s)\n",
+ strerror(errno));
+ return FALSE;
+ }
+ acquiredScreen = -1;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+KdAllocateGARTMemory(int screenNum, unsigned long size, int type,
+ unsigned long *physical)
+{
+ struct _agp_allocate alloc;
+ int pages;
+
+ /*
+ * Allocates "size" bytes of GART memory (rounds up to the next
+ * page multiple) or type "type". A handle (key) for the allocated
+ * memory is returned. On error, the return value is -1.
+ */
+
+ if (!GARTInit() || acquiredScreen != screenNum)
+ return -1;
+
+ pages = (size / AGP_PAGE_SIZE);
+ if (size % AGP_PAGE_SIZE != 0)
+ pages++;
+
+ /* XXX check for pages == 0? */
+
+ alloc.pg_count = pages;
+ alloc.type = type;
+
+ if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) {
+ fprintf(stderr, "KdAllocateGARTMemory: "
+ "allocation of %d pages failed\n\t(%s)\n", pages,
+ strerror(errno));
+ return -1;
+ }
+
+ if (physical)
+ *physical = alloc.physical;
+
+ return alloc.key;
+}
+
+
+/* Bind GART memory with "key" at "offset" */
+Bool
+KdBindGARTMemory(int screenNum, int key, unsigned long offset)
+{
+ struct _agp_bind bind;
+ int pageOffset;
+
+ if (!GARTInit() || acquiredScreen != screenNum)
+ return FALSE;
+
+ if (acquiredScreen != screenNum) {
+ fprintf(stderr,
+ "AGP not acquired by this screen\n");
+ return FALSE;
+ }
+
+ if (offset % AGP_PAGE_SIZE != 0) {
+ fprintf(stderr, "KdBindGARTMemory: "
+ "offset (0x%lx) is not page-aligned (%d)\n",
+ offset, AGP_PAGE_SIZE);
+ return FALSE;
+ }
+ pageOffset = offset / AGP_PAGE_SIZE;
+
+ bind.pg_start = pageOffset;
+ bind.key = key;
+
+ if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) {
+ fprintf(stderr, "KdBindGARTMemory: "
+ "binding of gart memory with key %d\n"
+ "\tat offset 0x%lx failed (%s)\n",
+ key, offset, strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/* Unbind GART memory with "key" */
+Bool
+KdUnbindGARTMemory(int screenNum, int key)
+{
+ struct _agp_unbind unbind;
+
+ if (!GARTInit() || acquiredScreen != screenNum)
+ return FALSE;
+
+ if (acquiredScreen != screenNum) {
+ fprintf(stderr,
+ "AGP not acquired by this screen\n");
+ return FALSE;
+ }
+
+ unbind.priority = 0;
+ unbind.key = key;
+
+ if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) {
+ fprintf(stderr, "KdUnbindGARTMemory: "
+ "unbinding of gart memory with key %d "
+ "failed (%s)\n", key, strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/* XXX Interface may change. */
+Bool
+KdEnableAGP(int screenNum, CARD32 mode)
+{
+ agp_setup setup;
+
+ if (!GARTInit() || acquiredScreen != screenNum)
+ return FALSE;
+
+ setup.agp_mode = mode;
+ if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) {
+ fprintf(stderr, "KdEnableAGP: "
+ "AGPIOC_SETUP with mode %ld failed (%s)\n",
+ mode, strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
diff --git a/hw/kdrive/linux/agp.h b/hw/kdrive/linux/agp.h
new file mode 100644
index 000000000..9146f3c39
--- /dev/null
+++ b/hw/kdrive/linux/agp.h
@@ -0,0 +1,70 @@
+/* COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000, 2001 Nokia Home Communications
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group */
+
+/* agp.h - header file for KDrive AGP GART interface
+ *
+ * Author: Pontus Lidman <pontus.lidman@nokia.com>
+ *
+ */
+
+#ifndef _AGP_H_
+#define _AGP_H_
+
+#include "Xdefs.h"
+
+/* These two definitions must be consistent with the kernel's,
+ but using 1 or 2 in driver code is even uglier */
+#define AGP_DCACHE_MEMORY 1
+#define AGP_PHYS_MEMORY 2
+
+typedef struct _AgpInfo {
+ CARD32 bridgeId;
+ CARD32 agpMode;
+ unsigned long base;
+ unsigned long size;
+ unsigned long totalPages;
+ unsigned long systemPages;
+ unsigned long usedPages;
+} AgpInfo, *AgpInfoPtr;
+
+extern Bool KdAgpGARTSupported(void);
+extern AgpInfoPtr KdGetAGPInfo(int screenNum);
+extern Bool KdAcquireGART(int screenNum);
+extern Bool KdReleaseGART(int screenNum);
+extern int KdAllocateGARTMemory(int screenNum, unsigned long size, int type,
+ unsigned long *physical);
+extern Bool KdBindGARTMemory(int screenNum, int key, unsigned long offset);
+extern Bool KdUnbindGARTMemory(int screenNum, int key);
+extern Bool KdEnableAGP(int screenNum, CARD32 mode);
+
+#endif /* _AGP_H_ */
diff --git a/hw/kdrive/src/kxv.c b/hw/kdrive/src/kxv.c
new file mode 100644
index 000000000..2b985fbb5
--- /dev/null
+++ b/hw/kdrive/src/kxv.c
@@ -0,0 +1,1784 @@
+/*
+
+ XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
+ Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
+
+ Copyright (C) 2000, 2001 - Nokia Home Communications
+ Copyright (C) 1998, 1999 - The XFree86 Project Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+*/
+
+/* $XFree86$ */
+
+#include "kdrive.h"
+
+#include "scrnintstr.h"
+#include "regionstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "mivalidate.h"
+#include "validate.h"
+#include "resource.h"
+#include "gcstruct.h"
+#include "dixstruct.h"
+
+#include "Xv.h"
+#include "Xvproto.h"
+
+#include "kxv.h"
+
+
+/* XvScreenRec fields */
+
+static Bool KdXVCloseScreen(int, ScreenPtr);
+static int KdXVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *);
+
+/* XvAdaptorRec fields */
+
+static int KdXVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*);
+static int KdXVFreePort(XvPortPtr);
+static int KdXVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int KdXVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int KdXVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int KdXVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+static int KdXVStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
+static int KdXVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
+static int KdXVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32 *);
+static int KdXVQueryBestSize(ClientPtr, XvPortPtr, CARD8,
+ CARD16, CARD16,CARD16, CARD16,
+ unsigned int*, unsigned int*);
+static int KdXVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16,
+ XvImagePtr, unsigned char*, Bool,
+ CARD16, CARD16);
+static int KdXVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr,
+ CARD16*, CARD16*, int*, int*);
+
+
+/* ScreenRec fields */
+
+static Bool KdXVCreateWindow(WindowPtr pWin);
+static Bool KdXVDestroyWindow(WindowPtr pWin);
+static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
+static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
+
+/* KdCardInfo functions */
+static Bool KdXVEnable(ScreenPtr);
+static void KdXVDisable(ScreenPtr);
+
+/* misc */
+
+static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr*, int);
+
+
+int KdXVWindowIndex = -1;
+int KdXvScreenIndex = -1;
+static unsigned long KdXVGeneration = 0;
+static unsigned long PortResource = 0;
+
+int (*XvGetScreenIndexProc)(void) = XvGetScreenIndex;
+unsigned long (*XvGetRTPortProc)(void) = XvGetRTPort;
+int (*XvScreenInitProc)(ScreenPtr) = XvScreenInit;
+
+#define GET_XV_SCREEN(pScreen) \
+ ((XvScreenPtr)((pScreen)->devPrivates[KdXvScreenIndex].ptr))
+
+#define GET_KDXV_SCREEN(pScreen) \
+ ((KdXVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr))
+
+#define GET_KDXV_WINDOW(pWin) \
+ ((KdXVWindowPtr)((pWin)->devPrivates[KdXVWindowIndex].ptr))
+
+static KdXVInitGenericAdaptorPtr *GenDrivers = NULL;
+static int NumGenDrivers = 0;
+
+int
+KdXVRegisterGenericAdaptorDriver(
+ KdXVInitGenericAdaptorPtr InitFunc
+){
+ KdXVInitGenericAdaptorPtr *newdrivers;
+
+/* fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */
+
+ newdrivers = xrealloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) *
+ (1 + NumGenDrivers));
+ if (!newdrivers)
+ return 0;
+ GenDrivers = newdrivers;
+
+ GenDrivers[NumGenDrivers++] = InitFunc;
+
+ return 1;
+}
+
+int
+KdXVListGenericAdaptors(
+ KdScreenInfo * screen,
+ KdVideoAdaptorPtr **adaptors
+){
+ int i,j,n,num;
+ KdVideoAdaptorPtr *DrivAdap,*new;
+
+ num = 0;
+ *adaptors = NULL;
+ for (i = 0; i < NumGenDrivers; i++) {
+ n = GenDrivers[i](screen,&DrivAdap);
+ if (0 == n)
+ continue;
+ new = xrealloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num+n));
+ if (NULL == new)
+ continue;
+ *adaptors = new;
+ for (j = 0; j < n; j++, num++)
+ (*adaptors)[num] = DrivAdap[j];
+ }
+ return num;
+}
+
+KdVideoAdaptorPtr
+KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen)
+{
+ return xcalloc(1, sizeof(KdVideoAdaptorRec));
+}
+
+void
+KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr)
+{
+ xfree(ptr);
+}
+
+
+Bool
+KdXVScreenInit(
+ ScreenPtr pScreen,
+ KdVideoAdaptorPtr *adaptors,
+ int num
+){
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ KdXVScreenPtr ScreenPriv;
+ XvScreenPtr pxvs;
+
+/* fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */
+
+ if(KdXVGeneration != serverGeneration) {
+ if((KdXVWindowIndex = AllocateWindowPrivateIndex()) < 0)
+ return FALSE;
+ KdXVGeneration = serverGeneration;
+ }
+
+ if(!AllocateWindowPrivate(pScreen,KdXVWindowIndex,sizeof(KdXVWindowRec)))
+ return FALSE;
+
+ if(!XvGetScreenIndexProc || !XvGetRTPortProc || !XvScreenInitProc)
+ return FALSE;
+
+ if(Success != (*XvScreenInitProc)(pScreen)) return FALSE;
+
+ KdXvScreenIndex = (*XvGetScreenIndexProc)();
+ PortResource = (*XvGetRTPortProc)();
+
+ pxvs = GET_XV_SCREEN(pScreen);
+
+
+ /* Anyone initializing the Xv layer must provide these two.
+ The Xv di layer calls them without even checking if they exist! */
+
+ pxvs->ddCloseScreen = KdXVCloseScreen;
+ pxvs->ddQueryAdaptors = KdXVQueryAdaptors;
+
+ /* The Xv di layer provides us with a private hook so that we don't
+ have to allocate our own screen private. They also provide
+ a CloseScreen hook so that we don't have to wrap it. I'm not
+ sure that I appreciate that. */
+
+ ScreenPriv = xalloc(sizeof(KdXVScreenRec));
+ pxvs->devPriv.ptr = (pointer)ScreenPriv;
+
+ if(!ScreenPriv) return FALSE;
+
+
+ ScreenPriv->CreateWindow = pScreen->CreateWindow;
+ ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
+ ScreenPriv->WindowExposures = pScreen->WindowExposures;
+ ScreenPriv->ClipNotify = pScreen->ClipNotify;
+
+/* fprintf(stderr,"XV: Wrapping screen & card funcs\n"); */
+
+ ScreenPriv->enable = card->cfuncs->enable;
+ ScreenPriv->disable = card->cfuncs->disable;
+
+ pScreen->CreateWindow = KdXVCreateWindow;
+ pScreen->DestroyWindow = KdXVDestroyWindow;
+ pScreen->WindowExposures = KdXVWindowExposures;
+ pScreen->ClipNotify = KdXVClipNotify;
+
+ card->cfuncs->disable = KdXVDisable;
+ card->cfuncs->enable = KdXVEnable;
+
+ if(!KdXVInitAdaptors(pScreen, adaptors, num))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
+{
+ int i;
+
+ if(pAdaptor->name)
+ xfree(pAdaptor->name);
+
+ if(pAdaptor->pEncodings) {
+ XvEncodingPtr pEncode = pAdaptor->pEncodings;
+
+ for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) {
+ if(pEncode->name) xfree(pEncode->name);
+ }
+ xfree(pAdaptor->pEncodings);
+ }
+
+ if(pAdaptor->pFormats)
+ xfree(pAdaptor->pFormats);
+
+ if(pAdaptor->pPorts) {
+ XvPortPtr pPort = pAdaptor->pPorts;
+ XvPortRecPrivatePtr pPriv;
+
+ for(i = 0; i < pAdaptor->nPorts; i++, pPort++) {
+ pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
+ if(pPriv) {
+ if(pPriv->clientClip)
+ REGION_DESTROY(pAdaptor->pScreen, pPriv->clientClip);
+ if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
+ REGION_DESTROY(pAdaptor->pScreen, pPriv->pCompositeClip);
+ xfree(pPriv);
+ }
+ }
+ xfree(pAdaptor->pPorts);
+ }
+
+ if(pAdaptor->nAttributes) {
+ XvAttributePtr pAttribute = pAdaptor->pAttributes;
+
+ for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) {
+ if(pAttribute->name) xfree(pAttribute->name);
+ }
+
+ xfree(pAdaptor->pAttributes);
+ }
+
+ if(pAdaptor->nImages)
+ xfree(pAdaptor->pImages);
+
+ if(pAdaptor->devPriv.ptr)
+ xfree(pAdaptor->devPriv.ptr);
+}
+
+static Bool
+KdXVInitAdaptors(
+ ScreenPtr pScreen,
+ KdVideoAdaptorPtr *infoPtr,
+ int number
+) {
+ KdScreenPriv(pScreen);
+ KdScreenInfo * screen = pScreenPriv->screen;
+
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+ KdVideoAdaptorPtr adaptorPtr;
+ XvAdaptorPtr pAdaptor, pa;
+ XvAdaptorRecPrivatePtr adaptorPriv;
+ int na, numAdaptor;
+ XvPortRecPrivatePtr portPriv;
+ XvPortPtr pPort, pp;
+ int numPort;
+ KdAttributePtr attributePtr;
+ XvAttributePtr pAttribute, pat;
+ KdVideoFormatPtr formatPtr;
+ XvFormatPtr pFormat, pf;
+ int numFormat, totFormat;
+ KdVideoEncodingPtr encodingPtr;
+ XvEncodingPtr pEncode, pe;
+ KdImagePtr imagePtr;
+ XvImagePtr pImage, pi;
+ int numVisuals;
+ VisualPtr pVisual;
+ int i;
+
+ pxvs->nAdaptors = 0;
+ pxvs->pAdaptors = NULL;
+
+ if(!(pAdaptor = xcalloc(number, sizeof(XvAdaptorRec))))
+ return FALSE;
+
+ for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
+ adaptorPtr = infoPtr[na];
+
+ if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
+ !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
+ continue;
+
+ /* client libs expect at least one encoding */
+ if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
+ continue;
+
+ pa->type = adaptorPtr->type;
+
+ if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
+ pa->type &= ~XvVideoMask;
+
+ if(!adaptorPtr->PutStill && !adaptorPtr->GetStill)
+ pa->type &= ~XvStillMask;
+
+ if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
+ pa->type &= ~XvImageMask;
+
+ if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
+ !adaptorPtr->PutStill)
+ pa->type &= ~XvInputMask;
+
+ if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
+ pa->type &= ~XvOutputMask;
+
+ if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
+ continue;
+ if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
+ continue;
+
+ pa->pScreen = pScreen;
+ pa->ddAllocatePort = KdXVAllocatePort;
+ pa->ddFreePort = KdXVFreePort;
+ pa->ddPutVideo = KdXVPutVideo;
+ pa->ddPutStill = KdXVPutStill;
+ pa->ddGetVideo = KdXVGetVideo;
+ pa->ddGetStill = KdXVGetStill;
+ pa->ddStopVideo = KdXVStopVideo;
+ pa->ddPutImage = KdXVPutImage;
+ pa->ddSetPortAttribute = KdXVSetPortAttribute;
+ pa->ddGetPortAttribute = KdXVGetPortAttribute;
+ pa->ddQueryBestSize = KdXVQueryBestSize;
+ pa->ddQueryImageAttributes = KdXVQueryImageAttributes;
+ if((pa->name = xalloc(strlen(adaptorPtr->name) + 1)))
+ strcpy(pa->name, adaptorPtr->name);
+
+ if(adaptorPtr->nEncodings &&
+ (pEncode = xcalloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
+
+ for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
+ i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++)
+ {
+ pe->id = encodingPtr->id;
+ pe->pScreen = pScreen;
+ if((pe->name = xalloc(strlen(encodingPtr->name) + 1)))
+ strcpy(pe->name, encodingPtr->name);
+ pe->width = encodingPtr->width;
+ pe->height = encodingPtr->height;
+ pe->rate.numerator = encodingPtr->rate.numerator;
+ pe->rate.denominator = encodingPtr->rate.denominator;
+ }
+ pa->nEncodings = adaptorPtr->nEncodings;
+ pa->pEncodings = pEncode;
+ }
+
+ if(adaptorPtr->nImages &&
+ (pImage = xcalloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
+
+ for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
+ i < adaptorPtr->nImages; i++, pi++, imagePtr++)
+ {
+ pi->id = imagePtr->id;
+ pi->type = imagePtr->type;
+ pi->byte_order = imagePtr->byte_order;
+ memcpy(pi->guid, imagePtr->guid, 16);
+ pi->bits_per_pixel = imagePtr->bits_per_pixel;
+ pi->format = imagePtr->format;
+ pi->num_planes = imagePtr->num_planes;
+ pi->depth = imagePtr->depth;
+ pi->red_mask = imagePtr->red_mask;
+ pi->green_mask = imagePtr->green_mask;
+ pi->blue_mask = imagePtr->blue_mask;
+ pi->y_sample_bits = imagePtr->y_sample_bits;
+ pi->u_sample_bits = imagePtr->u_sample_bits;
+ pi->v_sample_bits = imagePtr->v_sample_bits;
+ pi->horz_y_period = imagePtr->horz_y_period;
+ pi->horz_u_period = imagePtr->horz_u_period;
+ pi->horz_v_period = imagePtr->horz_v_period;
+ pi->vert_y_period = imagePtr->vert_y_period;
+ pi->vert_u_period = imagePtr->vert_u_period;
+ pi->vert_v_period = imagePtr->vert_v_period;
+ memcpy(pi->component_order, imagePtr->component_order, 32);
+ pi->scanline_order = imagePtr->scanline_order;
+ }
+ pa->nImages = adaptorPtr->nImages;
+ pa->pImages = pImage;
+ }
+
+ if(adaptorPtr->nAttributes &&
+ (pAttribute = xcalloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec))))
+ {
+ for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0;
+ i < adaptorPtr->nAttributes; pat++, i++, attributePtr++)
+ {
+ pat->flags = attributePtr->flags;
+ pat->min_value = attributePtr->min_value;
+ pat->max_value = attributePtr->max_value;
+ if((pat->name = xalloc(strlen(attributePtr->name) + 1)))
+ strcpy(pat->name, attributePtr->name);
+ }
+ pa->nAttributes = adaptorPtr->nAttributes;
+ pa->pAttributes = pAttribute;
+ }
+
+
+ totFormat = adaptorPtr->nFormats;
+
+ if(!(pFormat = xcalloc(totFormat, sizeof(XvFormatRec)))) {
+ KdXVFreeAdaptor(pa);
+ continue;
+ }
+ for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats;
+ i < adaptorPtr->nFormats; i++, formatPtr++)
+ {
+ numVisuals = pScreen->numVisuals;
+ pVisual = pScreen->visuals;
+
+ while(numVisuals--) {
+ if((pVisual->class == formatPtr->class) &&
+ (pVisual->nplanes == formatPtr->depth)) {
+
+ if(numFormat >= totFormat) {
+ void *moreSpace;
+ totFormat *= 2;
+ moreSpace = xrealloc(pFormat,
+ totFormat * sizeof(XvFormatRec));
+ if(!moreSpace) break;
+ pFormat = moreSpace;
+ pf = pFormat + numFormat;
+ }
+
+ pf->visual = pVisual->vid;
+ pf->depth = formatPtr->depth;
+
+ pf++;
+ numFormat++;
+ }
+ pVisual++;
+ }
+ }
+ pa->nFormats = numFormat;
+ pa->pFormats = pFormat;
+ if(!numFormat) {
+ KdXVFreeAdaptor(pa);
+ continue;
+ }
+
+ if(!(adaptorPriv = xcalloc(1, sizeof(XvAdaptorRecPrivate)))) {
+ KdXVFreeAdaptor(pa);
+ continue;
+ }
+
+ adaptorPriv->flags = adaptorPtr->flags;
+ adaptorPriv->PutVideo = adaptorPtr->PutVideo;
+ adaptorPriv->PutStill = adaptorPtr->PutStill;
+ adaptorPriv->GetVideo = adaptorPtr->GetVideo;
+ adaptorPriv->GetStill = adaptorPtr->GetStill;
+ adaptorPriv->StopVideo = adaptorPtr->StopVideo;
+ adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
+ adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
+ adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
+ adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
+ adaptorPriv->PutImage = adaptorPtr->PutImage;
+ adaptorPriv->ReputImage = adaptorPtr->ReputImage;
+
+ pa->devPriv.ptr = (pointer)adaptorPriv;
+
+ if(!(pPort = xcalloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
+ KdXVFreeAdaptor(pa);
+ continue;
+ }
+ for(pp = pPort, i = 0, numPort = 0;
+ i < adaptorPtr->nPorts; i++) {
+
+ if(!(pp->id = FakeClientID(0)))
+ continue;
+
+ if(!(portPriv = xcalloc(1, sizeof(XvPortRecPrivate))))
+ continue;
+
+ if(!AddResource(pp->id, PortResource, pp)) {
+ xfree(portPriv);
+ continue;
+ }
+
+ pp->pAdaptor = pa;
+ pp->pNotify = (XvPortNotifyPtr)NULL;
+ pp->pDraw = (DrawablePtr)NULL;
+ pp->client = (ClientPtr)NULL;
+ pp->grab.client = (ClientPtr)NULL;
+ pp->time = currentTime;
+ pp->devPriv.ptr = portPriv;
+
+ portPriv->screen = screen;
+ portPriv->AdaptorRec = adaptorPriv;
+ portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
+
+ pp++;
+ numPort++;
+ }
+ pa->nPorts = numPort;
+ pa->pPorts = pPort;
+ if(!numPort) {
+ KdXVFreeAdaptor(pa);
+ continue;
+ }
+
+ pa->base_id = pPort->id;
+
+ pa++;
+ numAdaptor++;
+ }
+
+ if(numAdaptor) {
+ pxvs->nAdaptors = numAdaptor;
+ pxvs->pAdaptors = pAdaptor;
+ } else {
+ xfree(pAdaptor);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Video should be clipped to the intersection of the window cliplist
+ and the client cliplist specified in the GC for which the video was
+ initialized. When we need to reclip a window, the GC that started
+ the video may not even be around anymore. That's why we save the
+ client clip from the GC when the video is initialized. We then
+ use KdXVUpdateCompositeClip to calculate the new composite clip
+ when we need it. This is different from what DEC did. They saved
+ the GC and used it's clip list when they needed to reclip the window,
+ even if the client clip was different from the one the video was
+ initialized with. If the original GC was destroyed, they had to stop
+ the video. I like the new method better (MArk).
+
+ This function only works for windows. Will need to rewrite when
+ (if) we support pixmap rendering.
+*/
+
+static void
+KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
+{
+ RegionPtr pregWin, pCompositeClip;
+ WindowPtr pWin;
+ Bool freeCompClip = FALSE;
+
+ if(portPriv->pCompositeClip)
+ return;
+
+ pWin = (WindowPtr)portPriv->pDraw;
+
+ /* get window clip list */
+ if(portPriv->subWindowMode == IncludeInferiors) {
+ pregWin = NotClippedByChildren(pWin);
+ freeCompClip = TRUE;
+ } else
+ pregWin = &pWin->clipList;
+
+ if(!portPriv->clientClip) {
+ portPriv->pCompositeClip = pregWin;
+ portPriv->FreeCompositeClip = freeCompClip;
+ return;
+ }
+
+ pCompositeClip = REGION_CREATE(pWin->pScreen, NullBox, 1);
+ REGION_COPY(pWin->pScreen, pCompositeClip, portPriv->clientClip);
+ REGION_TRANSLATE(pWin->pScreen, pCompositeClip,
+ portPriv->pDraw->x + portPriv->clipOrg.x,
+ portPriv->pDraw->y + portPriv->clipOrg.y);
+ REGION_INTERSECT(pWin->pScreen, pCompositeClip, pregWin, pCompositeClip);
+
+ portPriv->pCompositeClip = pCompositeClip;
+ portPriv->FreeCompositeClip = TRUE;
+
+ if(freeCompClip) {
+ REGION_DESTROY(pWin->pScreen, pregWin);
+ }
+}
+
+/* Save the current clientClip and update the CompositeClip whenever
+ we have a fresh GC */
+
+static void
+KdXVCopyClip(
+ XvPortRecPrivatePtr portPriv,
+ GCPtr pGC
+){
+ /* copy the new clip if it exists */
+ if((pGC->clientClipType == CT_REGION) && pGC->clientClip) {
+ if(!portPriv->clientClip)
+ portPriv->clientClip = REGION_CREATE(pGC->pScreen, NullBox, 1);
+ /* Note: this is in window coordinates */
+ REGION_COPY(pGC->pScreen, portPriv->clientClip, pGC->clientClip);
+ } else if(portPriv->clientClip) { /* free the old clientClip */
+ REGION_DESTROY(pGC->pScreen, portPriv->clientClip);
+ portPriv->clientClip = NULL;
+ }
+
+ /* get rid of the old clip list */
+ if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
+ REGION_DESTROY(pWin->pScreen, portPriv->pCompositeClip);
+ }
+
+ portPriv->clipOrg = pGC->clipOrg;
+ portPriv->pCompositeClip = pGC->pCompositeClip;
+ portPriv->FreeCompositeClip = FALSE;
+ portPriv->subWindowMode = pGC->subWindowMode;
+}
+
+static int
+KdXVRegetVideo(XvPortRecPrivatePtr portPriv)
+{
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ ScreenPtr pScreen = portPriv->pDraw->pScreen;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ KdXVUpdateCompositeClip(portPriv);
+
+ /* translate the video region to the screen */
+ WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
+ WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
+ WinBox.x2 = WinBox.x1 + portPriv->drw_w;
+ WinBox.y2 = WinBox.y1 + portPriv->drw_h;
+
+ /* clip to the window composite clip */
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
+
+ /* that's all if it's totally obscured */
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->screen,
+ portPriv->vid_x, portPriv->vid_y,
+ WinBox.x1, WinBox.y1,
+ portPriv->vid_w, portPriv->vid_h,
+ portPriv->drw_w, portPriv->drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ if(ret == Success)
+ portPriv->isOn = XV_ON;
+
+CLIP_VIDEO_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->screen, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ /* This clip was copied and only good for one shot */
+ if(!portPriv->FreeCompositeClip)
+ portPriv->pCompositeClip = NULL;
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+static int
+KdXVReputVideo(XvPortRecPrivatePtr portPriv)
+{
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ ScreenPtr pScreen = portPriv->pDraw->pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen=pScreenPriv->screen;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ KdXVUpdateCompositeClip(portPriv);
+
+ /* translate the video region to the screen */
+ WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
+ WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
+ WinBox.x2 = WinBox.x1 + portPriv->drw_w;
+ WinBox.y2 = WinBox.y1 + portPriv->drw_h;
+
+ /* clip to the window composite clip */
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
+
+ /* clip and translate to the viewport */
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = 0;
+ VPBox.y1 = 0;
+ VPBox.x2 = screen->width;
+ VPBox.y2 = screen->height;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ /* that's all if it's totally obscured */
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+
+ /* bailout if we have to clip but the hardware doesn't support it */
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->screen,
+ portPriv->vid_x, portPriv->vid_y,
+ WinBox.x1, WinBox.y1,
+ portPriv->vid_w, portPriv->vid_h,
+ portPriv->drw_w, portPriv->drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ if(ret == Success) portPriv->isOn = XV_ON;
+
+CLIP_VIDEO_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->screen, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ /* This clip was copied and only good for one shot */
+ if(!portPriv->FreeCompositeClip)
+ portPriv->pCompositeClip = NULL;
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+static int
+KdXVReputImage(XvPortRecPrivatePtr portPriv)
+{
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ ScreenPtr pScreen = portPriv->pDraw->pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen=pScreenPriv->screen;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ KdXVUpdateCompositeClip(portPriv);
+
+ /* translate the video region to the screen */
+ WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
+ WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
+ WinBox.x2 = WinBox.x1 + portPriv->drw_w;
+ WinBox.y2 = WinBox.y1 + portPriv->drw_h;
+
+ /* clip to the window composite clip */
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
+
+ /* clip and translate to the viewport */
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = 0;
+ VPBox.y1 = 0;
+ VPBox.x2 = screen->width;
+ VPBox.y2 = screen->height;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ /* that's all if it's totally obscured */
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+
+ /* bailout if we have to clip but the hardware doesn't support it */
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto CLIP_VIDEO_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->screen,
+ WinBox.x1, WinBox.y1,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
+
+CLIP_VIDEO_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->screen, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ /* This clip was copied and only good for one shot */
+ if(!portPriv->FreeCompositeClip)
+ portPriv->pCompositeClip = NULL;
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+static int
+KdXVReputAllVideo(WindowPtr pWin, pointer data)
+{
+ KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
+
+ while(WinPriv) {
+ if(WinPriv->PortRec->type == XvInputMask)
+ KdXVReputVideo(WinPriv->PortRec);
+ else
+ KdXVRegetVideo(WinPriv->PortRec);
+ WinPriv = WinPriv->next;
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+static int
+KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
+{
+ KdXVWindowPtr winPriv, PrivRoot;
+
+ winPriv = PrivRoot = GET_KDXV_WINDOW(pWin);
+
+ /* Enlist our port in the window private */
+ while(winPriv) {
+ if(winPriv->PortRec == portPriv) /* we're already listed */
+ break;
+ winPriv = winPriv->next;
+ }
+
+ if(!winPriv) {
+ winPriv = xalloc(sizeof(KdXVWindowRec));
+ if(!winPriv) return BadAlloc;
+ winPriv->PortRec = portPriv;
+ winPriv->next = PrivRoot;
+ pWin->devPrivates[KdXVWindowIndex].ptr = (pointer)winPriv;
+ }
+ return Success;
+}
+
+
+static void
+KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
+{
+ KdXVWindowPtr winPriv, prevPriv = NULL;
+
+ winPriv = GET_KDXV_WINDOW(pWin);
+
+ while(winPriv) {
+ if(winPriv->PortRec == portPriv) {
+ if(prevPriv)
+ prevPriv->next = winPriv->next;
+ else
+ pWin->devPrivates[KdXVWindowIndex].ptr =
+ (pointer)winPriv->next;
+ xfree(winPriv);
+ break;
+ }
+ prevPriv = winPriv;
+ winPriv = winPriv->next;
+ }
+ portPriv->pDraw = NULL;
+}
+
+/**** ScreenRec fields ****/
+
+
+static Bool
+KdXVCreateWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
+ int ret;
+
+ pScreen->CreateWindow = ScreenPriv->CreateWindow;
+ ret = (*pScreen->CreateWindow)(pWin);
+ pScreen->CreateWindow = KdXVCreateWindow;
+
+ if(ret) pWin->devPrivates[KdXVWindowIndex].ptr = NULL;
+
+ return ret;
+}
+
+
+static Bool
+KdXVDestroyWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
+ KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin);
+ int ret;
+
+ while(WinPriv) {
+ XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
+
+ if(pPriv->isOn > XV_OFF) {
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->screen, pPriv->DevPriv.ptr, TRUE);
+ pPriv->isOn = XV_OFF;
+ }
+
+ pPriv->pDraw = NULL;
+ tmp = WinPriv;
+ WinPriv = WinPriv->next;
+ xfree(tmp);
+ }
+
+ pWin->devPrivates[KdXVWindowIndex].ptr = NULL;
+
+ pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
+ ret = (*pScreen->DestroyWindow)(pWin);
+ pScreen->DestroyWindow = KdXVDestroyWindow;
+
+ return ret;
+}
+
+
+static void
+KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
+ KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
+ KdXVWindowPtr pPrev;
+ XvPortRecPrivatePtr pPriv;
+ Bool AreasExposed;
+
+ AreasExposed = (WinPriv && reg1 && REGION_NOTEMPTY(pScreen, reg1));
+
+ pScreen->WindowExposures = ScreenPriv->WindowExposures;
+ (*pScreen->WindowExposures)(pWin, reg1, reg2);
+ pScreen->WindowExposures = KdXVWindowExposures;
+
+ /* filter out XClearWindow/Area */
+ if (!pWin->valdata) return;
+
+ pPrev = NULL;
+
+ while(WinPriv) {
+ pPriv = WinPriv->PortRec;
+
+ /* Reput anyone with a reput function */
+
+ switch(pPriv->type) {
+ case XvInputMask:
+ KdXVReputVideo(pPriv);
+ break;
+ case XvOutputMask:
+ KdXVRegetVideo(pPriv);
+ break;
+ default: /* overlaid still/image*/
+ if (pPriv->AdaptorRec->ReputImage)
+ KdXVReputImage(pPriv);
+ else if(AreasExposed) {
+ KdXVWindowPtr tmp;
+
+ if (pPriv->isOn == XV_ON) {
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->screen, pPriv->DevPriv.ptr, FALSE);
+ pPriv->isOn = XV_PENDING;
+ }
+ pPriv->pDraw = NULL;
+
+ if(!pPrev)
+ pWin->devPrivates[KdXVWindowIndex].ptr =
+ (pointer)(WinPriv->next);
+ else
+ pPrev->next = WinPriv->next;
+ tmp = WinPriv;
+ WinPriv = WinPriv->next;
+ xfree(tmp);
+ continue;
+ }
+ break;
+ }
+ pPrev = WinPriv;
+ WinPriv = WinPriv->next;
+ }
+}
+
+
+static void
+KdXVClipNotify(WindowPtr pWin, int dx, int dy)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
+ KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
+ KdXVWindowPtr tmp, pPrev = NULL;
+ XvPortRecPrivatePtr pPriv;
+ Bool visible = (pWin->visibility == VisibilityUnobscured) ||
+ (pWin->visibility == VisibilityPartiallyObscured);
+
+ while(WinPriv) {
+ pPriv = WinPriv->PortRec;
+
+ if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
+ REGION_DESTROY(pScreen, pPriv->pCompositeClip);
+
+ pPriv->pCompositeClip = NULL;
+
+ /* Stop everything except images, but stop them too if the
+ window isn't visible. But we only remove the images. */
+
+ if(pPriv->type || !visible) {
+ if(pPriv->isOn == XV_ON) {
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->screen, pPriv->DevPriv.ptr, FALSE);
+ pPriv->isOn = XV_PENDING;
+ }
+
+ if(!pPriv->type) { /* overlaid still/image */
+ pPriv->pDraw = NULL;
+
+ if(!pPrev)
+ pWin->devPrivates[KdXVWindowIndex].ptr =
+ (pointer)(WinPriv->next);
+ else
+ pPrev->next = WinPriv->next;
+ tmp = WinPriv;
+ WinPriv = WinPriv->next;
+ xfree(tmp);
+ continue;
+ }
+ }
+
+ pPrev = WinPriv;
+ WinPriv = WinPriv->next;
+ }
+
+ if(ScreenPriv->ClipNotify) {
+ pScreen->ClipNotify = ScreenPriv->ClipNotify;
+ (*pScreen->ClipNotify)(pWin, dx, dy);
+ pScreen->ClipNotify = KdXVClipNotify;
+ }
+}
+
+
+
+/**** Required XvScreenRec fields ****/
+
+static Bool
+KdXVCloseScreen(int i, ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ KdScreenInfo *screen=pScreenPriv->screen;
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+ KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
+ XvAdaptorPtr pa;
+ int c;
+
+ if(!ScreenPriv) return TRUE;
+
+ pScreen->CreateWindow = ScreenPriv->CreateWindow;
+ pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
+ pScreen->WindowExposures = ScreenPriv->WindowExposures;
+ pScreen->ClipNotify = ScreenPriv->ClipNotify;
+
+/* fprintf(stderr,"XV: Unwrapping screen & card funcs\n"); */
+
+ card->cfuncs->enable = ScreenPriv->enable;
+ card->cfuncs->disable = ScreenPriv->disable;
+
+ for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
+ KdXVFreeAdaptor(pa);
+ }
+
+ if(pxvs->pAdaptors)
+ xfree(pxvs->pAdaptors);
+
+ xfree(ScreenPriv);
+
+
+ return TRUE;
+}
+
+
+static int
+KdXVQueryAdaptors(
+ ScreenPtr pScreen,
+ XvAdaptorPtr *p_pAdaptors,
+ int *p_nAdaptors
+){
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+
+ *p_nAdaptors = pxvs->nAdaptors;
+ *p_pAdaptors = pxvs->pAdaptors;
+
+ return (Success);
+}
+
+static Bool
+KdXVEnable(ScreenPtr pScreen)
+{
+ static int count=0;
+ KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
+ Bool ret;
+
+ ret = (*ScreenPriv->enable)(pScreen);
+
+ if(ret) WalkTree(pScreen, KdXVReputAllVideo, 0);
+
+ return ret;
+}
+
+static void
+KdXVDisable(ScreenPtr pScreen)
+{
+ XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
+ KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
+ XvAdaptorPtr pAdaptor;
+ XvPortPtr pPort;
+ XvPortRecPrivatePtr pPriv;
+ int i, j;
+
+ for(i = 0; i < pxvs->nAdaptors; i++) {
+ pAdaptor = &pxvs->pAdaptors[i];
+ for(j = 0; j < pAdaptor->nPorts; j++) {
+ pPort = &pAdaptor->pPorts[j];
+ pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
+ if(pPriv->isOn > XV_OFF) {
+
+ (*pPriv->AdaptorRec->StopVideo)(
+ pPriv->screen, pPriv->DevPriv.ptr, TRUE);
+ pPriv->isOn = XV_OFF;
+
+ if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
+ REGION_DESTROY(pScreen, pPriv->pCompositeClip);
+
+ pPriv->pCompositeClip = NULL;
+
+ if(!pPriv->type && pPriv->pDraw) { /* still */
+ KdXVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv);
+ }
+ }
+ }
+ }
+
+ (*ScreenPriv->disable)(pScreen);
+}
+
+/**** XvAdaptorRec fields ****/
+
+static int
+KdXVAllocatePort(
+ unsigned long port,
+ XvPortPtr pPort,
+ XvPortPtr *ppPort
+){
+ *ppPort = pPort;
+ return Success;
+}
+
+static int
+KdXVFreePort(XvPortPtr pPort)
+{
+ return Success;
+}
+
+static int
+KdXVPutVideo(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ KdScreenPriv(portPriv->screen->pScreen);
+ int result;
+
+ /* No dumping video to pixmaps... For now anyhow */
+ if(pDraw->type != DRAWABLE_WINDOW) {
+ pPort->pDraw = (DrawablePtr)NULL;
+ return BadAlloc;
+ }
+
+ /* If we are changing windows, unregister our port in the old window */
+ if(portPriv->pDraw && (portPriv->pDraw != pDraw))
+ KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+
+ /* Register our port with the new window */
+ result = KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ if(result != Success) return result;
+
+ portPriv->pDraw = pDraw;
+ portPriv->type = XvInputMask;
+
+ /* save a copy of these parameters */
+ portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
+ portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+
+ /* make sure we have the most recent copy of the clientClip */
+ KdXVCopyClip(portPriv, pGC);
+
+ /* To indicate to the DI layer that we were successful */
+ pPort->pDraw = pDraw;
+
+ if (!pScreenPriv->enabled) return Success;
+
+ return(KdXVReputVideo(portPriv));
+}
+
+static int
+KdXVPutStill(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ ScreenPtr pScreen = pDraw->pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen=pScreenPriv->screen;
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ if (!pScreenPriv->enabled) return Success;
+
+ WinBox.x1 = pDraw->x + drw_x;
+ WinBox.y1 = pDraw->y + drw_y;
+ WinBox.x2 = WinBox.x1 + drw_w;
+ WinBox.y2 = WinBox.y1 + drw_h;
+
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
+
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = 0;
+ VPBox.y1 = 0;
+ VPBox.x2 = screen->width;
+ VPBox.y2 = screen->height;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ if(portPriv->pDraw) {
+ KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+ }
+
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto PUT_STILL_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto PUT_STILL_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->PutStill)(portPriv->screen,
+ vid_x, vid_y, WinBox.x1, WinBox.y1,
+ vid_w, vid_h, drw_w, drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+ if((ret == Success) &&
+ (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
+
+ KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ portPriv->isOn = XV_ON;
+ portPriv->pDraw = pDraw;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+ portPriv->type = 0; /* no mask means it's transient and should
+ not be reput once it's removed */
+ pPort->pDraw = pDraw; /* make sure we can get stop requests */
+ }
+
+PUT_STILL_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->screen, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+static int
+KdXVGetVideo(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ int result;
+ KdScreenPriv(portPriv->screen->pScreen);
+
+ /* No pixmaps... For now anyhow */
+ if(pDraw->type != DRAWABLE_WINDOW) {
+ pPort->pDraw = (DrawablePtr)NULL;
+ return BadAlloc;
+ }
+
+ /* If we are changing windows, unregister our port in the old window */
+ if(portPriv->pDraw && (portPriv->pDraw != pDraw))
+ KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+
+ /* Register our port with the new window */
+ result = KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ if(result != Success) return result;
+
+ portPriv->pDraw = pDraw;
+ portPriv->type = XvOutputMask;
+
+ /* save a copy of these parameters */
+ portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
+ portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+
+ /* make sure we have the most recent copy of the clientClip */
+ KdXVCopyClip(portPriv, pGC);
+
+ /* To indicate to the DI layer that we were successful */
+ pPort->pDraw = pDraw;
+
+ if(!pScreenPriv->enabled) return Success;
+
+ return(KdXVRegetVideo(portPriv));
+}
+
+static int
+KdXVGetStill(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ ScreenPtr pScreen = pDraw->pScreen;
+ KdScreenPriv(pScreen);
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ if(!pScreenPriv->enabled) return Success;
+
+ WinBox.x1 = pDraw->x + drw_x;
+ WinBox.y1 = pDraw->y + drw_y;
+ WinBox.x2 = WinBox.x1 + drw_w;
+ WinBox.y2 = WinBox.y1 + drw_h;
+
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
+
+ if(portPriv->pDraw) {
+ KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+ }
+
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto GET_STILL_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->GetStill)(portPriv->screen,
+ vid_x, vid_y, WinBox.x1, WinBox.y1,
+ vid_w, vid_h, drw_w, drw_h,
+ &ClipRegion, portPriv->DevPriv.ptr);
+
+GET_STILL_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->screen, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+
+static int
+KdXVStopVideo(
+ ClientPtr client,
+ XvPortPtr pPort,
+ DrawablePtr pDraw
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ KdScreenPriv(portPriv->screen->pScreen);
+
+ if(pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ KdXVRemovePortFromWindow((WindowPtr)pDraw, portPriv);
+
+ if(!pScreenPriv->enabled) return Success;
+
+ /* Must free resources. */
+
+ if(portPriv->isOn > XV_OFF) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->screen, portPriv->DevPriv.ptr, TRUE);
+ portPriv->isOn = XV_OFF;
+ }
+
+ return Success;
+}
+
+static int
+KdXVSetPortAttribute(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 value
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->screen,
+ attribute, value, portPriv->DevPriv.ptr));
+}
+
+
+static int
+KdXVGetPortAttribute(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 *p_value
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->screen,
+ attribute, (int *) p_value, portPriv->DevPriv.ptr));
+}
+
+
+
+static int
+KdXVQueryBestSize(
+ ClientPtr client,
+ XvPortPtr pPort,
+ CARD8 motion,
+ CARD16 vid_w, CARD16 vid_h,
+ CARD16 drw_w, CARD16 drw_h,
+ unsigned int *p_w, unsigned int *p_h
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ (*portPriv->AdaptorRec->QueryBestSize)(portPriv->screen,
+ (Bool)motion, vid_w, vid_h, drw_w, drw_h,
+ p_w, p_h, portPriv->DevPriv.ptr);
+
+ return Success;
+}
+
+
+static int
+KdXVPutImage(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 src_x, INT16 src_y,
+ CARD16 src_w, CARD16 src_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h,
+ XvImagePtr format,
+ unsigned char* data,
+ Bool sync,
+ CARD16 width, CARD16 height
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+ ScreenPtr pScreen = pDraw->pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen=pScreenPriv->screen;
+ RegionRec WinRegion;
+ RegionRec ClipRegion;
+ BoxRec WinBox;
+ int ret = Success;
+ Bool clippedAway = FALSE;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return BadAlloc;
+
+ if(!pScreenPriv->enabled) return Success;
+
+ WinBox.x1 = pDraw->x + drw_x;
+ WinBox.y1 = pDraw->y + drw_y;
+ WinBox.x2 = WinBox.x1 + drw_w;
+ WinBox.y2 = WinBox.y1 + drw_h;
+
+ REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
+ REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
+ REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
+
+ if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
+ RegionRec VPReg;
+ BoxRec VPBox;
+
+ VPBox.x1 = 0;
+ VPBox.y1 = 0;
+ VPBox.x2 = screen->width;
+ VPBox.y2 = screen->height;
+
+ REGION_INIT(pScreen, &VPReg, &VPBox, 1);
+ REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
+ REGION_UNINIT(pScreen, &VPReg);
+ }
+
+ if(portPriv->pDraw) {
+ KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
+ }
+
+ if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
+ clippedAway = TRUE;
+ goto PUT_IMAGE_BAILOUT;
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
+ BoxPtr clipBox = REGION_RECTS(&ClipRegion);
+ if( (REGION_NUM_RECTS(&ClipRegion) != 1) ||
+ (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
+ (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
+ {
+ clippedAway = TRUE;
+ goto PUT_IMAGE_BAILOUT;
+ }
+ }
+
+ if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
+ REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
+ }
+
+ ret = (*portPriv->AdaptorRec->PutImage)(portPriv->screen,
+ src_x, src_y, WinBox.x1, WinBox.y1,
+ src_w, src_h, drw_w, drw_h, format->id, data, width, height,
+ sync, &ClipRegion, portPriv->DevPriv.ptr);
+
+ if((ret == Success) &&
+ (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
+
+ KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+ portPriv->isOn = XV_ON;
+ portPriv->pDraw = pDraw;
+ portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
+ portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
+ portPriv->type = 0; /* no mask means it's transient and should
+ not be reput once it's removed */
+ pPort->pDraw = pDraw; /* make sure we can get stop requests */
+ }
+
+PUT_IMAGE_BAILOUT:
+
+ if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
+ (*portPriv->AdaptorRec->StopVideo)(
+ portPriv->screen, portPriv->DevPriv.ptr, FALSE);
+ portPriv->isOn = XV_PENDING;
+ }
+
+ REGION_UNINIT(pScreen, &WinRegion);
+ REGION_UNINIT(pScreen, &ClipRegion);
+
+ return ret;
+}
+
+
+static int
+KdXVQueryImageAttributes(
+ ClientPtr client,
+ XvPortPtr pPort,
+ XvImagePtr format,
+ CARD16 *width,
+ CARD16 *height,
+ int *pitches,
+ int *offsets
+){
+ XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
+
+ return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->screen,
+ format->id, width, height, pitches, offsets);
+}
+
+
+/**************** Offscreen surface stuff *******************/
+
+typedef struct {
+ KdOffscreenImagePtr images;
+ int num;
+} OffscreenImageRec;
+
+static OffscreenImageRec OffscreenImages[MAXSCREENS];
+static Bool offscreenInited = FALSE;
+
+Bool
+KdXVRegisterOffscreenImages(
+ ScreenPtr pScreen,
+ KdOffscreenImagePtr images,
+ int num
+){
+ if(!offscreenInited) {
+ bzero(OffscreenImages, sizeof(OffscreenImages[MAXSCREENS]));
+ offscreenInited = TRUE;
+ }
+
+ OffscreenImages[pScreen->myNum].num = num;
+ OffscreenImages[pScreen->myNum].images = images;
+
+ return TRUE;
+}
+
+KdOffscreenImagePtr
+KdXVQueryOffscreenImages(
+ ScreenPtr pScreen,
+ int *num
+){
+ if(!offscreenInited) {
+ *num = 0;
+ return NULL;
+ }
+
+ *num = OffscreenImages[pScreen->myNum].num;
+ return OffscreenImages[pScreen->myNum].images;
+}
diff --git a/hw/kdrive/src/kxv.h b/hw/kdrive/src/kxv.h
new file mode 100644
index 000000000..5578e3960
--- /dev/null
+++ b/hw/kdrive/src/kxv.h
@@ -0,0 +1,302 @@
+/*
+
+ XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
+ Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
+
+ Copyright (C) 2000, 2001 - Nokia Home Communications
+ Copyright (C) 1998, 1999 - The XFree86 Project Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+*/
+
+/* $XFree86$ */
+
+#ifndef _XVDIX_H_
+#define _XVDIX_H_
+
+#include "scrnintstr.h"
+#include "regionstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "mivalidate.h"
+#include "validate.h"
+#include "resource.h"
+#include "gcstruct.h"
+#include "dixstruct.h"
+
+#include "../../Xext/xvdix.h"
+
+#define VIDEO_NO_CLIPPING 0x00000001
+#define VIDEO_INVERT_CLIPLIST 0x00000002
+#define VIDEO_OVERLAID_IMAGES 0x00000004
+#define VIDEO_OVERLAID_STILLS 0x00000008
+#define VIDEO_CLIP_TO_VIEWPORT 0x00000010
+
+typedef struct {
+ int id;
+ int type;
+ int byte_order;
+ unsigned char guid[16];
+ int bits_per_pixel;
+ int format;
+ int num_planes;
+
+ /* for RGB formats only */
+ int depth;
+ unsigned int red_mask;
+ unsigned int green_mask;
+ unsigned int blue_mask;
+
+ /* for YUV formats only */
+ unsigned int y_sample_bits;
+ unsigned int u_sample_bits;
+ unsigned int v_sample_bits;
+ unsigned int horz_y_period;
+ unsigned int horz_u_period;
+ unsigned int horz_v_period;
+ unsigned int vert_y_period;
+ unsigned int vert_u_period;
+ unsigned int vert_v_period;
+ char component_order[32];
+ int scanline_order;
+} KdImageRec, *KdImagePtr;
+
+
+typedef struct {
+ KdScreenInfo * screen;
+ int id;
+ unsigned short width, height;
+ int *pitches; /* bytes */
+ int *offsets; /* in bytes from start of framebuffer */
+ DevUnion devPrivate;
+} KdSurfaceRec, *KdSurfacePtr;
+
+
+typedef int (* PutVideoFuncPtr)( KdScreenInfo * screen,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* PutStillFuncPtr)( KdScreenInfo * screen,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* GetVideoFuncPtr)( KdScreenInfo * screen,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* GetStillFuncPtr)( KdScreenInfo * screen,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data );
+typedef void (* StopVideoFuncPtr)(KdScreenInfo * screen, pointer data, Bool Exit);
+typedef int (* SetPortAttributeFuncPtr)(KdScreenInfo * screen, Atom attribute,
+ int value, pointer data);
+typedef int (* GetPortAttributeFuncPtr)(KdScreenInfo * screen, Atom attribute,
+ int *value, pointer data);
+typedef void (* QueryBestSizeFuncPtr)(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);
+typedef int (* PutImageFuncPtr)( 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 image, unsigned char* buf, short width, short height, Bool Sync,
+ RegionPtr clipBoxes, pointer data );
+typedef int (* ReputImageFuncPtr)( KdScreenInfo * screen, short drw_x, short drw_y,
+ RegionPtr clipBoxes, pointer data );
+typedef int (*QueryImageAttributesFuncPtr)(KdScreenInfo * screen,
+ int image, unsigned short *width, unsigned short *height,
+ int *pitches, int *offsets);
+
+typedef enum {
+ XV_OFF,
+ XV_PENDING,
+ XV_ON
+} XvStatus;
+
+/*** this is what the driver needs to fill out ***/
+
+typedef struct {
+ int id;
+ char *name;
+ unsigned short width, height;
+ XvRationalRec rate;
+} KdVideoEncodingRec, *KdVideoEncodingPtr;
+
+typedef struct {
+ char depth;
+ short class;
+} KdVideoFormatRec, *KdVideoFormatPtr;
+
+typedef struct {
+ int flags;
+ int min_value;
+ int max_value;
+ char *name;
+} KdAttributeRec, *KdAttributePtr;
+
+typedef struct {
+ unsigned int type;
+ int flags;
+ char *name;
+ int nEncodings;
+ KdVideoEncodingPtr pEncodings;
+ int nFormats;
+ KdVideoFormatPtr pFormats;
+ int nPorts;
+ DevUnion *pPortPrivates;
+ int nAttributes;
+ KdAttributePtr pAttributes;
+ int nImages;
+ KdImagePtr pImages;
+ PutVideoFuncPtr PutVideo;
+ PutStillFuncPtr PutStill;
+ GetVideoFuncPtr GetVideo;
+ GetStillFuncPtr GetStill;
+ StopVideoFuncPtr StopVideo;
+ SetPortAttributeFuncPtr SetPortAttribute;
+ GetPortAttributeFuncPtr GetPortAttribute;
+ QueryBestSizeFuncPtr QueryBestSize;
+ PutImageFuncPtr PutImage;
+ ReputImageFuncPtr ReputImage;
+ QueryImageAttributesFuncPtr QueryImageAttributes;
+} KdVideoAdaptorRec, *KdVideoAdaptorPtr;
+
+typedef struct {
+ KdImagePtr image;
+ int flags;
+ int (*alloc_surface)(KdScreenInfo * screen,
+ int id,
+ unsigned short width,
+ unsigned short height,
+ KdSurfacePtr surface);
+ int (*free_surface)(KdSurfacePtr surface);
+ int (*display) (KdSurfacePtr surface,
+ short vid_x, short vid_y,
+ short drw_x, short drw_y,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ RegionPtr clipBoxes);
+ int (*stop) (KdSurfacePtr surface);
+ int (*getAttribute) (KdScreenInfo * screen, Atom attr, INT32 *value);
+ int (*setAttribute) (KdScreenInfo * screen, Atom attr, INT32 value);
+ int max_width;
+ int max_height;
+ int num_attributes;
+ KdAttributePtr attributes;
+} KdOffscreenImageRec, *KdOffscreenImagePtr;
+
+Bool
+KdXVScreenInit(
+ ScreenPtr pScreen,
+ KdVideoAdaptorPtr *Adaptors,
+ int num
+);
+
+typedef int (* KdXVInitGenericAdaptorPtr)(KdScreenInfo * screen,
+ KdVideoAdaptorPtr **Adaptors);
+
+int
+KdXVRegisterGenericAdaptorDriver(
+ KdXVInitGenericAdaptorPtr InitFunc
+);
+
+int
+KdXVListGenericAdaptors(
+ KdScreenInfo * screen,
+ KdVideoAdaptorPtr **Adaptors
+);
+
+Bool
+KdXVRegisterOffscreenImages(
+ ScreenPtr pScreen,
+ KdOffscreenImagePtr images,
+ int num
+);
+
+KdOffscreenImagePtr
+KdXVQueryOffscreenImages(
+ ScreenPtr pScreen,
+ int *num
+);
+
+KdVideoAdaptorPtr KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen);
+
+void KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr);
+
+/*** These are DDX layer privates ***/
+
+
+typedef struct {
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ ClipNotifyProcPtr ClipNotify;
+ WindowExposuresProcPtr WindowExposures;
+ void (*disable) (ScreenPtr); /* turn off rendering */
+ Bool (*enable) (ScreenPtr); /* set up for rendering */
+} KdXVScreenRec, *KdXVScreenPtr;
+
+typedef struct {
+ int flags;
+ PutVideoFuncPtr PutVideo;
+ PutStillFuncPtr PutStill;
+ GetVideoFuncPtr GetVideo;
+ GetStillFuncPtr GetStill;
+ StopVideoFuncPtr StopVideo;
+ SetPortAttributeFuncPtr SetPortAttribute;
+ GetPortAttributeFuncPtr GetPortAttribute;
+ QueryBestSizeFuncPtr QueryBestSize;
+ PutImageFuncPtr PutImage;
+ ReputImageFuncPtr ReputImage;
+ QueryImageAttributesFuncPtr QueryImageAttributes;
+} XvAdaptorRecPrivate, *XvAdaptorRecPrivatePtr;
+
+typedef struct {
+ KdScreenInfo * screen;
+ DrawablePtr pDraw;
+ unsigned char type;
+ unsigned int subWindowMode;
+ DDXPointRec clipOrg;
+ RegionPtr clientClip;
+ RegionPtr pCompositeClip;
+ Bool FreeCompositeClip;
+ XvAdaptorRecPrivatePtr AdaptorRec;
+ XvStatus isOn;
+ Bool moved;
+ int vid_x, vid_y, vid_w, vid_h;
+ int drw_x, drw_y, drw_w, drw_h;
+ DevUnion DevPriv;
+} XvPortRecPrivate, *XvPortRecPrivatePtr;
+
+typedef struct _KdXVWindowRec{
+ XvPortRecPrivatePtr PortRec;
+ struct _KdXVWindowRec *next;
+} KdXVWindowRec, *KdXVWindowPtr;
+
+#endif /* _XVDIX_H_ */
+