|
| 1 | +#ifndef _pf_dmpaging_h |
| 2 | +#define _pf_dmpaging_h |
| 3 | + |
| 4 | +/*************************************************************** |
| 5 | +** Include file for PForth Demand Paging |
| 6 | +** |
| 7 | +** Author: Phil Burk |
| 8 | +** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom |
| 9 | +** |
| 10 | +** Permission to use, copy, modify, and/or distribute this |
| 11 | +** software for any purpose with or without fee is hereby granted. |
| 12 | +** |
| 13 | +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| 14 | +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| 15 | +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL |
| 16 | +** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR |
| 17 | +** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING |
| 18 | +** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
| 19 | +** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 20 | +** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 21 | +** |
| 22 | +***************************************************************/ |
| 23 | + |
| 24 | +#ifdef __cplusplus |
| 25 | +extern "C" { |
| 26 | +#endif |
| 27 | + |
| 28 | +/** |
| 29 | + * To use demand paged memory, enable the code by passing -DPF_DEMAND_PAGING=1 |
| 30 | + * to the C compiler. |
| 31 | + */ |
| 32 | +typedef ucell_t paging_address_t; /** an address in paged memory */ |
| 33 | + |
| 34 | +/* Basic memory access macros. */ |
| 35 | +#if (PF_DEMAND_PAGING == 0) |
| 36 | +/* Straight memory access. */ |
| 37 | +#define DP_FETCH_U8(address) (*((const uint8_t *)(uintptr_t)(address))) |
| 38 | +#define DP_FETCH_U16(address) (*((const uint16_t *)(uintptr_t)(address))) |
| 39 | +#define DP_FETCH_CELL(address) (*((const cell_t *)(uintptr_t)(address))) |
| 40 | +#define DP_FETCH_FLOAT(address) (*((const PF_FLOAT *)(uintptr_t)(address))) |
| 41 | + |
| 42 | +#define DP_STORE_U8(address, value) *((uint8_t *)(uintptr_t)(address)) = (uint8_t)(value) |
| 43 | +#define DP_STORE_U16(address, value) *((uint16_t *)(uintptr_t)(address)) = (uint16_t)(value) |
| 44 | +#define DP_STORE_CELL(address, value) *((cell_t *)(uintptr_t)(address)) = (cell_t)(value) |
| 45 | +#define DP_STORE_FLOAT(address, value) *((PF_FLOAT *)(uintptr_t)(address)) = (PF_FLOAT)(value) |
| 46 | + |
| 47 | +#else /* PF_DEMAND_PAGING */ |
| 48 | + |
| 49 | +/* Use either physical or paged memory. */ |
| 50 | +#define DP_FETCH_U8(address) pfFetchVirtualU8(PTR_TO_VMA(address)) |
| 51 | +#define DP_FETCH_U16(address) pfFetchVirtualU16(PTR_TO_VMA(address)) |
| 52 | +#define DP_FETCH_CELL(address) pfFetchVirtualCell(PTR_TO_VMA(address)) |
| 53 | +#define DP_FETCH_FLOAT(address) pfFetchVirtualFloat(PTR_TO_VMA(address)) |
| 54 | + |
| 55 | +#define DP_STORE_U8(address, value) pfStoreVirtualU8(PTR_TO_VMA(address), (uint8_t)(value)) |
| 56 | +#define DP_STORE_U16(address, value) pfStoreVirtualU16(PTR_TO_VMA(address), (uint16_t)(value)) |
| 57 | +#define DP_STORE_CELL(address, value) pfStoreVirtualCell(PTR_TO_VMA(address), (cell_t)(value)) |
| 58 | +#define DP_STORE_FLOAT(address, value) pfStoreVirtualFloat(PTR_TO_VMA(address), (PF_FLOAT)(value)) |
| 59 | +#endif /* PF_DEMAND_PAGING */ |
| 60 | + |
| 61 | +uint8_t pfFetchVirtualU8(vm_address_t address); |
| 62 | +uint16_t pfFetchVirtualU16(vm_address_t address); |
| 63 | +cell_t pfFetchVirtualCell(vm_address_t address); |
| 64 | + |
| 65 | +void pfStoreVirtualU8(vm_address_t address, uint8_t value); |
| 66 | +void pfStoreVirtualU16(vm_address_t address, uint16_t value); |
| 67 | +void pfStoreVirtualCell(vm_address_t address, cell_t value); |
| 68 | + |
| 69 | +#ifdef PF_SUPPORT_FP |
| 70 | +PF_FLOAT pfFetchVirtualFloat(vm_address_t address); |
| 71 | +void pfStoreVirtualFloat(vm_address_t address, PF_FLOAT value); |
| 72 | +#endif /* PF_SUPPORT_FP */ |
| 73 | + |
| 74 | +/* Memory region locking and unlocking |
| 75 | + * A maximum of DP_MAX_REGIONS can be locked at one time. |
| 76 | + * The regions cannot overlap. |
| 77 | + * Adjacent virtual regions will not be adjacent in physical memory! |
| 78 | + */ |
| 79 | + |
| 80 | +/* maximum number of locked regions */ |
| 81 | +#define DP_MAX_REGIONS (4) |
| 82 | +/* maximum number of bytes per region */ |
| 83 | +#define DP_MAX_REGION_SIZE (256) |
| 84 | + |
| 85 | +void pfResetLockedMemory(void); |
| 86 | + |
| 87 | +/** |
| 88 | + * Lock a read-only region of demand paging in physical memory. |
| 89 | + * Load the data from demand paging if not already loaded. |
| 90 | + * A region should only be locked temporarily, for example within |
| 91 | + * a single primitive. |
| 92 | + * If the virtual memory address is not in paged memory then it will be passed through. |
| 93 | + * You cannot lock more than DP_MAX_REGION_SIZE bytes. |
| 94 | + * |
| 95 | + * @param vp virtual address in physical or paged memory |
| 96 | + * @param numBytes number of byte in region |
| 97 | + * @return physical address that can be used by normal C code as “const” memory. |
| 98 | + */ |
| 99 | +const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes); |
| 100 | + |
| 101 | +/** |
| 102 | + * Lock a read-write region of demand paging in physical memory. |
| 103 | + * Load the data from demand paging if not already loaded. |
| 104 | + * If the virtual memory address is not in paged memory then it will be passed through. |
| 105 | + * You cannot lock more than DP_MAX_REGION_SIZE bytes. |
| 106 | + * |
| 107 | + * @param vp virtual address in physical or paged memory |
| 108 | + * @param numBytes number of byte in region |
| 109 | + * @return physical address that can be read or written by normal C code. |
| 110 | + */ |
| 111 | +uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes); |
| 112 | + |
| 113 | +/** |
| 114 | + * Release a previously locked region of memory. |
| 115 | + * Writable regions will be written back to serial memory. |
| 116 | + * Regions may be kept in physical memory on an LRU basis |
| 117 | + * to improve performance. |
| 118 | + * @param vp virtual address in physical or paged memory |
| 119 | + * @param pp physical memory address |
| 120 | + * @return negative code if an error occured else zero |
| 121 | + */ |
| 122 | +int pfUnlockMemory(vm_address_t vp, const uint8_t *pp); |
| 123 | + |
| 124 | +/** Copy from virtual to physical memory. |
| 125 | + * @param destination target address in physical memory |
| 126 | + * @param source data address in physical or paged memory |
| 127 | + * @return destination |
| 128 | + */ |
| 129 | +void *pfCopyFromVirtualMemory(void *destination, |
| 130 | + vm_address_t source, |
| 131 | + uint32_t numBytes); |
| 132 | + |
| 133 | +/** Copy from physical to virtual memory. |
| 134 | + * @param destination target address in physical or paged memory |
| 135 | + * @param source in physical memory |
| 136 | + * @return destination |
| 137 | + */ |
| 138 | +vm_address_t pfCopyToVirtualMemory(vm_address_t destination, |
| 139 | + const void *source, |
| 140 | + uint32_t numBytes); |
| 141 | + |
| 142 | +/** Free virtual memory. |
| 143 | + * @param address may be in physical or paged memory |
| 144 | + */ |
| 145 | +void pfFreeVirtualMemory(vm_address_t address); |
| 146 | + |
| 147 | +/** Set a region of virtual memory to a byte value. |
| 148 | + * @param destination in physical or paged memory |
| 149 | + * @param value fill memory with this value |
| 150 | + * @param numBytes how many bytes to set |
| 151 | + * @return destination |
| 152 | + */ |
| 153 | +vm_address_t pfSetVirtualMemory(vm_address_t destination, |
| 154 | + uint8_t value, |
| 155 | + uint32_t numBytes); |
| 156 | + |
| 157 | +#ifdef __cplusplus |
| 158 | +} |
| 159 | +#endif |
| 160 | + |
| 161 | +#endif /* _pf_dmpaging_h */ |
0 commit comments