mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
9.1 KiB
314 lines
9.1 KiB
/*
|
|
*
|
|
* Copyright (C) 1993, 1995 by
|
|
* DIGITAL EQUIPMENT CORPORATION, Maynard, MA.
|
|
*
|
|
* This software is furnished under a license and may be used and copied
|
|
* only in accordance with the terms of such license and with the inclusion
|
|
* of the above copyright notice. This software or any other copies there-
|
|
* of may not be provided or otherwise made available to any other person.
|
|
* No title to and ownership of the software is hereby transferred.
|
|
*
|
|
* The information in this software is subject to change without notice
|
|
* and should not be construed as a commitment by DIGITAL EQUIPMENT COR-
|
|
* PORATION.
|
|
*
|
|
* DIGITAL assumes no responsibility for the use or reliability of its
|
|
* software on equipment which is not supplied by DIGITAL.
|
|
*
|
|
*******************************************************************************
|
|
*
|
|
* Module: bltshdm_.c
|
|
*
|
|
* Abstract: Contains the 'code' for the screen->host DMA routine.
|
|
*
|
|
* HISTORY
|
|
*
|
|
* 25-Aug-1994 Bob Seitsinger
|
|
* Original version.
|
|
*
|
|
* 2-Mar-1995 Barry Tannenbaum
|
|
* EV5 changes
|
|
*/
|
|
|
|
{
|
|
|
|
register int trgAlign; /* Last few bits of destination ptr */
|
|
register int srcAlign; /* last few bits of source ptr */
|
|
register int shift; /* Mostly trgAlign-srcAlign */
|
|
Pixel8 *psrcLine; /* Current source scanline */
|
|
Pixel8 *psrcNext; /* Next source scanline */
|
|
Pixel8 *ptrgLine; /* Current dest scanline */
|
|
Pixel8 *pPCIAddress; /* PCI address returned from IOCTL_VIDEO_LOCK_PAGES */
|
|
DMA_CONTROL DmaControl; /* structure passed to kernel driver */
|
|
CommandWord ones = TGAOnesDMA;
|
|
CommandWord leftMask, rightMask;
|
|
int w, h, width_, width__, chunkCount, avail;
|
|
CommandWord command;
|
|
ULONG mode;
|
|
DWORD returnedDataLength;
|
|
PPDEV ppdev = (PPDEV) pso->dhpdev;
|
|
ULONG ulMainPageBytes = ppdev->ulMainPageBytes;
|
|
ULONG ulMainPageBytesMask = ppdev->ulMainPageBytesMask;
|
|
ULONG ulOffset;
|
|
|
|
DISPDBG ((4, "TGA.DLL!vBitbltSHDMA - Entry\n"));
|
|
|
|
/*
|
|
* We are asking the hardware to use dma to write frame buffer contents
|
|
* into host memory. Alignment constraint is 4 for dst, 8 for src.
|
|
* We also can't cross TC page boundaries. Recomputing masks at least
|
|
* once per scan line satisfies all constraints.
|
|
*/
|
|
|
|
// Protect ourselves, cycle to the next register alias
|
|
|
|
CYCLE_REGS (ppdev);
|
|
|
|
// Set the MODE register
|
|
|
|
mode = TGA_MODE_DMA_WRITE_COPY | ppdev->ulModeTemplate;
|
|
TGAMODE (ppdev, mode);
|
|
|
|
/* The hardware must be idle before updating the Data register, */
|
|
/* per the TGA documentation .*/
|
|
|
|
TGASYNC(ppdev);
|
|
|
|
/* Now update the Data register */
|
|
|
|
#if TGADEPTHBITS == 8
|
|
TGADATA(ppdev, (CommandWord) ~0);
|
|
#else
|
|
TGADATA(ppdev, 0x00ffffff);
|
|
#endif
|
|
|
|
/* advance pointers to start of read and write areas */
|
|
|
|
psrcBase += (ppt->y * widthSrc) + (ppt->x * TGASRCPIXELBYTES);
|
|
ptrgBase += (prclTrg->top * widthTrg) + (prclTrg->left * TGAPIXELBYTES);
|
|
|
|
/*
|
|
** Point to the bits (and how many) that we'll be overlaying.
|
|
**
|
|
** We start at the 'offset' position to avoid locking down pages we'll
|
|
** never access. We don't have to take into consideration alignment
|
|
** adjustments, because worst case is the alignment adjustments will
|
|
** bring us back to the start of the page the bits are in, and we
|
|
** would have already locked that page.
|
|
**
|
|
** Be sensitive to forward or backward copies.
|
|
*/
|
|
|
|
if (widthTrg >= 0)
|
|
{
|
|
DmaControl.pBitmap = ptrgBase;
|
|
DmaControl.ulSize = ((height + 1) * widthTrg);
|
|
ulOffset = 0;
|
|
}
|
|
else
|
|
{
|
|
// Include one additional scan line to make sure we
|
|
// don't loose any straggling bits.
|
|
|
|
DmaControl.ulSize = ((height + 1) * -widthTrg);
|
|
|
|
// -widthTrg is added because we include one additional
|
|
// scan line in the above calculation.
|
|
|
|
DmaControl.pBitmap = ptrgBase - DmaControl.ulSize + -widthTrg;
|
|
|
|
// We'll need to add this offset into the returned PCI logical
|
|
// address to get the correct starting address.
|
|
|
|
ulOffset = (ULONG) ptrgBase - (ULONG) DmaControl.pBitmap;
|
|
}
|
|
|
|
// Lock the pages needed for this DMA.
|
|
//
|
|
// We'll be writing into these pages.
|
|
|
|
if (EngDeviceIoControl(ppdev->hDriver,
|
|
IOCTL_VIDEO_LOCK_PAGES,
|
|
&DmaControl,
|
|
sizeof(DmaControl),
|
|
&pPCIAddress,
|
|
sizeof(Pixel8 *),
|
|
&returnedDataLength))
|
|
{
|
|
DISPDBG((0, "TGA.DLL!SMDMA - EngDeviceIoControl IOCTL_VIDEO_LOCK_PAGES Error!!!\n"));
|
|
DISPDBG((0, "TGA.DLL!vBitbltSHDMA - Exit\n"));
|
|
return;
|
|
}
|
|
|
|
// If this is a backward copy, ulOffset will be non-zero.
|
|
|
|
pPCIAddress += ulOffset;
|
|
|
|
// Convert incoming width from pixels to bytes
|
|
|
|
width__ = width * TGASRCPIXELBYTES;
|
|
|
|
/*
|
|
* psrcLine, ptrgLine, etc. are byte pointers
|
|
* width is a byte count
|
|
* srcAlign and trgAlign are byte offsets
|
|
* shift is a byte shift
|
|
*/
|
|
|
|
h = height;
|
|
|
|
do { /* for h */
|
|
|
|
w = width__;
|
|
|
|
psrcLine = psrcBase;
|
|
ptrgLine = pPCIAddress;
|
|
|
|
do { /* while w */
|
|
|
|
width_ = w;
|
|
|
|
/* check to see if we can do all of this */
|
|
|
|
avail = ulMainPageBytes - ((long)ptrgLine & ulMainPageBytesMask);
|
|
|
|
if (width_ > avail)
|
|
{
|
|
width_ = avail;
|
|
}
|
|
|
|
w -= width_;
|
|
|
|
psrcNext = psrcLine + (width_ * TGASRCUNPACKED);
|
|
|
|
srcAlign = (long)psrcLine & TGASRCDMAWRITEALIGNMASK;
|
|
trgAlign = (long)ptrgLine & TGADMAWRITEALIGNMASK;
|
|
|
|
shift = TGA_FIGURE_SHIFT(trgAlign, srcAlign);
|
|
|
|
// DMAWRITE mode is weird...first chunk always loads residue
|
|
// register.
|
|
|
|
if (shift < 0)
|
|
{
|
|
// First source chunk has less data than destination needs,
|
|
// so loading residue reg with first chunk is good.
|
|
|
|
shift += TGADMAWRITESHIFTBYTES;
|
|
}
|
|
else
|
|
{
|
|
// First source chunk has enough data, but the dumb DMA logic
|
|
// is going to read up a chunk and load it into the residue
|
|
// register. Back up psrcLine to make this a nop load.
|
|
|
|
psrcLine -= TGASRCDMAWRITEALIGN;
|
|
}
|
|
|
|
// Write the shift register
|
|
|
|
CYCLE_REGS(ppdev);
|
|
TGASHIFT(ppdev, shift);
|
|
|
|
// Adjust the source and target addresses by the alignment amounts.
|
|
//
|
|
// The shift register identifies the number of bytes to shift the
|
|
// source to align it to the target.
|
|
|
|
psrcLine -= srcAlign;
|
|
ptrgLine -= trgAlign;
|
|
|
|
/*
|
|
* Now find out how many 64-bit chunks we need to write.
|
|
*
|
|
* For a packed8 dst and an unpacked8 src we just count 1 byte per
|
|
* pix. So we'll move the number of bytes in the dst, since dst
|
|
* will always be packed.
|
|
*/
|
|
|
|
width_ += trgAlign;
|
|
|
|
/* destination can't be unpacked, so don't have to squash alignment */
|
|
|
|
chunkCount =
|
|
(width_ + TGADMAWRITESHIFTBYTESMASK) / TGADMAWRITESHIFTBYTES;
|
|
|
|
/*
|
|
* width_ += TGADMAWRITESHIFTBYTES for first word read, but then
|
|
* width_ -= TGADMAWRITESHIFTBYTES because wordCount is 1 less
|
|
* than # words to transfer, so it's a wash.
|
|
*/
|
|
|
|
/* now compute both masks */
|
|
|
|
leftMask = TGALEFTDMAWRITEMASK(trgAlign, ones);
|
|
rightMask = TGARIGHTDMAWRITEMASK(width_, ones);
|
|
|
|
if (chunkCount == 1)
|
|
{
|
|
/* 1 chunk DMA. Hardware ignores left mask, uses right mask */
|
|
rightMask &= leftMask;
|
|
}
|
|
|
|
/*
|
|
** Build the 32-bit value that we'll be writing to the
|
|
** source frame buffer address. This value identifies
|
|
** the left and right edge masks and the number of quad-
|
|
** words to copy.
|
|
*/
|
|
|
|
command = TGADMACOMMAND (leftMask, rightMask, chunkCount);
|
|
|
|
// Write the DMA Address register. This is the PCI 'logical'
|
|
// address that points to the bitmap bits in host memory.
|
|
|
|
TGADMA(ppdev, (ULONG) ptrgLine);
|
|
|
|
// Invoke the DMA operation by writing the masks/count to
|
|
// the source frame buffer address.
|
|
|
|
TGAWRITE (ppdev, psrcLine, command);
|
|
|
|
/*
|
|
** Loop to next scan line fragment
|
|
*/
|
|
psrcLine = psrcNext;
|
|
ptrgLine += width_;
|
|
} while (w > 0);
|
|
|
|
/*
|
|
** Point to next scan line
|
|
*/
|
|
|
|
h--;
|
|
|
|
psrcBase += widthSrc;
|
|
pPCIAddress += widthTrg;
|
|
|
|
} while (h > 0);
|
|
|
|
// Make sure all the DMA requests are done before returning
|
|
|
|
WBFLUSH(ppdev);
|
|
TGASYNC(ppdev);
|
|
|
|
// Now it's safe to unlock the pages that were locked by
|
|
// the kernel driver
|
|
|
|
if (EngDeviceIoControl(ppdev->hDriver,
|
|
IOCTL_VIDEO_UNLOCK_PAGES,
|
|
&DmaControl,
|
|
sizeof(DmaControl),
|
|
NULL,
|
|
0,
|
|
&returnedDataLength))
|
|
{
|
|
DISPDBG((0, "TGA.DLL!SMDMA - EngDeviceIoControl IOCTL_VIDEO_UNLOCK_PAGES Error!!!\n"));
|
|
DISPDBG((0, "TGA.DLL!vBitbltSHDMA - Exit\n"));
|
|
return;
|
|
}
|
|
|
|
DISPDBG ((4, "TGA.DLL!vBitbltSHDMA - Exit\n"));
|
|
|
|
}
|