Source code of Windows XP (NT5)
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.
|
|
/*++
Module Name:
flush2.c
Abstract:
This module implements IA64 version of KeFlushIoBuffers.
N.B. May be implemented as a macro.
Author:
07-July-1998
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
VOID KeFlushIoBuffers ( IN PMDL Mdl, IN BOOLEAN ReadOperation, IN BOOLEAN DmaOperation ) /*++
Routine Description:
This function flushes the I/O buffer specified by the memory descriptor list from the data cache on the processor which executes.
Arugements:
Mdl - Supplies a pointer to a memory descriptor list that describes the I/O buffer location.
ReadOperation - Supplies a boolean value that determines whether the I/O operation is a read into memory.
DmaOperation - Supplies a boolean value that deternines whether the I/O operation is a DMA operation.
Return Value:
None.
--*/ { KIRQL OldIrql; ULONG Length, PartialLength, Offset; PFN_NUMBER PageFrameIndex; PPFN_NUMBER Page; PVOID CurrentVAddress = 0;
ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
//
// If the operation is a DMA operation, then check if the flush
// can be avoided because the host system supports the right set
// of cache coherency attributes. Otherwise, the flush can also
// be avoided if the operation is a programmed I/O and not a page
// read.
//
if (DmaOperation != FALSE) { if (ReadOperation != FALSE ) {
//
// Yes, it is a DMA operation, and yes, it is a read. IA64
// I-Caches DO snoop for DMA cycles.
//
return; } else { //
// It is a DMA Write operation
//
__mf(); return; }
} else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) == 0) { //
// It is a PIO operation and it is not Page in operation
//
return; } else if (ReadOperation != FALSE) {
//
// It is a PIO operation, it is Read operation and is Page in
// operation.
// We need to sweep the cache.
// Sweeping the range covered by the mdl will be broadcast to the
// other processors by the h/w coherency mechanism.
//
// Raise IRQL to synchronization level to prevent a context switch.
//
OldIrql = KeRaiseIrqlToSynchLevel();
//
// Compute the number of pages to flush and the starting MDL page
// frame address.
//
Length = Mdl->ByteCount;
if ( !Length ) { return; } Offset = Mdl->ByteOffset; PartialLength = PAGE_SIZE - Offset; if (PartialLength > Length) { PartialLength = Length; }
Page = (PPFN_NUMBER)(Mdl + 1); PageFrameIndex = *Page; CurrentVAddress = ((PVOID)(KSEG3_BASE | ((ULONG_PTR)(PageFrameIndex) << PAGE_SHIFT) | Offset));
//
// Region 4 maps 1:1 Virtual address to physical address
//
HalSweepIcacheRange ( CurrentVAddress, PartialLength );
Page++; Length -= PartialLength;
if (Length) { PartialLength = PAGE_SIZE; do { PageFrameIndex = *Page; CurrentVAddress = ((PVOID)(KSEG3_BASE | ((ULONG_PTR)(PageFrameIndex) << PAGE_SHIFT) | Offset));
if (PartialLength > Length) { PartialLength = Length; }
HalSweepIcacheRange ( CurrentVAddress, PartialLength );
Page++;
Length -= PartialLength; } while (Length != 0); }
//
// Synchronize the Instruction Prefetch pipe in the local processor.
//
__synci(); __isrlz();
//
// Lower IRQL to its previous level and return.
//
KeLowerIrql(OldIrql); return; } }
|