static void
Permedia3SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
{
    GLINTPtr pGlint = GLINTPTR(pScrn);
    CARD32 *srcp = (CARD32*)pGlint->XAAScanlineColorExpandBuffers[bufno];
    int dwords = pGlint->dwords;

    if (!pGlint->ScanlineDirect) {
	while(dwords >= pGlint->FIFOSize) {
	    GLINT_WAIT(pGlint->FIFOSize);
            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | 0x0D, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)srcp, pGlint->FIFOSize - 1);
	    dwords -= pGlint->FIFOSize - 1;
	    srcp += pGlint->FIFOSize - 1;
	}
	if(dwords) {
	    GLINT_WAIT(dwords + 1);
            GLINT_WRITE_REG(((dwords - 1) << 16) | 0x0D, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)srcp, dwords);
	}
    }
}
static void
Permedia3SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
{
    GLINTPtr pGlint = GLINTPTR(pScrn);
    int dwords = pGlint->dwords;

    if (pGlint->ScanlineDirect) {
    	if (pGlint->cpucount--)
    	    GLINT_WAIT(dwords);
	return;
    } else {
	while(dwords >= pGlint->FIFOSize) {
	    GLINT_WAIT(pGlint->FIFOSize);
            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
							0x05, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)pGlint->XAAScanlineColorExpandBuffers[bufno],
			pGlint->FIFOSize - 1);
	    dwords -= pGlint->FIFOSize - 1;
	}
	if(dwords) {
	    GLINT_WAIT(dwords + 1);
            GLINT_WRITE_REG(((dwords - 1) << 16) | (0x15 << 4) | 
							0x05, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)pGlint->XAAScanlineColorExpandBuffers[bufno],
			dwords);
	}
    }
}
static void
Permedia2WriteBitmap(ScrnInfoPtr pScrn,
    int x, int y, int w, int h,
    unsigned char *src,
    int srcwidth,
    int skipleft,
    int fg, int bg,
    int rop,
    unsigned int planemask
)
{
    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
    GLINTPtr pGlint = GLINTPTR(pScrn);
    unsigned char *srcpntr;
    int dwords, height, mode;
    Bool SecondPass = FALSE;

    TRACE_ENTER("Permedia2WriteBitmap");

    w += skipleft;
    x -= skipleft;
    dwords = (w + 31) >> 5;

    Permedia2SetClippingRectangle(pScrn,x+skipleft,y,x+w,y+h);
 
    if (pScrn->bitsPerPixel == 24) {
	GLINT_WAIT(10);
    } else {
        GLINT_WAIT(11);
        DO_PLANEMASK(planemask);
    }
    LOADROP(rop);
    Permedia2LoadCoord(pScrn, x&0xFFFF, y, w, h);
    if (rop == GXcopy) {
    	GLINT_WRITE_REG(pGlint->pprod, FBReadMode);
    } else {
	GLINT_WRITE_REG(pGlint->pprod | FBRM_DstEnable, FBReadMode);
    }
    if ((pScrn->bitsPerPixel != 24) && (rop == GXcopy)) {
	mode = FastFillEnable;
	GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
    	GLINT_WRITE_REG(pGlint->RasterizerSwap,RasterizerMode);
    } else {
	mode = 0;
	GLINT_WRITE_REG(UNIT_ENABLE, ColorDDAMode);
	GLINT_WRITE_REG(BitMaskPackingEachScanline|
		pGlint->RasterizerSwap,RasterizerMode);
    }

    if(bg == -1) {
	REPLICATE(fg);
        if ((pScrn->bitsPerPixel != 24) && (rop == GXcopy)) {
	    GLINT_WRITE_REG(fg, FBBlockColor);
	} else {
	    GLINT_WRITE_REG(fg, ConstantColor);
	}
    } else if((rop == GXcopy) && (pScrn->bitsPerPixel != 24)) {
	REPLICATE(bg);
	GLINT_WRITE_REG(bg, FBBlockColor);
	GLINT_WRITE_REG(PrimitiveRectangle | XPositive |YPositive |mode,Render);
	REPLICATE(fg);
	GLINT_WRITE_REG(fg, FBBlockColor);
    } else {
	SecondPass = TRUE;
	REPLICATE(fg);
        if ((pScrn->bitsPerPixel != 24) && (rop == GXcopy)) {
	    GLINT_WRITE_REG(fg, FBBlockColor);
	} else {
	    GLINT_WRITE_REG(fg, ConstantColor);
	}
    }

SECOND_PASS:
    GLINT_WRITE_REG(PrimitiveRectangle | XPositive | YPositive | mode | SyncOnBitMask, Render);
    
    height = h;
    srcpntr = src;
    while(height--) {
    	GLINT_WAIT(dwords + 1);
    	/* 0x0D is the TAG value for BitMaskPattern */
    	GLINT_WRITE_REG(((dwords - 1) << 16) | 0x0D, OutputFIFO);
   	GLINT_MoveDWORDS((CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
		(CARD32 *)srcpntr, dwords);
	srcpntr += srcwidth;
    }   

    if(SecondPass) {
	SecondPass = FALSE;
	REPLICATE(bg);
	GLINT_WAIT(3);
        if ((pScrn->bitsPerPixel != 24) && (rop == GXcopy)) {
   	    GLINT_WRITE_REG(InvertBitMask|pGlint->RasterizerSwap,RasterizerMode);
	    GLINT_WRITE_REG(bg, FBBlockColor);
	} else {
    	    GLINT_WRITE_REG(InvertBitMask|BitMaskPackingEachScanline|
    	    			pGlint->RasterizerSwap, RasterizerMode);
	    GLINT_WRITE_REG(bg, ConstantColor);
	}
	goto SECOND_PASS;
    }

    GLINT_WAIT(1);
    GLINT_WRITE_REG(pGlint->RasterizerSwap, RasterizerMode);
    Permedia2DisableClipping(pScrn);
    SET_SYNC_FLAG(infoRec);
    TRACE_EXIT("Permedia2WriteBitmap");
}
static void
Permedia3WriteBitmap(ScrnInfoPtr pScrn,
    int x, int y, int w, int h,
    unsigned char *src,
    int srcwidth, int skipleft,
    int fg, int bg, int rop,
    unsigned int planemask
)
{
    int dwords;
    GLINTPtr pGlint = GLINTPTR(pScrn);
    int count;
    CARD32 *srcp;
    TRACE_ENTER("Permedia3WriteBitmap");

    w += skipleft;
    x -= skipleft;
    dwords = (w + 31) >>5;

    REPLICATE(fg);
    pGlint->PM3_Render2D =
	PM3Render2D_SpanOperation |
	PM3Render2D_XPositive |
	PM3Render2D_YPositive |
	PM3Render2D_Operation_SyncOnBitMask;
    pGlint->PM3_Config2D =
	PM3Config2D_UserScissorEnable |
	PM3Config2D_UseConstantSource |
	PM3Config2D_ForegroundROPEnable |
	PM3Config2D_ForegroundROP(rop) |
	PM3Config2D_FBWriteEnable;
    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
    if (bg != -1) {
	REPLICATE(bg);
	pGlint->PM3_Config2D |= PM3Config2D_OpaqueSpan;
	GLINT_WAIT(8);
    	GLINT_WRITE_REG(bg, BackgroundColor);
    }
    else GLINT_WAIT(7);
    GLINT_WRITE_REG(fg, PM3ForegroundColor);
    PM3_PLANEMASK(planemask);
    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
    GLINT_WRITE_REG(((y&0x0fff)<<16)|((x+skipleft)&0x0fff), ScissorMinXY);
    GLINT_WRITE_REG((((y+h)&0x0fff)<<16)|((x+w)&0x0fff), ScissorMaxXY);
    GLINT_WRITE_REG(
	PM3RectanglePosition_XOffset(x) |
	PM3RectanglePosition_YOffset(y),
	PM3RectanglePosition);
    GLINT_WRITE_REG(pGlint->PM3_Render2D |
	PM3Render2D_Width(w) | PM3Render2D_Height(h),
	PM3Render2D);

    while(h--) {
	count = dwords;
	srcp = (CARD32*)src;
	while(count >= pGlint->FIFOSize) {
	    GLINT_WAIT(pGlint->FIFOSize);
            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) |
					0x0D, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)srcp, pGlint->FIFOSize - 1);
	    count -= pGlint->FIFOSize - 1;
	    srcp += pGlint->FIFOSize - 1;
	}
	if(count) {
	    GLINT_WAIT(count + 1);
            GLINT_WRITE_REG(((count - 1) << 16) | 0x0D, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)srcp, count);
	}
	src += srcwidth;
    }  

    Permedia3DisableClipping(pScrn);
    Permedia3Sync(pScrn);
}
static void
Permedia3WritePixmap(
    ScrnInfoPtr pScrn,
    int x, int y, int w, int h,
    unsigned char *src,
    int srcwidth,
    int rop,
    unsigned int planemask,
    int trans,
    int bpp, int depth
)
{
    int dwords;
    int count;
    int skipleft = (long)src & 0x03L;
    int Bpp = bpp >> 3;
    CARD32 *srcp;
    GLINTPtr pGlint = GLINTPTR(pScrn);
    TRACE_ENTER("Permedia3WritePixmap");

    if (skipleft) {
	/* Skipleft is either
	 *   - 0, 1, 2 or 3 in 8 bpp
	 *   - 0 or 1 in 16 bpp
	 *   - 0 in 32 bpp
	 */
	skipleft /= Bpp;

	x -= skipleft;	     
	w += skipleft;

	src = (unsigned char*)((long)src & ~0x03L);     
    }

    pGlint->PM3_Render2D =
	PM3Render2D_SpanOperation |
	PM3Render2D_XPositive |
	PM3Render2D_YPositive |
	PM3Render2D_Operation_SyncOnHostData;
    pGlint->PM3_Config2D =
	PM3Config2D_UserScissorEnable |
	PM3Config2D_ForegroundROPEnable |
	PM3Config2D_ForegroundROP(rop) |
	PM3Config2D_FBWriteEnable;
    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
    GLINT_WAIT(6);
    PM3_PLANEMASK(planemask);
    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
    GLINT_WRITE_REG(((y&0x0fff)<<16)|((x+skipleft)&0x0fff), ScissorMinXY);
    GLINT_WRITE_REG((((y+h)&0x0fff)<<16)|((x+w)&0x0fff), ScissorMaxXY);
    GLINT_WRITE_REG(
	PM3RectanglePosition_XOffset(x) |
	PM3RectanglePosition_YOffset(y),
	PM3RectanglePosition);
    GLINT_WRITE_REG(pGlint->PM3_Render2D |
	PM3Render2D_Width(w) | PM3Render2D_Height(h),
	PM3Render2D);
    /* width of the stuff to copy in 32 bit words */
    dwords = ((w * Bpp) + 3) >> 2;

    while(h--) {
	count = dwords;
	srcp = (CARD32*)src;
	while(count >= pGlint->FIFOSize) {
	    GLINT_WAIT(pGlint->FIFOSize);
	    /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) | 
					0x05, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)srcp, pGlint->FIFOSize - 1);
	    count -= pGlint->FIFOSize - 1;
	    srcp += pGlint->FIFOSize - 1;
	}
	if(count) {
	    GLINT_WAIT(count + 1);
	    /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
            GLINT_WRITE_REG(((count - 1) << 16) | (0x15 << 4) | 
					0x05, OutputFIFO);
	    GLINT_MoveDWORDS(
			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
	 		(CARD32*)srcp, count);
	}
	src += srcwidth;
    }  

    Permedia3DisableClipping(pScrn);
    Permedia3Sync(pScrn);
}