/*
 * Copyright (c) 2003 Linuxant inc.
 * Copyright (c) 2001-2003 Conexant Systems, Inc.
 *
 * NOTE: The use and distribution of this software is governed by the terms in
 * the file LICENSE, which is included in the package. You must read this and
 * agree to these terms before using or distributing this software.
 *
 */
#include "oscompat.h"
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <asm/io.h>

#include "framewrk.h"
#include "ossysenv.h"
#include "osmemory_ex.h"
#include "osstring_ex.h"

/******************************************************************************
	
	Function Name: OsPageReserve.

	Function Description:The function decommits a given memory space.

	Arguments: iPages - the base address of the memory space.
			   nPages - number of pages to be commited.
	

	Return Value: a pointer to the reserved memory space.

******************************************************************************/
PVOID OsPageReserve(UINT32 nPages, UINT32 Flags)
{
		PVOID temp = NULL;

		nPages *= PAGE_SIZE; // convert to bytes

		temp = vmalloc(nPages);
		if(!temp) {
			printk(KERN_ERR "%s: vmalloc(%ld) failed\n", __FUNCTION__, nPages);
			return NULL;
		}

		memset(temp, 0, nPages);
		return (temp);
}
 
/******************************************************************************
	
	Function Name: OsPageFree.

	Function Description:The function frees a given memory space.

	Arguments: iPages - the base address of the memory space.
			   nPages - number of pages to free.
	

	Return Value: BOOL

******************************************************************************/
BOOL OsPageFree(PVOID	pMem, UINT32 nPages)
{
		if ( NULL == pMem )
			return FALSE;
		vfree(pMem);
		return TRUE;
}
 
/******************************************************************************
	
	Function Name: OsHeapAllocate.

	Function Description:The function allocates a given memory space and initializes it to zero.

	Arguments: Size - the size of memory space (heap) to br allocated.
	
	Return Value: a pointer to the allocated memory..

******************************************************************************/
PVOID OsHeapAllocate(UINT32 Size, int flags)
{
	PVOID pMem;

	ASSERT((flags == OS_PAGED) || (flags == OS_NON_PAGED));

	pMem = kmalloc(Size, OSContextAllowsSleeping() ? GFP_KERNEL : GFP_ATOMIC);
	if(!pMem) {
	    printk(KERN_ERR "%s: kmalloc(%ld, %s) failed\n", __FUNCTION__, Size, OSContextAllowsSleeping() ? "GFP_KERNEL" : "GFP_ATOMIC");
	    return NULL;
	}

	memset(pMem, 0, Size);
	return pMem;
}
 
/******************************************************************************
	
	Function Name: OsHeapFree.

	Function Description:The function frees a memory space.

	Arguments: pMem - a pointer to the memory to be frees.
	
	Return Value: None.

******************************************************************************/
void OsHeapFree(PVOID pMem)
{
		kfree(pMem);
}
	
/******************************************************************************
 
	Function Name: OsGetPageSize.

	Function Description:The function returns the size of a page in the specific OS.

	Arguments: None.
	
	Return Value: The size of a page in the specific OS.

******************************************************************************/
UINT32	OsGetPageSize(void)
{
		return (PAGE_SIZE);
}
 
/******************************************************************************
	
	Function Name: OsMemDMAAllocate.

	Function Description:The function allocate a dma.

	Arguments: nPages - number of page to allocate..
			   ppPhysAddr - a pointer to be filled with the physical address of the dma.
			   pMemHandle - a pointer to be filled with the memory handle.
			   ppBuffer - a pointer to be filled with the ring-0 linear memory address.
	
	Return Value: boolean.

******************************************************************************/

//typedef struct *DMAALLOCATION PDMAALLOCATION;

//typedef struct tag_DMA_ALLOCATION 
//{
//	PUINT16 pBuff;
//	struct tag_DMA_ALLOCATION *next;
//}DMAALLOCATION, *PDMAALLOCATION;

BOOL	OsMemDMAAllocate(UINT32 nPages,PUINT16* ppPhysAddr, PHANDLE pMemHandle, PUINT16* ppBuffer)
{
	int count;
	unsigned long allocs[256];

	for ( count = 0 ; count < 256 ; count++  )
	{
		allocs[count] = __get_dma_pages(OSContextAllowsSleeping() ? GFP_KERNEL : GFP_ATOMIC, nPages);
		if ( !allocs[count] )
		{
			break;
		}

		if ( 0x0 == (((UINT32)(allocs[count])) & 0x0000FFFF) )
		{
			*ppBuffer = (PUINT16)allocs[count];
			if(pMemHandle)
				*pMemHandle = (PVOID) allocs[count];
			*ppPhysAddr = (PUINT16)virt_to_bus(*ppBuffer);
//			printk("OsMemDMAAllocate success - 0x%x(0x%x) after %d attempts\n",
//				   (int) allocs[count], (int) *ppPhysAddr, count);
			for ( count--; count >= 0; count-- )
			{
				free_pages(allocs[count], nPages);
			}
			return (TRUE);
		}
	}

	printk(KERN_ERR "%s: failed (attempt=%d, npages=%ld)\n", __FUNCTION__, count, nPages);

	for ( count--; count >= 0; count-- )
		free_pages(allocs[count], nPages);

	return (FALSE);
}
 
/******************************************************************************
	
	Function Name: OsMemDMAFree.

	Function Description:The function allocate a dma.

	Arguments: MemHandle - a memory handle.
			   Flags - flags.
	
	Return Value: boolean.

******************************************************************************/
BOOL	OsMemDMAFree(HANDLE MemHandle, UINT32 nPages)
{
		if (NULL == MemHandle)
			return (FALSE);

		ASSERT(nPages > 0);

//		printk( "OsMemDMAFree: freeing 0x%lx (%d pages)\n", MemHandle, nPages );
		free_pages((unsigned long)MemHandle, nPages);
		return (TRUE);
}

