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.
179 lines
4.1 KiB
179 lines
4.1 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)));
|
|
|
|
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;
|
|
}
|
|
}
|