File:  [WindowsNT SDKs] / ntddk / src / video / displays / s3 / s3sup.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/******************************Module*Header*******************************\
* Module Name: S3Sup.c
*
* S3 support routines.
*
* Copyright (c) 1992 Microsoft Corporation
*
\**************************************************************************/

#include "driver.h"

#define TOP_CLIP        0x1
#define LEFT_CLIP       0x2
#define RIGHT_CLIP      0x4
#define BOTTOM_CLIP     0x8

#if CATCHIT

ULONG nOutpAccesses,
      nOutpwAccesses,
      nInpAccesses,
      nInpwAccesses;

#define CHIP_STATE_TEST                                     \
            byte = inp(0x3d4);                              \
            outp(0x3d4, 0x39);                              \
            if ((inp(0x3d5) & 0xA0) != 0xA0)                \
                RIP("S3.DLL! Invalid Reg 39\n");            \
            outp(0x3d4, 0x40);                              \
            if (!(inp(0x3d5) & 0x1))                        \
                RIP("S3.DLL! Invalid Reg 40 bit 0\n");      \
            outp(0x3d4, byte);

#else

#if LOG_OUTS

#define MAX_LOG 256

typedef struct _logentry {
    WORD    port,
            val ;
} LOGENTRY;

LOGENTRY    aLogEntries[MAX_LOG];
INT         iCurrentLogEntry = 0;


#define LOG_OUTPUT                                      \
    aLogEntries[iCurrentLogEntry].port = (WORD) port;   \
    aLogEntries[iCurrentLogEntry].val  = (WORD) val;    \
    iCurrentLogEntry = ++iCurrentLogEntry % MAX_LOG;


#endif
#endif


BYTE Rop2ToS3Rop[] = {
    LOGICAL_0,              /*  0      1 */
    NOT_SCREEN_AND_NOT_NEW, /* DPon    2 */
    SCREEN_AND_NOT_NEW,     /* DPna    3 */
    NOT_NEW,                /* Pn      4 */
    NOT_SCREEN_AND_NEW,     /* PDna    5 */
    NOT_SCREEN,             /* Dn      6 */
    SCREEN_XOR_NEW,         /* DPx     7 */
    NOT_SCREEN_OR_NOT_NEW,  /* DPan    8 */
    SCREEN_AND_NEW,         /* DPa     9 */
    NOT_SCREEN_XOR_NEW,     /* DPxn    10 */
    LEAVE_ALONE,            /* D       11 */
    SCREEN_OR_NOT_NEW,      /* DPno    12 */
    OVERPAINT,              /* P       13 */
    NOT_SCREEN_OR_NEW,      /* PDno    14 */
    SCREEN_OR_NEW,          /* DPo     15 */
    LOGICAL_1               /*  1      16 */
};

#if defined(i386)

/****************************************************************************\
 * vDataPortInB
\****************************************************************************/
VOID vDataPortInB(PPDEV ppdev, PBYTE pb, UINT count)
{
    ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);

    _asm {
        cld

        mov ecx, count
        mov edi, pb
        mov edx, pixtrans

        rep insb
    }
}

/*****************************************************************************
 * vDataPortIn
 ****************************************************************************/
VOID vDataPortIn(PPDEV ppdev, PWORD pw, UINT count)
{
    ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);


    _asm {
        cld

        mov ecx, count
        mov edi, pw
        mov edx, pixtrans

        rep insw
    }
}


/*****************************************************************************
 * vDataPortOutB
 ****************************************************************************/
VOID vDataPortOutB(PPDEV ppdev, PBYTE pb, UINT count)
{
    ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);

    _asm {
        cld

        mov ecx, count
        mov esi, pb
        mov edx, pixtrans

        rep outsb
    }
}

/*****************************************************************************
 * vDataPortOut
 ****************************************************************************/
VOID vDataPortOut(PPDEV ppdev, PWORD pw, UINT count)
{
    ULONG pixtrans = (ULONG) (PIXEL_TRANSFER);

    _asm {
        cld

        mov ecx, count
        mov esi, pw
        mov edx, pixtrans

        rep outsw
    }
}

#else

/****************************************************************************\
 * vDataPortInB
\****************************************************************************/
VOID vDataPortInB(PPDEV ppdev, PBYTE pb, UINT count)
{
	while (count-- > 0) {
	    *((PUCHAR)pb)++ = READ_PORT_UCHAR (gpucCsrBase + PIXEL_TRANSFER);
	}
}

