1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include <X11/X.h> 7#include <X11/Xproto.h> 8#include "misc.h" 9#include "input.h" 10#include "cursorstr.h" 11#include "regionstr.h" 12#include "scrnintstr.h" 13#include "servermd.h" 14#include "windowstr.h" 15#include "mipointer.h" 16 17#include "apm.h" 18 19#define CURSORWIDTH 64 20#define CURSORHEIGHT 64 21#define CURSORSIZE (CURSORWIDTH * CURSORHEIGHT / 8) 22#define CURSORALIGN ((CURSORSIZE + 1023) & ~1023l) 23 24static void ApmShowCursor(ScrnInfoPtr pScrn); 25static void ApmHideCursor(ScrnInfoPtr pScrn); 26static void ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y); 27static void ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg); 28static void ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data); 29static Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs); 30 31static u8 ConvertTable[256]; 32 33/* Inline functions */ 34static __inline__ void 35WaitForFifo(ApmPtr pApm, int slots) 36{ 37 if (!pApm->UsePCIRetry) { 38 volatile int i; 39#define MAXLOOP 1000000 40 41 for(i = 0; i < MAXLOOP; i++) { 42 if ((STATUS() & STATUS_FIFO) >= slots) 43 break; 44 } 45 if (i == MAXLOOP) { 46 unsigned int status = STATUS(); 47 48 WRXB(0x1FF, 0); 49 if (!xf86ServerIsExiting()) 50 FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status); 51 } 52 } 53} 54 55void ApmHWCursorReserveSpace(ApmPtr pApm) 56{ 57 pApm->OffscreenReserved += 2 * CURSORALIGN; 58 pApm->DisplayedCursorAddress = pApm->BaseCursorAddress = 59 pApm->CursorAddress = 1024 * xf86ScreenToScrn(pApm->pScreen)->videoRam - 60 pApm->OffscreenReserved; 61} 62 63 64int ApmHWCursorInit(ScreenPtr pScreen) 65{ 66 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 67 APMDECL(pScrn); 68 xf86CursorInfoPtr infoPtr; 69 u32 i; 70 71 infoPtr = xf86CreateCursorInfoRec(); 72 if (!infoPtr) 73 return FALSE; 74 75 pApm->CursorInfoRec = infoPtr; 76 77 infoPtr->MaxWidth = CURSORWIDTH; 78 infoPtr->MaxHeight = CURSORHEIGHT; 79 80 infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1; 81 infoPtr->SetCursorColors = ApmSetCursorColors; 82 infoPtr->SetCursorPosition = ApmSetCursorPosition; 83 infoPtr->LoadCursorImage = ApmLoadCursorImage; 84 infoPtr->HideCursor = ApmHideCursor; 85 infoPtr->ShowCursor = ApmShowCursor; 86 infoPtr->UseHWCursor = ApmUseHWCursor; 87 88 /* Set up the convert table for the input cursor data */ 89 for (i = 0; i < 256; i++) 90 ConvertTable[i] = ((~i) & 0xAA) | (i & (i >> 1) & 0x55); 91 92 return xf86InitCursor(pScreen, infoPtr); 93} 94 95 96static void 97ApmShowCursor(ScrnInfoPtr pScrn) 98{ 99 APMDECL(pScrn); 100 101 WaitForFifo(pApm, 2); 102 WRXW(0x144, pApm->CursorAddress >> 10); 103 WRXB(0x140, 1); 104 pApm->DisplayedCursorAddress = pApm->CursorAddress; 105} 106 107 108static void 109ApmHideCursor(ScrnInfoPtr pScrn) 110{ 111 APMDECL(pScrn); 112 113 WaitForFifo(pApm, 1); 114 WRXB(0x140, 0); 115} 116 117static Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 118{ 119 return APMPTR(xf86ScreenToScrn(pScreen))->CurrentLayout.bitsPerPixel >= 8; 120} 121 122static void 123ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 124{ 125 APMDECL(pScrn); 126 int xoff, yoff; 127 128 if (x < -CURSORWIDTH || y < -CURSORHEIGHT) { 129 WaitForFifo(pApm, 1); 130 WRXB(0x140, 0); 131 return; 132 } 133 134 if (x < 0) { 135 xoff = -x; 136 x = 0; 137 } 138 else 139 xoff = 0; 140 if (y < 0) { 141 yoff = -y; 142 y = 0; 143 } 144 else 145 yoff = 0; 146 147 WaitForFifo(pApm, 2); 148 WRXW(0x14C, (yoff << 8) | (xoff & 0xFF)); 149 WRXL(0x148, (y << 16) | (x & 0xFFFF)); 150} 151 152 153static void 154ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 155{ 156 APMDECL(pScrn); 157 u16 packedcolfg, packedcolbg; 158 159 if (pApm->CurrentLayout.bitsPerPixel == 8) 160 { 161 WaitForFifo(pApm, 2); 162 WRXB(0x141, fg); 163 WRXB(0x142, bg); 164 } 165 else 166 { 167 packedcolfg = 168 ((fg & 0xE00000) >> 16) | 169 ((fg & 0x00E000) >> 11) | 170 ((fg & 0x0000C0) >> 6); 171 packedcolbg = 172 ((bg & 0xE00000) >> 16) | 173 ((bg & 0x00E000) >> 11) | 174 ((bg & 0x0000C0) >> 6); 175 WaitForFifo(pApm, 2); 176 WRXB(0x141, packedcolfg); 177 WRXB(0x142, packedcolbg); 178 } 179} 180 181 182static void 183ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data) 184{ 185 APMDECL(pScrn); 186 u32 i; 187 u8 tmp[2 * CURSORSIZE]; 188 189 /* Correct input data */ 190 for (i = 0; i < sizeof tmp; i++) 191 tmp[i] = ConvertTable[data[i]]; 192 /* 193 * To avoid flicker. 194 * Note: 2*pApm->BaseCursorAddress + CURSORALIGN (=1024) < 2^31 all the time. 195 */ 196 pApm->CursorAddress = 2*pApm->BaseCursorAddress + CURSORALIGN - pApm->DisplayedCursorAddress; 197 memcpy((u8*)pApm->FbBase + pApm->CursorAddress, tmp, sizeof tmp); 198} 199