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.
 
 
 
 
 
 

180 lines
4.0 KiB

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