// #pragma comment(exestr, "@(#) j4flshio.c 1.1 95/09/28 15:34:41 nec") /*++ Copyright (c) 1991 Microsoft Corporation Module Name: j4flshio.c Abstract: This module implements the system dependent kernel function to flush the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion, or Duo system. Author: David N. Cutler (davec) 24-Apr-1991 Environment: Kernel mode only. Revision History: Modification History for NEC R94A (MIPS R4400): H000 Fri Sep 30 20:23:02 JST 1994 kbnes!kishimoto - HalFlushIoBuffers() Modify to return only. R94A supports I/O coherency during I/O translation. N.B. This modify is enabled after Beta-machine. _R94ABBMIO_ means that machine is alpha-version. H001 Sat Mar 18 15:19:33 1995 kbnes!kishimoto - if operation is DMA, we have nothing to do. M002 kuriyama@oa2.kb.nec.co.jp Sat Apr 01 10:51:41 JST 1995 - add support I/O cache limit _IO_LIMIT_ --*/ #include "halp.h" VOID HalFlushIoBuffers ( 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 current processor. Arguments: 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 determines whether the I/O operation is a DMA operation. Return Value: None. --*/ { ULONG CacheSegment; ULONG Length; ULONG Offset; KIRQL OldIrql; PULONG PageFrame; ULONG Source; #if !defined(_IO_LIMIT_) && defined(_R94A_) // // H001 // R94A supports cache coherency during DMA operation, // so we have nothing to to. // if (DmaOperation == TRUE){ return; } #endif // // The Jazz R4000 uses a write back data cache and, therefore, must be // flushed on reads and writes. // // If the length of the I/O operation is greater than the size of the // data cache, then sweep the entire data cache. Otherwise, flush or // purge individual pages from the data cache as appropriate. // Offset = Mdl->ByteOffset & PCR->DcacheAlignment; Length = (Mdl->ByteCount + PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment; if ((Length > PCR->FirstLevelDcacheSize) && (Length > PCR->SecondLevelDcacheSize)) { // // If the I/O operation is a DMA operation, or the I/O operation is // not a DMA operation and the I/O operation is a page read operation, // then sweep (index/writeback/invalidate) the entire data cache. // if ((DmaOperation != FALSE) || ((DmaOperation == FALSE) && (ReadOperation != FALSE) && ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) { HalSweepDcache(); } // // If the I/O operation is a page read, then sweep (index/invalidate) // the entire instruction cache. // if ((ReadOperation != FALSE) && ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) { HalSweepIcache(); } } else { // // Flush or purge the specified pages from the data cache and // instruction caches as appropriate. // // Compute the number of pages to flush and the starting MDL page // frame address. // Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment; PageFrame = (PULONG)(Mdl + 1); Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset; // // Flush or purge the specified page segments from the data and // instruction caches as appropriate. // do { if (Length >= (PAGE_SIZE - Offset)) { CacheSegment = PAGE_SIZE - Offset; } else { CacheSegment = Length; } if (ReadOperation == FALSE) { // // The I/O operation is a write and the data only needs to // to be copied back into memory if the operation is also // a DMA operation. // if (DmaOperation != FALSE) { HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment); } } else { // // If the I/O operation is a DMA operation, then purge the // data cache. Otherwise, is the I/O operation is a page read // operation, then flush the data cache. // if (DmaOperation != FALSE) { HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment); } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) { HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment); } // // If the I/O operation is a page read, then the instruction // cache must be purged. // if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) { HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment); } } PageFrame += 1; Length -= CacheSegment; Offset = 0; Source += CacheSegment; } while(Length != 0); } return; } ULONG HalGetDmaAlignmentRequirement ( VOID ) /*++ Routine Description: This function returns the alignment requirements for DMA transfers on host system. Arguments: None. Return Value: The DMA alignment requirement is returned as the fucntion value. --*/ { return PCR->DcacheFillSize; }