/*****************************************************************************
 * vDataPortIn
 ****************************************************************************/
VOID vDataPortIn(PPDEV ppdev, PWORD pw, UINT count)
{
	while (count-- > 0) {
	    *((USHORT UNALIGNED *)pw)++ = READ_PORT_USHORT ((PUSHORT)(gpucCsrBase + PIXEL_TRANSFER));
	}
}


/*****************************************************************************
 * vDataPortOutB
 ****************************************************************************/
VOID vDataPortOutB(PPDEV ppdev, PBYTE pb, UINT count)
{
	while (count-- > 0) {
	    WRITE_PORT_UCHAR (gpucCsrBase + PIXEL_TRANSFER, *((PUCHAR)pb)++);
	}
}

/*****************************************************************************
 * vDataPortOut
 ****************************************************************************/
VOID vDataPortOut(PPDEV ppdev, PWORD pw, UINT count)
{
	while (count-- > 0) {
	    WRITE_PORT_USHORT ((PUSHORT)(gpucCsrBase + PIXEL_TRANSFER), *((USHORT UNALIGNED *)pw)++);
	}

}

#endif //i386

/*****************************************************************************
 * bIntersectTest -
 ****************************************************************************/
BOOL bIntersectTest(PRECTL prcl1, PRECTL prcl2)
{

    if (    (prcl1->left > prcl2->right) ||
            (prcl1->right < prcl2->left) ||
            (prcl1->top > prcl2->bottom) ||
            (prcl1->bottom < prcl2->top) )
        return(FALSE);

    return(TRUE);
}


/*****************************************************************************
 * bTrivialAccept   - Test for a trivial accept rect 1 being inside or
 *                    coincident with rect 2.
 ****************************************************************************/
BOOL bTrivialAcceptTest(PRECTL prcl1, PRECTL prcl2)
{

    if (    (prcl1->left < prcl2->left)     ||
            (prcl1->right > prcl2->right)   ||
            (prcl1->top < prcl2->top)       ||
            (prcl1->bottom > prcl2->bottom) )
        return(FALSE);

    return(TRUE);
}


/*****************************************************************************
 * vResetS3Clipping
 *****************************************************************************/
VOID vResetS3Clipping(PPDEV ppdev)
{
    RECTL   rcl;

    rcl.top    = 0;
    rcl.left   = 0;
    rcl.right  = S3_MAX_RAM_WIDTH;
    rcl.bottom = S3_MAX_RAM_HEIGHT;

    vSetS3ClipRect(ppdev, &rcl);
}

/*****************************************************************************
 * vSetS3ClipRect
 *
 * Important note: GDI is inclusive/exclusive,
 *                 the chip is inclusive/inclusive,
 *                 and this routine does the mapping.
 *****************************************************************************/
VOID vSetS3ClipRect(PPDEV ppdev, PRECTL prclClip)
{
    ULONG   fl;
    WORD    clipcount;

    fl = 0;
    clipcount = 0;

    if (ppdev->ClipTop != prclClip->top) {
        fl |= TOP_CLIP;
        ppdev->ClipTop = prclClip->top;
        clipcount++;
    }

    if (ppdev->ClipLeft != prclClip->left) {
        fl |= LEFT_CLIP;
        ppdev->ClipLeft = prclClip->left;
        clipcount++;
    }

    if (ppdev->ClipRight != prclClip->right) {
        fl |= RIGHT_CLIP;
        ppdev->ClipRight = prclClip->right;
        clipcount++;
    }

    if (ppdev->ClipBottom != prclClip->bottom) {
        fl |= BOTTOM_CLIP;
        ppdev->ClipBottom = prclClip->bottom;
        clipcount++;
    }

    if (fl == 0)
        return;
#if 1

    if (ppdev->cxScreen == ppdev->cxMaxRam)
    {
        if (ppdev->ClipRight > ( (LONG)(ppdev->cxScreen)))
        {
            RIP("S3.DLL!vSetS3ClipRect - (ppdev->ClipRight > ppdev->cxScreen)\n");
        }
    }

    DISPDBG((1, "S3.DLL!vSetS3ClipRect - New Clipping %d, %d  %d, %d\n",
                 ppdev->ClipTop, ppdev->ClipLeft,
                 ppdev->ClipRight, ppdev->ClipBottom));

#endif

    //
    // Wait for the minium amount of queue entries needed
    //

    clipcount = (FIFO_1_EMPTY << 1) >> clipcount;

    FIFOWAIT(clipcount);

    if (fl & TOP_CLIP)
        OUTPW (MULTIFUNC_CNTL, (CLIP_TOP | ppdev->ClipTop));

    if (fl & LEFT_CLIP)
        OUTPW (MULTIFUNC_CNTL, (CLIP_LEFT | ppdev->ClipLeft));

    if (fl & RIGHT_CLIP)
        OUTPW (MULTIFUNC_CNTL, (CLIP_RIGHT | (ppdev->ClipRight - 1)));

    if (fl & BOTTOM_CLIP)
        OUTPW (MULTIFUNC_CNTL, (CLIP_BOTTOM | (ppdev->ClipBottom - 1)));
}


