Windows NT 4.0 source code leak
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

/*
*
* 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"));
}