/* -*-C++-*- $NetBSD: memory.h,v 1.8 2008/04/28 20:23:20 martin Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by UCHIYAMA Yasushi.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _HPCBOOT_MEMORY_H_
#define _HPCBOOT_MEMORY_H_
#undef MEMORY_MAP_DEBUG // super verbose.
#include <hpcboot.h>
class Console;
template <class T>
inline T
ROUND(const T v, const T x) {
return((v + x - 1) / x) * x;
}
template <class T>
inline T
TRUNC(const T v, const T x) {
return(v / x) * x;
}
#define MAX_MEM_BANK 16
class MemoryManager {
private:
struct bank {
paddr_t addr;
psize_t size;
};
// Windows CE application virtual memory size
enum { WCE_VMEM_MAX = 32 * 1024 * 1024 };
// Windows CE VirtualAlloc() boundary
enum { WCE_REGION_SIZE = 64 * 1024 };
protected:
// Console options.
Console *&_cons;
BOOL _debug;
enum { BLOCK_SIZE = WCE_REGION_SIZE * 64 }; // 4MByte
// Pagesize, D-RAM bank
vsize_t _page_size;
int _page_shift;
int _page_per_region;
struct bank _bank[MAX_MEM_BANK];
int _nbank;
// Allocated memory
vaddr_t _memory;
// Virtual <-> Physical table
int _naddr_table;
struct AddressTranslationTable {
vaddr_t vaddr;
paddr_t paddr;
}
*_addr_table;
int _addr_table_idx;
public:
vsize_t getPageSize(void) { return _page_size; }
vsize_t getTaggedPageSize(void)
{ return _page_size - sizeof(struct PageTag); }
vsize_t estimateTaggedPageSize(vsize_t sz) {
vsize_t tsz = getTaggedPageSize();
return ((sz + tsz - 1) / tsz) * _page_size;
}
uint32_t roundPage(uint32_t v) { return ROUND(v, _page_size); }
uint32_t truncPage(uint32_t v) { return TRUNC(v, _page_size); }
uint32_t roundRegion(uint32_t v)
{ return ROUND(v, uint32_t(WCE_REGION_SIZE)); }
uint32_t truncRegion(uint32_t v)
{ return TRUNC(v, uint32_t(WCE_REGION_SIZE)); }
// Physical address ops.
vaddr_t mapPhysicalPage(paddr_t paddr, psize_t size, uint32_t flags);
void unmapPhysicalPage(vaddr_t vaddr);
uint32_t readPhysical4(paddr_t paddr);
// return physical address of coresspoing virtual address.
virtual paddr_t searchPage(vaddr_t vaddr) = 0;
MemoryManager(Console *&cons, size_t pagesize);
virtual ~MemoryManager(void);
BOOL &setDebug(void) { return _debug; }
virtual BOOL init(void) { return TRUE; }
// initialize page pool
BOOL reservePage(vsize_t size, BOOL page_commit = FALSE);
// register D-RAM banks
void loadBank(paddr_t paddr, psize_t psize);
// get 1 page from high address of pool.
BOOL getPage(vaddr_t &vaddr, paddr_t &paddr);
// get tagged page from low address of pool.
BOOL getTaggedPage(vaddr_t &vaddr, paddr_t &paddr);
BOOL getTaggedPage(vaddr_t &v, paddr_t &p, struct PageTag **pvec,
paddr_t &pvec_paddr);
};
//
// Use LockPages()
//
class MemoryManager_LockPages : public MemoryManager {
private:
BOOL(*_lock_pages)(LPVOID, DWORD, PDWORD, int);
BOOL(*_unlock_pages)(LPVOID, DWORD);
int _shift;
public:
MemoryManager_LockPages(BOOL(*)(LPVOID, DWORD, PDWORD, int),
BOOL(*)(LPVOID, DWORD), Console *&, size_t, int = 0);
virtual ~MemoryManager_LockPages(void);
paddr_t searchPage(vaddr_t vaddr);
};
//
// Use VirtualCopy()
//
class MemoryManager_VirtualCopy : public MemoryManager {
private:
// search guess
paddr_t _search_guess;
// Memory marker
uint32_t _magic0, _magic1;
volatile uint32_t *_magic_addr;
enum {
MAGIC_CHECK_DONE = 0xac1dcafe,
MAGIC_CHECK_DUMMY = 0xa5a5a5a5
};
void setMagic(vaddr_t v) {
_magic_addr =(uint32_t *)v;
while ((_magic0 = Random()) == MAGIC_CHECK_DONE)
;
while ((_magic1 = Random()) == MAGIC_CHECK_DONE)
;
_magic_addr[0] = _magic0;
_magic_addr[1] = _magic1;
}
BOOL checkMagic(vaddr_t v) {
volatile uint32_t *marker =(uint32_t *)v;
return (marker[0] == _magic0) && (marker[1] == _magic1);
}
void clearMagic(void) {
_magic_addr[0] = MAGIC_CHECK_DONE;
_magic_addr[1] = MAGIC_CHECK_DONE;
}
vaddr_t checkMagicRegion(vaddr_t start, vsize_t size,
vsize_t step = 8) {
for (vaddr_t ref = start; ref < start + size; ref += step)
if (checkMagic(ref))
return ref - start;
return ~0;
}
paddr_t searchBank(int banknum);
public:
MemoryManager_VirtualCopy(Console *&, size_t);
virtual ~MemoryManager_VirtualCopy(void);
paddr_t searchPage(vaddr_t vaddr);
};
#endif // _HPCBOOT_MEMORY_H_