static void
s3vsyncactive(void)
{
/*
* Hardware cursor information is fetched from display memory
* during the horizontal blank active time. The 80x chips may hang
* if the cursor is turned on or off during this period.
*/
while((vgai(Status1) & 0x08) == 0)
;
}
static void
s3enable(VGAscr* scr)
{
int i;
ulong storage;
s3disable(scr);
/*
* Cursor colours. Set both the CR0[EF] and the colour
* stack in case we are using a 16-bit RAMDAC.
*/
vgaxo(Crtx, 0x0E, Pwhite);
vgaxo(Crtx, 0x0F, Pblack);
vgaxi(Crtx, 0x45);
/*
* Find a place for the cursor data in display memory.
* Must be on a 1024-byte boundary.
*/
storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
vgaxo(Crtx, 0x4C, (storage>>8) & 0x0F);
vgaxo(Crtx, 0x4D, storage & 0xFF);
storage *= 1024;
scr->storage = storage;
/*
* Enable the cursor in Microsoft Windows format.
*/
vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10);
s3vsyncactive();
vgaxo(Crtx, 0x45, 0x01);
}
/*
* The cursor is set in Microsoft Windows format (the ViRGE/GX2 no
* longer supports the X11 format) which gives the following truth table:
* and xor colour
* 0 0 background colour
* 0 1 foreground colour
* 1 0 current screen pixel
* 1 1 NOT current screen pixel
* Put the cursor into the top-left of the 64x64 array.
*
* The cursor pattern in memory is interleaved words of
* AND and XOR patterns.
*/
for(y = 0; y < 64; y++){
for(x = 0; x < 64/8; x += 2){
if(x < 16/8 && y < 16){
*p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]);
*p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]);
*p++ = curs->set[2*y + x];
*p++ = curs->set[2*y + x+1];
}
else {
*p++ = 0xFF;
*p++ = 0xFF;
*p++ = 0x00;
*p++ = 0x00;
}
}
}
switch(id){
case 0xE131: /* ViRGE */
case 0xE18A: /* ViRGE/[DG]X */
case 0xE110: /* ViRGE/GX2 */
case 0xE13D: /* ViRGE/VX */
break;
/*
* Save the cursor hotpoint and enable the cursor.
*/
scr->offset = curs->offset;
s3vsyncactive();
vgaxo(Crtx, 0x45, 0x01);
}
static int
s3move(VGAscr* scr, Point p)
{
int x, xo, y, yo;
/*
* Mustn't position the cursor offscreen even partially,
* or it disappears. Therefore, if x or y is -ve, adjust the
* cursor offset instead.
* There seems to be a bug in that if the offset is 1, the
* cursor doesn't disappear off the left edge properly, so
* round it up to be even.
*/
if((x = p.x+scr->offset.x) < 0){
xo = -x;
xo = ((xo+1)/2)*2;
x = 0;
}
else
xo = 0;
if((y = p.y+scr->offset.y) < 0){
yo = -y;
y = 0;
}
else
yo = 0;
x = vgaxi(Seqx, CursorSyncCtl);
x &= ~0xF0;
if(blank)
x |= VsyncLo | HsyncLo;
vgaxo(Seqx, CursorSyncCtl, x);
}
static void
s3drawinit(VGAscr *scr)
{
ulong id;
id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E);
scr->id = id;
/*
* It's highly likely that other ViRGEs will work without
* change to the driver, with the exception of the size of
* the linear aperture memory write FIFO. Since we don't
* know that size, I'm not turning them on. See waitforlinearfifo
* above.
*/
switch(id){
case 0xE131: /* ViRGE */
case 0xE13D: /* ViRGE/VX */
case 0xE110: /* ViRGE/GX2 */
scr->mmio = (ulong*)(scr->pciaddr+0x1000000);
/*
* Untested on the Alpha.
*/
/*
scr->fill = hwfill;
scr->scroll = hwscroll;
*/
/* scr->blank = hwblank; */
}
}