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

  1. /*++
  2. Module Name:
  3. flush2.c
  4. Abstract:
  5. This module implements IA64 version of KeFlushIoBuffers.
  6. N.B. May be implemented as a macro.
  7. Author:
  8. 07-July-1998
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. VOID
  15. KeFlushIoBuffers (
  16. IN PMDL Mdl,
  17. IN BOOLEAN ReadOperation,
  18. IN BOOLEAN DmaOperation
  19. )
  20. /*++
  21. Routine Description:
  22. This function flushes the I/O buffer specified by the memory descriptor
  23. list from the data cache on the processor which executes.
  24. Arugements:
  25. Mdl - Supplies a pointer to a memory descriptor list that describes the
  26. I/O buffer location.
  27. ReadOperation - Supplies a boolean value that determines whether the I/O
  28. operation is a read into memory.
  29. DmaOperation - Supplies a boolean value that deternines whether the I/O
  30. operation is a DMA operation.
  31. Return Value:
  32. None.
  33. --*/
  34. {
  35. KIRQL OldIrql;
  36. ULONG Length, PartialLength, Offset;
  37. PFN_NUMBER PageFrameIndex;
  38. PPFN_NUMBER Page;
  39. PVOID CurrentVAddress = 0;
  40. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  41. //
  42. // If the operation is a DMA operation, then check if the flush
  43. // can be avoided because the host system supports the right set
  44. // of cache coherency attributes. Otherwise, the flush can also
  45. // be avoided if the operation is a programmed I/O and not a page
  46. // read.
  47. //
  48. if (DmaOperation != FALSE) {
  49. if (ReadOperation != FALSE ) {
  50. //
  51. // Yes, it is a DMA operation, and yes, it is a read. IA64
  52. // I-Caches DO snoop for DMA cycles.
  53. //
  54. return;
  55. } else {
  56. //
  57. // It is a DMA Write operation
  58. //
  59. __mf();
  60. return;
  61. }
  62. } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) == 0) {
  63. //
  64. // It is a PIO operation and it is not Page in operation
  65. //
  66. return;
  67. } else if (ReadOperation != FALSE) {
  68. //
  69. // It is a PIO operation, it is Read operation and is Page in
  70. // operation.
  71. // We need to sweep the cache.
  72. // Sweeping the range covered by the mdl will be broadcast to the
  73. // other processors by the h/w coherency mechanism.
  74. //
  75. // Raise IRQL to synchronization level to prevent a context switch.
  76. //
  77. OldIrql = KeRaiseIrqlToSynchLevel();
  78. //
  79. // Compute the number of pages to flush and the starting MDL page
  80. // frame address.
  81. //
  82. Length = Mdl->ByteCount;
  83. if ( !Length ) {
  84. return;
  85. }
  86. Offset = Mdl->ByteOffset;
  87. PartialLength = PAGE_SIZE - Offset;
  88. if (PartialLength > Length) {
  89. PartialLength = Length;
  90. }
  91. Page = (PPFN_NUMBER)(Mdl + 1);
  92. PageFrameIndex = *Page;
  93. CurrentVAddress = ((PVOID)(KSEG3_BASE
  94. | ((ULONG_PTR)(PageFrameIndex) << PAGE_SHIFT)
  95. | Offset));
  96. //
  97. // Region 4 maps 1:1 Virtual address to physical address
  98. //
  99. HalSweepIcacheRange (
  100. CurrentVAddress,
  101. PartialLength
  102. );
  103. Page++;
  104. Length -= PartialLength;
  105. if (Length) {
  106. PartialLength = PAGE_SIZE;
  107. do {
  108. PageFrameIndex = *Page;
  109. CurrentVAddress = ((PVOID)(KSEG3_BASE
  110. | ((ULONG_PTR)(PageFrameIndex) << PAGE_SHIFT)
  111. | Offset));
  112. if (PartialLength > Length) {
  113. PartialLength = Length;
  114. }
  115. HalSweepIcacheRange (
  116. CurrentVAddress,
  117. PartialLength
  118. );
  119. Page++;
  120. Length -= PartialLength;
  121. } while (Length != 0);
  122. }
  123. //
  124. // Synchronize the Instruction Prefetch pipe in the local processor.
  125. //
  126. __synci();
  127. __isrlz();
  128. //
  129. // Lower IRQL to its previous level and return.
  130. //
  131. KeLowerIrql(OldIrql);
  132. return;
  133. }
  134. }