diff options
-rw-r--r-- | man/apm.man | 106 | ||||
-rw-r--r-- | src/apm.h | 243 | ||||
-rw-r--r-- | src/apm_accel.c | 753 | ||||
-rw-r--r-- | src/apm_cursor.c | 208 | ||||
-rw-r--r-- | src/apm_dga.c | 434 | ||||
-rw-r--r-- | src/apm_driver.c | 2371 | ||||
-rw-r--r-- | src/apm_funcs.c | 1558 | ||||
-rw-r--r-- | src/apm_i2c.c | 86 | ||||
-rw-r--r-- | src/apm_regs.h | 231 | ||||
-rw-r--r-- | src/apm_rush.c | 730 | ||||
-rw-r--r-- | src/apm_video.c | 986 |
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 + |