117a48c7cSmrg
217a48c7cSmrg#ifdef HAVE_CONFIG_H
317a48c7cSmrg#include "config.h"
417a48c7cSmrg#endif
517a48c7cSmrg
617a48c7cSmrg#include <X11/X.h>
717a48c7cSmrg#include <X11/Xproto.h>
817a48c7cSmrg#include "misc.h"
917a48c7cSmrg#include "input.h"
1017a48c7cSmrg#include "cursorstr.h"
1117a48c7cSmrg#include "regionstr.h"
1217a48c7cSmrg#include "scrnintstr.h"
1317a48c7cSmrg#include "servermd.h"
1417a48c7cSmrg#include "windowstr.h"
1517a48c7cSmrg#include "mipointer.h"
1617a48c7cSmrg
1717a48c7cSmrg#include "apm.h"
1817a48c7cSmrg
1917a48c7cSmrg#define CURSORWIDTH	64
2017a48c7cSmrg#define CURSORHEIGHT	64
2117a48c7cSmrg#define CURSORSIZE	(CURSORWIDTH * CURSORHEIGHT / 8)
2217a48c7cSmrg#define CURSORALIGN	((CURSORSIZE + 1023) & ~1023l)
2317a48c7cSmrg
2417a48c7cSmrgstatic void	ApmShowCursor(ScrnInfoPtr pScrn);
2517a48c7cSmrgstatic void	ApmHideCursor(ScrnInfoPtr pScrn);
2617a48c7cSmrgstatic void	ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
2717a48c7cSmrgstatic void	ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
2817a48c7cSmrgstatic void	ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data);
2917a48c7cSmrgstatic Bool	ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
3017a48c7cSmrg
3117a48c7cSmrgstatic u8 ConvertTable[256];
3217a48c7cSmrg
3317a48c7cSmrg/* Inline functions */
3417a48c7cSmrgstatic __inline__ void
3517a48c7cSmrgWaitForFifo(ApmPtr pApm, int slots)
3617a48c7cSmrg{
3717a48c7cSmrg  if (!pApm->UsePCIRetry) {
3817a48c7cSmrg    volatile int i;
3917a48c7cSmrg#define MAXLOOP 1000000
4017a48c7cSmrg
4117a48c7cSmrg    for(i = 0; i < MAXLOOP; i++) {
4217a48c7cSmrg      if ((STATUS() & STATUS_FIFO) >= slots)
4317a48c7cSmrg	break;
4417a48c7cSmrg    }
4517a48c7cSmrg    if (i == MAXLOOP) {
4617a48c7cSmrg      unsigned int status = STATUS();
4717a48c7cSmrg
4817a48c7cSmrg      WRXB(0x1FF, 0);
4917a48c7cSmrg      if (!xf86ServerIsExiting())
5017a48c7cSmrg	FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
5117a48c7cSmrg    }
5217a48c7cSmrg  }
5317a48c7cSmrg}
5417a48c7cSmrg
5517a48c7cSmrgvoid ApmHWCursorReserveSpace(ApmPtr pApm)
5617a48c7cSmrg{
5717a48c7cSmrg  pApm->OffscreenReserved	+= 2 * CURSORALIGN;
5817a48c7cSmrg  pApm->DisplayedCursorAddress	= pApm->BaseCursorAddress =
590dd80ee0Smrg  pApm->CursorAddress	= 1024 * xf86ScreenToScrn(pApm->pScreen)->videoRam -
6017a48c7cSmrg					pApm->OffscreenReserved;
6117a48c7cSmrg}
6217a48c7cSmrg
6317a48c7cSmrg
6417a48c7cSmrgint ApmHWCursorInit(ScreenPtr pScreen)
6517a48c7cSmrg{
660dd80ee0Smrg  ScrnInfoPtr		pScrn = xf86ScreenToScrn(pScreen);
6717a48c7cSmrg  APMDECL(pScrn);
6817a48c7cSmrg  xf86CursorInfoPtr	infoPtr;
6917a48c7cSmrg  u32			i;
7017a48c7cSmrg
7117a48c7cSmrg  infoPtr = xf86CreateCursorInfoRec();
7217a48c7cSmrg  if (!infoPtr)
7317a48c7cSmrg      return FALSE;
7417a48c7cSmrg
7517a48c7cSmrg  pApm->CursorInfoRec		= infoPtr;
7617a48c7cSmrg
7717a48c7cSmrg  infoPtr->MaxWidth	= CURSORWIDTH;
7817a48c7cSmrg  infoPtr->MaxHeight	= CURSORHEIGHT;
7917a48c7cSmrg
8017a48c7cSmrg  infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
8117a48c7cSmrg  infoPtr->SetCursorColors	= ApmSetCursorColors;
8217a48c7cSmrg  infoPtr->SetCursorPosition	= ApmSetCursorPosition;
8317a48c7cSmrg  infoPtr->LoadCursorImage	= ApmLoadCursorImage;
8417a48c7cSmrg  infoPtr->HideCursor		= ApmHideCursor;
8517a48c7cSmrg  infoPtr->ShowCursor		= ApmShowCursor;
8617a48c7cSmrg  infoPtr->UseHWCursor		= ApmUseHWCursor;
8717a48c7cSmrg
8817a48c7cSmrg  /* Set up the convert table for the input cursor data */
8917a48c7cSmrg  for (i = 0; i < 256; i++)
9017a48c7cSmrg    ConvertTable[i] = ((~i) & 0xAA) | (i & (i >> 1) & 0x55);
9117a48c7cSmrg
9217a48c7cSmrg  return xf86InitCursor(pScreen, infoPtr);
9317a48c7cSmrg}
9417a48c7cSmrg
9517a48c7cSmrg
9617a48c7cSmrgstatic void
9717a48c7cSmrgApmShowCursor(ScrnInfoPtr pScrn)
9817a48c7cSmrg{
9917a48c7cSmrg  APMDECL(pScrn);
10017a48c7cSmrg
10117a48c7cSmrg  WaitForFifo(pApm, 2);
10217a48c7cSmrg  WRXW(0x144, pApm->CursorAddress >> 10);
10317a48c7cSmrg  WRXB(0x140, 1);
10417a48c7cSmrg  pApm->DisplayedCursorAddress = pApm->CursorAddress;
10517a48c7cSmrg}
10617a48c7cSmrg
10717a48c7cSmrg
10817a48c7cSmrgstatic void
10917a48c7cSmrgApmHideCursor(ScrnInfoPtr pScrn)
11017a48c7cSmrg{
11117a48c7cSmrg  APMDECL(pScrn);
11217a48c7cSmrg
11317a48c7cSmrg  WaitForFifo(pApm, 1);
11417a48c7cSmrg  WRXB(0x140, 0);
11517a48c7cSmrg}
11617a48c7cSmrg
11717a48c7cSmrgstatic Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
11817a48c7cSmrg{
1190dd80ee0Smrg    return APMPTR(xf86ScreenToScrn(pScreen))->CurrentLayout.bitsPerPixel >= 8;
12017a48c7cSmrg}
12117a48c7cSmrg
12217a48c7cSmrgstatic void
12317a48c7cSmrgApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
12417a48c7cSmrg{
12517a48c7cSmrg  APMDECL(pScrn);
12617a48c7cSmrg  int	xoff, yoff;
12717a48c7cSmrg
12817a48c7cSmrg  if (x < -CURSORWIDTH || y < -CURSORHEIGHT) {
12917a48c7cSmrg      WaitForFifo(pApm, 1);
13017a48c7cSmrg      WRXB(0x140, 0);
13117a48c7cSmrg      return;
13217a48c7cSmrg  }
13317a48c7cSmrg
13417a48c7cSmrg  if (x < 0) {
13517a48c7cSmrg      xoff = -x;
13617a48c7cSmrg      x = 0;
13717a48c7cSmrg  }
13817a48c7cSmrg  else
13917a48c7cSmrg      xoff = 0;
14017a48c7cSmrg  if (y < 0) {
14117a48c7cSmrg      yoff = -y;
14217a48c7cSmrg      y = 0;
14317a48c7cSmrg  }
14417a48c7cSmrg  else
14517a48c7cSmrg      yoff = 0;
14617a48c7cSmrg
14717a48c7cSmrg  WaitForFifo(pApm, 2);
14817a48c7cSmrg  WRXW(0x14C, (yoff << 8) | (xoff & 0xFF));
14917a48c7cSmrg  WRXL(0x148, (y << 16) | (x & 0xFFFF));
15017a48c7cSmrg}
15117a48c7cSmrg
15217a48c7cSmrg
15317a48c7cSmrgstatic void
15417a48c7cSmrgApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
15517a48c7cSmrg{
15617a48c7cSmrg  APMDECL(pScrn);
15717a48c7cSmrg  u16 packedcolfg, packedcolbg;
15817a48c7cSmrg
15917a48c7cSmrg  if (pApm->CurrentLayout.bitsPerPixel == 8)
16017a48c7cSmrg  {
16117a48c7cSmrg    WaitForFifo(pApm, 2);
16217a48c7cSmrg    WRXB(0x141, fg);
16317a48c7cSmrg    WRXB(0x142, bg);
16417a48c7cSmrg  }
16517a48c7cSmrg  else
16617a48c7cSmrg  {
16717a48c7cSmrg    packedcolfg =
16817a48c7cSmrg      ((fg & 0xE00000) >> 16) |
16917a48c7cSmrg      ((fg & 0x00E000) >> 11) |
17017a48c7cSmrg      ((fg & 0x0000C0) >> 6);
17117a48c7cSmrg    packedcolbg =
17217a48c7cSmrg      ((bg & 0xE00000) >> 16) |
17317a48c7cSmrg      ((bg & 0x00E000) >> 11) |
17417a48c7cSmrg      ((bg & 0x0000C0) >> 6);
17517a48c7cSmrg    WaitForFifo(pApm, 2);
17617a48c7cSmrg    WRXB(0x141, packedcolfg);
17717a48c7cSmrg    WRXB(0x142, packedcolbg);
17817a48c7cSmrg  }
17917a48c7cSmrg}
18017a48c7cSmrg
18117a48c7cSmrg
18217a48c7cSmrgstatic void
18317a48c7cSmrgApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data)
18417a48c7cSmrg{
18517a48c7cSmrg  APMDECL(pScrn);
18617a48c7cSmrg  u32 i;
18717a48c7cSmrg  u8 tmp[2 * CURSORSIZE];
18817a48c7cSmrg
18917a48c7cSmrg  /* Correct input data */
19017a48c7cSmrg  for (i = 0; i < sizeof tmp; i++)
19117a48c7cSmrg    tmp[i] = ConvertTable[data[i]];
19217a48c7cSmrg  /*
19317a48c7cSmrg   * To avoid flicker.
19417a48c7cSmrg   * Note: 2*pApm->BaseCursorAddress + CURSORALIGN (=1024) < 2^31 all the time.
19517a48c7cSmrg   */
19617a48c7cSmrg  pApm->CursorAddress = 2*pApm->BaseCursorAddress + CURSORALIGN - pApm->DisplayedCursorAddress;
19717a48c7cSmrg  memcpy((u8*)pApm->FbBase + pApm->CursorAddress, tmp, sizeof tmp);
19817a48c7cSmrg}
199