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