/*
 * $XConsortium: mipsCursor.c,v 1.2 91/07/18 22:58:13 keith Exp $
 *
 * Copyright 1991 MIPS Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of MIPS not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  MIPS makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * MIPS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL MIPS
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#ident	"$Header: mipsCursor.c,v 1.2 91/07/18 22:58:13 keith Exp $"

/*
 * Device independent (?) part of HW cursor support
 */



#include <signal.h>

#define NEED_EVENTS
#include <X.h>
#include "Xproto.h"
#include <misc.h>
#include <input.h>
#include <cursorstr.h>
#include <mipointer.h>
#include <regionstr.h>
#include <scrnintstr.h>
#include <servermd.h>
#include <windowstr.h>
#include "x386.h"
#include "x386Priv.h"
#include "x386OSD.h"
#include "ibm8514.h"
#include "reg8514.h"



static Bool s3RealizeCursor();
static Bool s3UnrealizeCursor();
static void s3SetCursor();
static void s3MoveCursor();
static void s3RecolorCursor();

static miPointerSpriteFuncRec s3PointerSpriteFuncs = {
	s3RealizeCursor,
	s3UnrealizeCursor,
	s3SetCursor,
	s3MoveCursor,
};

extern miPointerScreenFuncRec x386PointerScreenFuncs;
extern x386InfoRec x386Info;
int hotX,  hotY;
extern unsigned char swapbits[256];
extern ScrnInfoRec vga256InfoRec;

Bool
s3CursorInit(pm, pScr) 
	char * pm;
	ScreenPtr pScr;
{

  hotX = 0;
  hotY =0;
  if (!(miPointerInitialize(pScr, &s3PointerSpriteFuncs,
			    &x386PointerScreenFuncs, FALSE)))
    return FALSE;


}

static Bool
s3RealizeCursor(pScr, pCurs)
	ScreenPtr pScr;
	CursorPtr pCurs;

{
   register int	i,j, csz;
   unsigned short *pServMsk;
   unsigned short *pServSrc;
   int index = pScr->myNum;
   pointer *pPriv = &pCurs->bits->devPriv[index];
   unsigned int widthmask = (1<<pCurs->bits->width)-1;
   int w, wsrc, h;
   int x, y;
   unsigned short *ram;
   CursorBitsPtr bits = pCurs->bits;


   if (pCurs->bits->refcnt > 1) {
     return TRUE;

   }   

   ram = (unsigned short *) xalloc(1024);
   *pPriv = (pointer) ram;

   if (!ram)
   return FALSE;

   pServSrc = (unsigned short *) bits->source;
   pServMsk = (unsigned short *) bits->mask;


#define MAX_CURS 64

   h = bits->height;
   if (h > MAX_CURS)
     h = MAX_CURS;  
   

   wsrc = PixmapBytePad(bits->width, 1);  /* words per line */

   
   for (i=0; i < MAX_CURS; i++){
       for (j = 0; j < MAX_CURS/16; j++) {
         unsigned short mask, source;

         if (i < h && j < wsrc/2) {
	    mask   = *pServMsk++;
	    source = *pServSrc++;

	    ((char*)&mask)[0] = swapbits[((unsigned char*)&mask)[0]];
	    ((char*)&mask)[1] = swapbits[((unsigned char*)&mask)[1]];
	    
	    ((char*)&source)[0] = swapbits[((unsigned char*)&source)[0]];
	    ((char*)&source)[1] = swapbits[((unsigned char*)&source)[1]];
	    
	    if (j < MAX_CURS/8) {
	       *ram++ = ~mask;
	       *ram++ = source & mask;
	    }
	 }
	 else {
	    *ram++ = 0xffff;
	    *ram++ = 0x0;
	 }
       }
   }
   return TRUE;
}




static Bool
s3UnrealizeCursor(pScr, pCurs)
	ScreenPtr pScr;
	CursorPtr pCurs;
{
	pointer priv;

	if (pCurs->bits->refcnt <= 1 &&
		(priv = pCurs->bits->devPriv[pScr->myNum]))
		xfree(priv);
	return TRUE;
}

static void
s3SetCursor(pScr, pCurs, x, y, generateEvent)
	ScreenPtr pScr;
	CursorPtr pCurs;
	int x, y;
        Bool generateEvent;

