-
Notifications
You must be signed in to change notification settings - Fork 0
/
MemoryPrv.h
582 lines (457 loc) · 22.6 KB
/
MemoryPrv.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
/******************************************************************************
******************************************************************************
*** From <emulator>/SrcShared/Palm/Platform/Core/System/IncsPrv/MemoryPrv.h
******************************************************************************
******************************************************************************//******************************************************************************
*
* Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
* All rights reserved.
*
* File: MemoryPrv.h
*
* Description:
* Private includes for Memory Manager.
*
* History:
* 11/11/96 RM Re-written to allow heaps > 64K in size.
* 10/26/99 kwk Added memRomStoreNum & memRamStoreNum defines.
*
*****************************************************************************/
//#ifdef NON_PORTABLE
#if 0
// SystemPrv.h must be included before this header file. SystemPrv.h will
// then in turn include this header.
#ifndef __SYSTEMPRV_H__
#include "SystemPrv.h"
#endif
#endif
#ifndef __MEMORYPRV_H__
#define __MEMORYPRV_H__
//#include "PalmOptErrorCheckLevel.h"
/************************************************************
* Private Flags accepted as parameter for MemNewChunk.
*************************************************************/
#define memNewChunkFlagAllowLarge 0x1000 // allow >64K allocations
/************************************************************
* Store numbers for MemStoreInfo.
*************************************************************/
#define memRomStoreNum 0
#define memRamStoreNum 1
/********************************************************************
* Structure of a version 2 Master Pointer Table chunk.
* The first master pointer chunk is always immediately following the
* heap header. As more movable chunks are created, new master
* pointer chunks are allocated dynamically and linked together through
* the nextTblOffset field and prevTblOffset field.
********************************************************************/
typedef struct {
UInt16 numEntries; // number of master pointer entries
UInt32 nextTblOffset; // offset from start of heap to next table
//void * mstrP[numEntries]; // array of pointers to movable chunks
} MemMstrPtrTableType;
typedef MemMstrPtrTableType* MemMstrPtrTablePtr;
/********************************************************************
* Structure of a version 1 Master Pointer Table chunk.
* This is included for use by the Palm Debugger so that it can do
* heap dumps of devices that use the version 1 Memory Manager.
********************************************************************/
typedef struct {
UInt16 numEntries; // number of master pointer entries
UInt16 nextTblOffset; // offset from start of heap to next table
//void * mstrP[numEntries]; // array of pointers to movable chunks
} Mem1MstrPtrTableType;
typedef Mem1MstrPtrTableType* Mem1MstrPtrTablePtr;
/********************************************************************
* Structure of a version 2 Memory Manager Chunk Header.
********************************************************************/
#if CPU_ENDIAN == CPU_ENDIAN_BIG
typedef struct {
UInt32 free :1; // set if free chunk
UInt32 moved :1; // used by MemHeapScramble
UInt32 unused2 :1; // unused
UInt32 unused3 :1; // unused
UInt32 sizeAdj :4; // size adjustment
UInt32 size :24; // actual size of chunk
UInt32 lockCount :4; // lock count
UInt32 owner :4; // owner ID
Int32 hOffset :24; // signed MemHandle offset/2
// used in free chunks to point to next free chunk
} MemChunkHeaderType;
#else
// Since this is an internal structure, I rearranged the fields.
// There were two reasons: the size and hOffset fields are accessed
// more efficiently (no shifting needed) and the flags macros still
// return the flags as defined by the API (memChunkFlagsXXXX), without
// requiring a lot of bit manipulation.
// But, the size field needs to be in the first DWord because the
// MemHeapTerminatorType is assumed to be in the same position as size.
typedef struct {
UInt32 size :24; // actual size of chunk
UInt32 sizeAdj :4; // size adjustment
UInt32 unused3 :1; // unused
UInt32 unused2 :1; // unused
UInt32 moved :1; // used by MemHeapScramble
UInt32 free :1; // set if free chunk
Int32 hOffset :24; // signed MemHandle offset/2
// used in free chunks to point to next free chunk
UInt32 owner :4; // owner ID
UInt32 lockCount :4; // lock count
} MemChunkHeaderType;
#endif
typedef MemChunkHeaderType * MemChunkHeaderPtr;
// The MemHeapTerminatorType is stored at the end of every heap and
// is pointed to by the last real chunk in the heap
typedef UInt32 MemHeapTerminatorType;
// This macro is a quicker way of clearing a chunk header than
// MemSet...
#define memClearChunkHeader(p) { *((UInt32 *)p) = 0; *(((UInt32 *)p)+1) = 0;}
// This macro is used to initialize a freeChunk header
#define memInitFreeChunkHeader(p, size, hOffset) \
{ *((UInt32*)p) = (0x80000000 | (size)); *(((UInt32*)p)+1) = (hOffset); }
// This macro returns the data portion of a chunk given a pointer to the header
#define memChunkData(chunkP) (void *)(((MemChunkHeaderPtr)(chunkP)) + 1)
// This macro returns the memChunkHeader given a pointer to the start of the data
#define memChunkHeader(dataP) (((MemChunkHeaderPtr)(dataP)) - 1)
#if CPU_ENDIAN == CPU_ENDIAN_BIG
// This macro is used to grab all the flags at once and place them into
// a byte
#define memChunkFlags(p) (*((UInt8 *)p) & 0xF0)
// This macro is used to clear all the flags at once
#define memChunkFlagsClear(p) ((*((UInt8 *)p)) &= 0x0F)
#else
// This macro is used to grab all the flags at once and place them into
// a byte
#define memChunkFlags(p) (*(((UInt8 *)p)+3) & 0xF0)
// This macro is used to clear all the flags at once
#define memChunkFlagsClear(p) (*(((UInt8 *)p)+3) &= 0x0F)
#endif
// When flags are returned by the API (by MemPtrFlags, etc.)
#define memChunkFlagFree 0x80 // free bit
#define memChunkFlagUnused1 0x40 // unused
#define memChunkFlagUnused2 0x20 // unused
#define memChunkFlagUnused3 0x10 // unused
// A lockcount of memPtrLockCount means a permanently unmovable chunk
#define memPtrLockCount 15
// A ownerID of 15 is used for master pointer chunks
#define memOwnerMasterPtrTbl 15
// This equate returns the name of the ChunkHeaderType. This was created
// so that we can change the name of the CHunkHeaderType (as we did for V2 of
// the Memory Manager) and souce code won't know the difference
#define memChunkHeaderTypeName MemChunkHeaderType
/********************************************************************
* Structure of a version 1 Memory Manager Chunk Header.
* This is included for use by the Palm Debugger so that it can do
* heap dumps of devices that use the version 1 Memory Manager.
********************************************************************/
typedef struct {
UInt16 size; // size of block in bytes, including header
UInt8 lockOwner; // lock count in high nibble, owner in low
UInt8 flags; // flags, size adj in low nibble
Int16 hOffset; // offset/2 to MemHandle for movables
} Mem1ChunkHeaderType;
typedef Mem1ChunkHeaderType* Mem1ChunkHeaderPtr;
#define mem1ChunkFlagSizeAdj 0x0F // mask for size adjustment
// A non-movable chunk has 0xF as the lock count
#define mem1ChunkLockMask 0xF0
#define mem1ChunkOwnerMask 0x0F
/********************************************************************
* Structure of a Heap
*
* A heap starts with a HeapHeader
* Followed by the offset table (numHandles)
* Followed by movable chunks
* Followed by non-movable chunks
********************************************************************/
/********************************************************************
* Structure of a version 3 Memory Heap Header.
********************************************************************/
typedef struct {
UInt16 flags; // heap flags;
UInt32 size; // size of heap
UInt32 firstFreeChunkOffset;// offset/2 to first free chunk
MemMstrPtrTableType mstrPtrTbl; // Master pointer table
} MemHeapHeaderType;
typedef MemHeapHeaderType * MemHeapHeaderPtr;
// Flags Field
#define memHeapFlagReadOnly 0x0001 // heap is read-only (ROM based)
#define memHeapFlagVers2 0x8000 // version 2 heap (> 64K)
#define memHeapFlagVers3 0x4000 // version 3 heap (has free list)
#define memHeapFlagVers4 0x2000 // version 4 heap (has free master pointer table entry list)
#define memMstrPtrTableGrowBy 50 // # of entries to grow master pointer tables by
#define memMstrPtrTableInitSizeD 200 // # of entries to allocate initially for dynamic heap(s)
#define memMstrPtrTableInitSizeS 200 // # of entries to allocate initially for storage heap(s)
/********************************************************************
* Structure of a version 1 Memory Heap Header.
* This is included for use by the Palm Debugger so that it can do
* heap dumps of devices that use the version 1 Memory Manager.
********************************************************************/
typedef struct {
UInt16 flags; // heap flags;
UInt16 size; // size of heap - 0 means 64K;
Mem1MstrPtrTableType mstrPtrTbl; // Master pointer table
} Mem1HeapHeaderType;
typedef Mem1HeapHeaderType * Mem1HeapHeaderPtr;
/********************************************************************
* Structure of a version 2 Memory Heap Header.
* This is included for use by the Palm Debugger so that it can do
* heap dumps of devices that use the version 1 Memory Manager.
********************************************************************/
typedef struct {
UInt16 flags; // heap flags;
UInt32 size; // size of heap
MemMstrPtrTableType mstrPtrTbl; // Master pointer table
} Mem2HeapHeaderType;
typedef Mem2HeapHeaderType * Mem2HeapHeaderPtr;
/********************************************************************
* These macros pave the way for the version 2 Memory Manager that
* supports >64K chunks.
*
* They are a general way to get info out of a Chunk header and Heap header
* whether it be a version 1 or version 2 header. They are used almost
* exclusively by the Palm Debugger and Simulator Heap Dump utility
* since it must be able to do heap dumps of both versions of the Palm
* Memory Manager.
*
* The 'ver' parameter to these macros is either 1 for version 1 or
* 2 for version 2 and the 'p' parameter is the chunk header pointer.
********************************************************************/
// This structure is big enough to read in a version 1 or version 2
// Master Pointer Table into
typedef struct {
union {
MemMstrPtrTableType ver2;
Mem1MstrPtrTableType ver1;
} header;
} MemMstrPtrTableUnionType;
#define memUSizeOfMstrPtrTable(ver) \
(ver>1 ? sizeof(MemMstrPtrTableType) : sizeof(Mem1MstrPtrTableType))
#define memUMstrPtrTableNextTblOffset(p,ver) \
(ver>1 ? ((MemMstrPtrTablePtr)p)->nextTblOffset : ((Mem1MstrPtrTablePtr)p)->nextTblOffset)
#define memUMstrPtrTableNumEntries(p,ver) \
(ver>1 ? ((MemMstrPtrTablePtr)p)->numEntries : ((Mem1MstrPtrTablePtr)p)->numEntries)
// This structure is big enough to read in a version 1, version 2, or version 3
// heap header into
typedef struct {
union {
MemHeapHeaderType ver3;
Mem2HeapHeaderType ver2;
Mem1HeapHeaderType ver1;
} header;
} MemHeapHeaderUnionType;
#define memUHeapVer(p) \
(memUHeapFlags((p)) & memHeapFlagVers4 ? 4 : \
(memUHeapFlags((p)) & memHeapFlagVers3 ? 3 : \
(memUHeapFlags((p)) & memHeapFlagVers2 ? 2 : 1)))
#define memUSizeOfHeapHeader(ver) \
(ver>2 ? sizeof (MemHeapHeaderType) : (ver>1 ? sizeof(Mem2HeapHeaderType) : sizeof(Mem1HeapHeaderType)))
#define memUHeapSize(p,ver) \
(ver>2 ? ((MemHeapHeaderPtr)p)->size : (ver>1 ? ((Mem2HeapHeaderPtr)p)->size : ((Mem1HeapHeaderPtr)p)->size))
#define memUHeapFlags(p) \
(((MemHeapHeaderPtr)p)->flags)
#define memUHeapMstrPtrEntries(p,ver) \
(ver>2 ? ((MemHeapHeaderPtr)p)->mstrPtrTbl.numEntries : (ver>1 ? ((Mem2HeapHeaderPtr)p)->mstrPtrTbl.numEntries : ((Mem1HeapHeaderPtr)p)->mstrPtrTbl.numEntries))
#define memUHeapMstrPtrAddr(p,ver) \
(ver>2 ? (void *)&((MemHeapHeaderPtr)p)->mstrPtrTbl : (ver>1 ? (void *)&((Mem2HeapHeaderPtr)p)->mstrPtrTbl : (void *)&((Mem1HeapHeaderPtr)p)->mstrPtrTbl))
// This structure is big enough to read in a version 1 or version 2
// chunk header into.
typedef struct {
union {
MemChunkHeaderType ver2;
Mem1ChunkHeaderType ver1;
} header;
} MemChunkHeaderUnionType;
#define memUSizeOfHeapTerminator(ver) \
(ver>1 ? sizeof(MemHeapTerminatorType) : sizeof(UInt16))
#define memUSizeOfChunkHeader(ver) \
(ver>1 ? sizeof(MemChunkHeaderType) : sizeof(Mem1ChunkHeaderType))
#define memUChunkSize(p,ver) \
(ver>1 ? ((MemChunkHeaderPtr)p)->size : ((Mem1ChunkHeaderPtr)p)->size)
#define memUChunkFlags(p,ver) \
(ver>1 ? memChunkFlags(p) : ((Mem1ChunkHeaderPtr)p)->flags & 0xF0)
#define memUChunkSizeAdj(p,ver) \
(ver>1 ? ((MemChunkHeaderPtr)p)->sizeAdj : ((Mem1ChunkHeaderPtr)p)->flags & mem1ChunkFlagSizeAdj)
#define memUChunkLockCount(p,ver) \
(ver>1 ? ((MemChunkHeaderPtr)p)->lockCount : ((Mem1ChunkHeaderPtr)p)->lockOwner >> 4)
#define memUChunkOwner(p,ver) \
(ver>1 ? ((MemChunkHeaderPtr)p)->owner : ((Mem1ChunkHeaderPtr)p)->lockOwner & mem1ChunkOwnerMask)
#define memUChunkHOffset(p,ver) \
(ver>1 ? ((MemChunkHeaderPtr)p)->hOffset : ((Mem1ChunkHeaderPtr)p)->hOffset)
/************************************************************
* Structure of a Card Header.
* There is 1 card header for in every card that has ROM. The
* card header is stored at sysCardHeaderOffset into the card.
*
* RAM only cards will not have a card header
*************************************************************/
#define memMaxNameLen 32 // size of name and manuf fields including null
typedef struct CardHeaderType {
UInt32 initStack; // initial stack pointer (v4: offset to code in RomBoot)
UInt32 resetVector; // reset vector
UInt32 signature; // must be sysCardSignature
UInt16 hdrVersion; // header version
UInt16 flags; // card flags;
char name[memMaxNameLen]; // card name
char manuf[memMaxNameLen]; // card manufacturer's name
UInt16 version; // card version
UInt32 creationDate; // card creation date
UInt16 numRAMBlocks; // number of RAM blocks on card
UInt32 blockListOffset; // offset to RAM block list
UInt32 readWriteParmsOffset; // v2: offset from CardBase to r/w system data if any (in ROM)
UInt32 readWriteParmsSize; // v2: size of read/write system data if any (in ROM)
UInt32 readOnlyParmsOffset; // v2: offset from CardBase to read-only system data (in ROM)
UInt32 bigROMOffset; // v2: in SmallROM header: where SmallROM expects bigROM to live
// in BigROM header: where BigROM expects itself to live
UInt32 checksumBytes; // v2: size of card image in bytes (for checksum)
UInt16 checksumValue; // v2: checksum of card image (from Crc16CalcBlock)
UInt32 readWriteWorkingOffset; // v3: offset from CardBase to r/w working area if any (in ROM)
UInt32 readWriteWorkingSize; // v3: size of read/write working area if any (in ROM)
UInt32 halCodeOffset; // v4: offset from CardHeader to HAL code
UInt8 reserved[130]; // to bring us to 0x100 alignment
} CardHeaderType;
typedef CardHeaderType* CardHeaderPtr;
#define memCardHeaderFlagRAMOnly 0x0001 // RAM only card
#define memCardHeaderFlag328 0x0010 // ROM Supports 68328 processor
#define memCardHeaderFlagEZ 0x0020 // ROM SUpports 68EZ328 processor
#define memCardHeaderFlag230K 0x1000 // SmallROM supports 230Kbps
/************************************************************
* Structure of a Storage Header.
* There is 1 of these for every "store" on a memory card. A
* "store" can be all the RAM on a card or all the ROM on a card.
*
* The RAM storage header is stored at sysRAMHeader offset into the
* card. and the ROM storage header is stored at sysROMHeader offset
* into the card.
*************************************************************/
typedef struct {
UInt32 signature; // must be sysStoreSignature
UInt16 version; // version of header
UInt16 flags; // flags
char name[memMaxNameLen]; // name of store
UInt32 creationDate; // creation date
UInt32 backupDate; // last backup date
UInt32 heapListOffset; // offset to heap list for store
UInt32 initCodeOffset1; // init code for store, if any
UInt32 initCodeOffset2; // second init code for store, if any
LocalID databaseDirID; // local ID of database dir.
UInt32 rsvSpace; // where first heap starts.
UInt32 dynHeapSpace; // how big the dynamic heap area is
// (always 0 for ROM stores)
UInt32 firstRAMBlockSize; // Copy of firstRAMBlock size from cardinfo
// Used to determine if we're rebooting
// with a different amount of RAM.
// The following fields are used to store non-volatile information that
// must be accessed by the system but that is not convenient to store
// in a database due to access time or frequency. It is only valid
// in the RAM STORE ON CARD #0! Though some initialization values for
// the card 0 RAM store come from the ROM store's nvParams field.
SysNVParamsType nvParams;
// Filler bytes - reserved for future use. Size adjusted to
// keep total size of storage header at 0x100 bytes.
UInt8 reserved[172-sizeof(SysNVParamsType)];
// Pointer to System.prc boot.10003 record. Since we are doing a clean
// room implementation, and since this field is not mentioned in the pose
// sources, we're winging it here.
UInt32 initCodeOffset3;
// CRC value
UInt32 crc; // crc to check validity
} StorageHeaderType;
typedef StorageHeaderType* StorageHeaderPtr;
#define memStoreHeaderFlagRAMOnly 0x0001 // RAM store
// A Heap list for each store on a card (either RAM or ROM) gives a list of
// heaps' starting offsets for that store
typedef struct {
UInt16 numHeaps; // Number of heaps in store
UInt32 heapOffset[1]; // offset to heap
} HeapListType;
/********************************************************************
* CardInfo structure
* The Palm globals has a pointer to an array of CardInfo structures.
*
* This array is initialized by the Boot code before the Memory Manager
* starts up. Among other things, it tells the Memory Manager where
* every card is and the size of each card.
********************************************************************/
typedef struct CardInfoType {
// These fields are filled in by the boot code BEFORE
// MemInit() is called.
UInt8 *baseP; // base address of card
UInt32 size; // address range of card
UInt32 firstRAMBlockSize; // size of RAM block at offset 0
UInt32 targetROMShift; // used only under Emulation mode, must be
// added to emulated ROM pointers when calculating
// a LocalID for use in the device ROM.
UInt32 cardHeaderOffset; // offset to card header (usually in ROM)
// = 0 if RAM only card
UInt32 rsvSpace; // reserve space in RAM before first heap
UInt32 dynHeapSpace; // how much space to reserve for dynamic heap(s)
StorageHeaderPtr ramStoreP; // pointer to RAM store header
// This location depends on how much space
// was reserved on the card for the dynamic
// heap.
// These fields are copies of information in the card and storage headers
// they are cached here for quicker access by the Memory Manager. They
// are filled in by the Memory Manager during MemInit.
UInt16 numRAMHeaps; // Number of RAM heaps - for quick access
UInt32 *ramHeapOffsetsP; // Table of RAM heap offsets - for quick access
UInt16 numROMHeaps; // Number of RAM heaps - for quick access
UInt32 *romHeapOffsetsP; // Table of RAM heap offsets - for quick access
// This field was added for Palm OS v3.5. The HAL fills this in so the OS
// no longer has to use a #define'd value which can differ from device to device.
UInt32 cardOffsetMask; // converts a pointer to a card offset
} CardInfoType;
typedef CardInfoType* CardInfoPtr;
// The constant hwrNumCardSlots, defined in Hardware.h defines the maximum number
// of cards supported by the hardware.
/************************************************************
* Private Memory Manager Constants
*************************************************************/
// Private constant - # of dynamic heaps
#define memDynamicHeaps 1
// Private constant - maximum chunk size allowed (0xFFFFFFFFL = up to available memory)
// We're presently limiting the maximum chunk allocation because the current HotSync cannot
// transfer records/resources larger than (0x0FFFF - 30) bytes. This restriction will
// be removed when HotSync is extended to MemHandle larger transfers.
#define memMaxChunkAllocSize ((UInt32)(0x0FFFFUL - 30UL))
/************************************************************
* Private Memory Manager Macros. These macros are not
* guaranteed to be compatible in the future and should
* only be used in system code, not applications.
*
* To use these, define NON_PORTABLE at the top of your
* source code module.
*
* WARNING: This macro must only be used on Locked chunks!!!
* When running with error checking, it will verify
* that the chunk is locked before it dereferences it.
*************************************************************/
#if MEMORY_FORCE_LOCK == MEMORY_FORCE_LOCK_ON
#define memHandleProtect(h) \
((MemHandle)((UInt32)h | 0x80000000))
#define memHandleUnProtect(h) \
((void **)((UInt32)h & 0x7FFFFFFF))
#else
#define memHandleProtect(h) (h)
#define memHandleUnProtect(h) (h)
#endif
#if MEMORY_TYPE == MEMORY_LOCAL
#if ERROR_CHECK_LEVEL == ERROR_CHECK_FULL
#define MemDeref(h) \
((MemHandleLockCount(h)==0 ? (*((void **)0x80000000)) : (*memHandleUnProtect(h))))
#else
#define MemDeref(h) \
(*(memHandleUnProtect(h)))
#endif
#else
#if ERROR_CHECK_LEVEL == ERROR_CHECK_FULL
#define MemDeref(h) \
((MemHandleLockCount(h)==0 ? (*((void **)0x80000000)) : ((void *)ShlDWord(h))) )
#else
#define MemDeref(h) \
((void *)ShlDWord(memHandleUnProtect(h)))
#endif
#endif
// Typecast access to the MemCardInfo MemPtr
#define memCardInfoP(cardNo) \
( ((CardInfoPtr) ((LowMemHdrType*)PilotGlobalsP)->globals.memCardInfoP) + cardNo)
#endif // __MEMORYPRV_H__
//#endif // NON_PORTABLE