#if CATCHIT

VOID outpw_test(unsigned port , unsigned val)
{
    BYTE    byte;

    CHIP_STATE_TEST;

    LOGDBG((9, "Ow %lx: %lx\n", port, val));

    nOutpwAccesses++;

    outpw(port, val);
    return;
}


VOID outp_test(unsigned port, int val)
{
    BYTE    byte;

    CHIP_STATE_TEST;

    LOGDBG((9, "Ob %lx: %lx\n", port, val));

    nOutpAccesses++;

    outp(port, val);
    return;
}


BYTE inp_test(WORD port)
{
    BYTE    byte;

    CHIP_STATE_TEST;

    nInpAccesses++;

    return(inp(port));
}


WORD inpw_test(WORD port)
{
    BYTE    byte;

    CHIP_STATE_TEST;

    nInpwAccesses++;

    return(inpw(port));
}

VOID vCheckDataReady(PPDEV ppdev)
{
    ASSERTS3((INPW(GP_STAT) & HARDWARE_BUSY),
             "S3.DLL - S3 not ready for data transfer\n");
}

VOID vCheckDataComplete(PPDEV ppdev)
{
    LONG i;

// We loop because it may take a while for the hardware to finish
// digesting all the data we transferred:

    for (i = 1000; i > 0; i--)
    {
        if (!(INPW(GP_STAT) & HARDWARE_BUSY))
            return;
    }

    RIP("S3.DLL - S3 data transfer not complete\n");
}

#endif

#if LOG_OUTS

VOID outpw_log(unsigned port , unsigned val)
{
    BYTE    byte;

    LOG_OUTPUT;

    LOGDBG((9, "Ow %lx: %lx\n", port, val));

    return (outpw(port, val));
}


VOID outp_log(unsigned port, int val)
{
    BYTE    byte;

    LOG_OUTPUT;

    LOGDBG((9, "Ob %lx: %lx\n", port, val));

    return (outp(port, val));
}


#endif




#if !defined(_X86_) && !defined(i386)

/******************************************************************************
 * vPuntGetBits - Get the bits from the device surface onto the "punt" bitmap.
 *****************************************************************************/
