summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commit696e90e916d6f0db4057826115d74c5d968eb5e7 (patch)
treefe862c5efc82e1ee284f74571788c742cc66e58d
parent4a50a1da2ff5601a5721d1a06a23c7f75db958c4 (diff)
Initial revisionXORG-STABLE
-rw-r--r--man/apm.man106
-rw-r--r--src/apm.h243
-rw-r--r--src/apm_accel.c753
-rw-r--r--src/apm_cursor.c208
-rw-r--r--src/apm_dga.c434
-rw-r--r--src/apm_driver.c2371
-rw-r--r--src/apm_funcs.c1558
-rw-r--r--src/apm_i2c.c86
-rw-r--r--src/apm_regs.h231
-rw-r--r--src/apm_rush.c730
-rw-r--r--src/apm_video.c986
11 files changed, 7706 insertions, 0 deletions
diff --git a/man/apm.man b/man/apm.man
new file mode 100644
index 0000000..cb206c1
--- /dev/null
+++ b/man/apm.man
@@ -0,0 +1,106 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm.man,v 1.3 2002/05/07 12:53:49 alanh Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH APM __drivermansuffix__ __vendorversion__
+.SH NAME
+apm \- Alliance ProMotion video driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qapm\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B apm
+is an XFree86 driver for Alliance ProMotion video cards. The driver
+is accelerated for supported hardware/depth combination. It supports
+framebuffer depths of 8, 15, 16, 24 and 32 bits. For 6420, 6422, AT24,
+AT3D and AT25, all depths are fully accelerated except 24 bpp for which
+only screen to screen copy and rectangle filling is accelerated.
+.SH SUPPORTED HARDWARE
+The
+.B apm
+driver supports PCI and ISA video cards on the following Alliance
+ProMotion chipsets
+.TP 12
+.B ProMotion 6420
+.TP 12
+.B ProMotion 6422
+.TP 12
+.B AT24
+.TP 12
+.B AT3D
+.TP 12
+.B AT25
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver.
+.PP
+The driver auto-detects the chipset type, but the following
+.B ChipSet
+names may optionally be specified in the config file
+.B \*qDevice\*q
+section, and will override the auto-detection:
+.PP
+.RS 4
+"6422", "at24", "at3d".
+.PP
+The AT25 is Chipset "at3d" and the 6420 is 6422.
+.PP
+The driver will auto-detect the amount of video memory present for all
+chips. The actual amount of video memory can also be specified with a
+.B VideoRam
+entry in the config file
+.B \*qDevice\*q
+section.
+.PP
+The following driver
+.B Options
+are supported:
+.TP
+.BI "Option \*qHWCursor\*q \*q" boolean \*q
+Enable or disable the hardware cursor. Default: on.
+.TP
+.BI "Option \*qNoAccel\*q \*q" boolean \*q
+Disable or enable acceleration. Default: acceleration is enabled.
+.TP
+.BI "Option \*qNoLinear\*q \*q" boolean \*q
+Disable or enable use of linear frame buffer. Default: on.
+Note: it may or may not work. Tell me if you need it.
+.TP
+.BI "Option \*qPciRetry\*q \*q" boolean \*q
+Enable or disable PCI retries. Default: off.
+.TP
+.BI "Option \*qRemap_DPMS_On\*q \*q" string \*q
+.TP
+.BI "Option \*qRemap_DPMS_Standby\*q \*q" string \*q
+.TP
+.BI "Option \*qRemap_DPMS_Suspend\*q \*q" string \*q
+.TP
+.BI "Option \*qRemap_DPMS_Off\*q \*q" string \*q
+Remaps the corresponding DPMS events. I've found that my
+Hercules 128/3D swaps Off and Suspend events. You can correct
+that with
+.nf
+.RS
+.RS
+.BI "Option \*qRemap_DPMS_Suspend\*q \*qOff\*q"
+.BI "Option \*qRemap_DPMS_Off\*q \*qSuspend\*q"
+.RE
+.fi
+in the
+.B Device
+section of the config file.
+.TP
+.BI "Option \*qSWCursor\*q \*q" boolean \*q
+Force the software cursor. Default: off.
+.TP
+.BI "Option \*qShadowFB\*q \*q" boolean \*q
+Enable or disable use of the shadow framebuffer layer. Default: off.
+.SH "SEE ALSO"
+XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: ...
diff --git a/src/apm.h b/src/apm.h
new file mode 100644
index 0000000..44e37eb
--- /dev/null
+++ b/src/apm.h
@@ -0,0 +1,243 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm.h,v 1.19 2002/05/07 12:53:49 alanh Exp $ */
+
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+/* All drivers need this */
+#include "xf86_ansic.h"
+
+/* Everything using inb/outb, etc needs "compiler.h" */
+#include "compiler.h"
+
+/* This is used for module versioning */
+#include "xf86Version.h"
+
+/* Drivers for PCI hardware need this */
+#include "xf86PciInfo.h"
+
+/* Drivers that need to access the PCI config space directly need this */
+#include "xf86Pci.h"
+
+/* All drivers using the vgahw module need this */
+#include "vgaHW.h"
+
+/* Drivers using the mi banking wrapper need this */
+#include "mibank.h"
+
+/* All drivers using the mi colormap manipulation need this */
+#include "micmap.h"
+
+/* Needed for the 1 and 4 bpp framebuffers */
+#include "xf1bpp.h"
+#include "xf4bpp.h"
+
+#include "fb.h"
+
+/* Drivers using the XAA interface ... */
+#include "xaa.h"
+#include "xaalocal.h"
+#include "xf86Cursor.h"
+#include "xf86fbman.h"
+
+/* All drivers initialising the SW cursor need this */
+#include "mipointer.h"
+
+/* All drivers implementing backing store need this */
+#include "mibstore.h"
+
+/* I2C support */
+#include "xf86i2c.h"
+
+/* DDC support */
+#include "xf86DDC.h"
+
+#include "xf86xv.h"
+#include "Xv.h"
+
+#ifdef TRUE
+#undef TRUE
+#endif
+#define TRUE (1)
+
+#define rdinx(port, ind) (outb((port), (ind)), inb((port) + 1))
+#define wrinx(port, ind, val) outb((port), (ind)), outb((port) + 1, (val))
+#define modinx(port, ind, mask, bits) \
+ do { \
+ unsigned char tmp; \
+ tmp = (rdinx((port), (ind)) & ~(mask)) | ((bits) & (mask)); \
+ wrinx((port), (ind), tmp); \
+ } while(0)
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+#define NoSEQRegs 0x20
+#define NoCRTRegs 0x1F
+#define NoGRCRegs 0x09
+#define NoATCRegs 0x15
+
+enum {
+ XR80, XRC0, XRD0, XRE0, XRE8, XREC, XR140, XR144, XR148, XR14C, NoEXRegs
+};
+
+typedef struct {
+ unsigned char SEQ[NoSEQRegs];
+ unsigned char CRT[NoCRTRegs];
+ unsigned char GRC[NoGRCRegs];
+ unsigned char ATC[NoATCRegs];
+ unsigned int EX[NoEXRegs];
+} ApmRegStr, *ApmRegPtr;
+
+typedef struct {
+ int displayWidth, displayHeight;
+ int bitsPerPixel, bytesPerScanline;
+ int depth, Scanlines;
+ CARD32 mask32; /* Mask to have 32bit aligned data */
+ unsigned int Setup_DEC;
+ DisplayModePtr pMode;
+} ApmFBLayout;
+
+#define APM_CACHE_NUMBER 32
+
+typedef struct {
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+ int scrnIndex;
+ int Chipset;
+ int ChipRev;
+ CARD32 LinAddress;
+ unsigned long LinMapSize;
+ CARD32 FbMapSize;
+ pointer LinMap;
+ pointer FbBase;
+ char *VGAMap;
+ char *MemMap;
+ pointer BltMap;
+ Bool UnlockCalled;
+ IOADDRESS iobase, xport, xbase;
+ unsigned char savedSR10;
+ CARD8 MiscOut;
+ CARD8 c9, d9, db, Rush;
+ unsigned long saveCmd;
+ pointer FontInfo;
+ Bool hwCursor;
+ Bool noLinear;
+ ApmRegStr ModeReg, SavedReg;
+ CloseScreenProcPtr CloseScreen;
+ Bool UsePCIRetry; /* Do we use PCI-retry or busy-waiting */
+ Bool NoAccel; /* Do we use XAA acceleration architecture */
+ int MinClock; /* Min ramdac clock */
+ int MaxClock; /* Max ramdac clock */
+ ApmFBLayout CurrentLayout, SavedLayout;
+ EntityInfoPtr pEnt;
+ XAAInfoRecPtr AccelInfoRec, DGAXAAInfo;
+ xf86CursorInfoPtr CursorInfoRec;
+ int DGAactive, numDGAModes;
+ DGAModePtr DGAModes;
+ int BaseCursorAddress,CursorAddress,DisplayedCursorAddress;
+ int OffscreenReserved;
+ int blitxdir, blitydir;
+ Bool apmTransparency, apmClip, ShadowFB, I2C;
+ int rop, Bg8x8, Fg8x8;
+ I2CBusPtr I2CPtr;
+ struct ApmStippleCacheRec {
+ XAACacheInfoRec apmStippleCache;
+ FBAreaPtr area;
+ int apmStippleCached:1;
+ } apmCache[APM_CACHE_NUMBER];
+ int apmCachePtr;
+ unsigned char regcurr[0x54];
+ ScreenPtr pScreen;
+ int Generation;
+ int apmLock, pixelStride, RushY[7], CopyMode;
+ int PutImageStride;
+ Bool (*DestroyPixmap)(PixmapPtr);
+ PixmapPtr (*CreatePixmap)(ScreenPtr, int, int, int);
+ void (*SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+ void (*SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+ void (*SetupForSolidFill24)(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+ void (*SubsequentSolidFillRect24)(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+ void (*SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir,
+ int rop, unsigned int planemask,
+ int transparency_color);
+ void (*SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h);
+ void (*SetupForScreenToScreenCopy24)(ScrnInfoPtr pScrn, int xdir, int ydir,
+ int rop, unsigned int planemask,
+ int transparency_color);
+ void (*SubsequentScreenToScreenCopy24)(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h);
+ int MemClk;
+ unsigned char *ShadowPtr;
+ int ShadowPitch;
+ memType ScratchMem, ScratchMemSize, ScratchMemOffset;
+ memType ScratchMemPtr, ScratchMemEnd;
+ int ScratchMemWidth;
+ CARD32 color;
+ XF86VideoAdaptorPtr adaptor;
+ int timerIsOn;
+ Time offTime;
+ OptionInfoPtr Options;
+ char DPMSMask[4];
+} ApmRec, *ApmPtr;
+
+#define curr ((unsigned char *)pApm->regcurr)
+
+typedef struct {
+ u16 ca;
+ u8 font;
+ u8 pad;
+} ApmFontBuf;
+
+typedef struct {
+ u16 ca;
+ u8 font;
+ u8 pad;
+ u16 ca2;
+ u8 font2;
+ u8 pad2;
+} ApmTextBuf;
+
+enum ApmChipId {
+ AP6422 = 0x6422,
+ AT24 = 0x6424,
+ AT3D = 0x643D
+};
+
+typedef struct {
+ BoxRec box;
+ int num;
+ MoveAreaCallbackProcPtr MoveAreaCallback;
+ RemoveAreaCallbackProcPtr RemoveAreaCallback;
+ void *devPriv;
+} ApmPixmapRec, *ApmPixmapPtr;
+
+#define APMDECL(p) ApmPtr pApm = ((ApmPtr)(((ScrnInfoPtr)(p))->driverPrivate))
+#define APMPTR(p) ((ApmPtr)(((ScrnInfoPtr)(p))->driverPrivate))
+
+extern int ApmHWCursorInit(ScreenPtr pScreen);
+extern int ApmDGAInit(ScreenPtr pScreen);
+extern int ApmAccelInit(ScreenPtr pScreen);
+extern Bool ApmI2CInit(ScrnInfoPtr pScrn);
+extern void XFree86RushExtensionInit(ScreenPtr pScreen);
+extern void ApmInitVideo(ScreenPtr pScreen);
+extern void ApmInitVideo_IOP(ScreenPtr pScreen);
+extern void ApmSetupXAAInfo(ApmPtr pApm, XAAInfoRecPtr pXAAinfo);
+extern Bool ApmSwitchMode(int scrnIndex, DisplayModePtr mode,
+ int flags);
+extern void ApmAdjustFrame(int scrnIndex, int x, int y, int flags);
+extern void ApmHWCursorReserveSpace(ApmPtr pApm);
+extern void ApmAccelReserveSpace(ApmPtr pApm);
+
+extern int ApmPixmapIndex;
+#define APM_GET_PIXMAP_PRIVATE(pix)\
+ ((ApmPixmapPtr)(((PixmapPtr)(pix))->devPrivates[ApmPixmapIndex].ptr))
+
+#include "apm_regs.h"
diff --git a/src/apm_accel.c b/src/apm_accel.c
new file mode 100644
index 0000000..72b0cee
--- /dev/null
+++ b/src/apm_accel.c
@@ -0,0 +1,753 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_accel.c,v 1.21 2002/10/08 22:14:03 tsi Exp $ */
+
+#include "apm.h"
+#include "miline.h"
+
+/* Defines */
+#define MAXLOOP 1000000
+
+/* Translation from X ROP's to APM ROP's. */
+static unsigned char apmROP[] = {
+ 0,
+ 0x88,
+ 0x44,
+ 0xCC,
+ 0x22,
+ 0xAA,
+ 0x66,
+ 0xEE,
+ 0x11,
+ 0x99,
+ 0x55,
+ 0xDD,
+ 0x33,
+ 0xBB,
+ 0x77,
+ 0xFF
+};
+
+
+#include "apm_funcs.c"
+
+#define IOP_ACCESS
+#include "apm_funcs.c"
+
+#define PSZ 24
+#include "apm_funcs.c"
+
+#define PSZ 24
+#define IOP_ACCESS
+#include "apm_funcs.c"
+
+static void
+ApmRemoveStipple(FBAreaPtr area)
+{
+ ((struct ApmStippleCacheRec *)area->devPrivate.ptr)->apmStippleCached = FALSE;
+}
+
+static void
+ApmMoveStipple(FBAreaPtr from, FBAreaPtr to)
+{
+ struct ApmStippleCacheRec *pApm = (struct ApmStippleCacheRec *)to->devPrivate.ptr;
+
+ pApm->apmStippleCache.x = to->box.x1;
+ pApm->apmStippleCache.y += to->box.y1 - from->box.y1;
+ /* TODO : move data */
+}
+
+/*
+ * ApmCacheMonoStipple
+ * because my poor AT3D needs stipples stored linearly in memory.
+ */
+static XAACacheInfoPtr
+ApmCacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix)
+{
+ APMDECL(pScrn);
+ int w = pPix->drawable.width, W = (w + 31) & ~31;
+ int h = pPix->drawable.height;
+ int i, j, dwords, mem, width, funcNo;
+ FBAreaPtr draw;
+ struct ApmStippleCacheRec *pCache;
+ unsigned char *srcPtr;
+ CARD32 *dstPtr;
+
+ for (i = 0; i < APM_CACHE_NUMBER; i++)
+ if ((pApm->apmCache[i].apmStippleCache.serialNumber == pPix->drawable.serialNumber)
+ && pApm->apmCache[i].apmStippleCached &&
+ (pApm->apmCache[i].apmStippleCache.fg == -1) &&
+ (pApm->apmCache[i].apmStippleCache.bg == -1)) {
+ pApm->apmCache[i].apmStippleCache.trans_color = -1;
+ return &pApm->apmCache[i].apmStippleCache;
+ }
+ if ((i = ++pApm->apmCachePtr) >= APM_CACHE_NUMBER)
+ i = pApm->apmCachePtr = 0;
+ pCache = &pApm->apmCache[i];
+ if (pCache->apmStippleCached) {
+ pCache->apmStippleCached = FALSE;
+ xf86FreeOffscreenArea(pCache->area);
+ }
+
+ draw = xf86AllocateLinearOffscreenArea(pApm->pScreen, (W * h + 7) / 8,
+ (pApm->CurrentLayout.mask32 + 1) << 1,
+ ApmMoveStipple, ApmRemoveStipple, pCache);
+ if (!draw)
+ return NULL; /* Let's hope this will never happen... */
+
+ pCache->area = draw;
+ pCache->apmStippleCache.serialNumber = pPix->drawable.serialNumber;
+ pCache->apmStippleCache.trans_color =
+ pCache->apmStippleCache.bg =
+ pCache->apmStippleCache.fg = -1;
+ pCache->apmStippleCache.orig_w = w;
+ pCache->apmStippleCache.orig_h = h;
+ pCache->apmStippleCache.x = draw->box.x1;
+ pCache->apmStippleCache.y = draw->box.y1 + ((pCache - pApm->apmCache) + 1) * pApm->CurrentLayout.Scanlines;
+ mem = ((draw->box.x2 - draw->box.x1) * (draw->box.y2 - draw->box.y1) *
+ pScrn->bitsPerPixel) / (W * h);
+ width = 2;
+ while (width * width <= mem)
+ width++;
+ width--;
+ pCache->apmStippleCache.w = (width * W + pScrn->bitsPerPixel - 1) /
+ pScrn->bitsPerPixel;
+ pCache->apmStippleCache.h = ((draw->box.x2 - draw->box.x1) *
+ (draw->box.y2 - draw->box.y1)) /
+ pCache->apmStippleCache.w;
+ pCache->apmStippleCached = TRUE;
+
+ if (w < 32) {
+ if (w & (w - 1)) funcNo = 1;
+ else funcNo = 0;
+ } else funcNo = 2;
+
+ dstPtr = ((CARD32 *)pApm->FbBase) + (draw->box.x1 +
+ draw->box.y1*pApm->CurrentLayout.bytesPerScanline) / 4;
+ j = 0;
+ dwords = (pCache->apmStippleCache.w * pScrn->bitsPerPixel) / 32;
+ while (j + h <= pCache->apmStippleCache.h) {
+ srcPtr = (unsigned char *)pPix->devPrivate.ptr;
+ for (i = h; --i >= 0; ) {
+ (*XAAStippleScanlineFuncMSBFirst[funcNo])(dstPtr, (CARD32 *)srcPtr, 0, w, dwords);
+ srcPtr += pPix->devKind;
+ dstPtr += dwords;
+ }
+ j += h;
+ }
+ srcPtr = (unsigned char *)pPix->devPrivate.ptr;
+ for (i = pCache->apmStippleCache.h - j ; --i >= 0; ) {
+ (*XAAStippleScanlineFuncMSBFirst[funcNo])(dstPtr, (CARD32 *)srcPtr, 0, w, dwords);
+ srcPtr += pPix->devKind;
+ dstPtr += dwords;
+ }
+
+ return &pCache->apmStippleCache;
+}
+
+#if 0
+extern GCOps XAAPixmapOps;
+static RegionPtr (*SaveCopyAreaPixmap)(DrawablePtr, DrawablePtr, GC *, int, int, int, int, int, int);
+
+static RegionPtr
+ApmCopyAreaPixmap(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC,
+ int srcx, int srcy,
+ int width, int height,
+ int dstx, int dsty )
+{
+ register int Scanlines;
+ int is;
+ int id;
+ int sx = 0, sy = 0, dx = 0, dy = 0, pitch;
+ RegionPtr pReg;
+
+ if (APMPTR(xf86Screens[(pGC)->pScreen->myNum])->Chipset == AT3D) {
+ Scanlines = APMPTR(xf86Screens[(pGC)->pScreen->myNum])->CurrentLayout.Scanlines;
+ is = (pSrcDrawable->type == DRAWABLE_PIXMAP) ? APM_GET_PIXMAP_PRIVATE(pSrcDrawable)->num : 0;
+ id = (pDstDrawable->type == DRAWABLE_PIXMAP) ? APM_GET_PIXMAP_PRIVATE(pDstDrawable)->num : 0;
+ if (is) {
+ sx = pSrcDrawable->x;
+ sy = pSrcDrawable->y % Scanlines;
+ pitch = 2 * pSrcDrawable->width;
+ pSrcDrawable->x = (sx + ((PixmapPtr)pSrcDrawable)->devKind * sy) % pitch;
+ pSrcDrawable->y = (sx + ((PixmapPtr)pSrcDrawable)->devKind * sy) / pitch;
+ ((PixmapPtr)pSrcDrawable)->devKind = pitch;
+ pSrcDrawable->depth = 16;
+ }
+ if (id) {
+ dx = pDstDrawable->x;
+ dy = pDstDrawable->y % Scanlines;
+ pitch = 2 * pDstDrawable->width;
+ pDstDrawable->x = (dx + ((PixmapPtr)pDstDrawable)->devKind * dy) % pitch;
+ pDstDrawable->y = (dx + ((PixmapPtr)pDstDrawable)->devKind * dy) / pitch;
+ ((PixmapPtr)pDstDrawable)->devKind = pitch;
+ pDstDrawable->depth = 16;
+ }
+ pReg = (*SaveCopyAreaPixmap)(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy % Scanlines,
+ width, height,
+ dstx, dsty % Scanlines);
+ if (is) {
+ pSrcDrawable->x = sx;
+ pSrcDrawable->y = sy + is * Scanlines;
+ }
+ if (id) {
+ pDstDrawable->x = dx;
+ pDstDrawable->y = dy + id * Scanlines;
+ }
+ return pReg;
+ }
+ return (*SaveCopyAreaPixmap)(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy,
+ width, height,
+ dstx, dsty);
+}
+#endif
+
+void ApmAccelReserveSpace(ApmPtr pApm)
+{
+ memType mem, ScratchMemOffset;
+
+ mem = xf86Screens[pApm->pScreen->myNum]->videoRam << 10;
+ /*
+ * Reserve at least four lines for mono to color expansion
+ */
+ ScratchMemOffset = ((mem - pApm->OffscreenReserved) /
+ pApm->CurrentLayout.bytesPerScanline - 4) *
+ pApm->CurrentLayout.bytesPerScanline;
+ pApm->ScratchMemSize= mem - ScratchMemOffset - pApm->OffscreenReserved;
+ pApm->ScratchMemPtr = pApm->ScratchMemOffset
+ = (memType)pApm->FbBase + ScratchMemOffset;
+ pApm->ScratchMemEnd = (memType)pApm->FbBase + mem - pApm->OffscreenReserved;
+}
+
+/*********************************************************************************************/
+
+int
+ApmAccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ APMDECL(pScrn);
+ XAAInfoRecPtr pXAAinfo;
+ BoxRec AvailFBArea;
+ memType mem, ScratchMemOffset;
+ int i, stat;
+
+ pApm->AccelInfoRec = pXAAinfo = XAACreateInfoRec();
+ if (!pXAAinfo)
+ return FALSE;
+
+ mem = pScrn->videoRam << 10;
+ ScratchMemOffset = pApm->ScratchMemOffset - (memType)pApm->FbBase;
+ switch (pApm->CurrentLayout.bitsPerPixel) {
+ case 8:
+ case 24:
+ pApm->ScratchMemWidth =
+ (mem - ScratchMemOffset - pApm->OffscreenReserved) / 1;
+ pApm->ScratchMem =
+ ((ScratchMemOffset & 0xFFF000) << 4) |
+ (ScratchMemOffset & 0xFFF);
+ break;
+
+ case 16:
+ pApm->ScratchMemWidth =
+ (mem - ScratchMemOffset - pApm->OffscreenReserved) / 2;
+ pApm->ScratchMem =
+ ((ScratchMemOffset & 0xFFE000) << 3) |
+ ((ScratchMemOffset & 0x1FFE) >> 1);
+ break;
+
+ case 32:
+ pApm->ScratchMemWidth =
+ (mem - ScratchMemOffset - pApm->OffscreenReserved) / 4;
+ pApm->ScratchMem =
+ ((ScratchMemOffset & 0xFFC000) << 2) |
+ ((ScratchMemOffset & 0x3FFC) >> 2);
+ break;
+ }
+ pApm->OffscreenReserved = mem - ScratchMemOffset;
+
+ /*
+ * Abort
+ */
+ if (pApm->Chipset == AP6422)
+ i = 4;
+ else
+ i = 8;
+ if (pApm->noLinear) {
+ stat = RDXL_IOP(0x1FC);
+ while ((stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY)) ||
+ ((stat & STATUS_FIFO) < i)) {
+ WRXB_IOP(0x1FC, 0);
+ stat = RDXL_IOP(0x1FC);
+ }
+ }
+ else {
+ stat = RDXL_M(0x1FC);
+ while ((stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY)) ||
+ ((stat & STATUS_FIFO) < i)) {
+ WRXB_M(0x1FC, 0);
+ stat = RDXL_M(0x1FC);
+ }
+ }
+
+ /* Setup current register values */
+ for (i = 0; i < sizeof(pApm->regcurr) / 4; i++)
+ ((CARD32 *)curr)[i] = RDXL(0x30 + 4*i);
+
+ SETCLIP_CTRL(1);
+ SETCLIP_CTRL(0);
+ SETBYTEMASK(0x00);
+ SETBYTEMASK(0xFF);
+ SETROP(ROP_S_xor_D);
+ SETROP(ROP_S);
+
+#if 0
+ if (XAAPixmapOps.CopyArea != ApmCopyAreaPixmap) {
+ SaveCopyAreaPixmap = XAAPixmapOps.CopyArea;
+ XAAPixmapOps.CopyArea = ApmCopyAreaPixmap;
+ }
+#endif
+
+ ApmSetupXAAInfo(pApm, pXAAinfo);
+
+ if (!pApm->noLinear) {
+ pApm->SetupForSolidFill = ApmSetupForSolidFill;
+ pApm->SubsequentSolidFillRect = ApmSubsequentSolidFillRect;
+ pApm->SetupForSolidFill24 = ApmSetupForSolidFill24;
+ pApm->SubsequentSolidFillRect24 = ApmSubsequentSolidFillRect24;
+ pApm->SetupForScreenToScreenCopy = ApmSetupForScreenToScreenCopy;
+ pApm->SubsequentScreenToScreenCopy = ApmSubsequentScreenToScreenCopy;
+ pApm->SetupForScreenToScreenCopy24 = ApmSetupForScreenToScreenCopy24;
+ pApm->SubsequentScreenToScreenCopy24 = ApmSubsequentScreenToScreenCopy24;
+ }
+ else {
+ pApm->SetupForSolidFill = ApmSetupForSolidFill_IOP;
+ pApm->SubsequentSolidFillRect = ApmSubsequentSolidFillRect_IOP;
+ pApm->SetupForSolidFill24 = ApmSetupForSolidFill24_IOP;
+ pApm->SubsequentSolidFillRect24 = ApmSubsequentSolidFillRect24_IOP;
+ pApm->SetupForScreenToScreenCopy = ApmSetupForScreenToScreenCopy_IOP;
+ pApm->SubsequentScreenToScreenCopy = ApmSubsequentScreenToScreenCopy_IOP;
+ pApm->SetupForScreenToScreenCopy24 = ApmSetupForScreenToScreenCopy24_IOP;
+ pApm->SubsequentScreenToScreenCopy24 = ApmSubsequentScreenToScreenCopy24_IOP;
+ }
+
+ /*
+ * Init Rush extension.
+ * Must be initialized once per generation.
+ */
+#ifdef XF86RUSH_EXT
+ if (!pApm->CreatePixmap) {
+ pApm->CreatePixmap = pScreen->CreatePixmap;
+ pApm->DestroyPixmap = pScreen->DestroyPixmap;
+ }
+ XFree86RushExtensionInit(pScreen);
+#endif
+
+ /* Pixmap cache setup */
+ pXAAinfo->CachePixelGranularity = (pApm->CurrentLayout.mask32 + 1) << 1;
+ AvailFBArea.x1 = 0;
+ AvailFBArea.y1 = 0;
+ AvailFBArea.x2 = pScrn->displayWidth;
+ AvailFBArea.y2 = (pScrn->videoRam * 1024 - pApm->OffscreenReserved) /
+ (pScrn->displayWidth * ((pScrn->bitsPerPixel + 7) >> 3));
+
+ xf86InitFBManager(pScreen, &AvailFBArea);
+
+ bzero(pApm->apmCache, sizeof pApm->apmCache);
+
+ return XAAInit(pScreen, pXAAinfo);
+}
+
+void ApmSetupXAAInfo(ApmPtr pApm, XAAInfoRecPtr pXAAinfo)
+{
+ pApm->CurrentLayout.Setup_DEC = 0;
+ switch(pApm->CurrentLayout.bitsPerPixel)
+ {
+ case 8:
+ pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_8;
+ break;
+ case 16:
+ pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_16;
+ break;
+ case 24:
+ /* Note : in 24 bpp, the accelerator wants linear coordinates */
+ pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_24 | DEC_SOURCE_LINEAR |
+ DEC_DEST_LINEAR;
+ break;
+ case 32:
+ pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_32;
+ break;
+ default:
+ xf86DrvMsg(xf86Screens[pApm->pScreen->myNum]->scrnIndex, X_WARNING,
+ "Cannot set up drawing engine control for bpp = %d\n",
+ pApm->CurrentLayout.bitsPerPixel);
+ break;
+ }
+
+ switch(pApm->CurrentLayout.displayWidth)
+ {
+ case 640:
+ pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_640;
+ break;
+ case 800:
+ pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_800;
+ break;
+ case 1024:
+ pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1024;
+ break;
+ case 1152:
+ pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1152;
+ break;
+ case 1280:
+ pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1280;
+ break;
+ case 1600:
+ pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1600;
+ break;
+ default:
+ xf86DrvMsg(xf86Screens[pApm->pScreen->myNum]->scrnIndex, X_WARNING,
+ "Cannot set up drawing engine control "
+ "for screen width = %d\n", pApm->CurrentLayout.displayWidth);
+ break;
+ }
+
+ if (!pXAAinfo)
+ return;
+
+ /*
+ * Set up the main acceleration flags.
+ */
+ pXAAinfo->Flags = PIXMAP_CACHE | LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
+ pXAAinfo->CacheMonoStipple = ApmCacheMonoStipple;
+
+ if (pApm->CurrentLayout.bitsPerPixel != 24) {
+ if (!pApm->noLinear) {
+#define XAA(s) pXAAinfo->s = Apm##s
+ if (pApm->Chipset < AT24)
+ pXAAinfo->Sync = ApmSync6422;
+ else
+ XAA(Sync);
+
+ /* Accelerated filled rectangles */
+ pXAAinfo->SolidFillFlags = NO_PLANEMASK;
+ XAA(SetupForSolidFill);
+ XAA(SubsequentSolidFillRect);
+
+ /* Accelerated screen to screen color expansion */
+ pXAAinfo->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK;
+ XAA(SetupForScreenToScreenColorExpandFill);
+ XAA(SubsequentScreenToScreenColorExpandFill);
+
+#if 0
+ The constraints of the transfer range are incompatible with the
+ XAA architecture. I rewrote the XAA functions using ImageWrite
+ /* Accelerated CPU to screen color expansion */
+ if ((pApm->Chipset == AT24 && pApm->ChipRev >= 4) ||
+ pApm->Chipset == AT3D) {
+ pXAAinfo->CPUToScreenColorExpandFillFlags =
+ NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD
+ | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X | SYNC_AFTER_COLOR_EXPAND;
+ XAA(SetupForCPUToScreenColorExpandFill);
+ XAA(SubsequentCPUToScreenColorExpandFill);
+ pXAAinfo->ColorExpandBase = pApm->BltMap;
+ pXAAinfo->ColorExpandRange = (pApm->Chipset >= AT3D) ? 32*1024 : 30*1024;
+ }
+
+ /* Accelerated image transfers */
+ pXAAinfo->ImageWriteFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X |
+ SYNC_AFTER_IMAGE_WRITE;
+ pXAAinfo->ImageWriteBase = pApm->BltMap;
+ pXAAinfo->ImageWriteRange = (pApm->Chipset >= AT3D) ? 32*1024 : 30*1024;
+ XAA(SetupForImageWrite);
+ XAA(SubsequentImageWriteRect);
+#endif
+ pXAAinfo->WritePixmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(WritePixmap);
+ pXAAinfo->FillImageWriteRectsFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(FillImageWriteRects);
+ pXAAinfo->WriteBitmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X |
+ BIT_ORDER_IN_BYTE_LSBFIRST;
+ XAA(WriteBitmap);
+ pXAAinfo->TEGlyphRendererFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(TEGlyphRenderer);
+
+ /* Accelerated screen-screen bitblts */
+ pXAAinfo->ScreenToScreenCopyFlags = NO_PLANEMASK;
+ XAA(SetupForScreenToScreenCopy);
+ XAA(SubsequentScreenToScreenCopy);
+
+ /* Accelerated Line drawing */
+ pXAAinfo->SolidLineFlags = NO_PLANEMASK | HARDWARE_CLIP_LINE;
+ XAA(SetClippingRectangle);
+ pXAAinfo->SolidBresenhamLineErrorTermBits = 15;
+
+ if (pApm->Chipset >= AT24) {
+ XAA(SubsequentSolidBresenhamLine);
+
+ /* Pattern fill */
+ pXAAinfo->Mono8x8PatternFillFlags = NO_PLANEMASK |
+ HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_SCREEN_ORIGIN;
+ XAA(SetupForMono8x8PatternFill);
+ XAA(SubsequentMono8x8PatternFillRect);
+ if (pApm->CurrentLayout.bitsPerPixel == 8) {
+ pXAAinfo->Color8x8PatternFillFlags = NO_PLANEMASK |
+ HARDWARE_PATTERN_SCREEN_ORIGIN;
+ XAA(SetupForColor8x8PatternFill);
+ XAA(SubsequentColor8x8PatternFillRect);
+ }
+ }
+ else
+ pXAAinfo->SubsequentSolidBresenhamLine =
+ ApmSubsequentSolidBresenhamLine6422;
+#undef XAA
+ }
+ else {
+#define XAA(s) pXAAinfo->s = Apm##s##_IOP
+ if (pApm->Chipset < AT24)
+ pXAAinfo->Sync = ApmSync6422_IOP;
+ else
+ XAA(Sync);
+
+ /* Accelerated filled rectangles */
+ pXAAinfo->SolidFillFlags = NO_PLANEMASK;
+ XAA(SetupForSolidFill);
+ XAA(SubsequentSolidFillRect);
+
+ /* Accelerated screen to screen color expansion */
+ pXAAinfo->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK;
+ XAA(SetupForScreenToScreenColorExpandFill);
+ XAA(SubsequentScreenToScreenColorExpandFill);
+
+#if 0
+ The constraints of the transfer range are incompatible with the
+ XAA architecture. I rewrote the XAA functions using ImageWrite
+ /* Accelerated CPU to screen color expansion */
+ if ((pApm->Chipset == AT24 && pApm->ChipRev >= 4) ||
+ pApm->Chipset == AT3D) {
+ pXAAinfo->CPUToScreenColorExpandFillFlags =
+ NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD
+ | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X | SYNC_AFTER_COLOR_EXPAND;
+ XAA(SetupForCPUToScreenColorExpandFill);
+ XAA(SubsequentCPUToScreenColorExpandFill);
+ pXAAinfo->ColorExpandBase = pApm->BltMap;
+ pXAAinfo->ColorExpandRange = (pApm->Chipset >= AT3D) ? 32*1024 : 30*1024;
+ }
+
+ /* Accelerated image transfers */
+ pXAAinfo->ImageWriteFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD;
+ pXAAinfo->ImageWriteBase = pApm->BltMap;
+ pXAAinfo->ImageWriteRange = (pApm->Chipset >= AT3D) ? 32*1024 : 30*1024;
+ XAA(SetupForImageWrite);
+ XAA(SubsequentImageWriteRect);
+#endif
+ pXAAinfo->WritePixmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(WritePixmap);
+ pXAAinfo->FillImageWriteRectsFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(FillImageWriteRects);
+ pXAAinfo->WriteBitmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X |
+ BIT_ORDER_IN_BYTE_LSBFIRST;
+ XAA(WriteBitmap);
+ pXAAinfo->TEGlyphRendererFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(TEGlyphRenderer);
+
+ /* Accelerated screen-screen bitblts */
+ pXAAinfo->ScreenToScreenCopyFlags = NO_PLANEMASK;
+ XAA(SetupForScreenToScreenCopy);
+ XAA(SubsequentScreenToScreenCopy);
+
+ /* Accelerated Line drawing */
+ pXAAinfo->SolidLineFlags = NO_PLANEMASK | HARDWARE_CLIP_LINE;
+ XAA(SetClippingRectangle);
+ pXAAinfo->SolidBresenhamLineErrorTermBits = 15;
+
+ if (pApm->Chipset >= AT24) {
+ XAA(SubsequentSolidBresenhamLine);
+
+ /* Pattern fill */
+ pXAAinfo->Mono8x8PatternFillFlags = NO_PLANEMASK |
+ HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_SCREEN_ORIGIN;
+ XAA(SetupForMono8x8PatternFill);
+ XAA(SubsequentMono8x8PatternFillRect);
+ if (pApm->CurrentLayout.bitsPerPixel == 8) {
+ pXAAinfo->Color8x8PatternFillFlags = NO_PLANEMASK |
+ HARDWARE_PATTERN_SCREEN_ORIGIN;
+ XAA(SetupForColor8x8PatternFill);
+ XAA(SubsequentColor8x8PatternFillRect);
+ }
+ }
+ else
+ pXAAinfo->SubsequentSolidBresenhamLine =
+ ApmSubsequentSolidBresenhamLine6422_IOP;
+#undef XAA
+ }
+ }
+ else {
+ if (!pApm->noLinear) {
+#define XAA(s) pXAAinfo->s = Apm##s##24
+ XAA(Sync);
+
+ /* Accelerated filled rectangles */
+ pXAAinfo->SolidFillFlags = NO_PLANEMASK;
+ XAA(SetupForSolidFill);
+ XAA(SubsequentSolidFillRect);
+
+#if 0
+ /* Accelerated screen to screen color expansion */
+ pXAAinfo->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK;
+ XAA(SetupForScreenToScreenColorExpandFill);
+ XAA(SubsequentScreenToScreenColorExpandFill);
+
+#if 0
+ The constraints of the transfer range are incompatible with the
+ XAA architecture. I rewrote the XAA functions using ImageWrite
+ /* Accelerated CPU to screen color expansion */
+ if (pApm->Chipset == AT3D && pApm->ChipRev >= 4) {
+ pXAAinfo->CPUToScreenColorExpandFillFlags =
+ NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD
+ | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X | SYNC_AFTER_COLOR_EXPAND;
+ XAA(SetupForCPUToScreenColorExpandFill);
+ XAA(SubsequentCPUToScreenColorExpandFill);
+ pXAAinfo->ColorExpandBase = pApm->BltMap;
+ pXAAinfo->ColorExpandRange = 32*1024;
+ }
+
+ /* Accelerated image transfers */
+ pXAAinfo->ImageWriteFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD |
+ SYNC_AFTER_IMAGE_WRITE;
+ pXAAinfo->ImageWriteBase = pApm->BltMap;
+ pXAAinfo->ImageWriteRange = 32*1024;
+ XAA(SetupForImageWrite);
+ XAA(SubsequentImageWriteRect);
+#endif
+ pXAAinfo->WritePixmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(WritePixmap);
+ pXAAinfo->FillImageWriteRectsFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(FillImageWriteRects);
+ pXAAinfo->WriteBitmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X |
+ BIT_ORDER_IN_BYTE_LSBFIRST;
+ XAA(WriteBitmap);
+ pXAAinfo->TEGlyphRendererFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(TEGlyphRenderer);
+
+ /* Accelerated Line drawing */
+ pXAAinfo->SolidLineFlags = NO_PLANEMASK | HARDWARE_CLIP_LINE;
+ XAA(SubsequentSolidBresenhamLine);
+ XAA(SetClippingRectangle);
+ pXAAinfo->SolidBresenhamLineErrorTermBits = 15;
+
+ /* Pattern fill */
+ pXAAinfo->Mono8x8PatternFillFlags = NO_PLANEMASK | NO_TRANSPARENCY |
+ HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_SCREEN_ORIGIN;
+ XAA(SetupForMono8x8PatternFill);
+ XAA(SubsequentMono8x8PatternFillRect);
+#endif
+
+ /* Accelerated screen-screen bitblts */
+ pXAAinfo->ScreenToScreenCopyFlags = NO_PLANEMASK | NO_TRANSPARENCY;
+ XAA(SetupForScreenToScreenCopy);
+ XAA(SubsequentScreenToScreenCopy);
+#undef XAA
+ }
+ else {
+#define XAA(s) pXAAinfo->s = Apm##s##24##_IOP
+ XAA(Sync);
+
+ /* Accelerated filled rectangles */
+ pXAAinfo->SolidFillFlags = NO_PLANEMASK;
+ XAA(SetupForSolidFill);
+ XAA(SubsequentSolidFillRect);
+
+#if 0
+ /* Accelerated screen to screen color expansion */
+ pXAAinfo->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK;
+ XAA(SetupForScreenToScreenColorExpandFill);
+ XAA(SubsequentScreenToScreenColorExpandFill);
+
+#if 0
+ The constraints of the transfer range are incompatible with the
+ XAA architecture. I rewrote the XAA functions using ImageWrite
+ /* Accelerated CPU to screen color expansion */
+ if (pApm->Chipset == AT3D && pApm->ChipRev >= 4) {
+ pXAAinfo->CPUToScreenColorExpandFillFlags =
+ NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD
+ | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X | SYNC_AFTER_COLOR_EXPAND;
+ XAA(SetupForCPUToScreenColorExpandFill);
+ XAA(SubsequentCPUToScreenColorExpandFill);
+ pXAAinfo->ColorExpandBase = pApm->BltMap;
+ pXAAinfo->ColorExpandRange = 32*1024;
+ }
+
+ /* Accelerated image transfers */
+ pXAAinfo->ImageWriteFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD;
+ pXAAinfo->ImageWriteBase = pApm->BltMap;
+ pXAAinfo->ImageWriteRange = 32*1024;
+ XAA(SetupForImageWrite);
+ XAA(SubsequentImageWriteRect);
+#endif
+ pXAAinfo->WritePixmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(WritePixmap);
+ pXAAinfo->FillImageWriteRectsFlags =
+ LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(FillImageWriteRects);
+ pXAAinfo->WriteBitmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X |
+ BIT_ORDER_IN_BYTE_LSBFIRST;
+ XAA(WriteBitmap);
+ pXAAinfo->TEGlyphRendererFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK |
+ LEFT_EDGE_CLIPPING_NEGATIVE_X;
+ XAA(TEGlyphRenderer);
+
+ /* Accelerated Line drawing */
+ pXAAinfo->SolidLineFlags = NO_PLANEMASK | HARDWARE_CLIP_LINE;
+ XAA(SubsequentSolidBresenhamLine);
+ XAA(SetClippingRectangle);
+ pXAAinfo->SolidBresenhamLineErrorTermBits = 15;
+
+ /* Pattern fill */
+ pXAAinfo->Mono8x8PatternFillFlags = NO_PLANEMASK | NO_TRANSPARENCY |
+ HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_SCREEN_ORIGIN;
+ XAA(SetupForMono8x8PatternFill);
+ XAA(SubsequentMono8x8PatternFillRect);
+#endif
+
+ /* Accelerated screen-screen bitblts */
+ pXAAinfo->ScreenToScreenCopyFlags = NO_PLANEMASK | NO_TRANSPARENCY;
+ XAA(SetupForScreenToScreenCopy);
+ XAA(SubsequentScreenToScreenCopy);
+#undef XAA
+ }
+ }
+}
diff --git a/src/apm_cursor.c b/src/apm_cursor.c
new file mode 100644
index 0000000..4bf0f98
--- /dev/null
+++ b/src/apm_cursor.c
@@ -0,0 +1,208 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_cursor.c,v 1.14 2000/06/30 18:27:02 dawes Exp $ */
+
+
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "input.h"
+#include "cursorstr.h"
+#include "regionstr.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "windowstr.h"
+#include "mfb.h"
+#include "mipointer.h"
+
+#include "apm.h"
+
+#define CURSORWIDTH 64
+#define CURSORHEIGHT 64
+#define CURSORSIZE (CURSORWIDTH * CURSORHEIGHT / 8)
+#define CURSORALIGN ((CURSORSIZE + 1023) & ~1023l)
+
+static void ApmShowCursor(ScrnInfoPtr pScrn);
+static void ApmHideCursor(ScrnInfoPtr pScrn);
+static void ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static void ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
+static void ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data);
+static Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
+
+static u8 ConvertTable[256];
+
+/* Inline functions */
+static __inline__ void
+WaitForFifo(ApmPtr pApm, int slots)
+{
+ if (!pApm->UsePCIRetry) {
+ volatile int i;
+#define MAXLOOP 1000000
+
+ for(i = 0; i < MAXLOOP; i++) {
+ if ((STATUS() & STATUS_FIFO) >= slots)
+ break;
+ }
+ if (i == MAXLOOP) {
+ unsigned int status = STATUS();
+
+ WRXB(0x1FF, 0);
+ if (!xf86ServerIsExiting())
+ FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
+ }
+ }
+}
+
+void ApmHWCursorReserveSpace(ApmPtr pApm)
+{
+ pApm->OffscreenReserved += 2 * CURSORALIGN;
+ pApm->DisplayedCursorAddress = pApm->BaseCursorAddress =
+ pApm->CursorAddress = 1024 * xf86Screens[pApm->pScreen->myNum]->videoRam -
+ pApm->OffscreenReserved;
+}
+
+
+int ApmHWCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ APMDECL(pScrn);
+ xf86CursorInfoPtr infoPtr;
+ u32 i;
+
+ infoPtr = xf86CreateCursorInfoRec();
+ if (!infoPtr)
+ return FALSE;
+
+ pApm->CursorInfoRec = infoPtr;
+
+ infoPtr->MaxWidth = CURSORWIDTH;
+ infoPtr->MaxHeight = CURSORHEIGHT;
+
+ infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
+ infoPtr->SetCursorColors = ApmSetCursorColors;
+ infoPtr->SetCursorPosition = ApmSetCursorPosition;
+ infoPtr->LoadCursorImage = ApmLoadCursorImage;
+ infoPtr->HideCursor = ApmHideCursor;
+ infoPtr->ShowCursor = ApmShowCursor;
+ infoPtr->UseHWCursor = ApmUseHWCursor;
+
+ /*ErrorF("%s %s: %s: Using hardware cursor (XAA).\n",
+ XCONFIG_PROBED, vga256InfoRec.name, vga256InfoRec.chipset);
+
+ if(XAACursorInfoRec.Flags & USE_HARDWARE_CURSOR) {
+ vgaHWCursor.Init = XAACursorInit;
+ vgaHWCursor.Initialized = TRUE;
+ vgaHWCursor.Restore = XAARestoreCursor;
+ vgaHWCursor.Warp = XAAWarpCursor;
+ vgaHWCursor.QueryBestSize = XAAQueryBestSize;
+ }*/
+
+ /* Set up the convert table for the input cursor data */
+ for (i = 0; i < 256; i++)
+ ConvertTable[i] = ((~i) & 0xAA) | (i & (i >> 1) & 0x55);
+
+ return xf86InitCursor(pScreen, infoPtr);
+}
+
+
+static void
+ApmShowCursor(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+
+ WaitForFifo(pApm, 2);
+ WRXW(0x144, pApm->CursorAddress >> 10);
+ WRXB(0x140, 1);
+ pApm->DisplayedCursorAddress = pApm->CursorAddress;
+}
+
+
+static void
+ApmHideCursor(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+
+ WaitForFifo(pApm, 1);
+ WRXB(0x140, 0);
+}
+
+static Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ return APMPTR(xf86Screens[pScreen->myNum])->CurrentLayout.bitsPerPixel >= 8;
+}
+
+static void
+ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ APMDECL(pScrn);
+ int xoff, yoff;
+
+ if (x < -CURSORWIDTH || y < -CURSORHEIGHT) {
+ WaitForFifo(pApm, 1);
+ WRXB(0x140, 0);
+ return;
+ }
+
+ if (x < 0) {
+ xoff = -x;
+ x = 0;
+ }
+ else
+ xoff = 0;
+ if (y < 0) {
+ yoff = -y;
+ y = 0;
+ }
+ else
+ yoff = 0;
+
+ WaitForFifo(pApm, 2);
+ WRXW(0x14C, (yoff << 8) | (xoff & 0xFF));
+ WRXL(0x148, (y << 16) | (x & 0xFFFF));
+}
+
+
+static void
+ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ APMDECL(pScrn);
+ u16 packedcolfg, packedcolbg;
+
+ if (pApm->CurrentLayout.bitsPerPixel == 8)
+ {
+ WaitForFifo(pApm, 2);
+ WRXB(0x141, fg);
+ WRXB(0x142, bg);
+ }
+ else
+ {
+ packedcolfg =
+ ((fg & 0xE00000) >> 16) |
+ ((fg & 0x00E000) >> 11) |
+ ((fg & 0x0000C0) >> 6);
+ packedcolbg =
+ ((bg & 0xE00000) >> 16) |
+ ((bg & 0x00E000) >> 11) |
+ ((bg & 0x0000C0) >> 6);
+ WaitForFifo(pApm, 2);
+ WRXB(0x141, packedcolfg);
+ WRXB(0x142, packedcolbg);
+ }
+}
+
+
+static void
+ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data)
+{
+ APMDECL(pScrn);
+ u32 i;
+ u8 tmp[2 * CURSORSIZE];
+
+ /* Correct input data */
+ for (i = 0; i < sizeof tmp; i++)
+ tmp[i] = ConvertTable[data[i]];
+ /*
+ * To avoid flicker.
+ * Note: 2*pApm->BaseCursorAddress + CURSORALIGN (=1024) < 2^31 all the time.
+ */
+ pApm->CursorAddress = 2*pApm->BaseCursorAddress + CURSORALIGN - pApm->DisplayedCursorAddress;
+ memcpy((u8*)pApm->FbBase + pApm->CursorAddress, tmp, sizeof tmp);
+}
diff --git a/src/apm_dga.c b/src/apm_dga.c
new file mode 100644
index 0000000..3a5f362
--- /dev/null
+++ b/src/apm_dga.c
@@ -0,0 +1,434 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_dga.c,v 1.10 2002/01/25 21:55:54 tsi Exp $ */
+/*
+ * file: apm_dga.c
+ * ported from s3virge, ported from mga
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "apm.h"
+#include "dgaproc.h"
+
+
+static Bool ApmOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool ApmSetMode(ScrnInfoPtr, DGAModePtr);
+static int ApmGetViewport(ScrnInfoPtr);
+static void ApmSetViewport(ScrnInfoPtr, int, int, int);
+static void ApmFillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void ApmBlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+static void ApmBlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+static void ApmSync(ScrnInfoPtr);
+
+static
+DGAFunctionRec ApmDGAFuncs = {
+ ApmOpenFramebuffer,
+ NULL,
+ ApmSetMode,
+ ApmSetViewport,
+ ApmGetViewport,
+ ApmSync,
+ ApmFillRect,
+ ApmBlitRect,
+ ApmBlitTransRect
+};
+
+/*
+ * Placeholder
+ */
+void
+ApmSync(ScrnInfoPtr pScrn)
+{
+}
+
+static __inline__ int FindSmallestPitch(ApmPtr pApm, int Bpp, int width)
+{
+ if (width <= 640)
+ return 640;
+ else if (width <= 800)
+ return 800;
+ else if (width <= 1024)
+ return 1024;
+ else if (width <= 1152)
+ return 1152;
+ else if (width <= 1280)
+ return 1280;
+ else if (width <= 1600)
+ return 1600;
+ return (width + 7) & ~7;
+}
+
+static DGAModePtr
+ApmSetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, int *num,
+ int bitsPerPixel, int depth, Bool pixmap, int secondPitch,
+ unsigned long red, unsigned long green, unsigned long blue,
+ short visualClass)
+{
+ DisplayModePtr firstMode, pMode;
+ APMDECL(pScrn);
+ DGAModePtr mode, newmodes;
+ int size, pitch, Bpp = bitsPerPixel >> 3;
+ Bool reduced_pitch = TRUE;
+
+SECOND_PASS:
+
+ firstMode = NULL;
+
+ for (pMode = pScrn->modes; pMode != firstMode; pMode = pMode->next) {
+
+ if (!firstMode)
+ firstMode = pMode;
+
+ if (reduced_pitch)
+ pitch = FindSmallestPitch(pApm, Bpp, pMode->HDisplay);
+ else
+ pitch = pMode->HDisplay;
+ if (!reduced_pitch && pitch == FindSmallestPitch(pApm, Bpp, pMode->HDisplay))
+ continue;
+
+ size = pitch * Bpp * pMode->VDisplay;
+
+ if((!secondPitch || (pitch != secondPitch)) &&
+ (size <= pScrn->videoRam * 1024 - pApm->OffscreenReserved)) {
+
+ if(secondPitch)
+ pitch = secondPitch;
+
+ if(!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec))))
+ break;
+
+ modes = newmodes;
+ mode = modes + *num;
+
+ mode->mode = pMode;
+ mode->flags = DGA_CONCURRENT_ACCESS;
+
+ if(pixmap)
+ mode->flags |= DGA_PIXMAP_AVAILABLE;
+ if(!pApm->NoAccel) {
+ mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+ if (Bpp != 3)
+ mode->flags |= DGA_BLIT_RECT_TRANS;
+ }
+ if(pMode->Flags & V_DBLSCAN)
+ mode->flags |= DGA_DOUBLESCAN;
+ if(pMode->Flags & V_INTERLACE)
+ mode->flags |= DGA_INTERLACED;
+ mode->byteOrder = pScrn->imageByteOrder;
+ mode->depth = depth;
+ mode->bitsPerPixel = bitsPerPixel;
+ mode->red_mask = red;
+ mode->green_mask = green;
+ mode->blue_mask = blue;
+ mode->visualClass = visualClass;
+ mode->viewportWidth = pMode->HDisplay;
+ mode->viewportHeight = pMode->VDisplay;
+ mode->xViewportStep = (bitsPerPixel == 24) ? 4 : 1;
+ mode->yViewportStep = 1;
+ mode->viewportFlags = DGA_FLIP_RETRACE;
+ mode->offset = 0;
+ mode->address = pApm->FbBase;
+ mode->bytesPerScanline = pitch * Bpp;
+ mode->imageWidth = pitch;
+ mode->imageHeight = (pScrn->videoRam * 1024 -
+ pApm->OffscreenReserved) / mode->bytesPerScanline;
+ mode->pixmapWidth = mode->imageWidth;
+ mode->pixmapHeight = mode->imageHeight;
+ mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
+ /* this might need to get clamped to some maximum */
+ mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
+
+ (*num)++;
+ }
+
+ }
+
+ if(secondPitch) {
+ secondPitch = 0;
+ goto SECOND_PASS;
+ }
+
+ if (reduced_pitch) {
+ reduced_pitch = FALSE;
+ goto SECOND_PASS;
+ }
+
+ return modes;
+}
+
+Bool
+ApmDGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ APMDECL(pScrn);
+ DGAModePtr modes = NULL;
+ int num = 0;
+
+ /* 8 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 8, 8,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
+ 0, 0, 0, PseudoColor);
+
+ /* 15 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
+ 0x7C00, 0x03E0, 0x001F, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
+ 0x7C00, 0x03E0, 0x001F, DirectColor);
+
+ /* 16 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
+ 0xF800, 0x07E0, 0x001F, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
+ 0xF800, 0x07E0, 0x001F, DirectColor);
+
+ /* 24 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
+ (pScrn->bitsPerPixel == 24),
+ (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
+ (pScrn->bitsPerPixel == 24),
+ (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
+
+ /* 32 */
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
+
+ modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
+ (pScrn->bitsPerPixel != 24),
+ (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
+ 0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
+
+ pApm->numDGAModes = num;
+ pApm->DGAModes = modes;
+
+ return DGAInit(pScreen, &ApmDGAFuncs, modes, num);
+}
+
+
+static Bool
+ApmSetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ int index = pScrn->pScreen->myNum;
+ APMDECL(pScrn);
+
+ if (!pMode) { /* restore the original mode */
+ if (pApm->DGAactive) {
+ memcpy(&pApm->CurrentLayout, &pApm->SavedLayout,
+ sizeof pApm->CurrentLayout);
+ pApm->DGAactive = FALSE;
+ }
+
+ pScrn->currentMode = pApm->CurrentLayout.pMode;
+ ApmSwitchMode(index, pScrn->currentMode, 0);
+ ApmAdjustFrame(index, pScrn->frameX0, pScrn->frameY0, 0);
+#if 0
+ if (pApm->AccelInfoRec)
+ XAAInit(pScrn->pScreen, pApm->AccelInfoRec);
+#endif
+ }
+ else {
+ if (!pApm->DGAactive) {
+ memcpy(&pApm->SavedLayout, &pApm->CurrentLayout,
+ sizeof pApm->CurrentLayout);
+ pApm->DGAactive = TRUE;
+ }
+
+ pApm->CurrentLayout.displayWidth = pMode->imageWidth;
+ pApm->CurrentLayout.displayHeight = pMode->imageHeight;
+ pApm->CurrentLayout.Scanlines = pMode->imageHeight + 1;
+ pApm->CurrentLayout.depth = pMode->depth;
+ pApm->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
+ pApm->CurrentLayout.bytesPerScanline = pMode->bytesPerScanline;
+ pApm->CurrentLayout.pMode = pMode->mode;
+ if (pMode->bitsPerPixel == 24)
+ pApm->CurrentLayout.mask32 = 3;
+ else
+ pApm->CurrentLayout.mask32 = 32 / pMode->bitsPerPixel - 1;
+
+ ApmSwitchMode(index, pMode->mode, 0);
+ ApmSetupXAAInfo(pApm, NULL);
+
+#if 0
+ if (pApm->DGAXAAInfo)
+ bzero(pApm->DGAXAAInfo, sizeof(*pApm->DGAXAAInfo));
+ else
+ pApm->DGAXAAInfo = XAACreateInfoRec();
+ ApmSetupXAAInfo(pApm, pApm->DGAXAAInfo);
+ /*
+ * Let's hope this won't fail, that is reinitialize XAA for this
+ * setup...
+ */
+ XAAInit(pScrn->pScreen, pApm->DGAXAAInfo);
+#endif
+ }
+
+ return TRUE;
+}
+
+
+
+static int
+ApmGetViewport(
+ ScrnInfoPtr pScrn
+)
+{
+ return 0;
+}
+
+static void
+ApmSetViewport(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int flags
+)
+{
+ unsigned char tmp;
+
+ APMDECL(pScrn);
+
+ if (pApm->apmLock) {
+ /*
+ * This is just an attempt, because Daryll is tampering with MY
+ * registers.
+ */
+ if (!pApm->noLinear) {
+ tmp = (RDXB(0xDB) & 0xF4) | 0x0A;
+ WRXB(0xDB, tmp);
+ ApmWriteSeq(0x1B, 0x20);
+ ApmWriteSeq(0x1C, 0x2F);
+ }
+ else {
+ tmp = (RDXB_IOP(0xDB) & 0xF4) | 0x0A;
+ WRXB_IOP(0xDB, tmp);
+ wrinx(pApm->xport, 0x1B, 0x20);
+ wrinx(pApm->xport, 0x1C, 0x2F);
+ }
+ pApm->apmLock = FALSE;
+ }
+ pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+ if (pApm->VGAMap) {
+ /* Wait until vertical retrace is in progress. */
+ while (APMVGAB(0x3DA) & 0x08);
+ while (!(APMVGAB(0x3DA) & 0x08));
+ }
+ else {
+ /* Wait until vertical retrace is in progress. */
+ while (inb(pApm->iobase + 0x3DA) & 0x08);
+ while (!(inb(pApm->iobase + 0x3DA) & 0x08));
+ }
+}
+
+static void
+ApmFillRect (
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ unsigned long color
+)
+{
+ APMDECL(pScrn);
+
+ if(pApm->CurrentLayout.depth != 24) {
+ (*pApm->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
+ (*pApm->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+ }
+ else {
+ (*pApm->SetupForSolidFill24)(pScrn, color, GXcopy, ~0);
+ (*pApm->SubsequentSolidFillRect24)(pScrn, x, y, w, h);
+ }
+ SET_SYNC_FLAG(pApm->AccelInfoRec);
+}
+
+static void
+ApmBlitRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+)
+{
+ APMDECL(pScrn);
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ if(pApm->CurrentLayout.depth != 24) {
+ (*pApm->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*pApm->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ }
+ else {
+ (*pApm->SetupForScreenToScreenCopy24)(
+ pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*pApm->SubsequentScreenToScreenCopy24)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ }
+ SET_SYNC_FLAG(pApm->AccelInfoRec);
+}
+
+static void
+ApmBlitTransRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+)
+{
+ APMDECL(pScrn);
+
+ if(pApm->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pApm->AccelInfoRec->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, ~0, (int)color);
+ (*pApm->AccelInfoRec->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ SET_SYNC_FLAG(pApm->AccelInfoRec);
+ }
+}
+
+static Bool
+ApmOpenFramebuffer(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+)
+{
+ APMDECL(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)(pApm->LinAddress +
+ 0*((char *)pApm->FbBase - (char *)pApm->LinMap));
+ *size = pScrn->videoRam << 10;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ return TRUE;
+}
diff --git a/src/apm_driver.c b/src/apm_driver.c
new file mode 100644
index 0000000..dd877d3
--- /dev/null
+++ b/src/apm_driver.c
@@ -0,0 +1,2371 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_driver.c,v 1.61 2002/10/16 21:13:46 dawes Exp $ */
+
+#include "apm.h"
+#include "xf86cmap.h"
+#include "shadowfb.h"
+#include "xf86Resources.h"
+#include "xf86int10.h"
+#include "xf86RAC.h"
+#include "vbe.h"
+
+#include "opaque.h"
+#define DPMS_SERVER
+#include "extensions/dpms.h"
+
+#define VERSION 4000
+#define APM_NAME "APM"
+#define APM_DRIVER_NAME "apm"
+#define APM_MAJOR_VERSION 1
+#define APM_MINOR_VERSION 0
+#define APM_PATCHLEVEL 0
+#ifndef PCI_CHIP_AT3D
+#define PCI_CHIP_AT3D 0x643D
+#endif
+
+/* bytes to save for text/font data */
+#define TEXT_AMOUNT 32768
+
+/* Mandatory functions */
+static const OptionInfoRec * ApmAvailableOptions(int chipid, int busid);
+static void ApmIdentify(int flags);
+static Bool ApmProbe(DriverPtr drv, int flags);
+static Bool ApmPreInit(ScrnInfoPtr pScrn, int flags);
+static Bool ApmScreenInit(int Index, ScreenPtr pScreen, int argc,
+ char **argv);
+static Bool ApmEnterVT(int scrnIndex, int flags);
+static void ApmLeaveVT(int scrnIndex, int flags);
+static Bool ApmCloseScreen(int scrnIndex, ScreenPtr pScreen);
+static void ApmFreeScreen(int scrnIndex, int flags);
+static int ApmValidMode(int scrnIndex, DisplayModePtr mode,
+ Bool verbose, int flags);
+static Bool ApmSaveScreen(ScreenPtr pScreen, int mode);
+static void ApmUnlock(ApmPtr pApm);
+static void ApmLock(ApmPtr pApm);
+static void ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg,
+ ApmRegPtr ApmReg);
+static void ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO *colors, VisualPtr pVisual);
+static void ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode,
+ int flags);
+static void ApmProbeDDC(ScrnInfoPtr pScrn, int index);
+
+
+int ApmPixmapIndex = -1;
+static unsigned long ApmGeneration = 0;
+
+DriverRec APM = {
+ VERSION,
+ APM_DRIVER_NAME,
+ ApmIdentify,
+ ApmProbe,
+ ApmAvailableOptions,
+ NULL,
+ 0
+};
+
+static SymTabRec ApmChipsets[] = {
+ { AP6422, "AP6422" },
+ { AT24, "AT24" },
+ { AT3D, "AT3D" },
+ { -1, NULL }
+};
+
+static PciChipsets ApmPciChipsets[] = {
+ { PCI_CHIP_AP6422, PCI_CHIP_AP6422, RES_SHARED_VGA },
+ { PCI_CHIP_AT24, PCI_CHIP_AT24, RES_SHARED_VGA },
+ { PCI_CHIP_AT3D, PCI_CHIP_AT3D, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED }
+};
+
+static IsaChipsets ApmIsaChipsets[] = {
+ { PCI_CHIP_AP6422, RES_EXCLUSIVE_VGA},
+ {-1, RES_UNDEFINED}
+};
+
+typedef enum {
+ OPTION_SET_MCLK,
+ OPTION_SW_CURSOR,
+ OPTION_HW_CURSOR,
+ OPTION_NOLINEAR,
+ OPTION_NOACCEL,
+ OPTION_SHADOW_FB,
+ OPTION_PCI_BURST,
+ OPTION_REMAP_DPMS_ON,
+ OPTION_REMAP_DPMS_STANDBY,
+ OPTION_REMAP_DPMS_SUSPEND,
+ OPTION_REMAP_DPMS_OFF,
+ OPTION_PCI_RETRY
+} ApmOpts;
+
+static const OptionInfoRec ApmOptions[] =
+{
+ {OPTION_SET_MCLK, "SetMclk", OPTV_FREQ,
+ {0}, FALSE},
+ {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN,
+ {0}, FALSE},
+ {OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN,
+ {0}, TRUE},
+ {OPTION_NOLINEAR, "NoLinear", OPTV_BOOLEAN,
+ {0}, FALSE},
+ {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN,
+ {0}, FALSE},
+ {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN,
+ {0}, FALSE},
+ {OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN,
+ {0}, FALSE},
+ {OPTION_REMAP_DPMS_ON, "Remap_DPMS_On", OPTV_ANYSTR,
+ {0}, FALSE},
+ {OPTION_REMAP_DPMS_STANDBY, "Remap_DPMS_Standby", OPTV_ANYSTR,
+ {0}, FALSE},
+ {OPTION_REMAP_DPMS_SUSPEND, "Remap_DPMS_Suspend", OPTV_ANYSTR,
+ {0}, FALSE},
+ {OPTION_REMAP_DPMS_OFF, "Remap_DPMS_Off", OPTV_ANYSTR,
+ {0}, FALSE},
+ {OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN,
+ {0}, FALSE},
+ {-1, NULL, OPTV_NONE,
+ {0}, FALSE}
+};
+
+/*
+ * List of symbols from other modules that this module references. This
+ * list is used to tell the loader that it is OK for symbols here to be
+ * unresolved providing that it hasn't been told that they haven't been
+ * told that they are essential via a call to xf86LoaderReqSymbols() or
+ * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
+ * unresolved symbols that are not required.
+ */
+
+static const char *vgahwSymbols[] = {
+ "vgaHWBlankScreen",
+ "vgaHWCursor",
+ "vgaHWFreeHWRec",
+ "vgaHWGetHWRec",
+ "vgaHWGetIOBase",
+ "vgaHWInit",
+ "vgaHWLock",
+ "vgaHWMapMem",
+ "vgaHWProtect",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWSetMmioFuncs",
+ "vgaHWUnlock",
+ NULL
+};
+
+static const char *xaaSymbols[] = {
+ "XAACreateInfoRec",
+ "XAACursorInfoRec",
+ "XAACursorInit",
+ "XAADestroyInfoRec",
+ "XAAGlyphScanlineFuncLSBFirst",
+ "XAAInit",
+ "XAAQueryBestSize",
+ "XAAReverseBitOrder",
+ "XAARestoreCursor",
+ "XAAScreenIndex",
+ "XAAStippleScanlineFuncMSBFirst",
+ "XAAWarpCursor",
+ NULL
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+static const char *ddcSymbols[] = {
+ "xf86DoEDID_DDC1",
+ "xf86DoEDID_DDC2",
+ "xf86PrintEDID",
+ NULL
+};
+
+static const char *i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ NULL
+};
+
+static const char *shadowSymbols[] = {
+ "ShadowFBInit",
+ NULL
+};
+
+static const char *miscfbSymbols[] = {
+ "xf1bppScreenInit",
+ "xf4bppScreenInit",
+ NULL
+};
+
+static const char *fbSymbols[] = {
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+static const char *int10Symbols[] = {
+ "xf86Free10",
+ "xf86InitInt10",
+ NULL
+};
+
+#ifdef XFree86LOADER
+
+static XF86ModuleVersionInfo apmVersRec = {
+ "apm",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ APM_MAJOR_VERSION, APM_MINOR_VERSION, APM_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV, /* This is a video driver */
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0,0,0,0}
+};
+
+static MODULESETUPPROTO(apmSetup);
+
+/*
+ * This is the module init data.
+ * Its name has to be the driver name followed by ModuleData.
+ */
+XF86ModuleData apmModuleData = { &apmVersRec, apmSetup, NULL };
+
+static pointer
+apmSetup(pointer module, pointer opts, int *errmaj, int *errmain)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&APM, module, 0);
+
+ LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
+ miscfbSymbols, ramdacSymbols, vbeSymbols,
+ ddcSymbols, i2cSymbols, shadowSymbols,
+ int10Symbols, NULL);
+
+ return (pointer)1;
+ }
+ else {
+ if (errmaj) *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+#endif
+
+static Bool
+ApmGetRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate)
+ return TRUE;
+ pScrn->driverPrivate = xnfcalloc(sizeof(ApmRec), 1);
+ /* pScrn->driverPrivate != NULL at this point */
+
+ return TRUE;
+}
+
+static void
+ApmFreeRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate) {
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+ }
+}
+
+
+/* unlock Alliance registers */
+static void
+ApmUnlock(ApmPtr pApm)
+{
+ if (pApm->Chipset >= AT3D && !pApm->noLinear)
+ ApmWriteSeq(0x10, 0x12);
+ else
+ wrinx(pApm->xport, 0x10, 0x12);
+}
+
+/* lock Alliance registers */
+static void
+ApmLock(ApmPtr pApm)
+{
+ if (pApm->Chipset >= AT3D && !pApm->noLinear)
+ ApmWriteSeq(0x10, pApm->savedSR10 ? 0 : 0x12);
+ else
+ wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12);
+}
+
+static void
+ApmIdentify(int flags)
+{
+ xf86PrintChipsets(APM_NAME, "driver for the Alliance chipsets",
+ ApmChipsets);
+}
+
+static const OptionInfoRec *
+ApmAvailableOptions(int chipid, int busid)
+{
+ return ApmOptions;
+}
+
+static int
+ApmFindIsaDevice(GDevPtr dev)
+{
+ char save = rdinx(0x3C4, 0x10);
+ int i;
+ int apmChip = -1;
+
+ /*
+ * Start by probing the VGA chipset.
+ */
+ outw(0x3C4, 0x1210);
+ if (rdinx(0x3C4, 0x11) == 'P' && rdinx(0x3C4, 0x12) == 'r' &&
+ rdinx(0x3C4, 0x13) == 'o') {
+ char id_ap6420[] = "6420";
+ char id_ap6422[] = "6422";
+ char id_at24[] = "6424";
+ char id_at3d[] = "AT3D";
+ char idstring[] = " ";
+
+ /*
+ * Must be an Alliance !!!
+ */
+ for (i = 0; i < 4; i++)
+ idstring[i] = rdinx(0x3C4, 0x14 + i);
+ if (!memcmp(id_ap6420, idstring, 4) ||
+ !memcmp(id_ap6422, idstring, 4))
+ apmChip = AP6422;
+ else if (!memcmp(id_at24, idstring, 4))
+ apmChip = AT24;
+ else if (!memcmp(id_at3d, idstring, 4))
+ apmChip = AT3D;
+ if (apmChip >= 0) {
+ int apm_xbase;
+
+ apm_xbase = (rdinx(0x3C4, 0x1F) << 8) | rdinx(0x3C4, 0x1E);
+
+ if (!(wrinx(0x3C4, 0x1D, 0xCA >> 2), inb(apm_xbase + 2))) {
+ /*
+ * TODO Not PCI
+ */
+ }
+
+ }
+ }
+ wrinx(0x3C4, 0x10, save);
+
+ return apmChip;
+}
+
+static void
+ApmAssignFPtr(ScrnInfoPtr pScrn)
+{
+ pScrn->driverVersion = VERSION;
+ pScrn->driverName = APM_DRIVER_NAME;
+ pScrn->name = APM_NAME;
+ pScrn->Probe = ApmProbe;
+ pScrn->PreInit = ApmPreInit;
+ pScrn->ScreenInit = ApmScreenInit;
+ pScrn->SwitchMode = ApmSwitchMode;
+ pScrn->AdjustFrame = ApmAdjustFrame;
+ pScrn->EnterVT = ApmEnterVT;
+ pScrn->LeaveVT = ApmLeaveVT;
+ pScrn->FreeScreen = ApmFreeScreen;
+ pScrn->ValidMode = ApmValidMode;
+}
+
+static Bool
+ApmProbe(DriverPtr drv, int flags)
+{
+ int numDevSections, numUsed, i;
+ GDevPtr *DevSections;
+ int *usedChips;
+ int foundScreen = FALSE;
+
+ /*
+ * Check if there is a chipset override in the config file
+ */
+ if ((numDevSections = xf86MatchDevice(APM_DRIVER_NAME,
+ &DevSections)) <= 0)
+ return FALSE;
+
+ /*
+ * We need to probe the hardware first. We then need to see how this
+ * fits in with what is given in the config file, and allow the config
+ * file info to override any contradictions.
+ */
+
+ if (xf86GetPciVideoInfo() == NULL) {
+ return FALSE;
+ }
+ numUsed = xf86MatchPciInstances(APM_NAME, PCI_VENDOR_ALLIANCE,
+ ApmChipsets, ApmPciChipsets, DevSections, numDevSections,
+ drv, &usedChips);
+
+ if (numUsed > 0) {
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i = 0; i < numUsed; i++) {
+ ScrnInfoPtr pScrn;
+
+ /*
+ * Allocate a ScrnInfoRec and claim the slot
+ */
+ pScrn = NULL;
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ ApmPciChipsets, NULL,
+ NULL,NULL,NULL,NULL))){
+
+ /*
+ * Fill in what we can of the ScrnInfoRec
+ */
+ ApmAssignFPtr(pScrn);
+ foundScreen = TRUE;
+ }
+ }
+ }
+
+ /* Check for non-PCI cards */
+ numUsed = xf86MatchIsaInstances(APM_NAME, ApmChipsets,
+ ApmIsaChipsets, drv, ApmFindIsaDevice, DevSections,
+ numDevSections, &usedChips);
+ if (numUsed > 0) {
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i = 0; i < numUsed; i++) {
+ ScrnInfoPtr pScrn = NULL;
+ if ((pScrn = xf86ConfigIsaEntity(pScrn, 0, usedChips[i],
+ ApmIsaChipsets, NULL, NULL, NULL,
+ NULL, NULL))) {
+ /*
+ * Fill in what we can of the ScrnInfoRec
+ */
+ ApmAssignFPtr(pScrn);
+ foundScreen = TRUE;
+ }
+ }
+ }
+ xfree(DevSections);
+ return foundScreen;
+}
+
+/*
+ * GetAccelPitchValues -
+ *
+ * This function returns a list of display width (pitch) values that can
+ * be used in accelerated mode.
+ */
+static int *
+GetAccelPitchValues(ScrnInfoPtr pScrn)
+{
+ int *linePitches = NULL;
+ int linep[] = {640, 800, 1024, 1152, 1280, 1600, 0};
+
+ if (sizeof linep > 0) {
+ linePitches = (int *)xnfalloc(sizeof linep);
+ memcpy(linePitches, linep, sizeof linep);
+ }
+
+ return linePitches;
+}
+
+static unsigned int
+ddc1Read(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+ unsigned char tmp;
+
+ tmp = RDXB_IOP(0xD0);
+ WRXB_IOP(0xD0, tmp & 0x07);
+ while (STATUS_IOP() & 0x800);
+ while (!(STATUS_IOP() & 0x800));
+ return (STATUS_IOP() & STATUS_SDA) != 0;
+}
+
+static void
+ApmProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL, index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+static Bool
+ApmPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ APMDECL(pScrn);
+ EntityInfoPtr pEnt;
+ vgaHWPtr hwp;
+ MessageType from;
+ char *mod = NULL, *req = NULL, *s;
+ ClockRangePtr clockRanges;
+ int i;
+ xf86MonPtr MonInfo = NULL;
+ double real;
+
+ /*
+ * Note: This function is only called once at server startup, and
+ * not at the start of each server generation. This means that
+ * only things that are persistent across server generations can
+ * be initialised here. xf86Screens[] is (pScrn is a pointer to one
+ * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex()
+ * are too, and should be used for data that must persist across
+ * server generations.
+ *
+ * Per-generation data should be allocated with
+ * AllocateScreenPrivateIndex() from the ScreenInit() function.
+ */
+
+ /* Check the number of entities, and fail if it isn't one. */
+ if (pScrn->numEntities != 1)
+ return FALSE;
+
+ /* Allocate the ApmRec driverPrivate */
+ if (!ApmGetRec(pScrn)) {
+ return FALSE;
+ }
+ pApm = APMPTR(pScrn);
+
+ /* Get the entity */
+ pEnt = pApm->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (pEnt->location.type == BUS_PCI) {
+ pApm->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
+ pApm->PciTag = pciTag(pApm->PciInfo->bus, pApm->PciInfo->device,
+ pApm->PciInfo->func);
+ }
+ else {
+ pApm->PciInfo = NULL;
+ pApm->PciTag = 0;
+ }
+
+ if (flags & PROBE_DETECT) {
+ ApmProbeDDC(pScrn, pEnt->index);
+ return TRUE;
+ }
+
+ /* The vgahw module should be allocated here when needed */
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ return FALSE;
+
+ xf86LoaderReqSymLists(vgahwSymbols, NULL);
+
+ /*
+ * Allocate a vgaHWRec
+ */
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+
+ hwp = VGAHWPTR(pScrn);
+ vgaHWGetIOBase(hwp);
+ pApm->iobase = hwp->PIOOffset;
+ pApm->xport = hwp->PIOOffset + 0x3C4;
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ /* XXX: Access funcs */
+ /*
+ * The first thing we should figure out is the depth, bpp, etc.
+ */
+ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) {
+ return FALSE;
+ } else {
+ /* Check that the returned depth is one we support */
+ switch (pScrn->depth) {
+ case 4:
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ /* OK */
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ /*
+ * This must happen after pScrn->display has been set because
+ * xf86SetWeight references it.
+ */
+ if (pScrn->depth > 8) {
+ /* The defaults are OK for us */
+ rgb zeros = {0, 0, 0};
+
+ if (!xf86SetWeight(pScrn, zeros, zeros)) {
+ return FALSE;
+ } else {
+ /* XXX check that weight returned is supported */
+ ;
+ }
+ }
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) {
+ return FALSE;
+ } else {
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /* We use a programmable clock */
+ pScrn->progClock = TRUE;
+
+ /* Collect all of the relevant option flags (fill in pScrn->options) */
+ xf86CollectOptions(pScrn, NULL);
+
+ /* Process the options */
+ if (!(pApm->Options = xalloc(sizeof(ApmOptions))))
+ return FALSE;
+ memcpy(pApm->Options, ApmOptions, sizeof(ApmOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pApm->Options);
+
+ pApm->scrnIndex = pScrn->scrnIndex;
+ /* Set the bits per RGB for 8bpp mode */
+ if (pScrn->depth > 1 && pScrn->depth <= 8) {
+ /* Default to 8 */
+ pScrn->rgbBits = 8;
+ }
+ if (xf86ReturnOptValBool(pApm->Options, OPTION_NOLINEAR, FALSE)) {
+ pApm->noLinear = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "No linear framebuffer\n");
+ }
+ from = X_DEFAULT;
+ pApm->hwCursor = FALSE;
+ if (xf86GetOptValBool(pApm->Options, OPTION_HW_CURSOR, &pApm->hwCursor))
+ from = X_CONFIG;
+ if (pApm->noLinear ||
+ xf86ReturnOptValBool(pApm->Options, OPTION_SW_CURSOR, FALSE)) {
+ from = X_CONFIG;
+ pApm->hwCursor = FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
+ pApm->hwCursor ? "HW" : "SW");
+ from = X_DEFAULT;
+ if (pScrn->bitsPerPixel < 8)
+ pApm->NoAccel = TRUE;
+ if (xf86ReturnOptValBool(pApm->Options, OPTION_NOACCEL, FALSE)) {
+ from = X_CONFIG;
+ pApm->NoAccel = TRUE;
+ }
+ if (pApm->NoAccel)
+ xf86DrvMsg(pScrn->scrnIndex, from, "Acceleration disabled\n");
+ if (xf86GetOptValFreq(pApm->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MCLK used is %.1f MHz\n", real);
+ pApm->MemClk = (int)(real * 1000.0);
+ }
+ if (xf86ReturnOptValBool(pApm->Options, OPTION_SHADOW_FB, FALSE)) {
+ pApm->ShadowFB = TRUE;
+ pApm->NoAccel = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using \"Shadow Framebuffer\" - acceleration disabled\n");
+ }
+ if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_RETRY, FALSE)) {
+ if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_BURST, FALSE)) {
+ pApm->UsePCIRetry = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
+ }
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires pci_burst \"on\".\n");
+ }
+ pApm->DPMSMask[DPMSModeOn] = DPMSModeOn;
+ pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby;
+ pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend;
+ pApm->DPMSMask[DPMSModeOff] = DPMSModeOff;
+ if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_ON))) {
+ if (!strcmp(s, "on"))
+ pApm->DPMSMask[DPMSModeOn] = DPMSModeOn;
+ else if (!strcmp(s, "standby"))
+ pApm->DPMSMask[DPMSModeOn] = DPMSModeStandby;
+ else if (!strcmp(s, "suspend"))
+ pApm->DPMSMask[DPMSModeOn] = DPMSModeSuspend;
+ else if (!strcmp(s, "off"))
+ pApm->DPMSMask[DPMSModeOn] = DPMSModeOff;
+ else if (s[0] >= '0' && s[0] <= '9') {
+ pApm->DPMSMask[DPMSModeOn] = strtol(s, NULL, 0);
+ if (pApm->DPMSMask[DPMSModeOn] > (sizeof pApm->DPMSMask)-1)
+ pApm->DPMSMask[DPMSModeOn] = (sizeof pApm->DPMSMask) - 1;
+ }
+ }
+ if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_STANDBY))) {
+ if (!strcmp(s, "on"))
+ pApm->DPMSMask[DPMSModeStandby] = DPMSModeOn;
+ else if (!strcmp(s, "standby"))
+ pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby;
+ else if (!strcmp(s, "suspend"))
+ pApm->DPMSMask[DPMSModeStandby] = DPMSModeSuspend;
+ else if (!strcmp(s, "off"))
+ pApm->DPMSMask[DPMSModeStandby] = DPMSModeOff;
+ else if (s[0] >= '0' && s[0] <= '9') {
+ pApm->DPMSMask[DPMSModeStandby] = strtol(s, NULL, 0);
+ if (pApm->DPMSMask[DPMSModeStandby] > (sizeof pApm->DPMSMask)-1)
+ pApm->DPMSMask[DPMSModeStandby] = (sizeof pApm->DPMSMask) - 1;
+ }
+ }
+ if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_SUSPEND))) {
+ if (!strcmp(s, "on"))
+ pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOn;
+ else if (!strcmp(s, "standby"))
+ pApm->DPMSMask[DPMSModeSuspend] = DPMSModeStandby;
+ else if (!strcmp(s, "suspend"))
+ pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend;
+ else if (!strcmp(s, "off"))
+ pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOff;
+ else if (s[0] >= '0' && s[0] <= '9') {
+ pApm->DPMSMask[DPMSModeSuspend] = strtol(s, NULL, 0);
+ if (pApm->DPMSMask[DPMSModeSuspend] > (sizeof pApm->DPMSMask)-1)
+ pApm->DPMSMask[DPMSModeSuspend] = (sizeof pApm->DPMSMask) - 1;
+ }
+ }
+ if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_OFF))) {
+ if (!strcmp(s, "on"))
+ pApm->DPMSMask[DPMSModeOff] = DPMSModeOn;
+ else if (!strcmp(s, "standby"))
+ pApm->DPMSMask[DPMSModeOff] = DPMSModeStandby;
+ else if (!strcmp(s, "suspend"))
+ pApm->DPMSMask[DPMSModeOff] = DPMSModeSuspend;
+ else if (!strcmp(s, "off"))
+ pApm->DPMSMask[DPMSModeOff] = DPMSModeOff;
+ else if (s[0] >= '0' && s[0] <= '9') {
+ pApm->DPMSMask[DPMSModeOff] = strtol(s, NULL, 0);
+ if (pApm->DPMSMask[DPMSModeOff] > (sizeof pApm->DPMSMask)-1)
+ pApm->DPMSMask[DPMSModeOff] = (sizeof pApm->DPMSMask) - 1;
+ }
+ }
+
+ /*
+ * Set the Chipset and ChipRev, allowing config file entries to
+ * override.
+ */
+ if (pEnt->device->chipset && *pEnt->device->chipset) {
+ pScrn->chipset = pEnt->device->chipset;
+ pApm->Chipset = xf86StringToToken(ApmChipsets, pScrn->chipset);
+ from = X_CONFIG;
+ } else if (pEnt->device->chipID >= 0) {
+ pApm->Chipset = pEnt->device->chipID;
+ pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset);
+
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ pApm->Chipset);
+ } else {
+ from = X_PROBED;
+ if (pApm->PciInfo)
+ pApm->Chipset = pApm->PciInfo->chipType;
+ else
+ pApm->Chipset = pEnt->chipset;
+ pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset);
+ }
+ if (pScrn->bitsPerPixel == 24 && pApm->Chipset < AT24) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ if (pEnt->device->chipRev >= 0) {
+ pApm->ChipRev = pEnt->device->chipRev;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ pApm->ChipRev);
+ } else if (pApm->PciInfo) {
+ pApm->ChipRev = pApm->PciInfo->chipRev;
+ }
+
+ /*
+ * This shouldn't happen because such problems should be caught in
+ * ApmProbe(), but check it just in case.
+ */
+ if (pScrn->chipset == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ChipID 0x%04X is not recognised\n", pApm->Chipset);
+ return FALSE;
+ }
+ if (pApm->Chipset < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Chipset \"%s\" is not recognised\n", pScrn->chipset);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
+
+ if (pEnt->device->MemBase != 0) {
+ pApm->LinAddress = pEnt->device->MemBase;
+ from = X_CONFIG;
+ } else if (pApm->PciInfo) {
+ pApm->LinAddress = pApm->PciInfo->memBase[0] & 0xFF800000;
+ from = X_PROBED;
+ } else {
+ /*
+ * VESA local bus.
+ * Pray that 2048MB works.
+ */
+ pApm->LinAddress = 0x80000000;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ (unsigned long)pApm->LinAddress);
+
+ if (xf86LoadSubModule(pScrn, "ddc")) {
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+ if (xf86LoadSubModule(pScrn, "i2c")) {
+ xf86LoaderReqSymLists(i2cSymbols, NULL);
+ pApm->I2C = TRUE;
+ }
+ }
+
+ if (pApm->noLinear) {
+ /*
+ * TODO not AT3D.
+ * XXX ICI XXX
+ */
+ pApm->LinMapSize = 4 * 1024 * 1024 /* 0x10000 */;
+ pApm->FbMapSize = 4 * 1024 * 1024 /* 0x10000 */;
+ if (pApm->Chipset >= AT3D)
+ pApm->LinAddress += 8 * 1024 * 1024 /* 0xA0000 */;
+ }
+ else {
+ if (pApm->Chipset >= AT3D)
+ pApm->LinMapSize = 16 * 1024 * 1024;
+ else
+ pApm->LinMapSize = 6 * 1024 * 1024;
+ pApm->FbMapSize = 4 * 1024 * 1024;
+ }
+
+ if (xf86LoadSubModule(pScrn, "int10")) {
+ void *ptr;
+
+ xf86LoaderReqSymLists(int10Symbols, NULL);
+ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
+ ptr = xf86InitInt10(pEnt->index);
+ if (ptr)
+ xf86FreeInt10(ptr);
+ }
+
+ xf86RegisterResources(pEnt->index, NULL, ResNone);
+ xf86SetOperatingState(resVga, pEnt->index, ResDisableOpr);
+ pScrn->racMemFlags = 0; /* For noLinear, access to 0xA0000 */
+ if (pApm->VGAMap)
+ pScrn->racIoFlags = 0;
+ else
+ pScrn->racIoFlags = RAC_COLORMAP | RAC_VIEWPORT;
+
+ if (pEnt->device->videoRam != 0) {
+ pScrn->videoRam = pEnt->device->videoRam;
+ from = X_CONFIG;
+ } else if (!pApm->noLinear && pApm->Chipset >= AT3D) {
+ unsigned char d9, db, uc;
+ /*unsigned long save;*/
+ volatile unsigned char *LinMap;
+
+ LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
+ pApm->PciTag, pApm->LinAddress,
+ pApm->LinMapSize);
+ /*save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG);
+ pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_MEM_ENABLE);*/
+ d9 = LinMap[0xFFECD9];
+ db = LinMap[0xFFECDB];
+ LinMap[0xFFECDB] = (db & 0xF4) | 0x0A;
+ LinMap[0xFFECD9] = (d9 & 0xCF) | 0x20;
+ LinMap[0xFFF3C4] = 0x1C;
+ uc = LinMap[0xFFF3C5];
+ LinMap[0xFFF3C5] = 0x3F;
+ LinMap[0xFFF3C4] = 0x20;
+ pScrn->videoRam = LinMap[0xFFF3C5] * 64;
+ LinMap[0xFFF3C4] = 0x10;
+ pApm->savedSR10 = LinMap[0xFFF3C5];
+ LinMap[0xFFF3C4] = 0x1E;
+ pApm->xbase = LinMap[0xFFF3C5];
+ LinMap[0xFFF3C4] = 0x1F;
+ pApm->xbase |= LinMap[0xFFF3C5] << 8;
+ LinMap[0xFFF3C4] = 0x1C;
+ LinMap[0xFFF3C5] = uc;
+ LinMap[0xFFECDB] = db;
+ LinMap[0xFFECD9] = d9;
+ /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)LinMap, pApm->LinMapSize);
+ from = X_PROBED;
+ }
+ else {
+ /*unsigned long save;
+
+ save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG);
+ pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_IO_ENABLE);*/
+ pApm->savedSR10 = rdinx(pApm->xport, 0x10);
+ wrinx(pApm->xport, 0x10, 0x12);
+ pScrn->videoRam = rdinx(pApm->xport, 0x20) * 64;
+ pApm->xbase = rdinx(pApm->xport, 0x1F) << 8;
+ pApm->xbase |= rdinx(pApm->xport, 0x1E);
+ pApm->xbase += pApm->iobase;
+ wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12);
+ /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/
+ from = X_PROBED;
+ }
+ if (pApm->Chipset < AT3D && pScrn->videoRam >= 4096)
+ pScrn->videoRam -= 32;
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
+ pScrn->videoRam);
+
+ if (!xf86IsPc98()) {
+ hwp->MapSize = 0x10000;
+ vgaHWMapMem(pScrn);
+ if (pApm->I2C) {
+ if (!ApmI2CInit(pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n");
+ }
+ else {
+ MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pApm->I2CPtr);
+ }
+ }
+ if (0 && !MonInfo)
+ MonInfo = xf86DoEDID_DDC1(pScrn->scrnIndex,vgaHWddc1SetSpeed,ddc1Read);
+ if (MonInfo)
+ xf86PrintEDID(MonInfo);
+ pScrn->monitor->DDC = MonInfo;
+ }
+
+ /* The gamma fields must be initialised when using the new cmap code */
+ if (pScrn->depth > 1) {
+ Gamma zeros = {0.0, 0.0, 0.0};
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ return FALSE;
+ }
+ }
+
+ pApm->MinClock = 23125;
+ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock set to %d MHz\n",
+ pApm->MinClock / 1000);
+
+ /*
+ * If the user has specified ramdac speed in the XF86Config
+ * file, we respect that setting.
+ */
+ from = X_DEFAULT;
+ if (pEnt->device->dacSpeeds[0]) {
+ int speed = 0;
+
+ switch (pScrn->bitsPerPixel) {
+ case 4:
+ case 8:
+ speed = pEnt->device->dacSpeeds[DAC_BPP8];
+ break;
+ case 16:
+ speed = pEnt->device->dacSpeeds[DAC_BPP16];
+ break;
+ case 24:
+ speed = pEnt->device->dacSpeeds[DAC_BPP24];
+ break;
+ case 32:
+ speed = pEnt->device->dacSpeeds[DAC_BPP32];
+ break;
+ }
+ if (speed == 0)
+ pApm->MaxClock = pEnt->device->dacSpeeds[0];
+ else
+ pApm->MaxClock = speed;
+ from = X_CONFIG;
+ } else {
+ switch(pApm->Chipset)
+ {
+ /* These values come from the Manual for AT24 and AT3D
+ in the overview of various modes. I've taken the largest
+ number for the different modes. Alliance wouldn't
+ tell me what the maximum frequency was, so...
+ */
+ case AT24:
+ switch(pScrn->bitsPerPixel)
+ {
+ case 4:
+ case 8:
+ pApm->MaxClock = 160000;
+ break;
+ case 16:
+ pApm->MaxClock = 144000;
+ break;
+ case 24:
+ pApm->MaxClock = 75000; /* Hmm. */
+ break;
+ case 32:
+ pApm->MaxClock = 94500;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case AT3D:
+ switch(pScrn->bitsPerPixel)
+ {
+ case 4:
+ case 8:
+ pApm->MaxClock = 175500;
+ break;
+ case 16:
+ pApm->MaxClock = 144000;
+ break;
+ case 24:
+ pApm->MaxClock = 94000; /* Changed from 75000 by Grenié */
+ break;
+ case 32:
+ pApm->MaxClock = 94500;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case AP6422:
+ switch(pScrn->bitsPerPixel)
+ {
+ case 4:
+ case 8:
+ pApm->MaxClock = 135000;
+ break;
+ case 16:
+ pApm->MaxClock = 75000;
+ break;
+ case 32:
+ pApm->MaxClock = 60000;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ default:
+ pApm->MaxClock = 135000;
+ break;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
+ pApm->MaxClock / 1000);
+
+ /*
+ * Setup the ClockRanges, which describe what clock ranges are available,
+ * and what sort of modes they can be used for.
+ */
+ clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1);
+ clockRanges->next = NULL;
+ clockRanges->minClock = pApm->MinClock;
+ clockRanges->maxClock = pApm->MaxClock;
+ clockRanges->clockIndex = -1; /* programmable */
+ clockRanges->interlaceAllowed = FALSE; /* XXX change this */
+ clockRanges->doubleScanAllowed = FALSE; /* XXX check this */
+
+ /* Select valid modes from those available */
+ if (pApm->NoAccel) {
+ /*
+ * XXX Assuming min pitch 256, max 2048
+ * XXX Assuming min height 128, max 2048
+ */
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+ NULL, 256, 2048,
+ pScrn->bitsPerPixel, 128, 2048,
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ pApm->FbMapSize,
+ LOOKUP_BEST_REFRESH);
+ } else {
+ /*
+ * XXX Assuming min height 128, max 2048
+ */
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+ GetAccelPitchValues(pScrn), 0, 0,
+ pScrn->bitsPerPixel, 128, 2048,
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ pApm->FbMapSize,
+ LOOKUP_BEST_REFRESH);
+ }
+
+ if (i == -1) {
+ ApmFreeRec(pScrn);
+ return FALSE;
+ }
+
+ /* Prune the modes marked as invalid */
+ xf86PruneDriverModes(pScrn);
+
+ if (i == 0 || pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ ApmFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+ /* Set the current mode to the first in the list */
+ pScrn->currentMode = pScrn->modes;
+
+ /* Print the list of modes being used */
+ xf86PrintModes(pScrn);
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* Load bpp-specific modules */
+ switch (pScrn->bitsPerPixel) {
+ case 1:
+ mod = "xf1bpp";
+ req = "xf1bppScreenInit";
+ break;
+ case 4:
+ mod = "xf4bpp";
+ req = "xf4bppScreenInit";
+ break;
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ mod = "fb";
+ break;
+ }
+
+ if (mod && xf86LoadSubModule(pScrn, mod) == NULL) {
+ ApmFreeRec(pScrn);
+ return FALSE;
+ }
+
+ if (mod) {
+ if (req) {
+ xf86LoaderReqSymbols(req, NULL);
+ } else {
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+ }
+ }
+
+ /* Load XAA if needed */
+ if (!pApm->NoAccel) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ ApmFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+
+ /* Load ramdac if needed */
+ if (pApm->hwCursor) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ ApmFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+ /* Load shadowfb if needed */
+ if (pApm->ShadowFB) {
+ if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ ApmFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(shadowSymbols, NULL);
+ }
+
+ pApm->CurrentLayout.displayWidth = pScrn->virtualX;
+ pApm->CurrentLayout.displayHeight = pScrn->virtualY;
+ pApm->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
+ pApm->CurrentLayout.bytesPerScanline= (pApm->CurrentLayout.displayWidth * pApm->CurrentLayout.bitsPerPixel) >> 3;
+ pApm->CurrentLayout.depth = pScrn->depth;
+ pApm->CurrentLayout.Scanlines = 2 * (pScrn->videoRam << 10) / pApm->CurrentLayout.bytesPerScanline;
+ if (pScrn->bitsPerPixel == 24)
+ pApm->CurrentLayout.mask32 = 3;
+ else
+ pApm->CurrentLayout.mask32 = 32 / pScrn->bitsPerPixel - 1;
+
+ return TRUE;
+}
+
+/*
+ * Map the framebuffer and MMIO memory.
+ */
+
+static Bool
+ApmMapMem(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ pApm->LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pApm->PciTag,
+ (unsigned long)pApm->LinAddress,
+ pApm->LinMapSize);
+ if (pApm->LinMap == NULL)
+ return FALSE;
+
+ if (!pApm->noLinear) {
+ if (pApm->Chipset >= AT3D) {
+ pApm->FbBase = (void *)(((char *)pApm->LinMap) + 0x800000);
+ pApm->VGAMap = ((char *)pApm->LinMap) + 0xFFF000;
+ pApm->MemMap = ((char *)pApm->LinMap) + 0xFFEC00;
+ pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000);
+ }
+ else {
+ pApm->FbBase = (void *)pApm->LinMap;
+ pApm->VGAMap = NULL;
+ if (pScrn->videoRam == 6 * 1024 - 32) {
+ pApm->MemMap = ((char *)pApm->LinMap) + 0x5FF800;
+ pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x5F8000);
+ }
+ else {
+ pApm->MemMap = ((char *)pApm->LinMap) + 0x3FF800;
+ pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000);
+ }
+ }
+
+ /*
+ * Initialize chipset
+ */
+ pApm->c9 = RDXB(0xC9);
+ if (pApm->Chipset >= AT3D) {
+ pApm->d9 = RDXB(0xD9);
+ pApm->db = RDXB(0xDB);
+
+ /* If you change these two, change them also in apm_funcs.c */
+ WRXB(0xDB, (pApm->db & 0xF4) | 0x0A);
+ WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20);
+
+ vgaHWSetMmioFuncs(hwp, (CARD8 *)pApm->LinMap, 0xFFF000);
+ }
+ if (pApm->Chipset >= AP6422)
+ WRXB(0xC9, pApm->c9 | 0x10);
+ }
+ else {
+ pApm->FbBase = pApm->LinMap;
+
+ /*
+ * Initialize chipset
+ */
+ if (pApm->Chipset >= AT3D) {
+ pApm->d9 = RDXB_IOP(0xD9);
+ pApm->db = RDXB_IOP(0xDB);
+ WRXB_IOP(0xDB, pApm->db & 0xF4);
+ }
+ }
+ /*
+ * Save color mode
+ */
+ pApm->MiscOut = hwp->readMiscOut(hwp);
+
+ return TRUE;
+}
+
+/*
+ * Unmap the framebuffer and MMIO memory
+ */
+
+static Bool
+ApmUnmapMem(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ /*
+ * Reset color mode
+ */
+ hwp->writeMiscOut(hwp, pApm->MiscOut);
+ if (pApm->LinMap) {
+ if (pApm->Chipset >= AT3D) {
+ if (!pApm->noLinear) {
+ WRXB(0xD9, pApm->d9);
+ WRXB(0xDB, pApm->db);
+ }
+ else {
+ WRXB_IOP(0xD9, pApm->d9);
+ WRXB_IOP(0xDB, pApm->db);
+ }
+ }
+ WRXB(0xC9, pApm->c9);
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, pApm->LinMapSize);
+ pApm->LinMap = NULL;
+ }
+ else if (pApm->FbBase)
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, 0x10000);
+
+ return TRUE;
+}
+
+/*
+ * This function saves the video state.
+ */
+static void
+ApmSave(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+ ApmRegPtr ApmReg = &pApm->SavedReg;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ if (pApm->VGAMap) {
+ ApmReg->SEQ[0x1B] = ApmReadSeq(0x1B);
+ ApmReg->SEQ[0x1C] = ApmReadSeq(0x1C);
+
+ /*
+ * Save fonts
+ */
+ if (!(hwp->SavedReg.Attribute[0x10] & 1)) {
+ if (pApm->FontInfo || (pApm->FontInfo = (pointer)xalloc(TEXT_AMOUNT))) {
+ int locked;
+
+ locked = ApmReadSeq(0x10);
+ if (locked)
+ ApmWriteSeq(0x10, 0x12);
+ ApmWriteSeq(0x1C, 0x3F);
+ memcpy(pApm->FontInfo, pApm->FbBase, TEXT_AMOUNT);
+ ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]);
+ if (locked)
+ ApmWriteSeq(0x10, 0);
+ }
+ }
+ /*
+ * This function will handle creating the data structure and filling
+ * in the generic VGA portion.
+ */
+ vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_CMAP);
+
+ /* Hardware cursor registers. */
+ ApmReg->EX[XR140] = RDXL(0x140);
+ ApmReg->EX[XR144] = RDXW(0x144);
+ ApmReg->EX[XR148] = RDXL(0x148);
+ ApmReg->EX[XR14C] = RDXW(0x14C);
+
+ ApmReg->CRT[0x19] = ApmReadCrtc(0x19);
+ ApmReg->CRT[0x1A] = ApmReadCrtc(0x1A);
+ ApmReg->CRT[0x1B] = ApmReadCrtc(0x1B);
+ ApmReg->CRT[0x1C] = ApmReadCrtc(0x1C);
+ ApmReg->CRT[0x1D] = ApmReadCrtc(0x1D);
+ ApmReg->CRT[0x1E] = ApmReadCrtc(0x1E);
+
+ /* RAMDAC registers. */
+ ApmReg->EX[XRE8] = RDXL(0xE8);
+ ApmReg->EX[XREC] = RDXL(0xEC);
+
+ /* Color correction */
+ ApmReg->EX[XRE0] = RDXL(0xE0);
+
+ ApmReg->EX[XR80] = RDXB(0x80);
+ }
+ else {
+ /*
+ * This function will handle creating the data structure and filling
+ * in the generic VGA portion.
+ */
+ vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
+
+ ApmReg->SEQ[0x1B] = rdinx(pApm->xport, 0x1B);
+ ApmReg->SEQ[0x1C] = rdinx(pApm->xport, 0x1C);
+
+ /* Hardware cursor registers. */
+ if (pApm->noLinear) {
+ ApmReg->EX[XR140] = RDXL_IOP(0x140);
+ ApmReg->EX[XR144] = RDXW_IOP(0x144);
+ ApmReg->EX[XR148] = RDXL_IOP(0x148);
+ ApmReg->EX[XR14C] = RDXW_IOP(0x14C);
+ }
+ else {
+ ApmReg->EX[XR140] = RDXL(0x140);
+ ApmReg->EX[XR144] = RDXW(0x144);
+ ApmReg->EX[XR148] = RDXL(0x148);
+ ApmReg->EX[XR14C] = RDXW(0x14C);
+ }
+
+ ApmReg->CRT[0x19] = rdinx(pApm->iobase + 0x3D4, 0x19);
+ ApmReg->CRT[0x1A] = rdinx(pApm->iobase + 0x3D4, 0x1A);
+ ApmReg->CRT[0x1B] = rdinx(pApm->iobase + 0x3D4, 0x1B);
+ ApmReg->CRT[0x1C] = rdinx(pApm->iobase + 0x3D4, 0x1C);
+ ApmReg->CRT[0x1D] = rdinx(pApm->iobase + 0x3D4, 0x1D);
+ ApmReg->CRT[0x1E] = rdinx(pApm->iobase + 0x3D4, 0x1E);
+
+ if (pApm->noLinear) {
+ /* RAMDAC registers. */
+ ApmReg->EX[XRE8] = RDXL_IOP(0xE8);
+ ApmReg->EX[XREC] = RDXL_IOP(0xEC);
+
+ /* Color correction */
+ ApmReg->EX[XRE0] = RDXL_IOP(0xE0);
+
+ ApmReg->EX[XR80] = RDXB_IOP(0x80);
+ }
+ else {
+ /* RAMDAC registers. */
+ ApmReg->EX[XRE8] = RDXL(0xE8);
+ ApmReg->EX[XREC] = RDXL(0xEC);
+
+ /* Color correction */
+ ApmReg->EX[XRE0] = RDXL(0xE0);
+
+ ApmReg->EX[XR80] = RDXB(0x80);
+ }
+ }
+}
+
+#define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2)))
+
+static unsigned
+comp_lmn(ApmPtr pApm, long clock)
+{
+ int n, m, l, f;
+ double fvco;
+ double fout;
+ double fmax, fmin;
+ double fref;
+ double fvco_goal;
+ double k, c;
+
+ if (pApm->Chipset >= AT3D)
+ fmax = 370000.0;
+ else
+ fmax = 250000.0;
+
+ fref = 14318.0;
+ fmin = fmax / 2.0;
+
+ for (m = 1; m <= 5; m++)
+ {
+ for (l = 3; l >= 0; l--)
+ {
+ for (n = 8; n <= 127; n++)
+ {
+ fout = ((double)(n + 1) * fref)/((double)(m + 1) * (1 << l));
+ fvco_goal = (double)clock * (double)(1 << l);
+ fvco = fout * (double)(1 << l);
+ if (!WITHIN(fvco, 0.995*fvco_goal, 1.005*fvco_goal))
+ continue;
+ if (!WITHIN(fvco, fmin, fmax))
+ continue;
+ if (!WITHIN(fvco / (double)(n+1), 300.0, 300000.0))
+ continue;
+ if (!WITHIN(fref / (double)(m+1), 300.0, 300000.0))
+ continue;
+
+ /* The following formula was empirically derived by
+ matching a number of fvco values with acceptable
+ values of f.
+
+ (fvco can be 185MHz - 370MHz on AT3D)
+ (fvco can be 125MHz - 250MHz on AT24/AP6422)
+
+ The table that was measured up follows:
+
+ AT3D
+
+ fvco f
+ (125) (x-7) guess
+ 200 5-7
+ 219 4-7
+ 253 3-6
+ 289 2-5
+ 320 0-4
+ (400) (0-x) guess
+
+ AT24
+
+ fvco f
+ 126 7
+ 200 5-7
+ 211 4-7
+
+ AP6422
+
+ fvco f
+ 126 7
+ 169 5-7
+ 200 4-5
+ 211 4-5
+
+ From this, a function "f = k * fvco + c" was derived.
+
+ For AT3D, this table was measured with MCLK == 50MHz.
+ The driver has since been set to use MCLK == 57.3MHz for,
+ but I don't think that makes a difference here.
+ */
+
+ if (pApm->Chipset >= AT24)
+ {
+ k = 7.0 / (175.0 - 380.0);
+ c = -k * 380.0;
+ f = (int)(k * fvco/1000.0 + c + 0.5);
+ if (f > 7) f = 7;
+ if (f < 0) f = 0;
+ } else { /* i.e AP6422 */
+ c = (211.0*6.0-169.0*4.5)/(211.0-169.0);
+ k = (4.5-c)/211.0;
+ f = (int)(k * fvco/1000.0 + c + 0.5);
+ if (f > 7) f = 7;
+ if (f < 0) f = 0;
+ }
+
+ return (n << 16) | (m << 8) | (l << 2) | (f << 4);
+ }
+ }
+ }
+ xf86DrvMsg(pApm->scrnIndex, X_PROBED,
+ "Cannot find register values for clock %6.2f MHz. "
+ "Please use a (slightly) different clock.\n",
+ (double)clock / 1000.0);
+ return 0;
+}
+
+/*
+ * Initialise a new mode. This is currently still using the old
+ * "initialise struct, restore/write struct to HW" model. That could
+ * be changed.
+ */
+
+static Bool
+ApmModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ APMDECL(pScrn);
+ ApmRegPtr ApmReg = &pApm->ModeReg;
+ vgaHWPtr hwp;
+
+
+ /* set clockIndex to "2" for programmable clocks */
+ if (pScrn->progClock)
+ mode->ClockIndex = 2;
+
+ /* prepare standard VGA register contents */
+ if (!vgaHWInit(pScrn, mode))
+ return FALSE;
+ pScrn->vtSema = TRUE;
+ hwp = VGAHWPTR(pScrn);
+
+ hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F);
+
+ if (xf86IsPc98())
+ outb(0xFAC, 0xFF);
+
+ memcpy(ApmReg, &pApm->SavedReg, sizeof pApm->SavedReg);
+
+ /*
+ * The APM chips have a scale factor of 8 for the
+ * scanline offset. There are four extended bit in addition
+ * to the 8 VGA bits.
+ */
+ {
+ int offset;
+
+ offset = (pApm->CurrentLayout.displayWidth *
+ pApm->CurrentLayout.bitsPerPixel / 8) >> 3;
+ hwp->ModeReg.CRTC[0x13] = offset;
+ /* Bit 8 resides at CR1C bits 7:4. */
+ ApmReg->CRT[0x1C] = (offset & 0xF00) >> 4;
+ }
+
+ /* Set pixel depth. */
+ switch(pApm->CurrentLayout.bitsPerPixel)
+ {
+ case 4:
+ ApmReg->EX[XR80] = 0x01;
+ break;
+ case 8:
+ ApmReg->EX[XR80] = 0x02;
+ break;
+ case 16:
+ if (pApm->CurrentLayout.depth == 15)
+ ApmReg->EX[XR80] = 0x0C;
+ else
+ ApmReg->EX[XR80] = 0x0D;
+ break;
+ case 24:
+ ApmReg->EX[XR80] = 0x0E;
+ break;
+ case 32:
+ ApmReg->EX[XR80] = 0x0F;
+ break;
+ default:
+ FatalError("Unsupported bit depth %d\n", pApm->CurrentLayout.depth);
+ break;
+ }
+
+ /* Set banking register to zero. */
+ ApmReg->EX[XRC0] = 0;
+
+ /* Handle the CRTC overflow bits. */
+ {
+ unsigned char val;
+ /* Vertical Overflow. */
+ val = 0;
+ if ((mode->CrtcVTotal - 2) & 0x400)
+ val |= 0x01;
+ if ((mode->CrtcVDisplay - 1) & 0x400)
+ val |= 0x02;
+ /* VBlankStart is equal to VSyncStart + 1. */
+ if (mode->CrtcVSyncStart & 0x400)
+ val |= 0x04;
+ /* VRetraceStart is equal to VSyncStart + 1. */
+ if (mode->CrtcVSyncStart & 0x400)
+ val |= 0x08;
+ ApmReg->CRT[0x1A] = val;
+
+ /* Horizontal Overflow. */
+ val = 0;
+ if ((mode->CrtcHTotal / 8 - 5) & 0x100)
+ val |= 1;
+ if ((mode->CrtcHDisplay / 8 - 1) & 0x100)
+ val |= 2;
+ /* HBlankStart is equal to HSyncStart - 1. */
+ if ((mode->CrtcHSyncStart / 8 - 1) & 0x100)
+ val |= 4;
+ /* HRetraceStart is equal to HSyncStart. */
+ if ((mode->CrtcHSyncStart / 8) & 0x100)
+ val |= 8;
+ ApmReg->CRT[0x1B] = val;
+
+ /* Assume the CRTC is not KGA (see vgaHWInit) */
+ hwp->ModeReg.CRTC[3] = (hwp->ModeReg.CRTC[3] & 0xE0) |
+ (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
+ hwp->ModeReg.CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
+ | (hwp->ModeReg.CRTC[5] & 0x7F);
+ hwp->ModeReg.CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
+ }
+ ApmReg->CRT[0x1E] = 1; /* disable autoreset feature */
+
+ /* Program clock select. */
+ ApmReg->EX[XREC] = comp_lmn(pApm, mode->Clock);
+ if (!ApmReg->EX[XREC])
+ return FALSE;
+ hwp->ModeReg.MiscOutReg |= 0x0C;
+
+ /* Set up the RAMDAC registers. */
+
+ if (pApm->CurrentLayout.bitsPerPixel > 8)
+ /* Get rid of white border. */
+ hwp->ModeReg.Attribute[0x11] = 0x00;
+ else
+ hwp->ModeReg.Attribute[0x11] = 0xFF;
+ if (pApm->MemClk)
+ ApmReg->EX[XRE8] = comp_lmn(pApm, pApm->MemClk);
+ else if (pApm->Chipset >= AT3D)
+ ApmReg->EX[XRE8] = 0x071F01E8; /* Enable 58MHz MCLK (actually 57.3 MHz)
+ This is what is used in the Windows
+ drivers. The BIOS sets it to 50MHz. */
+ else if (!pApm->noLinear)
+ ApmReg->EX[XRE8] = RDXL(0xE8); /* No change */
+ else
+ ApmReg->EX[XRE8] = RDXL_IOP(0xE8); /* No change */
+
+ ApmReg->EX[XRE0] = 0x10;
+
+ /* If you change it, change in apm_funcs.c as well */
+ if (pApm->Chipset >= AT3D) {
+ ApmReg->SEQ[0x1B] = 0x20;
+ ApmReg->SEQ[0x1C] = 0x2F;
+ }
+ else {
+ ApmReg->SEQ[0x1B] = 0x24;
+ if (pScrn->videoRam >= 6 * 1024)
+ ApmReg->SEQ[0x1C] = 0x2F;
+ else
+ ApmReg->SEQ[0x1C] = 0x2D;
+ }
+
+ /* ICICICICI */
+ ApmRestore(pScrn, &hwp->ModeReg, ApmReg);
+
+ return TRUE;
+}
+
+/*
+ * Restore the initial mode.
+ */
+static void
+ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, ApmRegPtr ApmReg)
+{
+ APMDECL(pScrn);
+
+ vgaHWProtect(pScrn, TRUE);
+ ApmUnlock(pApm);
+
+ if (pApm->VGAMap) {
+ /*
+ * Restore fonts
+ */
+ if (!(vgaReg->Attribute[0x10] & 1) && pApm->FontInfo) {
+ ApmWriteSeq(0x1C, 0x3F);
+ memcpy(pApm->FbBase, pApm->FontInfo, TEXT_AMOUNT);
+ }
+
+ /* Set aperture index to 0. */
+ WRXW(0xC0, 0);
+
+ /*
+ * Write the extended registers first
+ */
+ ApmWriteSeq(0x1B, ApmReg->SEQ[0x1B]);
+ ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]);
+
+ /* Hardware cursor registers. */
+ WRXL(0x140, ApmReg->EX[XR140]);
+ WRXW(0x144, ApmReg->EX[XR144]);
+ WRXL(0x148, ApmReg->EX[XR148]);
+ WRXW(0x14C, ApmReg->EX[XR14C]);
+
+ ApmWriteCrtc(0x19, ApmReg->CRT[0x19]);
+ ApmWriteCrtc(0x1A, ApmReg->CRT[0x1A]);
+ ApmWriteCrtc(0x1B, ApmReg->CRT[0x1B]);
+ ApmWriteCrtc(0x1C, ApmReg->CRT[0x1C]);
+ ApmWriteCrtc(0x1D, ApmReg->CRT[0x1D]);
+ ApmWriteCrtc(0x1E, ApmReg->CRT[0x1E]);
+
+ /* RAMDAC registers. */
+ WRXL(0xE8, ApmReg->EX[XRE8]);
+ WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7));
+ WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */
+
+ /* Color correction */
+ WRXL(0xE0, ApmReg->EX[XRE0]);
+
+ WRXB(0x80, ApmReg->EX[XR80]);
+
+ /*
+ * This function handles restoring the generic VGA registers.
+ */
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
+ }
+ else {
+ /* Set aperture index to 0. */
+ if (pApm->noLinear)
+ WRXW_IOP(0xC0, 0);
+ else
+ WRXW(0xC0, 0);
+
+ /*
+ * Write the extended registers first
+ */
+ wrinx(pApm->xport, 0x1B, ApmReg->SEQ[0x1B]);
+ wrinx(pApm->xport, 0x1C, ApmReg->SEQ[0x1C]);
+
+ /* Hardware cursor registers. */
+ if (pApm->noLinear) {
+ WRXL_IOP(0x140, ApmReg->EX[XR140]);
+ WRXW_IOP(0x144, ApmReg->EX[XR144]);
+ WRXL_IOP(0x148, ApmReg->EX[XR148]);
+ WRXW_IOP(0x14C, ApmReg->EX[XR14C]);
+ }
+ else {
+ WRXL(0x140, ApmReg->EX[XR140]);
+ WRXW(0x144, ApmReg->EX[XR144]);
+ WRXL(0x148, ApmReg->EX[XR148]);
+ WRXW(0x14C, ApmReg->EX[XR14C]);
+ }
+
+ wrinx(pApm->iobase + 0x3D4, 0x19, ApmReg->CRT[0x19]);
+ wrinx(pApm->iobase + 0x3D4, 0x1A, ApmReg->CRT[0x1A]);
+ wrinx(pApm->iobase + 0x3D4, 0x1B, ApmReg->CRT[0x1B]);
+ wrinx(pApm->iobase + 0x3D4, 0x1C, ApmReg->CRT[0x1C]);
+ wrinx(pApm->iobase + 0x3D4, 0x1D, ApmReg->CRT[0x1D]);
+ wrinx(pApm->iobase + 0x3D4, 0x1E, ApmReg->CRT[0x1E]);
+
+ /* RAMDAC registers. */
+ if (pApm->noLinear) {
+ WRXL_IOP(0xE8, ApmReg->EX[XRE8]);
+ WRXL_IOP(0xEC, ApmReg->EX[XREC] & ~(1 << 7));
+ WRXL_IOP(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */
+ }
+ else {
+ WRXL(0xE8, ApmReg->EX[XRE8]);
+ WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7));
+ WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */
+ }
+
+ /* Color correction */
+ if (pApm->noLinear)
+ WRXL_IOP(0xE0, ApmReg->EX[XRE0]);
+ else
+ WRXL(0xE0, ApmReg->EX[XRE0]);
+
+ if (pApm->noLinear)
+ WRXB_IOP(0x80, ApmReg->EX[XR80]);
+ else
+ WRXB(0x80, ApmReg->EX[XR80]);
+
+ /*
+ * This function handles restoring the generic VGA registers.
+ */
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
+ }
+
+ vgaHWProtect(pScrn, FALSE);
+}
+
+
+/* Refresh a region of the shadow framebuffer to the screen */
+static void
+ApmRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ APMDECL(pScrn);
+ int width, height, Bpp, FBPitch;
+ unsigned char *src, *dst;
+
+ Bpp = pApm->CurrentLayout.bitsPerPixel >> 3;
+ FBPitch = pApm->CurrentLayout.bytesPerScanline;
+
+ while(num--) {
+ width = (pbox->x2 - pbox->x1) * Bpp;
+ height = pbox->y2 - pbox->y1;
+ src = pApm->ShadowPtr + (pbox->y1 * pApm->ShadowPitch) +
+ (pbox->x1 * Bpp);
+ dst = (unsigned char *)pApm->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
+
+ while(height--) {
+ memcpy(dst, src, width);
+ dst += FBPitch;
+ src += pApm->ShadowPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+/* Mandatory */
+
+/* This gets called at the start of each server generation */
+
+static Bool
+ApmScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ APMDECL(pScrn);
+ int ret;
+ unsigned char *FbBase;
+
+ pApm->pScreen = pScreen;
+
+ /* Map the chip memory and MMIO areas */
+ if (pApm->noLinear) {
+ pApm->saveCmd = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG);
+ pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, pApm->saveCmd | (PCI_CMD_IO_ENABLE|PCI_CMD_MEM_ENABLE));
+ pApm->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pApm->PciTag, 0xA0000, 0x10000);
+ }
+ else
+ if (!ApmMapMem(pScrn))
+ return FALSE;
+
+ /* No memory reserved yet */
+ pApm->OffscreenReserved = 0;
+
+ /* Save the current state */
+ ApmSave(pScrn);
+
+ /* Initialise the first mode */
+ ApmModeInit(pScrn, pScrn->currentMode);
+ pApm->CurrentLayout.pMode = pScrn->currentMode;
+
+ /* Darken the screen for aesthetic reasons and set the viewport */
+ ApmSaveScreen(pScreen, SCREEN_SAVER_ON);
+ ApmAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ /*
+ * Reset fb's visual list.
+ */
+ miClearVisualTypes();
+
+ /* Setup the visuals we support. */
+
+ /*
+ * For bpp > 8, the default visuals are not acceptable because we only
+ * support TrueColor and not DirectColor. To deal with this, call
+ * miSetVisualTypes for each visual supported.
+ */
+
+ if (pApm->CurrentLayout.bitsPerPixel > 8) {
+ if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
+ pScrn->defaultVisual))
+ return FALSE;
+ } else {
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+ }
+
+ /*
+ * Call the framebuffer layer's ScreenInit function, and fill in other
+ * pScreen fields.
+ */
+
+ if(pApm->ShadowFB) {
+ pApm->ShadowPitch =
+ ((pScrn->virtualX * pScrn->bitsPerPixel >> 3) + 3) & ~3L;
+ pApm->ShadowPtr = xalloc(pApm->ShadowPitch * pScrn->virtualY);
+ FbBase = pApm->ShadowPtr;
+ } else {
+ pApm->ShadowPtr = NULL;
+ FbBase = pApm->FbBase;
+ }
+
+ /* Reserve memory */
+ ApmHWCursorReserveSpace(pApm);
+ ApmAccelReserveSpace(pApm);
+
+ miSetPixmapDepths();
+
+ switch (pScrn->bitsPerPixel) {
+ case 1:
+ ret = xf1bppScreenInit(pScreen, FbBase,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth);
+ break;
+ case 4:
+ ret = xf4bppScreenInit(pScreen, FbBase,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth);
+ break;
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ ret = fbScreenInit(pScreen, FbBase, pScrn->virtualX,
+ pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth, pScrn->bitsPerPixel);
+ break;
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Internal error: invalid bpp (%d) in ApmScrnInit\n",
+ pScrn->bitsPerPixel);
+ ret = FALSE;
+ break;
+ }
+ if (!ret)
+ return FALSE;
+
+ if (pScrn->bitsPerPixel > 8) {
+ VisualPtr visual;
+
+ /* Fixup RGB ordering */
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ /* must be after visual RGB order fixed */
+ if (pScrn->bitsPerPixel > 4)
+ fbPictureInit(pScreen, 0, 0);
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (!pApm->ShadowFB) { /* hardware cursor needs to wrap this layer */
+ if(!ApmDGAInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DGA initialization failed\n");
+ }
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+
+ /* Initialise cursor functions */
+ miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
+
+ /* Initialize HW cursor layer (after DGA and SW cursor) */
+ if (pApm->hwCursor) {
+ if (!ApmHWCursorInit(pScreen))
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+
+ /*
+ * Initialize the acceleration interface.
+ */
+ if (!pApm->NoAccel) {
+ ApmAccelInit(pScreen); /* set up XAA interface */
+ }
+
+ /* Initialise default colourmap */
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ /*
+ * Initialize colormap layer.
+ * Must follow initialization of the default colormap.
+ */
+ if (!xf86HandleColormaps(pScreen, 256, 8, ApmLoadPalette, NULL,
+ CMAP_RELOAD_ON_MODE_SWITCH)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Colormap initialization failed\n");
+ return FALSE;
+ }
+
+ if (pApm->ShadowFB)
+ ShadowFBInit(pScreen, ApmRefreshArea);
+
+ xf86DPMSInit(pScreen, ApmDisplayPowerManagementSet, 0);
+
+ if (pApm->noLinear)
+ ApmInitVideo_IOP(pScreen);
+ else
+ ApmInitVideo(pScreen);
+
+ pScreen->SaveScreen = ApmSaveScreen;
+
+ pApm->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = ApmCloseScreen;
+
+ pScrn->memPhysBase = pApm->LinAddress;
+ pScrn->fbOffset = (((char *)pApm->FbBase) - ((char *)pApm->LinMap));
+
+ /* Report any unused options (only for the first generation) */
+ if (serverGeneration == 1) {
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+ }
+
+ if (ApmGeneration != serverGeneration) {
+ if ((ApmPixmapIndex = AllocatePixmapPrivateIndex()) < 0)
+ return FALSE;
+ ApmGeneration = serverGeneration;
+ }
+
+ if (!AllocatePixmapPrivate(pScreen, ApmPixmapIndex, sizeof(ApmPixmapRec)))
+ return FALSE;
+
+ /* Done */
+ return TRUE;
+}
+
+/* mandatory */
+static void
+ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
+ VisualPtr pVisual)
+{
+ APMDECL(pScrn);
+ int i, index, last = -1;
+
+ if (pApm->VGAMap) {
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ if (index != last)
+ ApmWriteDacWriteAddr(index);
+ last = index + 1;
+ ApmWriteDacData(colors[index].red);
+ ApmWriteDacData(colors[index].green);
+ ApmWriteDacData(colors[index].blue);
+ }
+ }
+ else {
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ if (index != last)
+ outb(pApm->iobase + 0x3C8, index);
+ last = index + 1;
+ outb(pApm->iobase + 0x3C9, colors[index].red);
+ outb(pApm->iobase + 0x3C9, colors[index].green);
+ outb(pApm->iobase + 0x3C9, colors[index].blue);
+ }
+ }
+}
+
+/* Usually mandatory */
+Bool
+ApmSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ return ApmModeInit(xf86Screens[scrnIndex], mode);
+}
+
+/*
+ * This function is used to initialize the Start Address - the first
+ * displayed location in the video memory.
+ */
+/* Usually mandatory */
+void
+ApmAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ APMDECL(pScrn);
+ int Base;
+
+ if (pApm->CurrentLayout.bitsPerPixel == 24)
+ x = (x + 3) & ~3;
+ Base = ((y * pApm->CurrentLayout.displayWidth + x) * (pApm->CurrentLayout.bitsPerPixel / 8)) >> 2;
+ /*
+ * These are the generic starting address registers.
+ */
+ if (pApm->VGAMap) {
+ ApmWriteCrtc(0x0C, Base >> 8);
+ ApmWriteCrtc(0x0D, Base);
+
+ /*
+ * Here the high-order bits are masked and shifted, and put into
+ * the appropriate extended registers.
+ */
+ ApmWriteCrtc(0x1C, (ApmReadCrtc(0x1C) & 0xF0) | ((Base & 0x0F0000) >> 16));
+ }
+ else {
+ outw(pApm->iobase + 0x3D4, (Base & 0x00FF00) | 0x0C);
+ outw(pApm->iobase + 0x3D4, ((Base & 0x00FF) << 8) | 0x0D);
+
+ /*
+ * Here the high-order bits are masked and shifted, and put into
+ * the appropriate extended registers.
+ */
+ modinx(pApm->iobase + 0x3D4, 0x1C, 0x0F, (Base & 0x0F0000) >> 16);
+ }
+}
+
+/*
+ * This is called when VT switching back to the X server. Its job is
+ * to reinitialise the video mode.
+ *
+ * We may wish to unmap video/MMIO memory too.
+ */
+
+/* Mandatory */
+static Bool
+ApmEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ APMDECL(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ if (pApm->Chipset >= AT3D) {
+ if (!pApm->noLinear) {
+ /* If you change it, change it also in apm_funcs.c */
+ WRXB(0xDB, (pApm->db & 0xF4) | 0x0A | pApm->Rush);
+ WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20);
+ }
+ else {
+ WRXB_IOP(0xDB, pApm->db & 0xF4);
+ }
+ }
+ if (pApm->Chipset >= AP6422)
+ WRXB(0xC9, pApm->c9 | 0x10);
+ ApmUnlock(APMPTR(pScrn));
+ vgaHWUnlock(hwp);
+ /*
+ * Set color mode
+ */
+ hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F);
+
+ if (!ApmModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+ ApmAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ return TRUE;
+}
+
+/* Mandatory */
+static void
+ApmLeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ APMDECL(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg);
+ /*
+ * Reset color mode
+ */
+ (*hwp->writeMiscOut)(hwp, pApm->MiscOut);
+ vgaHWLock(hwp);
+ ApmLock(pApm);
+ if (pApm->Chipset >= AT3D) {
+ if (!pApm->noLinear) {
+ WRXB(0xD9, pApm->d9);
+ WRXB(0xDB, pApm->db);
+ }
+ else {
+ WRXB_IOP(0xD9, pApm->d9);
+ WRXB_IOP(0xDB, pApm->db);
+ }
+ }
+ WRXB(0xC9, pApm->c9);
+
+ if (xf86IsPc98())
+ outb(0xFAC, 0xFE);
+}
+
+/*
+ * This is called at the end of each server generation. It restores the
+ * original (text) mode. It should really also unmap the video memory too.
+ */
+
+/* Mandatory */
+static Bool
+ApmCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ APMDECL(pScrn);
+
+ if (pScrn->vtSema) {
+ ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg);
+ vgaHWLock(hwp);
+ ApmUnmapMem(pScrn);
+ }
+ if(pApm->AccelInfoRec)
+ XAADestroyInfoRec(pApm->AccelInfoRec);
+ if(pApm->DGAXAAInfo)
+ XAADestroyInfoRec(pApm->DGAXAAInfo);
+ pApm->AccelInfoRec = NULL;
+ if(pApm->CursorInfoRec)
+ xf86DestroyCursorInfoRec(pApm->CursorInfoRec);
+ pApm->CursorInfoRec = NULL;
+ if (pApm->DGAModes)
+ xfree(pApm->DGAModes);
+ if (pApm->I2CPtr)
+ xf86DestroyI2CBusRec(pApm->I2CPtr, TRUE, TRUE);
+ pApm->I2CPtr = NULL;
+ if (pApm->adaptor)
+ xfree(pApm->adaptor);
+
+ pScrn->vtSema = FALSE;
+
+ if (xf86IsPc98())
+ outb(0xFAC, 0xFE);
+
+ pScreen->CloseScreen = pApm->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+/* Free up any per-generation data structures */
+
+/* Optional */
+static void
+ApmFreeScreen(int scrnIndex, int flags)
+{
+ vgaHWFreeHWRec(xf86Screens[scrnIndex]);
+ ApmFreeRec(xf86Screens[scrnIndex]);
+}
+
+/* Checks if a mode is suitable for the selected chipset. */
+
+/* Optional */
+static int
+ApmValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
+{
+ if (mode->Flags & V_INTERLACE)
+ return(MODE_BAD);
+
+ return(MODE_OK);
+}
+
+
+/*
+ * ApmDisplayPowerManagementSet --
+ *
+ * Sets VESA Display Power Management Signaling (DPMS) Mode.
+ */
+static void
+ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ APMDECL(pScrn);
+ unsigned char dpmsreg, tmp;
+
+ if (PowerManagementMode < sizeof pApm->DPMSMask &&
+ PowerManagementMode >= 0)
+ PowerManagementMode = pApm->DPMSMask[PowerManagementMode];
+ switch (PowerManagementMode)
+ {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ dpmsreg = 0x00;
+ break;
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ dpmsreg = 0x01;
+ break;
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ dpmsreg = 0x02;
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ dpmsreg = 0x03;
+ break;
+ default:
+ dpmsreg = 0;
+ }
+ if (pApm->noLinear) {
+ tmp = RDXB_IOP(0xD0);
+ WRXB_IOP(0xD0, (tmp & 0xFC) | dpmsreg);
+ } else {
+ tmp = RDXB(0xD0);
+ WRXB(0xD0, (tmp & 0xFC) | dpmsreg);
+ }
+}
+
+static Bool
+ApmSaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ Bool unblank;
+
+ unblank = xf86IsUnblank(mode);
+
+ if (unblank)
+ SetTimeSinceLastInputEvent();
+
+ if (pScrn->vtSema)
+ vgaHWBlankScreen(pScrn, unblank);
+ return TRUE;
+}
+
+#ifdef APM_DEBUG
+unsigned char _L_ACR(unsigned char *x);
+unsigned char _L_ACR(unsigned char *x)
+{
+ return *x;
+}
+
+unsigned short _L_ASR(unsigned short *x);
+unsigned short _L_ASR(unsigned short *x)
+{
+ return *x;
+}
+
+unsigned int _L_AIR(unsigned int *x);
+unsigned int _L_AIR(unsigned int *x)
+{
+ return *x;
+}
+
+void _L_ACW(char *x, char y);
+void _L_ACW(char *x, char y)
+{
+ *x = y;
+}
+
+void _L_ASW(short *x, short y);
+void _L_ASW(short *x, short y)
+{
+ *x = y;
+}
+
+void _L_AIW(int *x, int y);
+void _L_AIW(int *x, int y)
+{
+ *x = y;
+}
+#endif
diff --git a/src/apm_funcs.c b/src/apm_funcs.c
new file mode 100644
index 0000000..71f0fe8
--- /dev/null
+++ b/src/apm_funcs.c
@@ -0,0 +1,1558 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_funcs.c,v 1.17 2002/05/07 12:53:49 alanh Exp $ */
+
+#define FASTER
+#ifndef PSZ
+#define PSZ 8
+#endif
+#ifdef IOP_ACCESS
+# define APM_SUFF_IOP "_IOP"
+# undef RDXB
+# undef RDXW
+# undef RDXL
+# undef WRXB
+# undef WRXW
+# undef WRXL
+# undef ApmWriteSeq
+# define RDXB RDXB_IOP
+# define RDXW RDXW_IOP
+# define RDXL RDXL_IOP
+# define WRXB WRXB_IOP
+# define WRXW WRXW_IOP
+# define WRXL WRXL_IOP
+# define ApmWriteSeq(i, v) wrinx(pApm->xport, i, v)
+#else
+# define APM_SUFF_IOP ""
+#endif
+#if PSZ == 24
+# define APM_SUFF_24 "24"
+# ifdef IOP_ACCESS
+# define A(s) Apm##s##24##_IOP
+# else
+# define A(s) Apm##s##24
+# endif
+#else
+# define APM_SUFF_24 ""
+# ifdef IOP_ACCESS
+# define A(s) Apm##s##_IOP
+# else
+# define A(s) Apm##s
+# endif
+#endif
+#define DPRINTNAME(s) do { xf86DrvMsgVerb(pScrn->pScreen->myNum, X_NOTICE, 4, "Apm" #s APM_SUFF_24 APM_SUFF_IOP "\n"); } while (0)
+
+#if PSZ == 24
+#undef SETSOURCEXY
+#undef SETDESTXY
+#undef SETWIDTH
+#undef SETWIDTHHEIGHT
+#undef UPDATEDEST
+#define SETSOURCEXY(x,y) do { int off = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0x3FFF)) * 3); SETSOURCEOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); break;} while(1)
+#define SETDESTXY(x,y) do { int off = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0x3FFF)) * 3); SETDESTOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); break;} while(1)
+#define SETWIDTH(w) WRXW(0x58, ((w) & 0x3FFF) * 3)
+#define SETWIDTHHEIGHT(w,h) WRXL(0x58, ((h) << 16) | (((w) & 0x3FFF) * 3))
+#define UPDATEDEST(x,y) (void)(curr32[0x54 / 4] = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0xFFFF)) * 3))
+#endif
+
+/* Defines */
+#define MAXLOOP 1000000
+
+
+/* Local functions */
+static void A(Sync)(ScrnInfoPtr pScrn);
+static void A(SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+static void A(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+static void A(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir,
+ int rop, unsigned int planemask,
+ int transparency_color);
+static void A(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h);
+#if PSZ != 24
+static void A(Sync6422)(ScrnInfoPtr pScrn);
+static void A(WriteBitmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ unsigned char *src, int srcwidth, int skipleft,
+ int fg, int bg, int rop, unsigned int planemask);
+static void A(TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ int skipleft, int startline,
+ unsigned int **glyphs, int glyphWidth,
+ int fg, int bg, int rop, unsigned planemask);
+static void A(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void A(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx,
+ int paty, int x, int y,
+ int w, int h);
+#if 0
+static void A(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int bg, int fg, int rop, unsigned int planemask);
+static void A(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft);
+#endif
+static void A(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void A(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop,
+ unsigned int planemask, int trans_color,
+ int bpp, int depth);
+static void A(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h, int skipleft);
+static void A(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int srcx, int srcy,
+ int offset);
+static void A(SubsequentSolidBresenhamLine)(ScrnInfoPtr pScrn, int x1, int y1, int octant, int err, int e1, int e2, int length);
+static void A(SubsequentSolidBresenhamLine6422)(ScrnInfoPtr pScrn, int x1, int y1, int octant, int err, int e1, int e2, int length);
+static void A(SetClippingRectangle)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2);
+static void A(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ unsigned char *src, int srcwidth, int rop,
+ unsigned int planemask, int trans, int bpp,
+ int depth);
+static void A(FillImageWriteRects)(ScrnInfoPtr pScrn, int rop,
+ unsigned int planemask,
+ int nBox, BoxPtr pBox, int xorg, int yorg,
+ PixmapPtr pPix);
+static void A(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,int patx,int paty,
+ int rop, unsigned int planemask,
+ int transparency_color);
+static void A(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx,
+ int paty, int x, int y,
+ int w, int h);
+#endif
+
+/* Inline functions */
+static __inline__ void
+A(WaitForFifo)(ApmPtr pApm, int slots)
+{
+ if (!pApm->UsePCIRetry) {
+ volatile int i;
+
+ for(i = 0; i < MAXLOOP; i++) {
+ if ((STATUS() & STATUS_FIFO) >= slots)
+ break;
+ }
+ if (i == MAXLOOP) {
+ unsigned int status = STATUS();
+
+ WRXB(0x1FF, 0);
+ if (!xf86ServerIsExiting())
+ FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
+ }
+ }
+}
+
+
+static void
+A(SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetupForSolidFill);
+#ifdef FASTER
+ A(WaitForFifo)(pApm, 3 + pApm->apmClip);
+ SETDEC(DEC_QUICKSTART_ONDIMX | DEC_OP_RECT | DEC_DEST_UPD_TRCORNER |
+ pApm->CurrentLayout.Setup_DEC);
+#else
+ A(WaitForFifo)(pApm, 2 + pApm->apmClip);
+#endif
+#if PSZ == 2
+ pApm->color = ((color & 0xFF0000) << 8) | ((color & 0xFF0000) >> 16) |
+ ((color & 0xFF00) << 8) | ((color & 0xFF) << 16);
+#else
+ SETFOREGROUNDCOLOR(color);
+#endif
+
+ if (pApm->apmClip) {
+ SETCLIP_CTRL(0);
+ pApm->apmClip = FALSE;
+ }
+
+ SETROP(apmROP[rop]);
+}
+
+static void
+A(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SubsequentSolidFillRect);
+#if PSZ == 24
+# ifndef FASTER
+ A(WaitForFifo)(pApm, 5);
+# else
+ A(WaitForFifo)(pApm, 4);
+# endif
+ SETOFFSET(3*(pApm->CurrentLayout.displayWidth - w));
+#if 0
+ switch ((((y * pApm->CurrentLayout.displayWidth + x)* 3) / 8) % 3) {
+ case 0:
+ SETFOREGROUNDCOLOR(pApm->color);
+ break;
+ case 1:
+ SETFOREGROUNDCOLOR((pApm->color << 8) | (pApm->color >> 16));
+ break;
+ case 2:
+ SETFOREGROUNDCOLOR(pApm->color >> 8);
+ break;
+ }
+#endif
+#else
+# ifndef FASTER
+ A(WaitForFifo)(pApm, 3);
+# else
+ A(WaitForFifo)(pApm, 2);
+# endif
+#endif
+ SETDESTXY(x, y);
+ SETWIDTHHEIGHT(w, h);
+ UPDATEDEST(x + w + 1, y);
+#ifndef FASTER
+ SETDEC(DEC_START | DEC_OP_RECT | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC);
+#endif
+}
+
+static void
+A(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int transparency_color)
+{
+ unsigned char tmp;
+
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetupForScreenToScreenCopy);
+
+ if (pApm->apmLock) {
+ /*
+ * This is just an attempt, because Daryll is tampering with MY registers.
+ */
+ tmp = (RDXB(0xDB) & 0xF4) | 0x0A;
+ WRXB(0xDB, tmp);
+ ApmWriteSeq(0x1B, 0x20);
+ ApmWriteSeq(0x1C, 0x2F);
+ pApm->apmLock = FALSE;
+ }
+
+ pApm->blitxdir = xdir;
+ pApm->blitydir = ydir;
+
+ pApm->apmTransparency = (transparency_color != -1);
+
+#ifdef FASTER
+ A(WaitForFifo)(pApm, 2 + (transparency_color != -1));
+ SETDEC(DEC_QUICKSTART_ONDIMX | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER |
+ (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) | pApm->CurrentLayout.Setup_DEC |
+ ((xdir < 0) ? DEC_DIR_X_NEG : DEC_DIR_X_POS) |
+ ((ydir < 0) ? DEC_DIR_Y_NEG : DEC_DIR_Y_POS));
+#else
+ A(WaitForFifo)(pApm, 1 + (transparency_color != -1));
+#endif
+
+ if (transparency_color != -1)
+ SETBACKGROUNDCOLOR(transparency_color);
+
+ SETROP(apmROP[rop]);
+}
+
+static void
+A(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h)
+{
+ APMDECL(pScrn);
+#ifndef FASTER
+ u32 c = pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0;
+#endif
+ u32 sx, dx, sy, dy;
+ int i = y1 / pApm->CurrentLayout.Scanlines;
+
+ DPRINTNAME(SubsequentScreenToScreenCopy);
+ if (i && pApm->pixelStride) {
+#ifdef FASTER
+ A(WaitForFifo)(pApm, 1);
+ SETDEC(curr32[0x40 / 4] | (DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR));
+#else
+ c |= DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG;
+#endif
+ pApm->apmClip = TRUE;
+ A(WaitForFifo)(pApm, 3);
+ SETCLIP_LEFTTOP(x2, y2);
+ SETCLIP_RIGHTBOT(x2 + w - 1, y2 + h - 1);
+ SETCLIP_CTRL(1);
+ w = (pApm->pixelStride * 8) / pApm->CurrentLayout.bitsPerPixel;
+ }
+ else {
+#ifdef FASTER
+ A(WaitForFifo)(pApm, 1 + pApm->apmClip);
+ SETDEC(curr32[0x40 / 4] & ~(DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR));
+ if (pApm->apmClip)
+ SETCLIP_CTRL(0);
+ pApm->apmClip = FALSE;
+#else
+ if (pApm->apmClip) {
+ A(WaitForFifo)(pApm, 1);
+ SETCLIP_CTRL(0);
+ pApm->apmClip = FALSE;
+ }
+#endif
+ }
+ if (i) {
+ if (pApm->pixelStride) {
+ x1 += (((y1 % pApm->CurrentLayout.Scanlines) - pApm->RushY[i - 1]) * pApm->pixelStride * 8) / pApm->CurrentLayout.bitsPerPixel;
+ y1 = pApm->RushY[i - 1];
+ }
+ else
+ y1 -= i * pApm->CurrentLayout.Scanlines;
+ }
+ if (pApm->blitxdir < 0)
+ {
+#ifndef FASTER
+ c |= DEC_DIR_X_NEG;
+#endif
+ sx = x1+w-1;
+ dx = x2+w-1;
+ }
+ else
+ {
+#ifndef FASTER
+ c |= DEC_DIR_X_POS;
+#endif
+ sx = x1;
+ dx = x2;
+ }
+
+ if (pApm->blitydir < 0)
+ {
+#ifndef FASTER
+ c |= DEC_DIR_Y_NEG | DEC_START | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER |
+ pApm->CurrentLayout.Setup_DEC;
+#endif
+ sy = y1+h-1;
+ dy = y2+h-1;
+ }
+ else
+ {
+#ifndef FASTER
+ c |= DEC_DIR_Y_POS | DEC_START | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER |
+ pApm->CurrentLayout.Setup_DEC;
+#endif
+ sy = y1;
+ dy = y2;
+ }
+
+#if PSZ == 24
+# ifndef FASTER
+ A(WaitForFifo)(pApm, 5);
+# else
+ A(WaitForFifo)(pApm, 4);
+# endif
+ if (pApm->blitxdir == pApm->blitydir)
+ SETOFFSET(3 * (pApm->CurrentLayout.displayWidth - w));
+ else
+ SETOFFSET(3 * (pApm->CurrentLayout.displayWidth + w));
+#else
+# ifndef FASTER
+ A(WaitForFifo)(pApm, 4);
+# else
+ A(WaitForFifo)(pApm, 3);
+# endif
+#endif
+
+ if (i && pApm->pixelStride) {
+ register unsigned int off = sx + sy * pApm->CurrentLayout.displayWidth;
+
+ SETSOURCEOFF(((off & 0xFFF000) << 4) | (off & 0xFFF));
+ }
+ else
+ SETSOURCEXY(sx,sy);
+ SETDESTXY(dx,dy);
+ SETWIDTHHEIGHT(w,h);
+ UPDATEDEST(dx + (w + 1)*pApm->blitxdir, dy);
+
+#ifndef FASTER
+ SETDEC(c);
+#endif
+ if (i) A(Sync)(pScrn); /* Only for AT3D */
+}
+
+
+#if PSZ != 24
+static void
+A(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, int bg,
+ int rop, unsigned int planemask)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetupForScreenToScreenColorExpandFill);
+ A(WaitForFifo)(pApm, 3 + pApm->apmClip);
+ if (bg == -1)
+ {
+ SETFOREGROUNDCOLOR(fg);
+ SETBACKGROUNDCOLOR(fg+1);
+ pApm->apmTransparency = TRUE;
+ }
+ else
+ {
+ SETFOREGROUNDCOLOR(fg);
+ SETBACKGROUNDCOLOR(bg);
+ pApm->apmTransparency = FALSE;
+ }
+
+ SETROP(apmROP[rop]);
+}
+
+static void
+A(WriteBitmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ unsigned char *src, int srcwidth, int skipleft,
+ int fg, int bg, int rop, unsigned int planemask)
+{
+ APMDECL(pScrn);
+ Bool beCareful, apmClip = FALSE;
+ int wc, n, nc, wr, wrd;
+ CARD32 *dstPtr;
+#ifndef FASTER
+ int c;
+#endif
+
+ DPRINTNAME(WriteBitmap);
+
+ if (w <= 0 && h <= 0)
+ return;
+
+ /*
+ * The function is a bit long, but the spirit is simple : put the monochrome
+ * data in scratch memory and color-expand it using the
+ * ScreenToScreenColorExpand techniques.
+ */
+
+ w += skipleft;
+ x -= skipleft;
+ wc = pApm->ScratchMemSize * 8;
+ wrd = (w + 31) >> 5;
+ wr = wrd << 5;
+ nc = wc / wr;
+ if (nc > h)
+ nc = h;
+ if (wr / 8 > srcwidth)
+ beCareful = TRUE;
+ else
+ beCareful = FALSE;
+ srcwidth -= wr / 8;
+
+ if (skipleft || w != wr) {
+ apmClip = TRUE;
+ A(WaitForFifo)(pApm, 3);
+ SETCLIP_LEFTTOP(x + skipleft, y);
+ SETCLIP_RIGHTBOT(x + w - 1, y + h - 1);
+ SETCLIP_CTRL(1);
+ }
+ else if (pApm->apmClip) {
+ A(WaitForFifo)(pApm, 1);
+ SETCLIP_CTRL(0);
+ }
+ pApm->apmClip = FALSE;
+
+ A(SetupForScreenToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask);
+#ifdef FASTER
+ A(WaitForFifo)(pApm, 2);
+ if (pApm->apmTransparency)
+ SETDEC(DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME |
+ DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR |
+ DEC_SOURCE_CONTIG | DEC_SOURCE_TRANSPARENCY | pApm->CurrentLayout.Setup_DEC);
+ else
+ SETDEC(DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME |
+ DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR |
+ DEC_SOURCE_CONTIG | pApm->CurrentLayout.Setup_DEC);
+#else
+ A(WaitForFifo)(pApm, 1);
+ c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME |
+ DEC_START | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR |
+ DEC_SOURCE_CONTIG | pApm->CurrentLayout.Setup_DEC;
+ if (pApm->apmTransparency)
+ c |= DEC_SOURCE_TRANSPARENCY;
+#endif
+
+ SETDESTXY(x, y);
+
+ if (!beCareful || h % nc > 3 || (w > 16 && h % nc)) {
+#ifndef FASTER
+ if (h / nc)
+ SETWIDTHHEIGHT(wr, nc);
+#endif
+ for (n = h / nc; n-- > 0; ) {
+ int i, j;
+
+ if (pApm->ScratchMemPtr + nc * wrd * 4 < pApm->ScratchMemEnd) {
+#define d ((memType)dstPtr - (memType)pApm->FbBase)
+ A(WaitForFifo)(pApm, 1);
+ dstPtr = (CARD32 *)pApm->ScratchMemPtr;
+ switch(pApm->CurrentLayout.bitsPerPixel) {
+ case 8: case 24:
+ SETSOURCEOFF((d & 0xFFF000) << 4 |
+ (d & 0xFFF));
+ break;
+ case 16:
+ SETSOURCEOFF((d & 0xFFE000) << 3 |
+ ((d & 0x1FFE) >> 1));
+ break;
+ case 32:
+ SETSOURCEOFF((d & 0xFFC000) << 2 |
+ ((d & 0x3FFC) >> 2));
+ break;
+ }
+#undef d
+ }
+ else {
+ (*pApm->AccelInfoRec->Sync)(pScrn);
+ dstPtr = (CARD32 *)pApm->ScratchMemOffset;
+ SETSOURCEOFF(pApm->ScratchMem);
+ }
+ pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * nc) + 4)
+ & ~(memType)7;
+ for (i = nc; i-- > 0; ) {
+ for (j = wrd; j-- > 0; ) {
+ *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src);
+ src += 4;
+ }
+ src += srcwidth;
+ }
+ A(WaitForFifo)(pApm, 1);
+#ifdef FASTER
+ SETWIDTHHEIGHT(wr, nc);
+#else
+ SETDEC(c);
+#endif
+ }
+ }
+ else {
+#ifndef FASTER
+ if (h / nc)
+ SETWIDTHHEIGHT(wr, nc);
+#endif
+ for (n = h / nc; n-- > 0; ) {
+ int i, j;
+
+ if (pApm->ScratchMemPtr + nc * wrd * 4 < pApm->ScratchMemEnd) {
+#define d ((memType)dstPtr - (memType)pApm->FbBase)
+ A(WaitForFifo)(pApm, 1);
+ dstPtr = (CARD32 *)pApm->ScratchMemPtr;
+ switch(pApm->CurrentLayout.bitsPerPixel) {
+ case 8: case 24:
+ SETSOURCEOFF((d & 0xFFF000) << 4 |
+ (d & 0xFFF));
+ break;
+ case 16:
+ SETSOURCEOFF((d & 0xFFE000) << 3 |
+ ((d & 0x1FFE) >> 1));
+ break;
+ case 32:
+ SETSOURCEOFF((d & 0xFFC000) << 2 |
+ ((d & 0x3FFC) >> 2));
+ break;
+ }
+#undef d
+ }
+ else {
+ (*pApm->AccelInfoRec->Sync)(pScrn);
+ dstPtr = (CARD32 *)pApm->ScratchMemOffset;
+ SETSOURCEOFF(pApm->ScratchMem);
+ }
+ pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * nc * 4) + 4) & ~7;
+ for (i = nc; i-- > 0; ) {
+ for (j = wrd; j-- > 0; ) {
+ if (i || j || n)
+ *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src);
+ else if (srcwidth > -8) {
+ ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[2]];
+ ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[1]];
+ ((CARD8 *)dstPtr)[2] = byte_reversed[((CARD8 *)src)[0]];
+ dstPtr = (CARD32 *)(3 + (CARD8 *)dstPtr);
+ }
+ else if (srcwidth > -16) {
+ ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[1]];
+ ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[0]];
+ dstPtr = (CARD32 *)(2 + (CARD8 *)dstPtr);
+ }
+ else {
+ *(CARD8 *)dstPtr = byte_reversed[*(CARD8 *)src];
+ dstPtr = (CARD32 *)(1 + (CARD8 *)dstPtr);
+ }
+ src += 4;
+ }
+ src += srcwidth;
+ }
+ A(WaitForFifo)(pApm, 1);
+#ifdef FASTER
+ SETWIDTHHEIGHT(wr, nc);
+#else
+ SETDEC(c);
+#endif
+ }
+ }
+
+ /*
+ * Same thing for the remnant
+ */
+ UPDATEDEST(x, y + h + 1);
+ h %= nc;
+ if (h) {
+ if (!beCareful) {
+ int i, j;
+
+#ifndef FASTER
+ SETWIDTHHEIGHT(wr, h);
+#endif
+ if (pApm->ScratchMemPtr + h * wrd * 4 < pApm->ScratchMemEnd) {
+#define d ((memType)dstPtr - (memType)pApm->FbBase)
+ A(WaitForFifo)(pApm, 1);
+ dstPtr = (CARD32 *)pApm->ScratchMemPtr;
+ switch(pApm->CurrentLayout.bitsPerPixel) {
+ case 8: case 24:
+ SETSOURCEOFF((d & 0xFFF000) << 4 |
+ (d & 0xFFF));
+ break;
+ case 16:
+ SETSOURCEOFF((d & 0xFFE000) << 3 |
+ ((d & 0x1FFE) >> 1));
+ break;
+ case 32:
+ SETSOURCEOFF((d & 0xFFC000) << 2 |
+ ((d & 0x3FFC) >> 2));
+ break;
+ }
+#undef d
+ }
+ else {
+ (*pApm->AccelInfoRec->Sync)(pScrn);
+ dstPtr = (CARD32 *)pApm->ScratchMemOffset;
+ SETSOURCEOFF(pApm->ScratchMem);
+ }
+ pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * h) + 4) & ~7;
+ for (i = h; i-- > 0; ) {
+ for (j = wrd; j-- > 0; ) {
+ *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src);
+ src += 4;
+ }
+ src += srcwidth;
+ }
+ A(WaitForFifo)(pApm, 1);
+#ifdef FASTER
+ SETWIDTHHEIGHT(wr, h);
+#else
+ SETDEC(c);
+#endif
+ }
+ else {
+ int i, j;
+
+#ifndef FASTER
+ SETWIDTHHEIGHT(w, h);
+#endif
+ if (pApm->ScratchMemPtr + h * wrd * 4 < pApm->ScratchMemEnd) {
+#define d ((memType)dstPtr - (memType)pApm->FbBase)
+ A(WaitForFifo)(pApm, 1);
+ dstPtr = (CARD32 *)pApm->ScratchMemPtr;
+ switch(pApm->CurrentLayout.bitsPerPixel) {
+ case 8: case 24:
+ SETSOURCEOFF((d & 0xFFF000) << 4 |
+ (d & 0xFFF));
+ break;
+ case 16:
+ SETSOURCEOFF((d & 0xFFE000) << 3 |
+ ((d & 0x1FFE) >> 1));
+ break;
+ case 32:
+ SETSOURCEOFF((d & 0xFFC000) << 2 |
+ ((d & 0x3FFC) >> 2));
+ break;
+ }
+#undef d
+ }
+ else {
+ (*pApm->AccelInfoRec->Sync)(pScrn);
+ dstPtr = (CARD32 *)pApm->ScratchMemOffset;
+ SETSOURCEOFF(pApm->ScratchMem);
+ }
+ pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * h) + 4) & ~7;
+ for (i = h; i-- > 0; ) {
+ for (j = wrd; j-- > 0; ) {
+ if (i || j)
+ *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src);
+ else if (srcwidth > -8) {
+ ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[2]];
+ ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[1]];
+ ((CARD8 *)dstPtr)[2] = byte_reversed[((CARD8 *)src)[0]];
+ dstPtr = (CARD32 *)(3 + (CARD8 *)dstPtr);
+ }
+ else if (srcwidth > -16) {
+ ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[1]];
+ ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[0]];
+ dstPtr = (CARD32 *)(2 + (CARD8 *)dstPtr);
+ }
+ else {
+ *(CARD8 *)dstPtr = byte_reversed[*(CARD8 *)src];
+ dstPtr = (CARD32 *)(1 + (CARD8 *)dstPtr);
+ }
+ src += 4;
+ }
+ src += srcwidth;
+ }
+ A(WaitForFifo)(pApm, 1);
+#ifdef FASTER
+ SETWIDTHHEIGHT(w, h);
+#else
+ SETDEC(c);
+#endif
+ }
+ }
+ pApm->apmClip = apmClip;
+}
+
+static void
+A(TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ int skipleft, int startline,
+ unsigned int **glyphs, int glyphWidth,
+ int fg, int bg, int rop, unsigned planemask)
+{
+ CARD32 *base, *base0;
+ GlyphScanlineFuncPtr GlyphFunc = XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1];
+ int w2, h2, dwords;
+
+ w2 = w + skipleft;
+ h2 = h;
+ dwords = (w2 + 31) >> 5;
+ dwords <<= 2;
+
+ base0 = base = (CARD32*)xalloc(dwords * h);
+ if (!base)
+ return; /* Should not happen : it's rather small... */
+
+ while(h--) {
+ base = (*GlyphFunc)(base, glyphs, startline++, w2, glyphWidth);
+ }
+
+ A(WriteBitmap)(pScrn, x, y, w, h2, (unsigned char *)base0, dwords,
+ skipleft, fg, bg, rop, planemask);
+
+ xfree(base0);
+}
+
+static void A(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetupForMono8x8PatternFill);
+ pApm->apmTransparency = (pApm->Chipset >= AT3D) && (bg == -1);
+ pApm->Bg8x8 = bg;
+ pApm->Fg8x8 = fg;
+ pApm->rop = apmROP[rop];
+ A(WaitForFifo)(pApm, 3 + pApm->apmClip);
+ if (bg == -1)
+ SETBACKGROUNDCOLOR(fg + 1);
+ else
+ SETBACKGROUNDCOLOR(bg);
+ SETFOREGROUNDCOLOR(fg);
+ if (pApm->Chipset >= AT3D)
+ SETROP(apmROP[rop] & 0xF0);
+ else
+ SETROP((apmROP[rop] & 0xF0) | 0x0A);
+ if (pApm->apmClip) {
+ SETCLIP_CTRL(0);
+ pApm->apmClip = FALSE;
+ }
+}
+
+static void A(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx,
+ int paty, int x, int y,
+ int w, int h)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SubsequentMono8x8PatternFillRect);
+ SETDESTXY(x, y);
+ UPDATEDEST(x, y + h + 1);
+ A(WaitForFifo)(pApm, 6);
+ if (pApm->Chipset == AT24 && pApm->Bg8x8 != -1) {
+ SETROP(pApm->rop);
+ SETFOREGROUNDCOLOR(pApm->Bg8x8);
+#ifdef FASTER
+ SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) |
+ DEC_DEST_XY | DEC_QUICKSTART_ONDIMX);
+ SETWIDTHHEIGHT(w, h);
+#else
+ SETWIDTHHEIGHT(w, h);
+ SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) |
+ DEC_DEST_XY | DEC_START);
+#endif
+ A(WaitForFifo)(pApm, 6);
+ SETROP((pApm->rop & 0xF0) | 0x0A);
+ SETFOREGROUNDCOLOR(pApm->Fg8x8);
+ }
+ SETPATTERN(patx, paty);
+#ifdef FASTER
+ SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) |
+ DEC_DEST_XY | DEC_PATTERN_88_1bMONO | DEC_DEST_UPD_TRCORNER |
+ (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) |
+ DEC_QUICKSTART_ONDIMX);
+ SETWIDTHHEIGHT(w, h);
+#else
+ SETWIDTHHEIGHT(w, h);
+ SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) |
+ DEC_DEST_XY | DEC_PATTERN_88_1bMONO | DEC_DEST_UPD_TRCORNER |
+ (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) |
+ DEC_START);
+#endif
+}
+
+#if 0
+static void
+A(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, int bg,
+ int rop, unsigned int planemask)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetupForCPUToScreenColorExpandFill);
+ if (bg == -1)
+ {
+#ifndef FASTER
+ pApm->apmTransparency = TRUE;
+ A(WaitForFifo)(pApm, 3);
+#else
+ A(WaitForFifo)(pApm, 4);
+ SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG |
+ DEC_SOURCE_TRANSPARENCY | DEC_SOURCE_MONOCHROME | DEC_QUICKSTART_ONDIMX |
+ DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC);
+#endif
+ SETFOREGROUNDCOLOR(fg);
+ SETBACKGROUNDCOLOR(fg+1);
+ }
+ else
+ {
+#ifndef FASTER
+ pApm->apmTransparency = FALSE;
+ A(WaitForFifo)(pApm, 3);
+#else
+ A(WaitForFifo)(pApm, 4);
+ SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG |
+ DEC_DEST_UPD_TRCORNER | DEC_SOURCE_MONOCHROME |
+ DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC);
+#endif
+ SETFOREGROUNDCOLOR(fg);
+ SETBACKGROUNDCOLOR(bg);
+ }
+ SETROP(apmROP[rop]);
+}
+
+static void
+A(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h, int skipleft)
+{
+ APMDECL(pScrn);
+#ifndef FASTER
+ u32 c;
+#endif
+
+ DPRINTNAME(SubsequentCPUToScreenColorExpandFill);
+#ifndef FASTER
+ c = DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG |
+ DEC_SOURCE_MONOCHROME | DEC_START | DEC_DEST_UPD_TRCORNER |
+ pApm->CurrentLayout.Setup_DEC;
+
+ if (pApm->apmTransparency)
+ c |= DEC_SOURCE_TRANSPARENCY;
+
+ A(WaitForFifo)(pApm, 7);
+#else
+ A(WaitForFifo)(pApm, 6);
+#endif
+
+ SETCLIP_LEFTTOP(x+skipleft, y);
+ SETCLIP_RIGHTBOT(x+w-1, y+h-1);
+ SETCLIP_CTRL(0x01);
+ pApm->apmClip = TRUE;
+ SETSOURCEX(0); /* According to manual, it just has to be zero */
+ SETDESTXY(x, y);
+ SETWIDTHHEIGHT((w + 31) & ~31, h);
+ UPDATEDEST(x + ((w + 31) & ~31), y);
+
+#ifndef FASTER
+ SETDEC(c);
+#endif
+}
+#endif
+
+static void
+A(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, unsigned int planemask,
+ int trans_color, int bpp, int depth)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetupForImageWrite);
+ if (trans_color != -1)
+ {
+#ifndef FASTER
+ pApm->apmTransparency = TRUE;
+ A(WaitForFifo)(pApm, 3);
+#else
+ A(WaitForFifo)(pApm, 4);
+ SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG |
+ DEC_SOURCE_TRANSPARENCY | DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC);
+#endif
+ SETBACKGROUNDCOLOR(trans_color);
+ }
+ else {
+#ifndef FASTER
+ pApm->apmTransparency = FALSE;
+ A(WaitForFifo)(pApm, 2);
+#else
+ A(WaitForFifo)(pApm, 3);
+ SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG |
+ DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC);
+#endif
+ }
+
+ SETROP(apmROP[rop]);
+}
+
+static void
+A(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ int skipleft)
+{
+ APMDECL(pScrn);
+#ifndef FASTER
+ u32 c;
+#endif
+
+ DPRINTNAME(SubsequentImageWriteRect);
+#ifndef FASTER
+ c = DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG |
+ DEC_START | pApm->CurrentLayout.Setup_DEC;
+
+ if (pApm->apmTransparency)
+ c |= DEC_SOURCE_TRANSPARENCY;
+
+ if (pApm->Chipset >= AT24)
+ A(WaitForFifo)(pApm, 7);
+ else
+ A(WaitForFifo)(pApm, 3);
+#else
+ if (pApm->Chipset >= AT24)
+ A(WaitForFifo)(pApm, 6);
+ else
+ A(WaitForFifo)(pApm, 3);
+#endif
+
+ SETCLIP_LEFTTOP(x+skipleft, y);
+ SETCLIP_RIGHTBOT(x+w-1, y+h-1);
+ SETCLIP_CTRL(0x01);
+ pApm->apmClip = TRUE;
+ if (pApm->Chipset < AT24)
+ A(WaitForFifo)(pApm, 4);
+ SETSOURCEX(0); /* According to manual, it just has to be zero */
+ SETDESTXY(x, y);
+ SETWIDTHHEIGHT((w + 3) & ~3, h);
+
+#ifndef FASTER
+ SETDEC(c);
+#endif
+}
+
+static void
+A(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h, int srcx, int srcy,
+ int offset)
+{
+ APMDECL(pScrn);
+ u32 c;
+
+ DPRINTNAME(SubsequentScreenToScreenColorExpandFill);
+#ifdef FASTER
+ c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME |
+ DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC;
+#else
+ c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME |
+ DEC_START | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC;
+#endif
+
+ if (pApm->apmTransparency)
+ c |= DEC_SOURCE_TRANSPARENCY;
+
+ if (srcy >= pApm->CurrentLayout.Scanlines) {
+ struct ApmStippleCacheRec *pCache;
+ CARD32 dist;
+
+ /*
+ * Offscreen linear stipple
+ */
+ pCache = &pApm->apmCache[srcy / pApm->CurrentLayout.Scanlines - 1];
+ if (w != pCache->apmStippleCache.w * pApm->CurrentLayout.bitsPerPixel) {
+ A(WaitForFifo)(pApm, 3);
+ SETCLIP_LEFTTOP(x, y);
+ SETCLIP_RIGHTBOT(x + w - 1, y + h - 1);
+ SETCLIP_CTRL(0x01);
+ pApm->apmClip = TRUE;
+ w = pCache->apmStippleCache.w * pApm->CurrentLayout.bitsPerPixel;
+ x -= srcx - pCache->apmStippleCache.x + offset;
+ srcx = (srcy - pCache->apmStippleCache.y) & 7;
+ srcy -= srcx;
+ y -= srcx;
+ h += srcx;
+ srcx = pCache->apmStippleCache.x;
+ }
+ else if (pApm->apmClip) {
+ A(WaitForFifo)(pApm, 1);
+ SETCLIP_CTRL(0x00);
+ pApm->apmClip = FALSE;
+ }
+ srcx += (srcy - pCache->apmStippleCache.y) * pCache->apmStippleCache.w;
+ srcy = pCache->apmStippleCache.y % pApm->CurrentLayout.Scanlines;
+ dist = srcx + srcy * pApm->CurrentLayout.displayWidth;
+ srcx = dist & 0xFFF;
+ srcy = dist >> 12;
+ c |= DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR;
+ }
+ else if (offset) {
+ A(WaitForFifo)(pApm, 3);
+ SETCLIP_LEFTTOP(x, y);
+ SETCLIP_RIGHTBOT(x + w, y + h);
+ SETCLIP_CTRL(0x01);
+ pApm->apmClip = TRUE;
+ w += offset;
+ x -= offset;
+ }
+ else if (pApm->apmClip) {
+ A(WaitForFifo)(pApm, 1);
+ SETCLIP_CTRL(0x00);
+ pApm->apmClip = FALSE;
+ }
+
+ A(WaitForFifo)(pApm, 4);
+
+ SETSOURCEXY(srcx, srcy);
+ SETDESTXY(x, y);
+
+#ifdef FASTER
+ SETDEC(c);
+ SETWIDTHHEIGHT(w, h);
+#else
+ SETWIDTHHEIGHT(w, h);
+ SETDEC(c);
+#endif
+ UPDATEDEST(x + w + 1, h);
+}
+
+static void
+A(SubsequentSolidBresenhamLine)(ScrnInfoPtr pScrn, int x1, int y1, int e1,
+ int e2, int err, int length, int octant)
+{
+ APMDECL(pScrn);
+#ifdef FASTER
+ u32 c = DEC_QUICKSTART_ONDIMX | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX |
+ pApm->CurrentLayout.Setup_DEC;
+#else
+ u32 c = DEC_START | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | pApm->CurrentLayout.Setup_DEC;
+#endif
+ int tmp;
+
+ DPRINTNAME(SubsequentSolidBresenhamLine);
+
+ A(WaitForFifo)(pApm, 5);
+ SETDESTXY(x1,y1);
+ SETDDA_ERRORTERM(err);
+ SETDDA_ADSTEP(e1, e2);
+
+ if (octant & YMAJOR) {
+ c |= DEC_MAJORAXIS_Y;
+ tmp = e1; e1 = e2; e2 = tmp;
+ }
+ else
+ c |= DEC_MAJORAXIS_X;
+
+ if (octant & XDECREASING) {
+ c |= DEC_DIR_X_NEG;
+ e1 = -e1;
+ }
+ else
+ c |= DEC_DIR_X_POS;
+
+ if (octant & YDECREASING) {
+ c |= DEC_DIR_Y_NEG;
+ e2 = -e2;
+ }
+ else
+ c |= DEC_DIR_Y_POS;
+
+#ifdef FASTER
+ SETDEC(c);
+ SETWIDTH(length);
+#else
+ SETWIDTH(length);
+ SETDEC(c);
+#endif
+
+ if (octant & YMAJOR)
+ UPDATEDEST(x1 + e1 / 2, y1 + e2 / 2);
+ else
+ UPDATEDEST(x1 + e2 / 2, y1 + e1 / 2);
+ if (pApm->apmClip)
+ {
+ pApm->apmClip = FALSE;
+ A(WaitForFifo)(pApm, 1);
+ SETCLIP_CTRL(0);
+ }
+}
+
+static void
+A(SubsequentSolidBresenhamLine6422)(ScrnInfoPtr pScrn, int x1, int y1, int e1,
+ int e2, int err, int length, int octant)
+{
+ APMDECL(pScrn);
+#ifdef FASTER
+ u32 c = DEC_QUICKSTART_ONDIMX | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX |
+ pApm->CurrentLayout.Setup_DEC;
+#else
+ u32 c = DEC_START | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | pApm->CurrentLayout.Setup_DEC;
+#endif
+ int tmp;
+
+ DPRINTNAME(SubsequentSolidBresenhamLine6422);
+
+ A(WaitForFifo)(pApm, 1);
+ SETDESTXY(x1,y1);
+ A(WaitForFifo)(pApm, 4);
+ SETDDA_ERRORTERM(err);
+ SETDDA_ADSTEP(e1, e2);
+
+ if (octant & YMAJOR) {
+ c |= DEC_MAJORAXIS_Y;
+ tmp = e1; e1 = e2; e2 = tmp;
+ }
+ else
+ c |= DEC_MAJORAXIS_X;
+
+ if (octant & XDECREASING) {
+ c |= DEC_DIR_X_NEG;
+ e1 = -e1;
+ }
+ else
+ c |= DEC_DIR_X_POS;
+
+ if (octant & YDECREASING) {
+ c |= DEC_DIR_Y_NEG;
+ e2 = -e2;
+ }
+ else
+ c |= DEC_DIR_Y_POS;
+
+#ifdef FASTER
+ SETDEC(c);
+ SETWIDTH(length);
+#else
+ SETWIDTH(length);
+ SETDEC(c);
+#endif
+
+ if (octant & YMAJOR)
+ UPDATEDEST(x1 + e1 / 2, y1 + e2 / 2);
+ else
+ UPDATEDEST(x1 + e2 / 2, y1 + e1 / 2);
+ if (pApm->apmClip)
+ {
+ pApm->apmClip = FALSE;
+ A(WaitForFifo)(pApm, 1);
+ SETCLIP_CTRL(0);
+ }
+}
+
+static void
+A(SetClippingRectangle)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetClippingRectangle);
+ A(WaitForFifo)(pApm, 3);
+ SETCLIP_LEFTTOP(x1,y1);
+ SETCLIP_RIGHTBOT(x2,y2);
+ SETCLIP_CTRL(0x01);
+ pApm->apmClip = TRUE;
+}
+
+static void
+A(SyncBlt)(ApmPtr pApm)
+{
+ int again = (pApm->Chipset == AP6422);
+
+ do {
+ while (!(STATUS() & STATUS_HOSTBLTBUSY))
+ ;
+ }
+ while (again--); /* See remark in Sync6422 */
+}
+static void
+A(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ unsigned char *src, int srcwidth, int rop,
+ unsigned int planemask, int trans, int bpp, int depth)
+{
+ APMDECL(pScrn);
+ int dwords, skipleft, Bpp = bpp >> 3;
+ Bool beCareful = FALSE;
+ unsigned char *dst = ((unsigned char *)pApm->FbBase) + x * Bpp + y * pApm->CurrentLayout.bytesPerScanline;
+ int PlusOne = 0, mask, count;
+
+ DPRINTNAME(WritePixmap);
+ if (rop == GXnoop)
+ return;
+ /*
+ * The function seems to crash more than it feels good. I hope that a
+ * good sync will help. This sync is anyway needed for direct write.
+ */
+ (*pApm->AccelInfoRec->Sync)(pScrn);
+ /*
+ * First the fast case : source and dest have same alignment. Doc says
+ * it's faster to do it here, which may be true since one has to read
+ * the chip when CPU to screen-ing.
+ */
+ if ((skipleft = (long)src & 3L) == ((long)dst & 3L) && rop == GXcopy) {
+ int skipright;
+
+ if (skipleft)
+ skipleft = 4 - skipleft;
+ dwords = (skipright = w * Bpp - skipleft) >> 2;
+ skipright %= 4;
+ if (!skipleft && !skipright)
+ while (h-- > 0) {
+ CARD32 *src2 = (CARD32 *)src;
+ CARD32 *dst2 = (CARD32 *)dst;
+
+ for (count = dwords; count-- > 0; )
+ *dst2++ = *src2++;
+ src += srcwidth;
+ dst += pApm->CurrentLayout.bytesPerScanline;
+ }
+ else if (!skipleft)
+ while (h-- > 0) {
+ CARD32 *src2 = (CARD32 *)src;
+ CARD32 *dst2 = (CARD32 *)dst;
+
+ for (count = dwords; count-- > 0; )
+ *dst2++ = *src2++;
+ for (count = skipright; count-- > 0; )
+ ((char *)dst2)[count] = ((char *)src2)[count];
+ src += srcwidth;
+ dst += pApm->CurrentLayout.bytesPerScanline;
+ }
+ else if (!skipright)
+ while (h-- > 0) {
+ CARD32 *src2 = (CARD32 *)(src + skipleft);
+ CARD32 *dst2 = (CARD32 *)(dst + skipleft);
+
+ for (count = skipleft; count-- > 0; )
+ dst[count] = src[count];
+ for (count = dwords; count-- > 0; )
+ *dst2++ = *src2++;
+ src += srcwidth;
+ dst += pApm->CurrentLayout.bytesPerScanline;
+ }
+ else
+ while (h-- > 0) {
+ CARD32 *src2 = (CARD32 *)(src + skipleft);
+ CARD32 *dst2 = (CARD32 *)(dst + skipleft);
+
+ for (count = skipleft; count-- > 0; )
+ dst[count] = src[count];
+ for (count = dwords; count-- > 0; )
+ *dst2++ = *src2++;
+ for (count = skipright; count-- > 0; )
+ ((char *)dst2)[count] = ((char *)src2)[count];
+ src += srcwidth;
+ dst += pApm->CurrentLayout.bytesPerScanline;
+ }
+
+ return;
+ }
+
+ if (skipleft) {
+ if (Bpp == 3)
+ skipleft = 4 - skipleft;
+ else
+ skipleft /= Bpp;
+
+ if (x < skipleft) {
+ skipleft = 0;
+ beCareful = TRUE;
+ goto BAD_ALIGNMENT;
+ }
+
+ x -= skipleft;
+ w += skipleft;
+
+ if (Bpp == 3)
+ src -= 3 * skipleft;
+ else /* is this Alpha friendly ? */
+ src = (unsigned char*)((long)src & ~0x03L);
+ }
+
+BAD_ALIGNMENT:
+
+ dwords = ((w * Bpp) + 3) >> 2;
+ mask = (pApm->CurrentLayout.bitsPerPixel / 8) - 1;
+
+ if (dwords & mask) {
+ /*
+ * Experimental...
+ * It seems the AT3D needs a padding of scanline to a multiple of
+ * 4 pixels, not only bytes.
+ */
+ PlusOne = mask - (dwords & mask) + 1;
+ }
+
+ A(SetupForImageWrite)(pScrn, rop, planemask, trans, bpp, depth);
+ A(SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft);
+
+ if (beCareful) {
+ /* in cases with bad alignment we have to be careful not
+ to read beyond the end of the source */
+ if (((x * Bpp) + (dwords << 2)) > srcwidth) h--;
+ else beCareful = FALSE;
+ }
+
+ srcwidth -= (dwords << 2);
+
+ while (h--) {
+ for (count = dwords; count-- > 0; ) {
+ A(SyncBlt)(pApm);
+ *(CARD32*)pApm->BltMap = *(CARD32*)src;
+ src += 4;
+ }
+ src += srcwidth;
+ for (count = PlusOne; count-- > 0; ) {
+ int status;
+
+ while (!((status = STATUS()) & STATUS_HOSTBLTBUSY))
+ if (!(status & STATUS_ENGINEBUSY))
+ break;
+ if (pApm->Chipset == AP6422) /* See remark in Sync6422 */
+ while (!((status = STATUS()) & STATUS_HOSTBLTBUSY))
+ if (!(status & STATUS_ENGINEBUSY))
+ break;
+ if (status & STATUS_ENGINEBUSY)
+ *(CARD32*)pApm->BltMap = 0x00000000;
+ }
+ }
+ if (beCareful) {
+ int shift = ((long)src & 0x03L) << 3;
+
+ if (--dwords) {
+ for (count = dwords >> 2; count-- > 0; ) {
+ A(SyncBlt)(pApm);
+ *(CARD32*)pApm->BltMap = *(CARD32*)src;
+ src += 4;
+ }
+ }
+ A(SyncBlt)(pApm);
+ *((CARD32*)pApm->BltMap) = *((CARD32*)src) >> shift;
+ }
+
+ pApm->apmClip = FALSE;
+ A(WaitForFifo)(pApm, 1);
+ SETCLIP_CTRL(0);
+}
+
+static void
+A(FillImageWriteRects)(ScrnInfoPtr pScrn, int rop, unsigned int planemask,
+ int nBox, BoxPtr pBox, int xorg, int yorg,
+ PixmapPtr pPix)
+{
+ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
+ int x, y, phaseY, phaseX, phaseXB, height, width, blit_w;
+ int pHeight = pPix->drawable.height;
+ int pWidth = pPix->drawable.width;
+ int depth = pPix->drawable.depth;
+ int bpp = pPix->drawable.bitsPerPixel;
+ unsigned char *pSrc;
+ int srcwidth = pPix->devKind;
+
+ while(nBox--) {
+ x = pBox->x1;
+ y = pBox->y1;
+ phaseY = (pBox->y1 - yorg) % pHeight;
+ if(phaseY < 0) phaseY += pHeight;
+ phaseX = (x - xorg) % pWidth;
+ pSrc = (unsigned char *)pPix->devPrivate.ptr +
+ phaseX * pPix->drawable.bitsPerPixel / 8;
+ if(phaseX < 0) phaseX += pWidth;
+ height = pBox->y2 - pBox->y1;
+ width = pBox->x2 - x;
+
+ while(1) {
+ int ch = height, cp = phaseY, cy = y;
+
+ blit_w = pWidth - phaseX;
+ if(blit_w > width) blit_w = width;
+
+ while (ch > 0) {
+ int h = MIN(pHeight - cp, ch);
+
+ A(WritePixmap)(pScrn, x, cy, blit_w, h, pSrc + cp * srcwidth,
+ srcwidth, rop, planemask, FALSE, bpp, depth);
+ cy += h;
+ ch -= h;
+ cp = 0;
+ }
+
+ width -= blit_w;
+ if(!width) break;
+ x += blit_w;
+ phaseX = (phaseX + blit_w) % pWidth;
+ phaseXB = phaseX * pPix->drawable.bitsPerPixel / 8;
+ }
+ pBox++;
+ }
+
+ SET_SYNC_FLAG(infoRec);
+}
+
+static void A(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,int patx,int paty,
+ int rop, unsigned int planemask,
+ int transparency_color)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SetupForColor8x8PatternFillRect);
+ if (transparency_color != -1) {
+#ifndef FASTER
+ pApm->apmTransparency = TRUE;
+ A(WaitForFifo)(pApm, 2 + pApm->apmClip);
+#else
+ A(WaitForFifo)(pApm, 3 + pApm->apmClip);
+ SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT |
+ DEC_DEST_XY | DEC_PATTERN_88_8bCOLOR | DEC_SOURCE_TRANSPARENCY |
+ DEC_QUICKSTART_ONDIMX);
+#endif
+ SETBACKGROUNDCOLOR(transparency_color);
+ }
+ else {
+#ifndef FASTER
+ pApm->apmTransparency = FALSE;
+ A(WaitForFifo)(pApm, 1 + pApm->apmClip);
+#else
+ A(WaitForFifo)(pApm, 2 + pApm->apmClip);
+ SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT |
+ DEC_DEST_XY | DEC_PATTERN_88_8bCOLOR | DEC_QUICKSTART_ONDIMX);
+#endif
+ }
+ if (pApm->apmClip) {
+ SETCLIP_CTRL(0);
+ pApm->apmClip = FALSE;
+ }
+ SETROP(apmROP[rop]);
+}
+
+static void A(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx,
+ int paty, int x, int y,
+ int w, int h)
+{
+ APMDECL(pScrn);
+
+ DPRINTNAME(SubsequentColor8x8PatternFillRect);
+#ifndef FASTER
+ A(WaitForFifo)(pApm, 5);
+#else
+ A(WaitForFifo)(pApm, 4);
+#endif
+ SETSOURCEXY(patx, paty);
+ SETDESTXY(x, y);
+ SETWIDTHHEIGHT(w, h);
+ UPDATEDEST(x + w + 1, y);
+#ifndef FASTER
+ SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT |
+ DEC_DEST_XY | (pApm->apmTransparency * DEC_SOURCE_TRANSPARENCY) |
+ DEC_PATTERN_88_8bCOLOR | DEC_START);
+#endif
+}
+#endif
+
+static void
+A(Sync)(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+ volatile u32 i, stat;
+
+ for(i = 0; i < MAXLOOP; i++) {
+ stat = STATUS();
+ if ((!(stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY))) &&
+ ((stat & STATUS_FIFO) >= 8))
+ break;
+ }
+ if (i == MAXLOOP) {
+ unsigned int status = STATUS();
+
+ WRXB(0x1FF, 0);
+ if (!xf86ServerIsExiting())
+ FatalError("Hung in ApmSync" APM_SUFF_24 APM_SUFF_IOP "(%d) (Status = 0x%08X)\n", pScrn->pScreen->myNum, status);
+ }
+ if (pApm->apmClip) {
+ SETCLIP_CTRL(0);
+ pApm->apmClip = FALSE;
+ }
+}
+
+#if PSZ != 24
+static void
+A(Sync6422)(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+ volatile u32 i, j, stat;
+
+ for (j = 0; j < 2; j++) {
+ /*
+ * From Henrik Harmsen :
+ *
+ * This is a kludge. We can't trust the status register. Don't
+ * know why... We shouldn't be forced to read the status reg and get
+ * a correct value more than once...
+ */
+ for(i = 0; i < MAXLOOP; i++) {
+ stat = STATUS();
+ if ((!(stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY))) &&
+ ((stat & STATUS_FIFO) >= 4))
+ break;
+ }
+ }
+ if (i == MAXLOOP) {
+ unsigned int status = STATUS();
+
+ WRXB(0x1FF, 0);
+ if (!xf86ServerIsExiting())
+ FatalError("Hung in ApmSync6422() (Status = 0x%08X)\n", status);
+ }
+ if (pApm->apmClip) {
+ SETCLIP_CTRL(0);
+ pApm->apmClip = FALSE;
+ }
+}
+#endif
+#include "apm_video.c"
+
+
+#undef RDXB
+#undef RDXW
+#undef RDXL
+#undef WRXB
+#undef WRXW
+#undef WRXL
+#undef ApmWriteSeq
+#define RDXB RDXB_M
+#define RDXW RDXW_M
+#define RDXL RDXL_M
+#define WRXB WRXB_M
+#define WRXW WRXW_M
+#define WRXL WRXL_M
+#define ApmWriteSeq(idx, val) do { APMVGAB(0x3C4) = (idx); APMVGAB(0x3C5) = (val); break; } while(1)
+#undef DPRINTNAME
+#undef A
+#undef DEPTH
+#undef PSZ
+#undef IOP_ACCESS
+#undef APM_SUFF_24
+#undef APM_SUFF_IOP
diff --git a/src/apm_i2c.c b/src/apm_i2c.c
new file mode 100644
index 0000000..dc250b1
--- /dev/null
+++ b/src/apm_i2c.c
@@ -0,0 +1,86 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_i2c.c,v 1.7 2002/01/25 21:55:55 tsi Exp $ */
+
+#include "apm.h"
+#include "apm_regs.h"
+
+/* Inline functions */
+static __inline__ void
+WaitForFifo(ApmPtr pApm, int slots)
+{
+ if (!pApm->UsePCIRetry) {
+ volatile int i;
+#define MAXLOOP 1000000
+
+ for(i = 0; i < MAXLOOP; i++) {
+ if ((STATUS_IOP() & STATUS_FIFO) >= slots)
+ break;
+ }
+ if (i == MAXLOOP) {
+ unsigned int status = STATUS_IOP();
+
+ WRXB_IOP(0x1FF, 0);
+ FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
+ }
+ }
+}
+
+static void
+ApmI2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ unsigned int reg;
+ unsigned char lock;
+ ApmPtr pApm = ((ApmPtr)b->DriverPrivate.ptr);
+
+ lock = rdinx(pApm->xport, 0x10);
+ wrinx(pApm->xport, 0x10, 0x12);
+ WaitForFifo(pApm, 2);
+ reg = (RDXB_IOP(0xD0) & 0x07) | 0x60;
+ if(clock) reg |= 0x08;
+ if(data) reg |= 0x10;
+ WRXB_IOP(0xD0, reg);
+ if (lock)
+ wrinx(pApm->xport, 0x10, 0);
+}
+
+static void
+ApmI2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ unsigned int reg;
+ unsigned char lock;
+ ApmPtr pApm = ((ApmPtr)b->DriverPrivate.ptr);
+ unsigned char tmp;
+
+ lock = rdinx(pApm->xport, 0x10);
+ wrinx(pApm->xport, 0x10, 0x12);
+ WaitForFifo(pApm, 2);
+ tmp = RDXB_IOP(0xD0);
+ WRXB_IOP(0xD0, tmp & 0x07);
+ reg = STATUS_IOP();
+ *clock = (reg & STATUS_SCL) != 0;
+ *data = (reg & STATUS_SDA) != 0;
+ if (lock)
+ wrinx(pApm->xport, 0x10, 0);
+}
+
+Bool
+ApmI2CInit(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+ I2CBusPtr I2CPtr;
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if(!I2CPtr) return FALSE;
+
+ pApm->I2CPtr = I2CPtr;
+
+ I2CPtr->BusName = "Alliance bus";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = ApmI2CPutBits;
+ I2CPtr->I2CGetBits = ApmI2CGetBits;
+ I2CPtr->DriverPrivate.ptr = pApm;
+
+ if(!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/apm_regs.h b/src/apm_regs.h
new file mode 100644
index 0000000..633a1eb
--- /dev/null
+++ b/src/apm_regs.h
@@ -0,0 +1,231 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_regs.h,v 1.8 2002/01/25 21:55:55 tsi Exp $ */
+
+
+
+#define curr08 (curr - 0x30)
+#define curr16 ((CARD16 *)(curr - 0x30))
+#define curr32 ((CARD32 *)(curr - 0x30))
+#define check08(addr, val) \
+ ((addr) >= 0x80 || (((addr)&0xF8) == 0x48) || curr08[(addr)] != (val))
+#define check16(addr, val) \
+ ((addr) >= 0x80 || (((addr)&0xF8) == 0x48) || curr16[(addr) / 2] != (val)||\
+ ((addr) == 0x50 && curr32[0x40 / 4] & DEC_QUICKSTART_ONSOURCE)||\
+ ((addr) == 0x52 && curr32[0x40 / 4] & DEC_QUICKSTART_ONSOURCE)||\
+ ((addr) == 0x54 && curr32[0x40 / 4] & DEC_QUICKSTART_ONDEST) || \
+ ((addr) == 0x56 && curr32[0x40 / 4] & DEC_QUICKSTART_ONDEST) || \
+ ((addr) == 0x58 && curr32[0x40 / 4] & DEC_QUICKSTART_ONDIMX))
+#define check32(addr, val) \
+ ((addr) >= 0x80 || (((addr)&0xF8) == 0x48) || curr32[(addr) / 4] != (val)||\
+ ((addr) == 0x50 && curr32[0x40 / 4] & DEC_QUICKSTART_ONSOURCE)||\
+ ((addr) == 0x54 && curr32[0x40 / 4] & DEC_QUICKSTART_ONDEST) || \
+ ((addr) == 0x58 && curr32[0x40 / 4] & DEC_QUICKSTART_ONDIMX) || \
+ ((addr) == 0x40 && (val) & DEC_START))
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+/* Memory mapped access to extended registers */
+#define RDXB_M(addr) (MMIO_IN8 (pApm->MemMap, (addr)))
+#define RDXW_M(addr) (MMIO_IN16(pApm->MemMap, (addr)))
+#define RDXL_M(addr) (MMIO_IN32(pApm->MemMap, (addr)))
+#define WRXB_M(addr,val) do { if (check08((addr), (val))) { \
+ MMIO_OUT8 (pApm->MemMap, (addr), (val)); \
+ /*xf86DrvMsg(xf86Screens[pApm->pScreen->myNum]->scrnIndex, X_INFO, \
+ "File %s, line %d, %02X <- %02X\n", \
+ __FILE__, __LINE__, (addr), (val) & 255); */\
+ curr08[MIN((addr), 0x80)] = (val); }} while (0)
+#define WRXW_M(addr,val) do { if (check16((addr), (val))) { \
+ MMIO_OUT16(pApm->MemMap, (addr), (val)); \
+ /*xf86DrvMsg(xf86Screens[pApm->pScreen->myNum]->scrnIndex, X_INFO, \
+ "File %s, line %d, %02X <- %04X\n", \
+ __FILE__, __LINE__, (addr), (val)&65535); */\
+ curr16[MIN(((addr) / 2), 0x40)] = (val); }} while (0)
+#define WRXL_M(addr,val) do { if (check32((addr), (val))) { \
+ MMIO_OUT32(pApm->MemMap, (addr), (val)); \
+ /*xf86DrvMsg(xf86Screens[pApm->pScreen->myNum]->scrnIndex, X_INFO, \
+ "File %s, line %d, %02X <- %08X\n", \
+ __FILE__, __LINE__, (addr), (val)); */\
+ curr32[MIN(((addr) / 4), 0x20)] = (val); }} while (0)
+
+/* IO port access to extended registers */
+#define RDXB_IOP(addr) (wrinx(pApm->xport, 0x1D, (addr) >> 2), \
+ inb(pApm->xbase + ((addr) & 3)))
+#define RDXW_IOP(addr) (wrinx(pApm->xport, 0x1D, (addr) >> 2), \
+ inw(pApm->xbase + ((addr) & 2)))
+#define RDXL_IOP(addr) (wrinx(pApm->xport, 0x1D, (addr) >> 2), \
+ inl(pApm->xbase))
+#define WRXB_IOP(addr,val) \
+ do { \
+ if (check08((addr), (val))) { \
+ wrinx(pApm->xport, 0x1D, (addr) >> 2); \
+ outb(pApm->xbase + ((addr) & 3), (val)); \
+ curr08[MIN((addr), 0x80)] = (val); \
+ break; \
+ } \
+ } while (1)
+#define WRXW_IOP(addr,val) \
+ do { \
+ if (check16((addr), (val))) { \
+ wrinx(pApm->xport, 0x1D, (addr) >> 2); \
+ outw(pApm->xbase + ((addr) & 2), (val)); \
+ curr16[MIN(((addr) / 2), 0x40)] = (val); \
+ break; \
+ } \
+ } while (1)
+#define WRXL_IOP(addr,val) \
+ do { \
+ if (check32((addr), (val))) { \
+ wrinx(pApm->xport, 0x1D, (addr) >> 2); \
+ outl(pApm->xbase, (val)); \
+ curr32[MIN(((addr) / 4), 0x20)] = (val); \
+ break; \
+ } \
+ } while (1)
+
+#define WRXL WRXL_M
+#define WRXW WRXW_M
+#define WRXB WRXB_M
+#define RDXL RDXL_M
+#define RDXW RDXW_M
+#define RDXB RDXB_M
+#define UPDATEDEST(x,y) (void)(curr32[0x54 / 4] = ((y) << 16) | ((x) & 0xFFFF))
+
+/* Memory mapped access to VGA registers */
+#define APMVGAB(idx) (((volatile unsigned char *)pApm->VGAMap)[idx])
+#define APMVGAS(idx) (((volatile unsigned short *)pApm->VGAMap)[(idx) >> 1])
+#define APMVGAW(idx) (((volatile unsigned int *)pApm->VGAMap)[(idx) >> 2])
+#define ApmWriteCrtc(idx, val) do { APMVGAS(0x3D4) = ((val) << 8) | ((idx) & 0xFF); break; } while(1)
+#define ApmReadCrtc(idx) ((APMVGAB(0x3D4) = (idx)), APMVGAB(0x3D5))
+#define ApmWriteGr(idx, val) do { APMVGAS(0x3CE) = ((val) << 8) | ((idx) & 0xFF); break; } while(1)
+#define ApmReadGr(idx) ((APMVGAB(0x3CE) = (idx)), APMVGAB(0x3CF))
+#define ApmWriteSeq(idx, val) do { APMVGAB(0x3C4) = (idx); APMVGAB(0x3C5) = (val); break; } while(1)
+#define ApmReadSeq(idx) ((APMVGAB(0x3C4) = (idx)), APMVGAB(0x3C5))
+#define ApmWriteAttr(idx, val) do { int tmp = APMVGAB(0x3DA); APMVGAB(0x3C0) = (idx); APMVGAB(0x3C0) = (val); break; } while(1)
+#define ApmReadAttr(idx) (APMVGAB(0x3DA), (APMVGAB(0x3C0) = (idx)), APMVGAB(0x3C1))
+#define ApmWriteMiscOut(val) do { APMVGAB(0x3C2) = (val); break; } while(1)
+#define ApmReadMiscOut() APMVGAB(0x3CC)
+#define ApmWriteDacMask(val) do { APMVGAB(0x3C6) = (val); break; } while(1)
+#define ApmReadDacMask() APMVGAB(0x3C6)
+#define ApmWriteDacReadAddr(val)do { APMVGAB(0x3C7) = (val); break; } while(1)
+#define ApmWriteDacWriteAddr(val)do{ APMVGAB(0x3C8) = (val); break; } while(1)
+#define ApmWriteDacData(val) do { APMVGAB(0x3C9) = (val); break; } while(1)
+#define ApmReadDacData() APMVGAB(0x3C9)
+
+#define STATUS() (RDXL(0x1FC))
+#define STATUS_IOP() (RDXL_IOP(0x1FC))
+#define STATUS_FIFO (0x0F)
+#define STATUS_HOSTBLTBUSY (1 << 8)
+#define STATUS_ENGINEBUSY (1 << 10)
+#define STATUS_SDA (1 << 16)
+#define STATUS_SCL (1 << 17)
+
+#define SETFOREGROUNDCOLOR(c) WRXL(0x60,c)
+#define SETBACKGROUNDCOLOR(c) WRXL(0x64,c)
+
+#define SETSOURCEX(x) WRXW(0x50, x)
+#define SETSOURCEY(y) WRXW(0x52, y)
+#define SETSOURCEXY(x,y) WRXL(0x50, ((y) << 16) | ((x) & 0xFFFF))
+#define SETSOURCEOFF(o) WRXL(0x50, (o))
+
+#define SETDESTX(x) WRXW(0x54, x)
+#define SETDESTY(y) WRXW(0x56, y)
+#define SETDESTXY(x,y) WRXL(0x54, ((y) << 16) | ((x) & 0xFFFF))
+#define SETDESTOFF(o) WRXL(0x54, (o))
+
+#define SETWIDTH(w) WRXW(0x58, w)
+#define SETHEIGHT(h) WRXW(0x5A, h)
+#define SETWIDTHHEIGHT(w,h) WRXL(0x58, ((h) << 16) | ((w) & 0xFFFF))
+
+#define SETOFFSET(o) WRXW(0x5C, (o))
+#define SETSOURCEOFFSET(o) WRXW(0x5E, (o))
+
+#define SETBYTEMASK(mask) WRXB(0x47, (mask))
+
+#define SETPATTERN(p1, p2) do {WRXL(0x48, p1); WRXL(0x4C, p2);} while(0)
+
+#define SETDDA_AXIALSTEP(step) WRXW(0x70, (step))
+#define SETDDA_DIAGONALSTEP(step) WRXW(0x72, (step))
+#define SETDDA_ERRORTERM(eterm) WRXW(0x74, (eterm))
+#define SETDDA_ADSTEP(s1,s2) WRXL(0x70, ((s2) << 16)|((s1) & 0xFFFF))
+
+#define SETCLIP_CTRL(ctrl) WRXB(0x30, (ctrl))
+#define SETCLIP_LEFT(x) WRXW(0x38, (x))
+#define SETCLIP_TOP(y) WRXW(0x3A, (y))
+#define SETCLIP_LEFTTOP(x,y) WRXL(0x38, ((y) << 16) | ((x) & 0xFFFF))
+#define SETCLIP_RIGHT(x) WRXW(0x3C, (x))
+#define SETCLIP_BOT(y) WRXW(0x3E, (y))
+#define SETCLIP_RIGHTBOT(x,y) WRXL(0x3C, ((y) << 16) | ((x) & 0xFFFF))
+
+/* RASTER OPERATION REGISTER */
+/* P = pattern S = source D = destination */
+#define SETROP(rop) WRXB(0x46, (rop))
+#define ROP_P_and_S_and_D 0x80
+#define ROP_S_xor_D 0x66
+#define ROP_S 0xCC
+#define ROP_P 0xF0
+/* Then there are about 252 more operations ... */
+
+
+/* DRAWING ENGINE CONTROL REGISTER */
+#define SETDEC(control) WRXL(0x40, (control))
+#define DEC_OP_VECT_NOENDP 0x0000000D
+#define DEC_OP_VECT_ENDP 0x0000000C
+#define DEC_OP_HOSTBLT_SCREEN2HOST 0x00000009
+#define DEC_OP_HOSTBLT_HOST2SCREEN 0x00000008
+#define DEC_OP_STRIP 0x00000004
+#define DEC_OP_BLT_STRETCH 0x00000003
+#define DEC_OP_RECT 0x00000002
+#define DEC_OP_BLT 0x00000001
+#define DEC_OP_NOOP 0x00000000
+#define DEC_DIR_X_NEG (1 << 6)
+#define DEC_DIR_X_POS (0 << 6)
+#define DEC_DIR_Y_NEG (1 << 7)
+#define DEC_DIR_Y_POS (0 << 7)
+#define DEC_MAJORAXIS_X (0 << 8) /* Looks like an error in the docs ...*/
+#define DEC_MAJORAXIS_Y (1 << 8)
+#define DEC_SOURCE_LINEAR (1 << 9)
+#define DEC_SOURCE_XY (0 << 9)
+#define DEC_SOURCE_CONTIG (1 << 11)
+#define DEC_SOURCE_RECTANGULAR (0 << 11)
+#define DEC_SOURCE_MONOCHROME (1 << 12)
+#define DEC_SOURCE_COLOR (0 << 12)
+#define DEC_SOURCE_TRANSPARENCY (1 << 13)
+#define DEC_SOURCE_NO_TRANSPARENCY (0 << 13)
+#define DEC_BITDEPTH_MASK (7 << 14)
+#define DEC_BITDEPTH_24 (4 << 14)
+#define DEC_BITDEPTH_32 (3 << 14)
+#define DEC_BITDEPTH_16 (2 << 14)
+#define DEC_BITDEPTH_8 (1 << 14)
+#define DEC_DEST_LINEAR (1 << 18)
+#define DEC_DEST_XY (0 << 18)
+#define DEC_DEST_CONTIG (1 << 19)
+#define DEC_DEST_RECTANGULAR (0 << 19)
+#define DEC_DEST_TRANSPARENCY (1 << 20)
+#define DEC_DEST_NO_TRANSPARENCY (0 << 20)
+#define DEC_DEST_TRANSP_POLARITY (1 << 21)
+#define DEC_DEST_TRANSP_POLARITYINV (0 << 21)
+#define DEC_PATTERN_88_8bCOLOR (3 << 22)
+#define DEC_PATTERN_88_1bMONO (2 << 22)
+#define DEC_PATTERN_44_4bDITHER (1 << 22)
+#define DEC_PATTERN_NONE (0 << 22)
+#define DEC_WIDTH_MASK (7 << 24)
+#define DEC_WIDTH_1600 (7 << 24)
+#define DEC_WIDTH_1280 (6 << 24)
+#define DEC_WIDTH_1152 (5 << 24)
+#define DEC_WIDTH_1024 (4 << 24)
+#define DEC_WIDTH_800 (2 << 24)
+#define DEC_WIDTH_640 (1 << 24)
+#define DEC_WIDTH_LINEAR (0 << 24)
+#define DEC_DEST_UPD_LASTPIX (3 << 27)
+#define DEC_DEST_UPD_BLCORNER (2 << 27)
+#define DEC_DEST_UPD_TRCORNER (1 << 27)
+#define DEC_DEST_UPD_NONE (0 << 27)
+#define DEC_QUICKSTART_ONDEST (3 << 29)
+#define DEC_QUICKSTART_ONSOURCE (2 << 29)
+#define DEC_QUICKSTART_ONDIMX (1 << 29)
+#define DEC_QUICKSTART_NONE (0 << 29)
+#define DEC_START (1 << 31)
+#define DEC_START_NO (0 << 31)
+
+#define AT3D_SST_STATUS 0x1F4
+#define SST_BUSY 1
diff --git a/src/apm_rush.c b/src/apm_rush.c
new file mode 100644
index 0000000..9b4da96
--- /dev/null
+++ b/src/apm_rush.c
@@ -0,0 +1,730 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_rush.c,v 1.12 2003/02/12 21:46:42 tsi Exp $ */
+/*
+ * Copyright Loïc Grenié 1999
+ */
+
+#include "apm.h"
+#include "xaalocal.h"
+
+extern DriverRec APM;
+
+static Bool RushDestroyPixmap(PixmapPtr);
+static __inline__ void __xf86UnlockPixmap(ApmPtr, PixmapLinkPtr);
+static int xf86RushLockPixmap(int, PixmapPtr);
+static void xf86RushUnlockPixmap(int, PixmapPtr);
+static void xf86RushUnlockAllPixmaps(void);
+
+static Bool RushDestroyPixmap(PixmapPtr pPix)
+{
+ APMDECL(xf86Screens[pPix->drawable.pScreen->myNum]);
+ ApmPixmapPtr pPriv = APM_GET_PIXMAP_PRIVATE(pPix);
+
+ if (pPriv->num)
+ pApm->RushY[pPriv->num - 1] = 0;
+ return (*pApm->DestroyPixmap)(pPix);
+}
+
+static PixmapPtr RushCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
+{
+ APMDECL(xf86Screens[pScreen->myNum]);
+ PixmapPtr pPix = (*pApm->CreatePixmap)(pScreen, w, h, depth);
+ ApmPixmapPtr pPriv = APM_GET_PIXMAP_PRIVATE(pPix);
+
+ bzero(pPriv, sizeof(*pPriv));
+ return pPix;
+}
+
+static int
+xf86RushLockPixmap(int scrnIndex, PixmapPtr pix)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ APMDECL(pScrn);
+ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
+ ApmPixmapPtr pApmPriv = APM_GET_PIXMAP_PRIVATE(pix);
+ XAAPixmapPtr pXAAPriv = XAA_GET_PIXMAP_PRIVATE(pix);
+ FBAreaPtr area = pXAAPriv->offscreenArea;
+ int p2, width = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
+
+ if (pScrn->drv != &APM || pApm->Chipset != AT3D)
+ return 0;
+ pApm->apmLock = TRUE;
+ pApmPriv->num = 0;
+ if (area && pApm->pixelStride) {
+ if (area->RemoveAreaCallback) {
+ (*area->RemoveAreaCallback)(area);
+ xf86FreeOffscreenArea(area);
+ area = NULL;
+ }
+ else
+ return 0;
+ }
+ if (area) {
+ /*
+ * 1) Make it unmovable so that XAA won't know we're playing
+ * with the cache.
+ * 2) Play musical chairs if needed.
+ */
+ pApmPriv->MoveAreaCallback = area->MoveAreaCallback;
+ area->MoveAreaCallback = NULL;
+ pApmPriv->RemoveAreaCallback = area->RemoveAreaCallback;
+ area->RemoveAreaCallback = NULL;
+ pApmPriv->devPriv = area->devPrivate.ptr;
+ }
+ else {
+ pApmPriv->MoveAreaCallback = NULL;
+ pApmPriv->RemoveAreaCallback = NULL;
+ pApmPriv->devPriv = NULL;
+ }
+ if (pApm->pixelStride || !area ||
+ (((pix->drawable.x + pScrn->displayWidth * pix->drawable.y) *
+ pScrn->bitsPerPixel) & 32767)) {
+ int p1, i;
+
+ /*
+ * Not aligned on a 4KB boundary, need to move it around.
+ */
+ if (area)
+ xf86FreeOffscreenArea(area);
+ if (pApm->pixelStride) {
+ area = xf86AllocateLinearOffscreenArea(pScrn->pScreen,
+ ((pix->drawable.width * pix->drawable.height *
+ pix->drawable.depth) / pScrn->bitsPerPixel) +
+ 4095,
+ pScrn->displayWidth, NULL, NULL, NULL);
+ if (!area) {
+ xf86PurgeUnlockedOffscreenAreas(pScrn->pScreen);
+ area = xf86AllocateLinearOffscreenArea(pScrn->pScreen,
+ ((pix->drawable.width * pix->drawable.height *
+ pix->drawable.depth) / pScrn->bitsPerPixel) +
+ 4095,
+ pScrn->displayWidth, NULL, NULL, NULL);
+ }
+ if (area) {
+ if (!pApmPriv->devPriv) {
+ PixmapLinkPtr pLink;
+ ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr pScreenPix;
+
+ pLink = xalloc(sizeof(PixmapLink));
+ if (!pLink) {
+ xf86FreeOffscreenArea(area);
+ return 0;
+ }
+ pXAAPriv->flags |= OFFSCREEN;
+ pix->devKind = pApm->pixelStride;
+ pScreenPix = (*pScreen->GetScreenPixmap)(pScreen);
+ pix->devPrivate.ptr = pScreenPix->devPrivate.ptr;
+ pLink->next = infoRec->OffscreenPixmaps;
+ pLink->pPix = pix;
+ infoRec->OffscreenPixmaps = pLink;
+ }
+ for (i = 0; i < 7; i++)
+ if (!pApm->RushY[i])
+ break;
+ pApmPriv->num = i + 1;
+ pix->drawable.y = area->box.y1 + (i+1)*pApm->CurrentLayout.Scanlines;
+ pApm->RushY[i] = area->box.y1;
+ pix->drawable.x = (32768 - (((area->box.x1 + pScrn->displayWidth * area->box.y1) * pScrn->bitsPerPixel) & 32767)) / pApm->CurrentLayout.bitsPerPixel;
+ if (pix->drawable.x == 32768 / pApm->CurrentLayout.bitsPerPixel)
+ pix->drawable.x = 0;
+ }
+ }
+ else {
+ p2 = 1;
+ while (!(p2 & width))
+ p2 *= 2;
+ p1 = 4096 / p2 - 1;
+ switch(pScrn->bitsPerPixel) {
+ case 16:
+ p2 /= 2;
+ break;
+ case 32:
+ p2 /= 4;
+ break;
+ }
+ area = xf86AllocateOffscreenArea(pScrn->pScreen,
+ (pix->drawable.width * pix->drawable.bitsPerPixel) /
+ pScrn->bitsPerPixel,
+ pix->drawable.height + p1,
+ p2, NULL, NULL, pApmPriv->devPriv);
+ if (!area) {
+ xf86PurgeUnlockedOffscreenAreas(pScrn->pScreen);
+ area = xf86AllocateOffscreenArea(pScrn->pScreen,
+ (pix->drawable.width * pix->drawable.bitsPerPixel) /
+ pScrn->bitsPerPixel,
+ pix->drawable.height + p1,
+ p2, NULL, NULL, pApmPriv->devPriv);
+ }
+ if (area) {
+ int devKind = (pScrn->bitsPerPixel * pScrn->displayWidth) / 8;
+ int off = devKind * p1, h;
+ int goal = (-area->box.x1 * (pScrn->bitsPerPixel >> 3) - area->box.y1 * devKind) & 4095;
+
+ if (!pApmPriv->devPriv) {
+ PixmapLinkPtr pLink;
+ ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr pScreenPix;
+
+ pLink = xalloc(sizeof(PixmapLink));
+ if (!pLink) {
+ xf86FreeOffscreenArea(area);
+ return 0;
+ }
+ pXAAPriv->flags |= OFFSCREEN;
+ pix->devKind = pApm->CurrentLayout.bytesPerScanline;
+ pScreenPix = (*pScreen->GetScreenPixmap)(pScreen);
+ pix->devPrivate.ptr = pScreenPix->devPrivate.ptr;
+ pLink->next = infoRec->OffscreenPixmaps;
+ pLink->pPix = pix;
+ infoRec->OffscreenPixmaps = pLink;
+ }
+ pix->drawable.x = area->box.x1;
+ for (h = p1; h >= 0; h--, off -= devKind)
+ if ((off & 4095) == goal)
+ break;
+ for (i = 0; i < 7; i++)
+ if (!pApm->RushY[i])
+ break;
+ pApmPriv->num = i + 1;
+ pix->drawable.y = area->box.y1 + h + (i+1)*pApm->CurrentLayout.Scanlines;
+ pApm->RushY[i] = area->box.y1 + h;
+ }
+ }
+ if (!area && (pXAAPriv->flags & OFFSCREEN)) {
+ /*
+ * Failed, return the old one
+ */
+ switch(pScrn->bitsPerPixel) {
+ case 24:
+ case 8: p2 = 4; break;
+ case 16: p2 = 2; break;
+ case 32: p2 = 1; break;
+ default: p2 = 0; break;
+ }
+ pXAAPriv->offscreenArea =
+ area = xf86AllocateOffscreenArea(pScrn->pScreen,
+ pix->drawable.width, pix->drawable.height,
+ p2,
+ pApmPriv->MoveAreaCallback,
+ pApmPriv->RemoveAreaCallback,
+ pApmPriv->devPriv);
+ /* The allocate can not fail: we just removed the old one. */
+ pix->drawable.x = area->box.x1;
+ pix->drawable.y = area->box.y1;
+ }
+ if (!area)
+ return 0;
+ pXAAPriv->offscreenArea = area;
+ }
+ return pApm->LinAddress +
+ ((pix->drawable.x + pScrn->displayWidth *
+ (pix->drawable.y % pApm->CurrentLayout.Scanlines)) * pApm->CurrentLayout.bitsPerPixel) / 8;
+}
+
+static __inline__ void
+__xf86UnlockPixmap(ApmPtr pApm, PixmapLinkPtr pLink)
+{
+ PixmapPtr pix = pLink->pPix;
+ ApmPixmapPtr pApmPriv = APM_GET_PIXMAP_PRIVATE(pix);
+ XAAPixmapPtr pXAAPriv = XAA_GET_PIXMAP_PRIVATE(pix);
+ FBAreaPtr area = pXAAPriv->offscreenArea;
+ int i;
+
+ if (!area)
+ area = pLink->area;
+ if ((pXAAPriv->flags & OFFSCREEN) && !area->MoveAreaCallback && !area->RemoveAreaCallback) {
+ area->MoveAreaCallback = pApmPriv->MoveAreaCallback;
+ area->RemoveAreaCallback = pApmPriv->RemoveAreaCallback;
+ area->devPrivate.ptr = pApmPriv->devPriv;
+ }
+ i = pApmPriv->num;
+ if (i) {
+ pApm->RushY[i - 1] = 0;
+ pix->drawable.y %= pApm->CurrentLayout.Scanlines;
+ }
+}
+
+static void
+xf86RushUnlockPixmap(int scrnIndex, PixmapPtr pix)
+{
+ APMDECL(xf86Screens[scrnIndex]);
+ PixmapLinkPtr pLink = GET_XAAINFORECPTR_FROM_SCREEN(xf86Screens[scrnIndex]->pScreen)->OffscreenPixmaps;
+
+ if (xf86Screens[scrnIndex]->drv != &APM || pApm->Chipset != AT3D)
+ return;
+ if (pApm->apmLock) {
+ /*
+ * This is just an attempt, because Daryll is tampering with MY
+ * registers.
+ */
+ if (!pApm->noLinear) {
+ CARD8 db;
+
+ db = RDXB(0xDB);
+ WRXB(0xDB, (db & 0xF4) | 0x0A);
+ ApmWriteSeq(0x1B, 0x20);
+ ApmWriteSeq(0x1C, 0x2F);
+ }
+ else {
+ CARD8 db;
+
+ db = RDXB_IOP(0xDB);
+ WRXB_IOP(0xDB, (db & 0xF4) | 0x0A);
+ wrinx(pApm->xport, 0x1B, 0x20);
+ wrinx(pApm->xport, 0x1C, 0x2F);
+ }
+ pApm->apmLock = FALSE;
+ }
+ while (pLink && pLink->pPix != pix)
+ pLink = pLink->next;
+ if (pLink)
+ __xf86UnlockPixmap(pApm, pLink);
+}
+
+static void
+xf86RushUnlockAllPixmaps()
+{
+ int scrnIndex;
+
+ for (scrnIndex = 0; scrnIndex < screenInfo.numScreens; scrnIndex++) {
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ APMDECL(pScrn);
+ PixmapLinkPtr pLink = GET_XAAINFORECPTR_FROM_SCREEN(pScrn->pScreen)->OffscreenPixmaps;
+
+ if (pScrn->drv != &APM || pApm->Chipset != AT3D)
+ continue;
+ while(pLink) {
+ __xf86UnlockPixmap(pApm, pLink);
+ pLink = pLink->next;
+ }
+ }
+}
+
+/*
+
+Copyright (c) 1998 Daryll Strauss
+
+*/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "scrnintstr.h"
+#define _XF86RUSH_SERVER_
+#include "xf86rushstr.h"
+
+static unsigned char RushReqCode = 0;
+static int RushErrorBase;
+
+static DISPATCH_PROC(ProcXF86RushDispatch);
+static DISPATCH_PROC(ProcXF86RushQueryVersion);
+static DISPATCH_PROC(ProcXF86RushLockPixmap);
+static DISPATCH_PROC(ProcXF86RushUnlockPixmap);
+static DISPATCH_PROC(ProcXF86RushUnlockAllPixmaps);
+static DISPATCH_PROC(ProcXF86RushSetCopyMode);
+#if 0
+static DISPATCH_PROC(ProcXF86RushSetPixelStride);
+#endif
+static DISPATCH_PROC(ProcXF86RushOverlayPixmap);
+static DISPATCH_PROC(ProcXF86RushStatusRegOffset);
+static DISPATCH_PROC(ProcXF86RushAT3DEnableRegs);
+static DISPATCH_PROC(ProcXF86RushAT3DDisableRegs);
+
+static int rush_ext_generation = -1;
+
+static DISPATCH_PROC(SProcXF86RushDispatch);
+
+static void XF86RushResetProc(ExtensionEntry* extEntry);
+
+void
+XFree86RushExtensionInit(ScreenPtr pScreen)
+{
+ ExtensionEntry* extEntry;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ return;
+#endif
+ if (rush_ext_generation == serverGeneration) {
+ if (xf86Screens[pScreen->myNum]->drv == &APM &&
+ APMPTR(xf86Screens[pScreen->myNum])->Chipset == AT3D) {
+ pScreen->CreatePixmap = RushCreatePixmap;
+ pScreen->DestroyPixmap = RushDestroyPixmap;
+ }
+ return;
+ }
+ rush_ext_generation = serverGeneration;
+ if ((extEntry = AddExtension(XF86RUSHNAME,
+ XF86RushNumberEvents,
+ XF86RushNumberErrors,
+ ProcXF86RushDispatch,
+ SProcXF86RushDispatch,
+ XF86RushResetProc,
+ StandardMinorOpcode))) {
+ RushReqCode = (unsigned char)extEntry->base;
+ RushErrorBase = extEntry->errorBase;
+ if (xf86Screens[pScreen->myNum]->drv == &APM &&
+ APMPTR(xf86Screens[pScreen->myNum])->Chipset == AT3D) {
+ pScreen->CreatePixmap = RushCreatePixmap;
+ pScreen->DestroyPixmap = RushDestroyPixmap;
+ }
+ }
+ else {
+ pScreen->CreatePixmap = APMPTR(xf86Screens[pScreen->myNum])->CreatePixmap;
+ pScreen->DestroyPixmap = APMPTR(xf86Screens[pScreen->myNum])->DestroyPixmap;
+ }
+}
+
+/*ARGSUSED*/
+static void
+XF86RushResetProc (ExtensionEntry *extEntry)
+{
+}
+
+static int
+ProcXF86RushQueryVersion(register ClientPtr client)
+{
+ xXF86RushQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xXF86RushQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = XF86RUSH_MAJOR_VERSION;
+ rep.minorVersion = XF86RUSH_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sz_xXF86RushQueryVersionReply, (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcXF86RushLockPixmap(register ClientPtr client)
+{
+ REQUEST(xXF86RushLockPixmapReq);
+ xXF86RushLockPixmapReply rep;
+ PixmapPtr pix;
+
+ if (stuff->screen > screenInfo.numScreens)
+ return BadValue;
+
+ REQUEST_SIZE_MATCH(xXF86RushLockPixmapReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ pix = (PixmapPtr)SecurityLookupIDByType(client,
+ stuff->pixmap, RT_PIXMAP,
+ SecurityReadAccess);
+ rep.addr = xf86RushLockPixmap(stuff->screen, pix);
+
+ WriteToClient(client, SIZEOF(xXF86RushLockPixmapReply), (char*)&rep);
+ return client->noClientException;
+}
+
+static int
+ProcXF86RushUnlockPixmap(register ClientPtr client)
+{
+ REQUEST(xXF86RushUnlockPixmapReq);
+ PixmapPtr pix;
+
+ if (stuff->screen > screenInfo.numScreens)
+ return BadValue;
+
+ REQUEST_SIZE_MATCH(xXF86RushUnlockPixmapReq);
+ pix = (PixmapPtr)SecurityLookupIDByType(client,
+ stuff->pixmap, RT_PIXMAP,
+ SecurityReadAccess);
+ xf86RushUnlockPixmap(stuff->screen, pix);
+ return client->noClientException;
+}
+
+static int
+ProcXF86RushUnlockAllPixmaps(register ClientPtr client)
+{
+
+ REQUEST_SIZE_MATCH(xXF86RushUnlockAllPixmapsReq);
+ xf86RushUnlockAllPixmaps();
+ return client->noClientException;
+}
+
+static int
+ProcXF86RushSetCopyMode(register ClientPtr client)
+{
+ REQUEST(xXF86RushSetCopyModeReq);
+
+ REQUEST_SIZE_MATCH(xXF86RushSetCopyModeReq);
+ APMPTR(xf86Screens[stuff->screen])->CopyMode = stuff->CopyMode;
+ return client->noClientException;
+}
+
+#if 0
+static int
+ProcXF86RushSetPixelStride(register ClientPtr client)
+{
+ REQUEST(xXF86RushSetPixelStrideReq);
+
+ REQUEST_SIZE_MATCH(xXF86RushSetPixelStrideReq);
+ APMPTR(xf86Screens[stuff->screen])->pixelStride = stuff->PixelStride;
+ return client->noClientException;
+}
+#endif
+
+int
+ProcXF86RushDispatch (register ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if (!LocalClient(client))
+ return RushErrorBase + XF86RushClientNotLocal;
+
+ switch (stuff->data)
+ {
+ case X_XF86RushQueryVersion:
+ return ProcXF86RushQueryVersion(client);
+ case X_XF86RushLockPixmap:
+ return ProcXF86RushLockPixmap(client);
+ case X_XF86RushUnlockPixmap:
+ return ProcXF86RushUnlockPixmap(client);
+ case X_XF86RushUnlockAllPixmaps:
+ return ProcXF86RushUnlockAllPixmaps(client);
+ case X_XF86RushSetCopyMode:
+ return ProcXF86RushSetCopyMode(client);
+#if 0
+ case X_XF86RushSetPixelStride:
+ return ProcXF86RushSetPixelStride(client);
+#endif
+ case X_XF86RushOverlayPixmap:
+ return ProcXF86RushOverlayPixmap(client);
+ case X_XF86RushStatusRegOffset:
+ return ProcXF86RushStatusRegOffset(client);
+ case X_XF86RushAT3DEnableRegs:
+ return ProcXF86RushAT3DEnableRegs(client);
+ case X_XF86RushAT3DDisableRegs:
+ return ProcXF86RushAT3DDisableRegs(client);
+ default:
+ return BadRequest;
+ }
+}
+
+int
+SProcXF86RushDispatch (register ClientPtr client)
+{
+ return RushErrorBase + XF86RushClientNotLocal;
+}
+
+#include "xvdix.h"
+/*
+ * The one below is just a subtle modification of ProcXvShmPutImage
+ */
+
+static int
+ProcXF86RushOverlayPixmap(ClientPtr client)
+{
+ DrawablePtr pDraw;
+ ScrnInfoPtr pScrn;
+ PixmapPtr pPixmap;
+ XvPortPtr pPort;
+ XvImagePtr pImage = NULL;
+ GCPtr pGC;
+ int status, i;
+ unsigned char *offset;
+ ApmPtr pApm;
+ ApmPixmapPtr pPriv;
+ REQUEST(xXF86RushOverlayPixmapReq);
+
+ REQUEST_SIZE_MATCH(xXF86RushOverlayPixmapReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+
+ pScrn = xf86Screens[pDraw->pScreen->myNum];
+ pApm = APMPTR(pScrn);
+ if (pScrn->drv != &APM || pApm->Chipset != AT3D)
+ return (_XvBadPort);
+
+ if(!(pPort = LOOKUP_PORT(stuff->port, client) )) {
+ client->errorValue = stuff->port;
+ return (_XvBadPort);
+ }
+
+ if (pPort->id != stuff->port) {
+ if ((status = (*pPort->pAdaptor->ddAllocatePort)(stuff->port, pPort, &pPort)) != Success) {
+ client->errorValue = stuff->port;
+ return (status);
+ }
+ }
+
+ if (!(pPort->pAdaptor->type & XvImageMask) ||
+ !(pPort->pAdaptor->type & XvInputMask)) {
+ client->errorValue = stuff->port;
+ return (BadMatch);
+ }
+
+ status = XVCALL(diMatchPort)(pPort, pDraw);
+ if (status != Success)
+ return status;
+
+ pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
+ stuff->pixmap, RT_PIXMAP,
+ SecurityReadAccess);
+ if (!pPixmap) {
+ client->errorValue = stuff->pixmap;
+ return (BadPixmap);
+ }
+ status = XVCALL(diMatchPort)(pPort, (DrawablePtr)pPixmap);
+ if (status != Success)
+ return status;
+ pPriv = APM_GET_PIXMAP_PRIVATE(pPixmap);
+ pApm = APMPTR(pScrn);
+ if (pPriv->num == 0) {
+ client->errorValue = stuff->pixmap;
+ return (BadMatch);
+ }
+ offset = (unsigned char *)pApm->FbBase +
+ pApm->RushY[pPriv->num - 1] * pApm->CurrentLayout.bytesPerScanline +
+ pPixmap->drawable.x * pScrn->bitsPerPixel / 8;
+
+ for(i = 0; i < pPort->pAdaptor->nImages; i++) {
+ if(pPort->pAdaptor->pImages[i].id == stuff->id) {
+ pImage = &(pPort->pAdaptor->pImages[i]);
+ break;
+ }
+ }
+
+ if(!pImage)
+ return BadMatch;
+
+ pApm->PutImageStride = pPixmap->devKind;
+ status = XVCALL(diPutImage)(client, pDraw, pPort, pGC,
+ stuff->src_x, stuff->src_y,
+ stuff->src_w, stuff->src_h,
+ stuff->drw_x, stuff->drw_y,
+ stuff->drw_w, stuff->drw_h,
+ pImage, offset, TRUE,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height);
+ pApm->PutImageStride = 0;
+
+ return status;
+}
+
+static int
+ProcXF86RushStatusRegOffset(ClientPtr client)
+{
+ int scrnIndex;
+ ScrnInfoPtr pScrn;
+ ApmPtr pApm;
+ REQUEST(xXF86RushStatusRegOffsetReq);
+ xXF86RushStatusRegOffsetReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xXF86RushStatusRegOffsetReq);
+ scrnIndex = stuff->screen;
+ if (scrnIndex < 0 || scrnIndex > screenInfo.numScreens)
+ return BadValue;
+ pScrn = xf86Screens[scrnIndex];
+ pApm = APMPTR(pScrn);
+ if (pScrn->drv != &APM || pApm->Chipset != AT3D)
+ return BadMatch;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.offset = 0xFFEDF4;
+ if (client->swapped) {
+ swapl(&rep.offset, n);
+ }
+ WriteToClient(client, sz_xXF86RushStatusRegOffsetReply, (char *)&rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcXF86RushAT3DEnableRegs(ClientPtr client)
+{
+ u32 db, tmp;
+ int scrnIndex;
+ ScrnInfoPtr pScrn;
+ ApmPtr pApm;
+ REQUEST(xXF86RushAT3DEnableRegsReq);
+
+ REQUEST_SIZE_MATCH(xXF86RushAT3DEnableRegsReq);
+ scrnIndex = stuff->screen;
+ if (scrnIndex < 0 || scrnIndex > screenInfo.numScreens)
+ return BadValue;
+ pScrn = xf86Screens[scrnIndex];
+ pApm = APMPTR(pScrn);
+ if (pScrn->drv != &APM || pApm->Chipset != AT3D)
+ return BadMatch;
+ pApm->Rush = 0x04;
+ if (!pApm->noLinear) {
+ db = RDXL(0xDB);
+ WRXL(0xDB, db | 0x04);
+ WRXB(0x110, 0x03);
+ tmp = RDXB(0x1F0);
+ WRXB(0x1F0, tmp | 0xD0);
+ tmp = RDXB(0x1F1);
+ WRXB(0x1F1, (tmp & ~0xC0) | 0x10);
+ tmp = RDXB(0x1F2);
+ WRXB(0x1F2, tmp | 0x10);
+ }
+ else {
+ db = RDXL(0xDB);
+ WRXL_IOP(0xDB, db | 0x04);
+ WRXB_IOP(0x110, 0x03);
+ tmp = RDXB_IOP(0x1F0);
+ WRXB_IOP(0x1F0, tmp | 0xD0);
+ tmp = RDXB_IOP(0x1F1);
+ WRXB_IOP(0x1F1, (tmp & ~0xC0) | 0x10);
+ tmp = RDXB_IOP(0x1F2);
+ WRXB_IOP(0x1F2, tmp | 0x10);
+ }
+
+ return client->noClientException;
+}
+
+static int
+ProcXF86RushAT3DDisableRegs(ClientPtr client)
+{
+ u32 db, tmp;
+ int scrnIndex;
+ ScrnInfoPtr pScrn;
+ ApmPtr pApm;
+ REQUEST(xXF86RushAT3DDisableRegsReq);
+
+ REQUEST_SIZE_MATCH(xXF86RushAT3DDisableRegsReq);
+ scrnIndex = stuff->screen;
+ if (scrnIndex < 0 || scrnIndex > screenInfo.numScreens)
+ return BadValue;
+ pScrn = xf86Screens[scrnIndex];
+ pApm = APMPTR(pScrn);
+ if (pScrn->drv != &APM || pApm->Chipset != AT3D)
+ return BadMatch;
+ if (!pApm->noLinear) {
+ tmp = RDXB(0x1F2);
+ WRXB(0x1F2, tmp & ~0x10);
+ tmp = RDXB(0x1F0);
+ WRXB(0x1F0, tmp & ~0xD0);
+ WRXB(0x110, 0);
+ pApm->Rush = 0x00;
+ db = RDXL(0xDB);
+ WRXL(0xDB, db & ~0x04);
+ }
+ else {
+ tmp = RDXB_IOP(0x1F2);
+ WRXB_IOP(0x1F2, tmp & ~0x10);
+ tmp = RDXB_IOP(0x1F0);
+ WRXB_IOP(0x1F0, tmp & ~0xD0);
+ WRXB_IOP(0x110, 0);
+ pApm->Rush = 0x00;
+ db = RDXL_IOP(0xDB);
+ WRXL_IOP(0xDB, db & ~0x04);
+ }
+
+ return client->noClientException;
+}
diff --git a/src/apm_video.c b/src/apm_video.c
new file mode 100644
index 0000000..4f57808
--- /dev/null
+++ b/src/apm_video.c
@@ -0,0 +1,986 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_video.c,v 1.9 2001/06/15 21:22:45 dawes Exp $ */
+
+#if PSZ != 24
+#include "dixstruct.h"
+
+/*
+ * Ported from mga_video.c by Loïc Grenié
+ */
+
+#ifndef XvExtension
+void A(InitVideo)(ScreenPtr pScreen) {}
+void A(ResetVideo)(ScrnInfoPtr pScrn) {}
+#else
+
+#ifndef OFF_DELAY
+#define OFF_DELAY 200
+#endif
+
+static XF86VideoAdaptorPtr A(SetupImageVideo)(ScreenPtr);
+
+static void A(StopVideo)(ScrnInfoPtr, pointer, Bool);
+static int A(SetPortAttribute)(ScrnInfoPtr, Atom, INT32, pointer);
+#ifndef IOP_ACCESS
+static int ApmGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static void ApmQueryBestSize(ScrnInfoPtr, Bool, short, short, short,
+ short, unsigned int *, unsigned int *,
+ pointer);
+static int ApmQueryImageAttributes(ScrnInfoPtr, int,
+ unsigned short *, unsigned short *,
+ int *, int *);
+#endif
+static int A(ReputImage)(ScrnInfoPtr, short, short, RegionPtr, pointer);
+static int A(PutImage)(ScrnInfoPtr, short, short, short, short, short,
+ short, short, short, int, unsigned char*,
+ short, short, Bool, RegionPtr, pointer);
+
+static void A(ResetVideo)(ScrnInfoPtr);
+static void A(XvMoveCB)(FBAreaPtr, FBAreaPtr);
+static void A(XvRemoveCB)(FBAreaPtr);
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+void A(InitVideo)(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors;
+ XF86VideoAdaptorPtr newAdaptor;
+ APMDECL(pScrn);
+ int num_adaptors;
+ Bool freeAdaptors = FALSE;
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+
+ if (pApm->Chipset >= AT24) {
+ if ((newAdaptor = A(SetupImageVideo)(pScreen))) {
+
+ newAdaptors = xalloc((num_adaptors + 1) *
+ sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ if(num_adaptors)
+ memcpy(newAdaptors, adaptors, num_adaptors *
+ sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newAdaptor;
+ adaptors = newAdaptors;
+ num_adaptors++;
+ freeAdaptors = TRUE;
+ }
+ }
+ }
+
+ if(num_adaptors)
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+
+ if(freeAdaptors)
+ xfree(adaptors);
+}
+
+#ifndef APM_VIDEO_DEFINES
+#define APM_VIDEO_DEFINES
+
+static Atom xvBrightness, xvContrast;
+
+/* client libraries expect an encoding */
+static XF86VideoEncodingRec DummyEncoding[1] =
+{
+ {
+ 0,
+ "XV_IMAGE",
+ 1024, 1024,
+ {1, 1}
+ }
+};
+
+#define NUM_FORMATS 24
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] =
+{
+ { 8, PseudoColor},
+ {15, PseudoColor},
+ {16, PseudoColor},
+ {24, PseudoColor},
+ {32, PseudoColor},
+ { 8, DirectColor},
+ {15, DirectColor},
+ {16, DirectColor},
+ {24, DirectColor},
+ {32, DirectColor},
+ { 8, TrueColor},
+ {15, TrueColor},
+ {16, TrueColor},
+ {24, TrueColor},
+ {32, TrueColor}
+};
+
+#define NUM_ATTRIBUTES 2
+
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
+{
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+
+#define NUM_IMAGES 8
+typedef char c8;
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+ {
+ 0x35315652,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','5',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 15, 0x001F, 0x03E0, 0x7C00,
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ {'R','V','B',0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ 0x36315652,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','6',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 16, 0x001F, 0x07E0, 0xF800,
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ {'R','V','B',0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ 0x32335652,
+ XvRGB,
+ LSBFirst,
+ {'R','V','3','2',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 32,
+ XvPacked,
+ 1,
+ 24, 0x0000FF, 0x00FF00, 0xFF0000,
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ {'R','V','B',0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ 0x59595959,
+ XvYUV,
+ LSBFirst,
+ {0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 8,
+ XvPacked,
+ 1,
+ 0, 0, 0, 0,
+ 8, 0, 0,
+ 1, 1, 1,
+ 1, 1, 1,
+ {'Y','Y','Y','Y',
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ 0x32315659,
+ XvYUV,
+ LSBFirst,
+ {'Y','V','1','2',
+ 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
+ 12,
+ XvPlanar,
+ 3,
+ 0, 0, 0, 0 ,
+ 8, 8, 8,
+ 1, 2, 2,
+ 1, 2, 2,
+ {'Y','V','U',
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ 0x59565955,
+ XvYUV,
+ LSBFirst,
+ {'U','Y','V','Y',
+ 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
+ 16,
+ XvPlanar,
+ 1,
+ 0, 0, 0, 0,
+ 8, 8, 8,
+ 1, 2, 2,
+ 1, 1, 1,
+ {'U','Y','V','Y',
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ 0x55595659,
+ XvYUV,
+ LSBFirst,
+ {'Y','V','Y','U',
+ 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
+ 16,
+ XvPlanar,
+ 1,
+ 0, 0, 0, 0,
+ 8, 8, 8,
+ 1, 2, 2,
+ 1, 1, 1,
+ {'Y','V','Y','U',
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ 0x59555956,
+ XvYUV,
+ LSBFirst,
+ {'V','Y','U','Y',
+ 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
+ 16,
+ XvPlanar,
+ 1,
+ 0, 0, 0, 0,
+ 8, 8, 8,
+ 1, 2, 2,
+ 1, 1, 1,
+ {'V','Y','U','Y',
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ }
+};
+
+typedef struct {
+ Bool on;
+ unsigned char brightness;
+ unsigned char contrast;
+ unsigned short reg, val;
+ ApmPtr pApm;
+ int x1, x10, y1, drw_x, drw_y, Bpp, Bps;
+ FBAreaPtr area;
+ RegionRec clip;
+ int xnum, xden, ynum, yden;
+ CARD32 scalex, scaley;
+ CARD32 data;
+} ApmPortPrivRec, *ApmPortPrivPtr;
+#endif
+
+
+static void
+A(ResetVideo)(ScrnInfoPtr pScrn)
+{
+ APMDECL(pScrn);
+
+ A(WaitForFifo)(pApm, 2);
+ ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr)->on = 0;
+ ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr)->on = 0;
+ WRXW(0x82, 0);
+ WRXW(0x92, 0);
+}
+
+
+static XF86VideoAdaptorPtr
+A(SetupImageVideo)(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ APMDECL(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ ApmPortPrivPtr pPriv;
+
+ if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+ 2 * sizeof(ApmPortPrivRec) +
+ 2 * sizeof(DevUnion))))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES;
+ adapt->name = "Alliance Pro Motion video engine";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 2;
+ adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+ pPriv = (ApmPortPrivPtr)(&adapt->pPortPrivates[2]);
+ pPriv->pApm = pApm;
+ pPriv[1].pApm = pApm;
+ pPriv->reg = 0x82;
+ pPriv[1].reg = 0x92;
+ adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
+ adapt->pPortPrivates[1].ptr = (pointer)(pPriv + 1);
+ adapt->nAttributes = NUM_ATTRIBUTES;
+ adapt->pAttributes = Attributes;
+ adapt->nImages = NUM_IMAGES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = A(StopVideo);
+ adapt->SetPortAttribute = A(SetPortAttribute);
+ adapt->GetPortAttribute = ApmGetPortAttribute;
+ adapt->QueryBestSize = ApmQueryBestSize;
+ adapt->PutImage = A(PutImage);
+ adapt->ReputImage = A(ReputImage);
+ adapt->QueryImageAttributes = ApmQueryImageAttributes;
+
+ pPriv->brightness = 0;
+ pPriv->contrast = 128;
+ pPriv[1].brightness = 0;
+ pPriv[1].contrast = 128;
+
+ /* gotta uninit this someplace */
+ REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
+ REGION_INIT(pScreen, &(pPriv + 1)->clip, NullBox, 0);
+
+ pApm->adaptor = adapt;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+
+ A(ResetVideo)(pScrn);
+
+ return adapt;
+}
+
+#ifndef IOP_ACCESS
+/* ApmClipVideo -
+
+ 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.
+
+ extents is the extents of the clip region
+*/
+
+static void
+ApmClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2,
+ BoxPtr extents, INT32 width, INT32 height,
+ CARD32 *scalex, CARD32 *scaley, INT32 mask)
+{
+ INT32 vscale, hscale;
+ int diff;
+
+ if (dst->x2 - dst->x1 < *x2 - *x1)
+ dst->x2 = dst->x1 + *x2 - *x1;
+
+ if (dst->y2 - dst->y1 < *y2 - *y1)
+ dst->y2 = dst->y1 + *y2 - *y1;
+
+ *x1 <<= 12; *x2 <<= 16;
+ *y1 <<= 12; *y2 <<= 16;
+
+ hscale = (*x2 - *x1) / (dst->x2 - dst->x1);
+ vscale = (*y2 - *y1) / (dst->y2 - dst->y1);
+
+ 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 (*x2 - *x1 == 0x10000 * (dst->x2 - dst->x1)) /* Shrinking */
+ *scalex = 0;
+ else
+ *scalex = ((*x2 - *x1) / (dst->x2 - dst->x1)) >> 4;
+ if (*y2 - *y1 == 0x10000 * (dst->y2 - dst->y1)) /* Shrinking */
+ *scaley = 0;
+ else
+ *scaley = ((*y2 - *y1) / (dst->y2 - dst->y1)) >> 4;
+}
+#endif
+
+static void
+A(StopVideo)(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
+{
+ ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
+ APMDECL(pScrn);
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ pPriv->on = 0;
+ A(WaitForFifo)(pApm, 1);
+ WRXB(pPriv->reg, 0);
+}
+
+static int
+A(SetPortAttribute)(ScrnInfoPtr pScrn, Atom attribute, INT32 value,
+ pointer data)
+{
+ ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
+ /*APMDECL(pScrn);*/
+
+ if(attribute == xvBrightness) {
+ if((value < -128) || (value > 127))
+ return BadValue;
+ pPriv->brightness = value;
+ /* TODO : enable */
+ } else if(attribute == xvContrast) {
+ if((value < 0) || (value > 255))
+ return BadValue;
+ pPriv->contrast = value;
+ /* TODO : enable */
+ }
+
+ return Success;
+}
+
+#ifndef IOP_ACCESS
+static int
+ApmGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value,
+ pointer data)
+{
+ ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
+
+ if(attribute == xvBrightness) {
+ *value = pPriv->brightness;
+ } else
+ if(attribute == xvContrast) {
+ *value = pPriv->contrast;
+ }
+
+ return Success;
+}
+
+static void
+ApmQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h, pointer data)
+{
+ APMDECL(pScrn);
+ unsigned short round = ~pApm->CurrentLayout.mask32;
+
+ *p_w = drw_w & round;
+ *p_h = drw_h & round;
+}
+
+static void
+ApmCopyData(unsigned char *src, unsigned char *dst, int srcPitch, int dstPitch,
+ int h, int w)
+{
+ w <<= 1;
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+static void
+ApmCopyMungedData(unsigned char *src1, unsigned char *src2,
+ unsigned char *src3, unsigned char *dst1,
+ int srcPitch, int srcPitch2, int dstPitch, int h, int w)
+{
+ CARD32 *dst = (CARD32*)dst1;
+ int i, j;
+
+ dstPitch >>= 2;
+ w >>= 1;
+
+ for(j = 0; j < h; j++) {
+ for(i = 0; i < w; i++) {
+ dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
+ (src2[i] << 8) | (src3[i] << 24);
+ }
+ dst += dstPitch;
+ src1 += srcPitch;
+ if(j & 1) {
+ src2 += srcPitch2;
+ src3 += srcPitch2;
+ }
+ }
+}
+#endif
+
+static void A(XvMoveCB)(FBAreaPtr area1, FBAreaPtr area2)
+{
+ ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area1->devPrivate.ptr;
+ ApmPtr pApm = pPriv->pApm;
+
+ pPriv->on = 0;
+ A(WaitForFifo)(pApm, 1);
+ WRXB(pPriv->reg, 0); /* Stop video for this port */
+ pPriv->area = area2;
+}
+
+static void A(XvRemoveCB)(FBAreaPtr area)
+{
+ ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area->devPrivate.ptr;
+ ApmPtr pApm = pPriv->pApm;
+
+ pPriv->on = 0;
+ A(WaitForFifo)(pApm, 1);
+ WRXB(pPriv->reg, 0); /* Stop video for this port */
+ pPriv->area = NULL;
+}
+
+static int
+A(ReputImage)(ScrnInfoPtr pScrn, short drw_x, short drw_y,
+ RegionPtr clipBoxes, pointer pdata)
+{
+ APMDECL(pScrn);
+ ApmPortPrivPtr pPriv = pdata, pPriv0, pPriv1;
+ register int fx, fy;
+ CARD32 mask;
+ RegionRec Union;
+ RegionPtr reg0;
+ int nrects, CurrY, tile;
+ int X1, X2, Y1, y2, xmax, ymax;
+ BoxPtr rects;
+ Bool didit = 0;
+
+ mask = pApm->CurrentLayout.mask32;
+ fx = pScrn->frameX0 & ~mask;
+ fy = pScrn->frameY0 + 1;
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ pPriv->x1 += drw_x - pPriv->drw_x;
+ pPriv->x10 = ((pPriv->x1 + mask) & ~mask) - fx;
+ pPriv->y1 += drw_y - pPriv->drw_y;
+ pPriv->drw_x = drw_x;
+ pPriv->drw_y = drw_y;
+ A(WaitForFifo)(pApm, 2);
+ WRXW(pPriv->reg + 0x06, 0xFFF - ((pPriv->scalex * pPriv->x10) & 0xFFF));
+ WRXW(pPriv->reg + 0x0A, 0xFFF - ((pPriv->scaley * pPriv->y1) & 0xFFF));
+ pPriv0 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr;
+ pPriv1 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr;
+ reg0 = &pPriv0->clip;
+ bzero(&Union, sizeof Union);
+ REGION_EMPTY(pScreen, &Union);
+ REGION_INIT(pScreen, &Union, NullBox, 0);
+ REGION_UNION(pScreen, &Union, reg0, &pPriv1->clip);
+ nrects = REGION_NUM_RECTS(&Union);
+ rects = REGION_RECTS(&Union);
+ tile = 0x200;
+ xmax = pScrn->frameX1 - pScrn->frameX0 + 1;
+ ymax = pScrn->frameY1 - pScrn->frameY0;
+ CurrY = -1;
+ goto BEGIN_LOOP_1;
+ do {
+ rects++;
+BEGIN_LOOP_1:
+ X1 = ((rects->x1 + mask) & ~mask) - fx;
+ if (X1 < 0)
+ X1 = 0;
+ X2 = (rects->x2 & ~mask) - fx;
+ if (X2 > xmax)
+ X2 = xmax;
+ y2 = rects->y2 - fy;
+ } while ((X2 <= X1 || y2 < -1) && --nrects > 0);
+ Y1 = rects->y1 - fy;
+
+ while (!(STATUS() & 0x800));
+ while (STATUS() & 0x800);
+ while (nrects-- > 0) {
+ CARD32 reg, data;
+ int x1, x2, y1;
+
+ x1 = X1;
+ x2 = X2;
+ y1 = Y1;
+ if (y1 < -1) y1 = -1;
+ if (y1 > ymax)
+ break;
+ didit = 1;
+ if (y1 > CurrY) {
+ A(WaitForFifo)(pApm, 3);
+ WRXL(tile + 0x00, 0xFFF0011);
+ WRXL(tile + 0x04, y1 << 16);
+ WRXL(tile + 0x08, 0);
+ tile += 16;
+ }
+ if (RECT_IN_REGION(pScreen, reg0, rects)) {
+ pPriv = pPriv0;
+ reg = (x1 << 16) | 1;
+ }
+ else {
+ pPriv = pPriv1;
+ reg = (x1 << 16) | 2;
+ }
+ CurrY = y2;
+ if (nrects <= 0)
+ goto BEGIN_LOOP_2;
+ do {
+ rects++;
+BEGIN_LOOP_2:
+ X1 = ((rects->x1 + mask) & ~mask) - fx;
+ if (X1 < 0)
+ X1 = 0;
+ X2 = (rects->x2 & ~mask) - fx;
+ if (X2 > xmax)
+ X2 = xmax;
+ } while (X2 <= X1 && --nrects > 0);
+ Y1 = rects->y1 - fy;
+ y2 = rects->y2 - fy;
+ data = pPriv->data + (((x1 - pPriv->x10)
+ * pPriv->xden) / pPriv->xnum) * pPriv->Bpp +
+ (((y1 - pPriv->y1 + fy) * pPriv->yden) / pPriv->ynum) * pPriv->Bps;
+ A(WaitForFifo)(pApm, 4);
+ if (!nrects || tile == 0x2B0 || y1 < Y1) {
+ WRXL(tile , 0x10 | reg);
+ }
+ else {
+ WRXL(tile , reg);
+ }
+ WRXL(tile + 0x04, x2 | (CurrY << 16));
+ WRXL(tile + 0x08, (((x2-x1)*pPriv->xden+pPriv->xnum-1) / pPriv->xnum) |
+ (data << 16));
+ WRXB(tile + 0x0C, data >> 16);
+ tile += 16;
+ if (tile == 0x2C0) {
+ tile = 0x200;
+ break;
+ }
+ }
+ REGION_UNINIT(pScreen, &Union);
+
+ if (didit) {
+ A(WaitForFifo)(pApm, 1);
+ WRXW(0x8E, tile - 0x200);
+ }
+
+ if (didit ^ ((pPriv0->val | pPriv1->val) & 1)) {
+ if (didit) {
+ pPriv0->val |= 1;
+ pPriv1->val |= 1;
+ }
+ else {
+ pPriv0->val &= 0xFFFE;
+ pPriv1->val &= 0xFFFE;
+ }
+ if (pPriv0->on) {
+ A(WaitForFifo)(pApm, 1);
+ WRXW(0x82, pPriv0->val);
+ }
+ if (pPriv1->on) {
+ A(WaitForFifo)(pApm, 1);
+ WRXW(0x92, pPriv1->val);
+ }
+ }
+
+ return Success;
+}
+
+static int
+A(PutImage)(ScrnInfoPtr pScrn, 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)
+{
+ ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
+ ScreenPtr pScreen = pScrn->pScreen;
+ APMDECL(pScrn);
+ INT32 x1, x2, y1, y2;
+ unsigned char *dst_start;
+ int pitch, Bpp, new_h, offset = 0, offset2 = 0, offset3 = 0;
+ CARD32 mask;
+ FBAreaPtr area;
+ int srcPitch, dstPitch, srcPitch2 = 0;
+ int top, left, npixels, nlines;
+ BoxRec dstBox;
+ CARD32 scalex, scaley, scale;
+ CARD32 tmp;
+ Bool offscreen;
+
+ offscreen = (buf < (unsigned char *)pApm->FbBase ||
+ buf > (unsigned char *)pApm->FbBase + 0x400000);
+
+ if(drw_w > 16384) drw_w = 16384;
+
+ /* 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;
+
+ mask = pApm->CurrentLayout.mask32;
+
+ ApmClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(pScreen, clipBoxes), width, height,
+ &scalex, &scaley, mask);
+
+ pPriv->drw_x = drw_x;
+ pPriv->drw_y = drw_y;
+ pPriv->xnum = drw_w;
+ if (scalex)
+ pPriv->xden = src_w;
+ else
+ pPriv->xden = drw_w; /* If image is larger than window */
+ pPriv->ynum = drw_h;
+ if (scaley)
+ pPriv->yden = src_h;
+ else
+ pPriv->yden = drw_h;
+ if((x1 - x2 >= 0xFFFF) || (y1 - y2 >= 0xFFFF))
+ return Success;
+
+ Bpp = pScrn->bitsPerPixel >> 3;
+ pitch = Bpp * pScrn->displayWidth;
+
+ switch(id) {
+ case 0x32315659:
+ dstPitch = ((width << 1) + 3) & ~3;
+ srcPitch = (width + 3) & ~3;
+ offset2 = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ offset = srcPitch2 * (height >> 1);
+ offset3 = offset + offset2;
+ new_h = (2 * offset2 + pitch - 1) / pitch;
+ break;
+ case 0x59595959:
+ srcPitch = width;
+ dstPitch = (srcPitch + 3) & ~3;
+ offset = dstPitch * height;
+ new_h = (offset + pitch - 1) / pitch;
+ break;
+ case 0x32335652:
+ srcPitch = (width << 2);
+ dstPitch = (srcPitch + 3) & ~3;
+ offset = dstPitch * height;
+ new_h = (offset + pitch - 1) / pitch;
+ break;
+ default:
+ if (pApm->PutImageStride)
+ srcPitch = pApm->PutImageStride;
+ else
+ srcPitch = (width << 1);
+ dstPitch = (srcPitch + 3) & ~3;
+ offset = dstPitch * height;
+ new_h = (offset + pitch - 1) / pitch;
+ break;
+ }
+
+ area = pPriv->area;
+
+ /* Allocate offscreen memory */
+ if (offscreen && (!area || ((area->box.y2 - area->box.y1) < new_h))) {
+ Bool nukeMem = FALSE;
+ int max_w, max_h;
+
+ xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
+ FAVOR_WIDTH_THEN_AREA, PRIORITY_LOW);
+ if (max_w == pScrn->displayWidth && max_h >= new_h) {
+ area = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth, new_h,
+ 4, A(XvMoveCB), A(XvRemoveCB), pPriv);
+ if (area) {
+ if (pPriv->area)
+ xf86FreeOffscreenArea(pPriv->area);
+ }
+ else
+ area = pPriv->area; /* Should not happen */
+ }
+ if(!area) {
+ if(!(area = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth, new_h, 4,
+ A(XvMoveCB), A(XvRemoveCB), pPriv)))
+ {
+ nukeMem = TRUE;
+ }
+ } else {
+ if(!xf86ResizeOffscreenArea(area, pScrn->displayWidth, new_h)) {
+ xf86FreeOffscreenArea(area);
+ pPriv->area = area = NULL;
+ nukeMem = TRUE;
+ }
+ }
+ if(nukeMem) {
+ xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
+ FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
+
+ if((max_w < pScrn->displayWidth) || (max_h < new_h))
+ return BadAlloc;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+
+ area = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth, new_h, 4,
+ A(XvMoveCB), A(XvRemoveCB), pPriv);
+ }
+
+ pPriv->area = area;
+ }
+
+ /* copy data */
+ pPriv->x1 = dstBox.x1 /*drw_x*/;
+ pPriv->y1 = dstBox.y1 /*drw_y*/;
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+ switch(id) {
+ case 0x59595959:
+ pPriv->Bpp = 1;
+ break;
+ default:
+ pPriv->Bpp = 2;
+ left <<= 1;
+ break;
+ case 0x32335652:
+ pPriv->Bpp = 4;
+ left <<= 2;
+ break;
+ }
+ pPriv->Bps = pPriv->Bpp * pPriv->xden;
+ if (offscreen) {
+ offset = (area->box.y1 * pitch) + (top * dstPitch);
+ dst_start = ((unsigned char *)pApm->FbBase) +
+ (pPriv->data = offset + left);
+ switch(id) {
+ case 0x32315659:
+ top &= ~1;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 2);
+ offset2 += tmp;
+ offset3 += tmp;
+ nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+ ApmCopyMungedData(buf + (top * srcPitch) + (left >> 1),
+ buf + offset2, buf + offset3, dst_start,
+ srcPitch, srcPitch2, dstPitch, nlines, npixels);
+ break;
+ default:
+ if (id == 0x32335652)
+ npixels <<= 1;
+ else if (id == 0x59595959)
+ npixels >>= 1;
+ buf += (top * srcPitch) + left;
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ if (offscreen)
+ ApmCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
+ break;
+ }
+ }
+ else
+ pPriv->data = buf - (unsigned char *)pApm->FbBase;
+ pPriv->on = 1;
+ A(WaitForFifo)(pApm, 3);
+ WRXW(pPriv->reg + 0x02, dstPitch >> 2);
+ WRXW(pPriv->reg + 0x04, scalex);
+ WRXW(pPriv->reg + 0x08, scaley);
+ pPriv->scalex = scalex;
+ pPriv->scaley = scaley;
+ if (scalex && scaley)
+ scale = 0x0E00;
+ else if (scalex)
+ scale = 0x0600;
+ else if (scaley)
+ scale = 0x0A00;
+ else
+ scale = 0;
+ switch(id) {
+ case 0x59595959:
+ pPriv->val = 0x017B | scale;
+ break;
+ case 0x32335652:
+ pPriv->val = 0x002F | (scale & 0xF7FF);/*Smoothing filter doesn't work*/
+ break;
+ case 0x36315652:
+ pPriv->val = 0x002B | (scale & 0xF7FF);
+ break;
+ case 0x35315652:
+ pPriv->val = 0x0029 | (scale & 0xF7FF);
+ break;
+ case 0x59555956:
+ pPriv->val = 0x013B | scale;
+ break;
+ case 0x55595659:
+ pPriv->val = 0x014B | scale;
+ break;
+ case 0x32315659:
+ case 0x59565955:
+ default:
+ pPriv->val = 0x016B | scale;
+ break;
+ }
+
+ (void) A(ReputImage)(pScrn, drw_x, drw_y, clipBoxes, data);
+
+ A(WaitForFifo)(pApm, 1);
+ WRXW(pPriv->reg, pPriv->val);
+
+ return Success;
+}
+
+#ifndef IOP_ACCESS
+static int
+ApmQueryImageAttributes(ScrnInfoPtr pScrn, int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets)
+{
+ int size, tmp;
+
+ if(*w > 1024) *w = 1024;
+ if(*h > 1024) *h = 1024;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ case 0x32315659:
+ *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 0x59565955:
+ case 0x55595659:
+ case 0x59555956:
+ size = *w << 1;
+ goto common;
+ case 0x59595959:
+ default:
+ size = *w;
+common:
+ if (pitches)
+ pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+#endif
+#endif
+#endif
+