VxWorks Reference Manual : Libraries
cacheLib - cache management library
cacheLibInit( ) - initialize the cache library for a processor architecture
cacheEnable( ) - enable the specified cache
cacheDisable( ) - disable the specified cache
cacheLock( ) - lock all or part of a specified cache
cacheUnlock( ) - unlock all or part of a specified cache
cacheFlush( ) - flush all or some of a specified cache
cacheInvalidate( ) - invalidate all or some of a specified cache
cacheClear( ) - clear all or some entries from a cache
cachePipeFlush( ) - flush processor write buffers to memory
cacheTextUpdate( ) - synchronize the instruction and data caches
cacheDmaMalloc( ) - allocate a cache-safe buffer for DMA devices and drivers
cacheDmaFree( ) - free the buffer acquired with cacheDmaMalloc( )
cacheDrvFlush( ) - flush the data cache for drivers
cacheDrvInvalidate( ) - invalidate data cache for drivers
cacheDrvVirtToPhys( ) - translate a virtual address for drivers
cacheDrvPhysToVirt( ) - translate a physical address for drivers
This library provides architecture-independent routines for managing the instruction and data caches. Architecture-dependent routines are documented in the architecture-specific libraries.
The cache library is initialized by cacheLibInit( ) in usrInit( ). The cacheLibInit( ) routine typically calls an architecture-specific initialization routine in one of the architecture-specific libraries. The initialization routine places the cache in a known and quiescent state, ready for use, but not yet enabled. Cache devices are enabled and disabled by calls to cacheEnable( ) and cacheDisable( ), respectively.
The structure CACHE_LIB in cacheLib.h provides a function pointer that allows for the installation of different cache implementations in an architecture-independent manner. If the processor family allows more than one cache implementation, the board support package (BSP) must select the appropriate cache library using the function pointer sysCacheLibInit. The cacheLibInit( ) routine calls the initialization function attached to sysCacheLibInit to perform the actual CACHE_LIB function pointer initialization (see cacheLib.h). Note that sysCacheLibInit must be initialized when declared; it need not exist for architectures with a single cache design. Systems without caches have all NULL pointers in the CACHE_LIB structure. For systems with bus snooping, NULLifying the flush and invalidate function pointers in sysHwInit( ) improves overall system and driver performance.
Function pointers also provide a way to supplement the cache library or attach user-defined cache functions for managing secondary cache systems.
Parameters specified by cacheLibInit( ) are used to select the cache mode, either write-through (CACHE_WRITETHROUGH) or copyback (CACHE_COPYBACK), as well as to implement all other cache configuration features via software bit-flags. Note that combinations, such as setting copyback and write-through at the same time, do not make sense.
Typically, the first argument passed to cache routines after initialization is the CACHE_TYPE, which selects the data cache (DATA_CACHE) or the instruction cache (INSTRUCTION_CACHE).
Several routines accept two additional arguments: an address and the number of bytes. Some cache operations can be applied to the entire cache (bytes = ENTIRE_CACHE) or to a portion of the cache. This range specification allows the cache to be selectively locked, unlocked, flushed, invalidated, and cleared. The two complementary routines, cacheDmaMalloc( ) and cacheDmaFree( ), are tailored for efficient driver writing. The cacheDmaMalloc( ) routine attempts to return a "cache-safe" buffer, which is created by the MMU and a set of flush and invalidate function pointers. Examples are provided below in the section "Using the Cache Library."
Most routines in this library return a STATUS value of OK, or ERROR if the cache selection is invalid or the cache operation fails.
The emergence of RISC processors and effective CISC caches has made cache and MMU support a key enhancement to VxWorks. (For more information about MMU support, see the manual entry for vmLib.) The VxWorks cache strategy is to maintain coherency between the data cache and RAM and between the instruction and data caches. VxWorks also preserves overall system performance. The product is designed to support several architectures and board designs, to have a high-performance implementation for drivers, and to make routines functional for users, as well as within the entire operating system. The lack of a consistent cache design, even within architectures, has required designing for the case with the greatest number of coherency issues (Harvard architecture, copyback mode, DMA devices, multiple bus masters, and no hardware coherency support).
Caches run in two basic modes, write-through and copyback. The write-through mode forces all writes to the cache and to RAM, providing partial coherency. Writing to RAM every time, however, slows down the processor and uses bus bandwidth. The copyback mode conserves processor performance time and bus bandwidth by writing only to the cache, not RAM. Copyback cache entries are only written to memory on demand. A Least Recently Used (LRU) algorithm is typically used to determine which cache line to displace and flush. Copyback provides higher system performance, but requires more coherency support. Below is a logical diagram of a cached system to aid in the visualization of the coherency issues.
+---------------+ +-----------------+ +--------------+ | | | | | | | INSTRUCTION |---->| PROCESSOR |<--->| DATA CACHE | (3) | CACHE | | | | (copyback) | | | | | | | +---------------+ +-----------------+ +--------------+ ^ (2) ^ | | | +-----------------+ | | | | (1) | +-------------| RAM |<------------+ | | +-----------------+ ^ ^ | | +-------------+ | | +-------------+ | | | | | | | DMA Devices |<--+ +-->| VMEbus, etc.| | | | | +-------------+ +-------------+The loss of cache coherency for a VxWorks system occurs in three places:(1) data cache / RAM
(2) instruction cache / data cache
(3) shared cache linesA problem between the data cache and RAM (1) results from asynchronous accesses (reads and writes) to the RAM by the processor and other masters. Accesses by DMA devices and alternate bus masters (shared memory) are the primary causes of incoherency, which can be remedied with minor code additions to the drivers.
The instruction cache and data cache (2) can get out of sync when the loader, the debugger, and the interrupt connection routines are being used. The instructions resulting from these operations are loaded into the data cache, but not necessarily the instruction cache, in which case there is a coherency problem. This can be fixed by "flushing" the data cache entries to RAM, then "invalidating" the instruction cache entries. The invalid instruction cache tags will force the retrieval of the new instructions that the data cache has just flushed to RAM.
Cache lines that are shared (3) by more than one task create coherency problems. These are manifest when one thread of execution invalidates a cache line in which entries may belong to another thread. This can be avoided by allocating memory on a cache line boundary, then rounding up to a multiple of the cache line size.
The best way to preserve cache coherency with optimal performance (Harvard architecture, copyback mode, no software intervention) is to use hardware with bus snooping capabilities. The caches, the RAM, the DMA devices, and all other bus masters are tied to a physical bus where the caches can "snoop" or watch the bus transactions. The address cycle and control (read/write) bits are broadcast on the bus to allow snooping. Data transfer cycles are deferred until absolutely necessary. When one of the entries on the physical side of the cache is modified by an asynchronous action, the cache(s) marks its entry(s) as invalid. If an access is made by the processor (logical side) to the now invalid cached entry, it is forced to retrieve the valid entry from RAM. If while in copyback mode the processor writes to a cached entry, the RAM version becomes stale. If another master attempts to access that stale entry in RAM, the cache with the valid version pre-empts the access and writes the valid data to RAM. The interrupted access then restarts and retrieves the now-valid data in RAM. Note that this configuration allows only one valid entry at any time. At this time, only a few boards provide the snooping capability; therefore, cache support software must be designed to handle incoherency hazards without degrading performance.
The determinism, interrupt latency, and benchmarks for a cached system are exceedingly difficult to specify (best case, worst case, average case) due to cache hits and misses, line flushes and fills, atomic burst cycles, global and local instruction and data cache locking, copyback versus write-through modes, hardware coherency support (or lack of), and MMU operations (table walks, TLB locking).
The coherency problems described above can be overcome by adding cache support to existing software. For code segments that are not time-critical (loader, debugger, interrupt connection), the following sequence should be used first to flush the data cache entries and then to invalidate the corresponding instruction cache entries.
cacheFlush (DATA_CACHE, address, bytes); cacheInvalidate (INSTRUCTION_CACHE, address, bytes);For time-critical code, implementation is up to the driver writer. The following are tips for using the VxWorks cache library effectively.Incorporate cache calls in the driver program to maintain overall system performance. The cache may be disabled to facilitate driver development; however, high-performance production systems should operate with the cache enabled. A disabled cache will dramatically reduce system performance for a completed application.
Buffers can be static or dynamic. Mark buffers "non-cacheable" to avoid cache coherency problems. This usually requires MMU support. Dynamic buffers are typically smaller than their static counterparts, and they are allocated and freed often. When allocating either type of buffer, it should be designated non-cacheable; however, dynamic buffers should be marked "cacheable" before being freed. Otherwise, memory becomes fragmented with numerous non-cacheable dynamic buffers.
Alternatively, use the following flush/invalidate scheme to maintain cache coherency.
cacheInvalidate (DATA_CACHE, address, bytes); /* input buffer */ cacheFlush (DATA_CACHE, address, bytes); /* output buffer */The principle is to flush output buffers before each use and invalidate input buffers before each use. Flushing only writes modified entries back to RAM, and instruction cache entries never get modified.Several flush and invalidate macros are defined in cacheLib.h. Since optimized code uses these macros, they provide a mechanism to avoid unnecessary cache calls and accomplish the necessary work (return OK). Needless work includes flushing a write-through cache, flushing or invalidating cache entries in a system with bus snooping, and flushing or invalidating cache entries in a system without caches. The macros are set to reflect the state of the cache system hardware and software. Example 1 The following example is of a simple driver that uses cacheFlush( ) and cacheInvalidate( ) from the cache library to maintain coherency and performance. There are two buffers (lines 3 and 4), one for input and one for output. The output buffer is obtained by the call to memalign( ), a special version of the well-known malloc( ) routine (line 6). It returns a pointer that is rounded down and up to the alignment parameter's specification. Note that cache lines should not be shared, therefore _CACHE_ALIGN_SIZE is used to force alignment. If the memory allocator fails (line 8), the driver will typically return ERROR (line 9) and quit.
The driver fills the output buffer with initialization information, device commands, and data (line 11), and is prepared to pass the buffer to the device. Before doing so the driver must flush the data cache (line 13) to ensure that the buffer is in memory, not hidden in the cache. The drvWrite( ) routine lets the device know that the data is ready and where in memory it is located (line 14).
More driver code is executed (line 16), then the driver is ready to receive data that the device has placed in an input buffer in memory (line 18). Before the driver can work with the incoming data, it must invalidate the data cache entries (line 19) that correspond to the input buffer's data in order to eliminate stale entries. That done, it is safe for the driver to retrieve the input data from memory (line 21). Remember to free (line 23) the buffer acquired from the memory allocator. The driver will return OK (line 24) to distinguish a successful from an unsuccessful operation.
STATUS drvExample1 () /* simple driver - good performance */ { 3: void * pInBuf; /* input buffer */ 4: void * pOutBuf; /* output buffer */ 6: pOutBuf = memalign (_CACHE_ALIGN_SIZE, BUF_SIZE); 8: if (pOutBuf == NULL) 9: return (ERROR); /* memory allocator failed */ 11: /* other driver initialization and buffer filling */ 13: cacheFlush (DATA_CACHE, pOutBuf, BUF_SIZE); 14: drvWrite (pOutBuf); /* output data to device */ 16: /* more driver code */ 18: pInBuf = drvRead (); /* wait for device data */ 19: cacheInvalidate (DATA_CACHE, pInBuf, BUF_SIZE); 21: /* handle input data from device */ 23: free (pOutBuf); /* return buffer to memory pool */ 24: return (OK); }Extending this flush/invalidate concept further, individual buffers can be treated this way, not just the entire cache system. The idea is to avoid unnecessary flush and/or invalidate operations on a per-buffer basis by allocating cache-safe buffers. Calls to cacheDmaMalloc( ) optimize the flush and invalidate function pointers to NULL, if possible, while maintaining data integrity. Example 2 The following example is of a high-performance driver that takes advantage of the cache library to maintain coherency. It uses cacheDmaMalloc( ) and the macros CACHE_DMA_FLUSH and CACHE_DMA_INVALIDATE. A buffer pointer is passed as a parameter (line 2). If the pointer is not NULL (line 7), it is assumed that the buffer will not experience any cache coherency problems. If the driver was not provided with a cache-safe buffer, it will get one (line 11) from cacheDmaMalloc( ). A CACHE_FUNCS structure (see cacheLib.h) is used to create a buffer that will not suffer from cache coherency problems. If the memory allocator fails (line 13), the driver will typically return ERROR (line 14) and quit.The driver fills the output buffer with initialization information, device commands, and data (line 17), and is prepared to pass the buffer to the device. Before doing so, the driver must flush the data cache (line 19) to ensure that the buffer is in memory, not hidden in the cache. The routine drvWrite( ) lets the device know that the data is ready and where in memory it is located (line 20).
More driver code is executed (line 22), and the driver is then ready to receive data that the device has placed in the buffer in memory (line 24). Before the driver cache can work with the incoming data, it must invalidate the data cache entries (line 25) that correspond to the input buffer`s data in order to eliminate stale entries. That done, it is safe for the driver to handle the input data (line 27), which the driver retrieves from memory. Remember to free the buffer (line 29) acquired from the memory allocator. The driver will return OK (line 30) to distinguish a successful from an unsuccessful operation.
STATUS drvExample2 (pBuf) /* simple driver - great performance */ 2: void * pBuf; /* buffer pointer parameter */ { 5: if (pBuf != NULL) { 7: /* no cache coherency problems with buffer passed to driver */ } else { 11: pBuf = cacheDmaMalloc (BUF_SIZE); 13: if (pBuf == NULL) 14: return (ERROR); /* memory allocator failed */ } 17: /* other driver initialization and buffer filling */ 19: CACHE_DMA_FLUSH (pBuf, BUF_SIZE); 20: drvWrite (pBuf); /* output data to device */ 22: /* more driver code */ 24: drvWait (); /* wait for device data */ 25: CACHE_DMA_INVALIDATE (pBuf, BUF_SIZE); 27: /* handle input data from device */ 29: cacheDmaFree (pBuf); /* return buffer to memory pool */ 30: return (OK); }Do not use CACHE_DMA_FLUSH or CACHE_DMA_INVALIDATE without first calling cacheDmaMalloc( ), otherwise the function pointers may not be initialized correctly. Note that this driver scheme assumes all cache coherency modes have been set before driver initialization, and that the modes do not change after driver initialization. The cacheFlush( ) and cacheInvalidate( ) functions can be used at any time throughout the system since they are affiliated with the hardware, not the malloc/free buffer.A call to cacheLibInit( ) in write-through mode makes the flush function pointers NULL. Setting the caches in copyback mode (if supported) should set the pointer to and call an architecture-specific flush routine. The invalidate and flush macros may be NULLified if the hardware provides bus snooping and there are no cache coherency problems. Example 3 The next example shows a more complex driver that requires address translations to assist in the cache coherency scheme. The previous example had a priori knowledge of the system memory map and/or the device interaction with the memory system. This next driver demonstrates a case in which the virtual address returned by cacheDmaMalloc( ) might differ from the physical address seen by the device. It uses the CACHE_DMA_VIRT_TO_PHYS and CACHE_DMA_PHYS_TO_VIRT macros in addition to the CACHE_DMA_FLUSH and CACHE_DMA_INVALIDATE macros.
The cacheDmaMalloc( ) routine initializes the buffer pointer (line 3). If the memory allocator fails (line 5), the driver will typically return ERROR (line 6) and quit. The driver fills the output buffer with initialization information, device commands, and data (line 8), and is prepared to pass the buffer to the device. Before doing so, the driver must flush the data cache (line 10) to ensure that the buffer is in memory, not hidden in the cache. The flush is based on the virtual address since the processor filled in the buffer. The drvWrite( ) routine lets the device know that the data is ready and where in memory it is located (line 11). Note that the CACHE_DMA_VIRT_TO_PHYS macro converts the buffer's virtual address to the corresponding physical address for the device.
More driver code is executed (line 13), and the driver is then ready to receive data that the device has placed in the buffer in memory (line 15). Note the use of the CACHE_DMA_PHYS_TO_VIRT macro on the buffer pointer received from the device. Before the driver cache can work with the incoming data, it must invalidate the data cache entries (line 16) that correspond to the input buffer's data in order to eliminate stale entries. That done, it is safe for the driver to handle the input data (line 17), which it retrieves from memory. Remember to free (line 19) the buffer acquired from the memory allocator. The driver will return OK (line 20) to distinguish a successful from an unsuccessful operation.
STATUS drvExample3 () /* complex driver - great performance */ { 3: void * pBuf = cacheDmaMalloc (BUF_SIZE); 5: if (pBuf == NULL) 6: return (ERROR); /* memory allocator failed */ 8: /* other driver initialization and buffer filling */ 10: CACHE_DMA_FLUSH (pBuf, BUF_SIZE); 11: drvWrite (CACHE_DMA_VIRT_TO_PHYS (pBuf)); 13: /* more driver code */ 15: pBuf = CACHE_DMA_PHYS_TO_VIRT (drvRead ()); 16: CACHE_DMA_INVALIDATE (pBuf, BUF_SIZE); 17: /* handle input data from device */ 19: cacheDmaFree (pBuf); /* return buffer to memory pool */ 20: return (OK); }Driver Summary The virtual-to-physical and physical-to-virtual function pointers associated with cacheDmaMalloc( ) are supplements to a cache-safe buffer. Since the processor operates on virtual addresses and the devices access physical addresses, discrepant addresses can occur and might prevent DMA-type devices from being able to access the allocated buffer. Typically, the MMU is used to return a buffer that has pages marked as non-cacheable. An MMU is used to translate virtual addresses into physical addresses, but it is not guaranteed that this will be a "transparent" translation.When cacheDmaMalloc( ) does something that makes the virtual address different from the physical address needed by the device, it provides the translation procedures. This is often the case when using translation lookaside buffers (TLB) or a segmented address space to inhibit caching (e.g., by creating a different virtual address for the same physical space.) If the virtual address returned by cacheDmaMalloc( ) is the same as the physical address, the function pointers are made NULL so that no calls are made when the macros are expanded. Board Support Packages Each board for an architecture with more than one cache implementation has the potential for a different cache system. Hence the BSP for selecting the appropriate cache library. The function pointer sysCacheLibInit is set to cacheXxxLibInit( ) ("Xxx" refers to the chip-specific name of a library or function) so that the function pointers for that cache system will be initialized and the linker will pull in only the desired cache library. Below is an example of cacheXxxLib being linked in by sysLib.c. For systems without caches and for those architectures with only one cache design, there is no need for the sysCacheLibInit variable.
FUNCPTR sysCacheLibInit = (FUNCPTR) cacheXxxLibInit;For cache systems with bus snooping, the flush and invalidate macros should be NULLified to enhance system and driver performance in sysHwInit( ).void sysHwInit () { ... cacheLib.flushRtn = NULL; /* no flush necessary */ cacheLib.invalidateRtn = NULL; /* no invalidate necessary */ ... }There may be some drivers that require numerous cache calls, so many that they interfere with the code clarity. Additional checking can be done at the initialization stage to determine if cacheDmaMalloc( ) returned a buffer in non-cacheable space. Remember that it will return a cache-safe buffer by virtue of the function pointers. Ideally, these are NULL, since the MMU was used to mark the pages as non-cacheable. The macros CACHE_Xxx_IS_WRITE_COHERENT and CACHE_Xxx_IS_READ_COHERENT can be used to check the flush and invalidate function pointers, respectively.Write buffers are used to allow the processor to continue execution while the bus interface unit moves the data to the external device. In theory, the write buffer should be smart enough to flush itself when there is a write to non-cacheable space or a read of an item that is in the buffer. In those cases where the hardware does not support this, the software must flush the buffer manually. This often is accomplished by a read to non-cacheable space or a NOP instruction that serializes the chip's pipelines and buffers. This is not really a caching issue; however, the cache library provides a CACHE_PIPE_FLUSH macro. External write buffers may still need to be handled in a board-specific manner.
cacheLib.h
cacheLib, Architecture-specific cache-management libraries (cacheXxxLib), vmLib, VxWorks Programmer's Guide: I/O System
cacheLibInit( ) - initialize the cache library for a processor architecture
STATUS cacheLibInit ( CACHE_MODE instMode, /* inst cache mode */ CACHE_MODE dataMode /* data cache mode */ )
This routine initializes the function pointers for the appropriate cache library. For architectures with more than one cache implementation, the board support package must select the appropriate cache library with sysCacheLibInit. Systems without cache coherency problems (i.e., bus snooping) should NULLify the flush and invalidate function pointers in the cacheLib structure to enhance driver and overall system performance. This can be done in sysHwInit( ).
OK, or ERROR if there is no cache library installed.
cacheEnable( ) - enable the specified cache
STATUS cacheEnable ( CACHE_TYPE cache /* cache to enable */ )
This routine invalidates the cache tags and enables the instruction or data cache.
OK, or ERROR if the cache type is invalid or the cache control is not supported.
cacheDisable( ) - disable the specified cache
STATUS cacheDisable ( CACHE_TYPE cache /* cache to disable */ )
This routine flushes the cache and disables the instruction or data cache.
OK, or ERROR if the cache type is invalid or the cache control is not supported.
cacheLock( ) - lock all or part of a specified cache
STATUS cacheLock ( CACHE_TYPE cache, /* cache to lock */ void * address, /* virtual address */ size_t bytes /* number of bytes to lock */ )
This routine locks all (global) or some (local) entries in the specified cache. Cache locking is useful in real-time systems. Not all caches can perform locking.
OK, or ERROR if the cache type is invalid or the cache control is not supported.
cacheUnlock( ) - unlock all or part of a specified cache
STATUS cacheUnlock ( CACHE_TYPE cache, /* cache to unlock */ void * address, /* virtual address */ size_t bytes /* number of bytes to unlock */ )
This routine unlocks all (global) or some (local) entries in the specified cache. Not all caches can perform unlocking.
OK, or ERROR if the cache type is invalid or the cache control is not supported.
cacheFlush( ) - flush all or some of a specified cache
STATUS cacheFlush ( CACHE_TYPE cache, /* cache to flush */ void * address, /* virtual address */ size_t bytes /* number of bytes to flush */ )
This routine flushes (writes to memory) all or some of the entries in the specified cache. Depending on the cache design, this operation may also invalidate the cache tags. For write-through caches, no work needs to be done since RAM already matches the cached entries. Note that write buffers on the chip may need to be flushed to complete the flush.
OK, or ERROR if the cache type is invalid or the cache control is not supported.
cacheInvalidate( ) - invalidate all or some of a specified cache
STATUS cacheInvalidate ( CACHE_TYPE cache, /* cache to invalidate */ void * address, /* virtual address */ size_t bytes /* number of bytes to invalidate */ )
This routine invalidates all or some of the entries in the specified cache. Depending on the cache design, the invalidation may be similar to the flush, or one may invalidate the tags directly.
OK, or ERROR if the cache type is invalid or the cache control is not supported.
cacheClear( ) - clear all or some entries from a cache
STATUS cacheClear ( CACHE_TYPE cache, /* cache to clear */ void * address, /* virtual address */ size_t bytes /* number of bytes to clear */ )
This routine flushes and invalidates all or some entries in the specified cache.
OK, or ERROR if the cache type is invalid or the cache control is not supported.
cachePipeFlush( ) - flush processor write buffers to memory
STATUS cachePipeFlush (void)
This routine forces the processor output buffers to write their contents to RAM. A cache flush may have forced its data into the write buffers, then the buffers need to be flushed to RAM to maintain coherency.
OK, or ERROR if the cache control is not supported.
cacheTextUpdate( ) - synchronize the instruction and data caches
STATUS cacheTextUpdate ( void * address, /* virtual address */ size_t bytes /* number of bytes to sync */ )
This routine flushes the data cache, then invalidates the instruction cache. This operation forces the instruction cache to fetch code that may have been created via the data path.
OK, or ERROR if the cache control is not supported.
cacheDmaMalloc( ) - allocate a cache-safe buffer for DMA devices and drivers
void * cacheDmaMalloc ( size_t bytes /* number of bytes to allocate */ )
This routine returns a pointer to a section of memory that will not experience any cache coherency problems. Function pointers in the CACHE_FUNCS structure provide access to DMA support routines.
A pointer to the cache-safe buffer, or NULL.
cacheDmaFree( ) - free the buffer acquired with cacheDmaMalloc( )
STATUS cacheDmaFree ( void * pBuf /* pointer to malloc/free buffer */ )
This routine frees the buffer returned by cacheDmaMalloc( ).
OK, or ERROR if the cache control is not supported.
cacheDrvFlush( ) - flush the data cache for drivers
STATUS cacheDrvFlush ( CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */ void * address, /* virtual address */ size_t bytes /* number of bytes to flush */ )
This routine flushes the data cache entries using the function pointer from the specified set.
OK, or ERROR if the cache control is not supported.
cacheDrvInvalidate( ) - invalidate data cache for drivers
STATUS cacheDrvInvalidate ( CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */ void * address, /* virtual address */ size_t bytes /* no. of bytes to invalidate */ )
This routine invalidates the data cache entries using the function pointer from the specified set.
OK, or ERROR if the cache control is not supported.
cacheDrvVirtToPhys( ) - translate a virtual address for drivers
void * cacheDrvVirtToPhys ( CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */ void * address /* virtual address */ )
This routine performs a virtual-to-physical address translation using the function pointer from the specified set.
The physical address translation of a virtual address argument.
cacheDrvPhysToVirt( ) - translate a physical address for drivers
void * cacheDrvPhysToVirt ( CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */ void * address /* physical address */ )
This routine performs a physical-to-virtual address translation using the function pointer from the specified set.
The virtual address that maps to the physical address argument.