Esempio n. 1
0
static void
SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg,
									   int rop, unsigned int planemask)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SetupForCPUToScreenColorExpandFill");
	DEBUG((VERBLEV, "fg=%08X bg=%08X rop=%02X\n", fg, bg, rop));

	pSmi->AccelCmd = XAACopyROP[rop]
				   | SMI_HOSTBLT_WRITE
				   | SMI_SRC_MONOCHROME
				   | SMI_START_ENGINE;

	if (bg == -1)
	{
		pSmi->AccelCmd |= SMI_TRANSPARENT_SRC;

		WaitQueue(3);
		WRITE_DPR(pSmi, 0x14, fg);
		WRITE_DPR(pSmi, 0x18, ~fg);
		WRITE_DPR(pSmi, 0x20, fg);
	}
	else
	{
		WaitQueue(2);
		WRITE_DPR(pSmi, 0x14, fg);
		WRITE_DPR(pSmi, 0x18, bg);
	}

	LEAVE_PROC("SMI_SetupForCPUToScreenColorExpandFill");
}
Esempio n. 2
0
static void
SMI_SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
					  unsigned int planemask)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SetupForSolidFill");
	DEBUG((VERBLEV, "color=%08X rop=%02X\n", color, rop));

	pSmi->AccelCmd = XAAPatternROP[rop]
				   | SMI_BITBLT
				   | SMI_START_ENGINE;

	if (pSmi->ClipTurnedOn)
	{
		WaitQueue(4);
		WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
		pSmi->ClipTurnedOn = FALSE;
	}
	else
	{
		WaitQueue(3);
	}
	WRITE_DPR(pSmi, 0x14, color);
	WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF);
	WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF);

	LEAVE_PROC("SMI_SetupForSolidFill");
}
Esempio n. 3
0
static void
SMI_SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
							   unsigned int planemask, int trans)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SetupForScreenToScreenCopy");
	DEBUG((VERBLEV, "xdir=%d ydir=%d rop=%02X trans=%08X\n", xdir, ydir,
			rop, trans));

	pSmi->AccelCmd = XAACopyROP[rop]
				   | SMI_BITBLT
				   | SMI_START_ENGINE;

	if ((xdir == -1) || (ydir == -1))
	{
		pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT;
	}

	if (trans != -1)
	{
		pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;
		WaitQueue(1);
		WRITE_DPR(pSmi, 0x20, trans);
	}

	if (pSmi->ClipTurnedOn)
	{
		WaitQueue(1);
		WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
		pSmi->ClipTurnedOn = FALSE;
	}

	LEAVE_PROC("SMI_SetupForScreenToScreenCopy");
}
Esempio n. 4
0
static void
SMI_SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int rop,
								unsigned int planemask, int trans_color)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SetupForColor8x8PatternFill");
	DEBUG((VERBLEV, "patx=%d paty=%d rop=%02X trans_color=%08X\n", patx, paty,
			rop, trans_color));

	pSmi->AccelCmd = XAAPatternROP[rop]
				   | SMI_BITBLT
				   | SMI_COLOR_PATTERN
				   | SMI_START_ENGINE;

	if (pScrn->bitsPerPixel <= 16)
	{
		/* PDR#950 */
		CARD8* pattern = pSmi->FBBase
					   + (patx + paty * pSmi->Stride) * pSmi->Bpp;

		WaitIdleEmpty();
		WRITE_DPR(pSmi, 0x0C, SMI_BITBLT | SMI_COLOR_PATTERN);
		memcpy(pSmi->DataPortBase, pattern, 8 * pSmi->Bpp * 8);
	}
	else
	{
		if (pScrn->bitsPerPixel == 24)
		{
			patx *= 3;

			if (pSmi->Chipset == SMI_LYNX)
			{
				paty *= 3;
			}
		}

		WaitQueue(1);
		WRITE_DPR(pSmi, 0x00, (patx << 16) | (paty & 0xFFFF));
	}

	if (trans_color == -1)
	{
		pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;

		WaitQueue(1);
		WRITE_DPR(pSmi, 0x20, trans_color);
	}

	if (pSmi->ClipTurnedOn)
	{
		WaitQueue(1);
		WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
		pSmi->ClipTurnedOn = FALSE;
	}

	LEAVE_PROC("SMI_SetupForColor8x8PatternFill");
}
Esempio n. 5
0
/*	InitEnvironment()

	Initializes the 8514/A's drawing environment and clears the display.
*/
void InitEnvironment(void)
{

    InitLUT();

    /* Current mixes, src, foreground active */
    outw(FRGD_MIX, FSS_FRGDCOL | MIX_SRC);
    outw(BKGD_MIX, BSS_BKGDCOL | MIX_SRC);

    /* Clipping rectangle to full drawable space */
    outw(MULTIFUNC_CNTL, SCISSORS_T | 0x000);
    outw(MULTIFUNC_CNTL, SCISSORS_L | 0x000);
    if (resolution == MODE_640) {
	outw(MULTIFUNC_CNTL, SCISSORS_R | 0x3ff); /* Should these be */
	outw(MULTIFUNC_CNTL, SCISSORS_B | 0x3ff); /* different???    */
    } else {
	outw(MULTIFUNC_CNTL, SCISSORS_R | 0x3ff);
	outw(MULTIFUNC_CNTL, SCISSORS_B | 0x3ff);
    }

    /* Enable writes to all planes and reset color compare */
    outw(WRT_MASK, 0xffff);
    outw(MULTIFUNC_CNTL, PIX_CNTL | 0x0000);

#ifndef DIRTY_STARTUP
    if (serverGeneration == 1) /* 5-5-93 TCG : servergen.. is always 1 ? */
    {
	/* Clear the display.  Need to set the color, origin, and size.
	 * Then draw.
	 */
	WaitQueue(6);
	if( xf86FlipPixels )
	  outw(FRGD_COLOR, 1);
	else
	  outw(FRGD_COLOR, 0);
	outw(CUR_X, 0);
	outw(CUR_Y, 0);
	outw(MAJ_AXIS_PCNT, 1023);
	outw(MULTIFUNC_CNTL, MIN_AXIS_PCNT | 1023);
	outw(CMD, CMD_RECT | INC_Y | INC_X | DRAW | PLANAR | WRTDATA);
    }
#endif /* ! DIRTY_STARTUP */

    WaitQueue(4);

    /* Reset current draw position */
    outw(CUR_X, 0);
    outw(CUR_Y, 0);

    /* Reset current colors, foreground is all on, background is 0. */
    outw(FRGD_COLOR, 0xffff);
    outw(BKGD_COLOR, 0x0000);
}
Esempio n. 6
0
static void
SMI_SubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h,
							 int skipleft)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SubsequentImageWriteRect");
	DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft));

	if (pScrn->bitsPerPixel == 24)
	{
		x        *= 3;
		w        *= 3;
		skipleft *= 3;

		if (pSmi->Chipset == SMI_LYNX)
		{
			y *= 3;
		}
	}

	if (skipleft)
	{
		WaitQueue(5);
		WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) |
				(x + skipleft) | 0x2000);
		pSmi->ClipTurnedOn = TRUE;
	}
	else
	{
		if (pSmi->ClipTurnedOn)
		{
			WaitQueue(5);
			WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
			pSmi->ClipTurnedOn = FALSE;
		}
		else
		{
			WaitQueue(4);
		}
	}
	WRITE_DPR(pSmi, 0x00, 0);
	WRITE_DPR(pSmi, 0x04, (x << 16) | (y * 0xFFFF));
	WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
	WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);

	LEAVE_PROC("SMI_SubsequentImageWriteRect");
}
Esempio n. 7
0
extern	void	*
DeQueue(
	Queue	*que)
{
	QueueElement	*el;
	void			*ret;

ENTER_FUNC;
	if		(	(  que             !=  NULL  )
			&&	(  LockQueue(que)  ==  0     ) ) {
		WaitQueue(que);
		el = que->head;
		if		(  el->next  ==  NULL  ) {
			que->tail = NULL;
		} else {
			el->next->prev = NULL;
		}
		que->head = el->next;
		ret = el->data;
		xfree(el);
		que->length--;
		UnLockQueue(que);
	} else {
		ret = NULL;
	}
LEAVE_FUNC;
	return	(ret);
}
Esempio n. 8
0
static void
SMI_DisableClipping(ScrnInfoPtr pScrn)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_DisableClipping");

	pSmi->ScissorsLeft = 0;
	if (pScrn->bitsPerPixel == 24)
	{
		if (pSmi->Chipset == SMI_LYNX)
		{
			pSmi->ScissorsRight = ((pSmi->height * 3) << 16)
								| (pSmi->width * 3);
		}
		else
		{
			pSmi->ScissorsRight = (pSmi->height << 16) | (pSmi->width * 3);
		}
	}
	else
	{
		pSmi->ScissorsRight = (pSmi->height << 16) | pSmi->width;
	}

	pSmi->ClipTurnedOn = FALSE;

	WaitQueue(2);
	WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
	WRITE_DPR(pSmi, 0x30, pSmi->ScissorsRight);

	LEAVE_PROC("SMI_DisableClipping");
}
Esempio n. 9
0
static void
SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
									  int x, int y, int w, int h)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SubsequentColor8x8PatternFillRect");
	DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h));

	if (pScrn->bitsPerPixel == 24)
	{
		x *= 3;
		w *= 3;

		if (pSmi->Chipset == SMI_LYNX)
		{
			y *= 3;
		}
	}

	WaitQueue(3);
	WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
	WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));	/* PDR#950 */
	WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);

	LEAVE_PROC("SMI_SubsequentColor8x8PatternFillRect");
}
Esempio n. 10
0
static void
SMI_SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg,
							   int bg, int rop, unsigned int planemask)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SetupForMono8x8PatternFill");
	DEBUG((VERBLEV, "patx=%08X paty=%08X fg=%08X bg=%08X rop=%02X\n", patx,
			paty, fg, bg, rop));

	pSmi->AccelCmd = XAAPatternROP[rop]
				   | SMI_BITBLT
				   | SMI_START_ENGINE;

	if (pSmi->ClipTurnedOn)
	{
		WaitQueue(1);
		WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
		pSmi->ClipTurnedOn = FALSE;
	}

	if (bg == -1)
	{
		WaitQueue(5);
		WRITE_DPR(pSmi, 0x14, fg);
		WRITE_DPR(pSmi, 0x18, ~fg);
		WRITE_DPR(pSmi, 0x20, fg);
		WRITE_DPR(pSmi, 0x34, patx);
		WRITE_DPR(pSmi, 0x38, paty);
	}
	else
	{
		WaitQueue(4);
		WRITE_DPR(pSmi, 0x14, fg);
		WRITE_DPR(pSmi, 0x18, bg);
		WRITE_DPR(pSmi, 0x34, patx);
		WRITE_DPR(pSmi, 0x38, paty);
	}

	LEAVE_PROC("SMI_SetupForMono8x8PatternFill");
}
Esempio n. 11
0
static void
SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
								 int y2, int w, int h)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SubsequentScreenToScreenCopy");
	DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n", x1, y1, x2, y2, w,
			h));

	if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT)
	{
		x1 += w - 1;
		y1 += h - 1;
		x2 += w - 1;
		y2 += h - 1;
	}

	if (pScrn->bitsPerPixel == 24)
	{
		x1 *= 3;
		x2 *= 3;
		w  *= 3;

		if (pSmi->Chipset == SMI_LYNX)
		{
			y1 *= 3;
			y2 *= 3;
		}

		if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT)
		{
			x1 += 2;
			x2 += 2;
		}
	}

	WaitQueue(4);
	WRITE_DPR(pSmi, 0x00, (x1 << 16) + (y1 & 0xFFFF));
	WRITE_DPR(pSmi, 0x04, (x2 << 16) + (y2 & 0xFFFF));
	WRITE_DPR(pSmi, 0x08, (w  << 16) + (h  & 0xFFFF));
	WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);

	LEAVE_PROC("SMI_SubsequentScreenToScreenCopy");
}
Esempio n. 12
0
extern	void
WaitQueueTime(
	Queue	*que,
	int		ms)
{
	struct	timespec	wtime;
	struct	timeval	tv;

	if		(  ms  ==  0  ) {
		WaitQueue(que);
	} else {
		if	(  que->head  ==  NULL  ) {
			dbgmsg("wait");
			gettimeofday(&tv,NULL);
			wtime.tv_sec = tv.tv_sec + ms / 1000;
			wtime.tv_nsec = tv.tv_usec * 1000 + ( ms % 1000 ) * 1000000;
			pthread_cond_timedwait(&que->isdata,&que->qlock,&wtime);
		}
	}
}
Esempio n. 13
0
static void
SMI_SetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right,
						 int bottom)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SetClippingRectangle");
	DEBUG((VERBLEV, "left=%d top=%d right=%d bottom=%d\n", left, top, right,
			bottom));

    /* CZ 26.10.2001: this code prevents offscreen pixmaps being drawn ???
	left   = max(left, 0);
	top    = max(top, 0);
	right  = min(right, pSmi->width);
	bottom = min(bottom, pSmi->height);
    */

	if (pScrn->bitsPerPixel == 24)
	{
		left  *= 3;
		right *= 3;

		if (pSmi->Chipset == SMI_LYNX)
		{
			top    *= 3;
			bottom *= 3;
		}
	}

	pSmi->ScissorsLeft = (top << 16) | (left & 0xFFFF) | 0x2000;
	pSmi->ScissorsRight = (bottom << 16) | (right & 0xFFFF);

	pSmi->ClipTurnedOn = FALSE;

	WaitQueue(2);
	WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
	WRITE_DPR(pSmi, 0x30, pSmi->ScissorsRight);

	LEAVE_PROC("SMI_SetClippingRectangle");
}
Esempio n. 14
0
static void
SMI_SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
							   int dir)
{
	SMIPtr pSmi = SMIPTR(pScrn);
	int w, h;

	ENTER_PROC("SMI_SubsequentSolidHorVertLine");
	DEBUG((VERBLEV, "x=%d y=%d len=%d dir=%d\n", x, y, len, dir));

	if (dir == DEGREES_0)
	{
		w = len;
		h = 1;
	}
	else
	{
		w = 1;
		h = len;
	}

	if (pScrn->bitsPerPixel == 24)
	{
		x *= 3;
		w *= 3;

		if (pSmi->Chipset == SMI_LYNX)
		{
			y *= 3;
		}
	}

	WaitQueue(3);
	WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
	WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
	WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);

	LEAVE_PROC("SMI_SubsequentSolidHorVertLine");
}
Esempio n. 15
0
static void
SMI_SetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask,
					   int trans_color, int bpp, int depth)
{
	SMIPtr pSmi = SMIPTR(pScrn);

	ENTER_PROC("SMI_SetupForImageWrite");
	DEBUG((VERBLEV, "rop=%02X trans_color=%08X bpp=%d depth=%d\n", rop,
			trans_color, bpp, depth));

	pSmi->AccelCmd = XAACopyROP[rop]
				   | SMI_HOSTBLT_WRITE
				   | SMI_START_ENGINE;

	if (trans_color != -1)
	{
		pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;

		WaitQueue(1);
		WRITE_DPR(pSmi, 0x20, trans_color);
	}

	LEAVE_PROC("SMI_SetupForImageWrite");
}
Esempio n. 16
0
void
s3CleanUp(void)
{
   int   i;
   unsigned char tmp;

   outb(vgaCRIndex, 0x39);
   outb(vgaCRReg, 0xa5);

   if (s3MmioMem != NULL ) {
      WaitIdle();
      VerticalRetraceWait();
      ((mmtr)s3MmioMem)->memport_regs.regs.fifo_control = oldS3->fifo[0];
      WaitIdle();                  /* Don't ask... */
      ((mmtr)s3MmioMem)->memport_regs.regs.streams_timeout = oldS3->fifo[1];
   }

   #if 1			   
   			/* This seems to help, but maybe a wait for */
			/* VSYNC would be better than WaitIdleEmpty(). */
   				/* STREAMS disable code, for 24 & 32 Bpp */
   if ( ( s3InfoRec.bitsPerPixel == 32 || 
          s3InfoRec.bitsPerPixel == 24 ) &&
          s3MmioMem != NULL ) {
	  			/* temp - KJB */
       ((mmtr)s3MmioMem)->streams_regs.regs.prim_fbaddr0 = 0;
	      /*  ((y * s3DisplayWidth + (x & ~3)) * s3Bpp) */ /* & ~3 */;
	      			/* end temp */
       
       outb(vgaCRIndex, 0x67);
       tmp = inb(vgaCRReg);
       /* WaitIdleEmpty(); */
 				/* Disable STREAMS processor */
       outb( vgaCRReg, tmp & ~0x0C );
   }	
   #endif

   vgaProtect(TRUE);

   if (s3NewMmio)	{
      outb (vgaCRIndex, 0x58);
      outb (vgaCRReg, s3SAM256); /* disable linear mode */
   } /* end BL */


   WaitQueue(8);
   outb(vgaCRIndex, 0x35);
   tmp = inb(vgaCRReg);
   outb(vgaCRReg, (tmp & 0xf0));
   cebank();

   if (s3NewMmio) {
      outb(vgaCRIndex, 0x53);
      outb(vgaCRReg, 0x00);
   }

   /* Restore S3 Trio32/64 ext. sequenzer (PLL) registers */
   if (DAC_IS_TRIO)
   {
      outb(0x3c2, oldS3->Trio[0]);
      outb(0x3c4, 0x08); outb(0x3c5, 0x06);

      outb(0x3c4, 0x09); outb(0x3c5, oldS3->Trio[2]);
      outb(0x3c4, 0x0a); outb(0x3c5, oldS3->Trio[3]);
      outb(0x3c4, 0x0b); outb(0x3c5, oldS3->Trio[4]);
      outb(0x3c4, 0x0d); outb(0x3c5, oldS3->Trio[5]);

      outb(0x3c4, 0x10); outb(0x3c5, oldS3->Trio[8]);
      outb(0x3c4, 0x11); outb(0x3c5, oldS3->Trio[9]);
      outb(0x3c4, 0x12); outb(0x3c5, oldS3->Trio[10]);
      outb(0x3c4, 0x13); outb(0x3c5, oldS3->Trio[11]);
      outb(0x3c4, 0x1a); outb(0x3c5, oldS3->Trio[12]);
      outb(0x3c4, 0x1b); outb(0x3c5, oldS3->Trio[13]);
      outb(0x3c4, 0x15);
      tmp = inb(0x3c5) & ~0x21;
      outb(0x3c5, tmp | 0x03);
      outb(0x3c5, tmp | 0x23);
      outb(0x3c5, tmp | 0x03);

      outb(0x3c4, 0x15); outb(0x3c5, oldS3->Trio[6]);
      outb(0x3c4, 0x18); outb(0x3c5, oldS3->Trio[7]);

      outb(0x3c4, 0x08); outb(0x3c5, oldS3->Trio[1]);

   }



   /* restore s3 special bits */

   /* restore 801 specific registers */

   for (i = 32; i < 46; i++) {
      outb(vgaCRIndex, 0x40 + i);
      outb(vgaCRReg, oldS3->s3sysreg[i]);

   }
   for (i = 0; i < 16; i++) {
      if (!((1 << i) & reg50_mask))
	 continue;
      outb(vgaCRIndex, 0x50 + i);
      outb(vgaCRReg, oldS3->s3sysreg[i + 16]);
   }
   for (i = 0; i < 5; i++) {
      outb(vgaCRIndex, 0x30 + i);
      outb(vgaCRReg, oldS3->s3reg[i]);
      outb(vgaCRIndex, 0x38 + i);
      outb(vgaCRReg, oldS3->s3reg[5 + i]);
   }
   outb(vgaCRIndex, 0x36);
   outb(vgaCRReg, oldS3->s3reg[10]);


   for (i = 0; i < 16; i++) {
      outb(vgaCRIndex, 0x40 + i);
      outb(vgaCRReg, oldS3->s3sysreg[i]);
   }

   outb(vgaCRIndex, 0x45);
   inb(vgaCRReg);         /* reset color stack pointer */
   outb(vgaCRIndex, 0x4A);
   for (i = 0; i < 4; i++)
      outb(vgaCRReg, oldS3->ColorStack[i]);

   outb(vgaCRIndex, 0x45);
   inb(vgaCRReg);         /* reset color stack pointer */
   outb(vgaCRIndex, 0x4B);
   for (i = 4; i < 8; i++)
      outb(vgaCRReg, oldS3->ColorStack[i]);


   if (OFLG_ISSET(CLOCK_OPTION_ICS2595, &s3InfoRec.clockOptions)){
      outb(vgaCRIndex, 0x42);
      outb(vgaCRReg, (oldS3->s3sysreg[2] & 0xf0) | 0x01);
      outb(vgaCRIndex, 0x5c);	/* switch back to 28MHz clock */
      outb(vgaCRReg,   0x20);
      outb(vgaCRReg,   0x00);
   }

   vgaHWRestore((vgaHWPtr)oldS3);

   outb(0x3c2, old_clock);

   i = inb(0x3CC);
   if (savedVgaIOBase == 0x3B0)
      i &= 0xFE;
   else
      i |= 0x01;
   outb(0x3C2, i);

   vgaIOBase = savedVgaIOBase;
   vgaCRIndex = vgaIOBase + 4;
   vgaCRReg = vgaIOBase + 5;

   vgaProtect(FALSE);

#ifdef PC98
	crtswitch(0);
#endif

   xf86DisableIOPorts(s3InfoRec.scrnIndex);
}