VOID vPuntGetBits(PPDEV ppdev, SURFOBJ *psoTrg, RECTL *prclTrg)
{
UINT    i, j ;

LONG    lDestDelta,
        xTrg, yTrg,
        cxTrg, cyTrg ;

PBYTE   pbScan0,
        pbDestRect ;

PWORD   pw ;

WORD    s3Cmd ;

RECTL   rclClip ;


        // Default the clipping to the entire screen to get the data.
        // we can over write portions of the host dest bitmap
        // because we never display it, we only use this dest bitmap
        // as work surface for the engine.

        rclClip.left   = 0 ;
        rclClip.top    = 0 ;
        rclClip.right  = S3BM_WIDTH;
        rclClip.bottom = S3BM_HEIGHT;

        vSetS3ClipRect(ppdev, &rclClip) ;

        // Calculate the size of the target rectangle, and pick up
        // some convienent locals.

        pbScan0 = (PBYTE) ppdev->psoTemp->pvScan0 ;

        // The source rectangle passed into DrvCopyBits/DrvBitBlt might
        // not be clipped to the visible surface (because the clip object
        // would take care of that), so we have to be careful that we don't
        // overwrite anything outside the visible surface:

        xTrg = max(prclTrg->left, 0) ;
        yTrg = max(prclTrg->top, 0) ;

        cxTrg = min(prclTrg->right, (LONG) ppdev->cxScreen) - xTrg ;
        cyTrg = min(prclTrg->bottom, (LONG) ppdev->cyScreen) - yTrg ;

        lDestDelta = ppdev->psoTemp->lDelta ;

        // Copy the target rectangle from the real screen to the
        // bitmap we are telling the engine is the screen.

        // Calculate the location of the dest rect.

        pbDestRect = pbScan0 + (yTrg * lDestDelta) + xTrg ;

        // Set the S3 chip up for the copy.

        s3Cmd = RECTANGLE_FILL     | BYTE_SWAP      | BUS_SIZE_16     |
                DRAWING_DIR_TBLRXM | DIR_TYPE_XY    | WAIT |
                DRAW               | LAST_PIXEL_ON  | READ ;

        FIFOWAIT(FIFO_6_EMPTY) ;

        outpw (MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)) ;
        outpw (CUR_X, xTrg) ;
        outpw (CUR_Y, yTrg) ;
        outpw (RECT_WIDTH, cxTrg - 1) ;
        outpw (MULTIFUNC_CNTL, (RECT_HEIGHT | (cyTrg - 1))) ;
        outpw (CMD, s3Cmd) ;

        // Wait for the Data Available.

        while (!(inpw(GP_STAT) & READ_DATA_AVAILABLE)) ;

        // Now transfer the data from the screen to the host memory bitmap.

        pw = (PWORD) pbDestRect ;
        j = (cxTrg + 1) / 2 ;

        for (i = 0 ; i < (UINT) cyTrg ; i++)
        {
            vDataPortIn(ppdev, pw, j) ;
            ((PBYTE) pw) += lDestDelta ;
        }

}

/******************************************************************************
 * vPuntPutBits - Put the bits from  the "punt" bitmap to the device surface.
 *****************************************************************************/
VOID vPuntPutBits(PPDEV ppdev, SURFOBJ *psoTrg, RECTL *prclTrg)
{
UINT    i, j ;

LONG    lDestDelta,
        xTrg, yTrg,
        cxTrg, cyTrg ;

PBYTE   pbScan0,
        pbDestRect ;

PWORD   pw ;

WORD    s3Cmd ;

        // Set the clipping to exactly what we need on the destination.

        vSetS3ClipRect(ppdev, prclTrg) ;

        // Recalculate the target position(s) and extent(s)

        // The target rectangle passed into DrvCopyBits/DrvBitBlt might
        // not be clipped to the visible surface (because the clip object
        // would take care of that), so we have to be careful that we don't
        // overwrite anything outside the visible surface:

        xTrg = max(prclTrg->left, 0) ;
        yTrg = max(prclTrg->top, 0) ;

        cxTrg = min(prclTrg->right, (LONG) ppdev->cxScreen) - xTrg ;
        cyTrg = min(prclTrg->bottom, (LONG) ppdev->cyScreen) - yTrg ;

        pbScan0    = (PBYTE) (ppdev->psoTemp->pvScan0) ;
        lDestDelta = ppdev->psoTemp->lDelta ;
        pbDestRect = pbScan0 + (yTrg * lDestDelta) + xTrg ;

        // Put the bits back on the screen.

        s3Cmd = RECTANGLE_FILL | BUS_SIZE_16        | BYTE_SWAP   | WAIT |
                DRAW           | DRAWING_DIR_TBLRXM | DIR_TYPE_XY |
                LAST_PIXEL_ON  | SINGLE_PIXEL       | WRITE ;

        FIFOWAIT(FIFO_7_EMPTY) ;

        outpw(FRGD_MIX, (SRC_CPU_DATA | OVERPAINT)) ;
        outpw(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)) ;
        outpw (CUR_X, xTrg) ;
        outpw (CUR_Y, yTrg) ;
        outpw (RECT_WIDTH, cxTrg - 1) ;
        outpw (MULTIFUNC_CNTL, (RECT_HEIGHT | (cyTrg - 1))) ;
        outpw(CMD, s3Cmd) ;

        // Now transfer the data, from the host memory bitmap to the screen.

        pw = (PWORD) pbDestRect ;
        j = (cxTrg + 1) / 2 ;

        for (i = 0 ; i < (UINT) cyTrg ; i++)
        {
            vDataPortOut(ppdev, pw, j) ;
            ((PBYTE) pw) += lDestDelta ;
        }

        return ;
}

#endif // !defined(_X86_) && !defined(i386)


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.