{
	int index = pScr->myNum;
	pointer priv = 	pCurs ? pCurs->bits->devPriv[index] : 0;
	int i;
	unsigned short * ram;
	xEvent	motion; 

/*	s3ScreenPtr pm = s3ScreenNumToPriv(index); */


	int block; 


	block = sigblock(sigmask(SIGIO)); 

	if (!pCurs)
		return;

        hotX = pCurs->bits->xhot;
	hotY = pCurs->bits->yhot;
	/* load colormap */
	s3RecolorCursor(pScr, pCurs);

	ram = ( unsigned short *) priv;

/* s3 stuff */
   while ((inpw(0x9ae8) & 0x200) != 0);
   
	outp(0x3d4,  0x0e);
	outp(0x3d5, 0xff );
	outp(0x3d4,  0xf);
	outp(0x3d5,  0x0 );
	WaitQueue(4);
	outpw(MULTIFUNC_CNTL, SCISSORS_L | 0);
	outpw(MULTIFUNC_CNTL, SCISSORS_T | 0);
	outpw(MULTIFUNC_CNTL, SCISSORS_R |  1023);
	outpw(MULTIFUNC_CNTL, SCISSORS_B | 1023);

        while ((inpw(0x9ae8) & 0x200) != 0); 


	outpw(WRT_MASK, 0x0ff);
	outpw(FRGD_MIX, 0x40 | 0x7);
	outpw(MULTIFUNC_CNTL,PIX_CNTL+ 0x7);
	outpw(MULTIFUNC_CNTL, 0);
	outpw(MAJ_AXIS_PCNT, 1023);
	outpw(CUR_X, 0);
	outpw(CUR_Y, 1023);

	outpw(CMD, CMD_RECT |_16BIT | BYTSEQ | INC_X | INC_Y
			| PCDATA | DRAW | WRTDATA);

	WaitQueue(8);


	for (i = 0; i < 512; i++) {
	    outpw(PIX_TRANS,  ram[i]);
	}
	

	WaitQueue(8);
	outp(0x3d4, 0x4d);
	outp(0x3d5, (0xff & 1023 ));
	outp(0x3d4, 0x4c);
	outp(0x3d5, (0xff00 & 1023 ) >> 8);

/* turn cursor on */
	outp(0x3d4, 0x45);
	outp(0x3d5, inp(0x3d5)| 1);

	WaitQueue(6);
	outpw(MULTIFUNC_CNTL, SCISSORS_L | 0);
	outpw(MULTIFUNC_CNTL, SCISSORS_T | 0);
	outpw(MULTIFUNC_CNTL, SCISSORS_R | 1023);
	outpw(MULTIFUNC_CNTL, SCISSORS_B | 1023);

	WaitQueue(8);
	outp(0x3d4, 0x4e);
	outp(0x3d5, 0 );
	outp(0x3d4, 0x4f);
	outp(0x3d5, 0xff ); 
	/* position cursor */
	s3MoveCursor(0, x, y);

	(void) sigsetmask(block);
}


static void
s3MoveCursor(pScr, x, y)
 	ScreenPtr pScr;
	int x, y;
{
	x -= hotX;
        y -= hotY;


	x -= vga256InfoRec.frameX0;
	y -= vga256InfoRec.frameY0;

   
	outp(0x3d4, 0x45);
	outp(0x3d5, inp(0x3d5) & 0xfe);
	
	WaitQueue(8);

        if (x < 0) {
	 outpw(0x3d4, 0x004e | (-x <<8));
	 x = 0;
	}
	else {
	  outpw(0x3d4, 0x004e);
	}

	if (y < 0) {
	 outpw(0x3d4, 0x004f | (-y <<8));
	 y = 0;
	}
	else {
	 outpw(0x3d4, 0x004f);
	}
	
	outpw(0x3d4, ((x & 0xff) << 8) | 0x47);
	outpw(0x3d4, (x & 0xff00) | 0x46);
	

	outpw(0x3d4, (( y & 0xff) << 8 )| 0x49);
	outpw(0x3d4, (y & 0xff00) | 0x48);
	

	outp(0x3d4, 0x45);
	outp(0x3d5, inp(0x3d5)| 1);
	
}

static void
s3RecolorCursor(pScr, pCurs, displayed)
	ScreenPtr pScr;
	CursorPtr pCurs;
	Bool displayed;
{
/*	s3ScreenPtr pm = s3ScreenToPriv(pScr); */
   Colormap cmap;

#ifdef 0
   ibm8514ListInstalledColormaps(pScr, &cmap);
   ErrorF("%d %d %d\n", pCurs->foreRed, pCurs->foreGreen, pCurs->foreBlue);
   ErrorF("%d\n", &cmap, ibmFindColor(pScr->defColormap,
         pCurs->foreRed, pCurs->foreGreen, pCurs->foreBlue));
/* s3 stuff find out how to transform rgb to color register */
/*	if (displayed)
		(*pm->RecolorCursor)(pm, pCurs);
*/
#endif
}


void
s3WarpCursor (pScr, x, y)
ScreenPtr	pScr;
int		x, y;
{
    int		block;

    block = sigblock(sigmask(SIGIO));

    miPointerWarpCursor (pScr, x, y);
    x386Info.currentScreen = pScr;
    (void) sigsetmask(block);

}


