/*

* Copyright (c) 2007, John Cronin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * 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.
*     * Neither the name of the copyright holder nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY John Cronin ``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 John Cronin 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 PMEM_H
#define PMEM_H

#include "sys/types.h"
#include "stdlib.h"

#define NULL_ADDRESS					(uintptr)~0
#define NULL_ADDR						NULL_ADDRESS

#define PMEM_PAGESTATUS_USEDNOSWAP		((uint8)0x00)
#define PMEM_PAGESTATUS_USED			((uint8)0x01)
#define PMEM_PAGESTATUS_FREE			((uint8)0x03)

#define PMEM_BUDDYLOCATION_HIGH			((uint8)0x00)	/* will only return memory > 16MB */
#define PMEM_BUDDYLOCATION_LOW			((uint8)0x01)	/* will only return memory 1MB - 16MB */
#define PMEM_BUDDYLOCATION_ALL			((uint8)0x02)	/* whole of memory */

#ifdef __64
typedef uint64 physaddr_t;
#else
typedef uint32 physaddr_t;
#endif

/* Aligns a uintptr value to a uintptr size */
#define ALIGN_UP(up) \
	(up) += sizeof(uintptr); \
	(up) -= (up) % sizeof(uintptr);

/* Align up to a 4kB page boundary */
#define ALIGN_PAGE(up) \
	if((up) & 0xfff) { \
		(up) += 4096; \
		(up) &= 0xfffff000; \
	}

/* Align down to a 4kB boundary */
#define ALIGN_PAGE_DOWN(up) \
	((up) &= 0xfffff000);

#define ALIGN_BYTE(up) \
	if((up) & 0xf) { \
		(up) += 8; \
		(up) &= 0xfffffff0; \
	}

typedef struct _buddy_def {
	uintptr b_ps;
	uintptr b_start;
	uintptr b_end;
} buddy_def;

typedef struct _buddy_header {
	uintptr bh_count;
	uintptr bh_smallest;
	uintptr bh_largest;
	uintptr bh_size;
	buddy_def *bh_bd;
} buddy_header;

physaddr_t find_free_address(uintptr size);

uintptr allocate_buddy(physaddr_t addr, uintptr smallest_page, uintptr largest_page);

physaddr_t pmem_alloc(uintptr page_size, uint8 bpval, uint8 buddy_loc);
physaddr_t pmem_allocp(uintptr page_size, physaddr_t address, uint8 bpval);
void pmem_free(uintptr page_size, physaddr_t address);

void pmem_dump_buddies(void);

#endif
