⛏️ index : haiku.git

// ****************************************************************************
//
//		OsSupportBeOS.cpp
//
//		Implementation file for BeOS support services to the CEchoGals
//		generic driver class
//		Set editor tabs to 3 for your viewing pleasure.
//
// ----------------------------------------------------------------------------
//
// This file is part of Echo Digital Audio's generic driver library.
// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
// All rights reserved
// www.echoaudio.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// ****************************************************************************

#include "OsSupportBeOS.h"

#include "EchoGalsXface.h"

#include <KernelExport.h>
#include "util.h"

//
//	Version information.
//	In NT, we want to get this from a resource
//
BYTE OsGetVersion()
{
	// Use EngFindResource, for now hard code
	return( 1 );	
}	// BYTE OsGetVersion()

BYTE OsGetRevision()
{
	// Use EngFindResource, for now hard code
	return( 0 );	
}	// BYTE OsGetRevision()

BYTE OsGetRelease()
{
	// Use EngFindResource, for now hard code
	return( 0 );	
}	// BYTE OsGetRelease()

//
//	Global Memory Management Functions
//
DWORD gAllocNonPagedCount = 0;

LIST_HEAD(mems, _echo_mem) mems;


static echo_mem *
echo_mem_new(size_t size)
{
	echo_mem *mem = NULL;

	if ((mem = (echo_mem*)malloc(sizeof(*mem))) == NULL)
		return (NULL);

	mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "echo buffer", true);
	mem->size = size;
	if (mem->area < B_OK) {
		free(mem);
		return NULL;
	}
	return mem;
}

static void
echo_mem_delete(echo_mem *mem)
{
	if(mem->area > B_OK)
		delete_area(mem->area);
	free(mem);
}

echo_mem *
echo_mem_alloc(size_t size)
{
	echo_mem *mem = NULL;

	mem = echo_mem_new(size);
	if (mem == NULL)
		return (NULL);

	LIST_INSERT_HEAD(&mems, mem, next);

	return mem;
}

void
echo_mem_free(void *ptr)
{
	echo_mem *mem = NULL;

	LIST_FOREACH(mem, &mems, next) {
		if (mem->log_base != ptr)
			continue;
		LIST_REMOVE(mem, next);

		echo_mem_delete(mem);
		break;
	}
}

void OsAllocateInit()
{
	gAllocNonPagedCount = 0;

	/* Init mems list */
	LIST_INIT(&mems);
}

// ***********************************************************************
//
//  Allocate locked, non-pageable block of memory.  Does not have to be
//	physically contiguous.  Primarily used to implement the overloaded
//	new operator.
//
// ***********************************************************************

ECHOSTATUS OsAllocateNonPaged
(
    DWORD	dwByteCt,				// Block size in bytes
    PPVOID	ppMemAddr				// Where to return memory ptr
)
{
	
	
	echo_mem * mem = echo_mem_alloc( dwByteCt );
	if(mem)
		*ppMemAddr = mem->log_base;
	
	if ( NULL == *ppMemAddr )
	{
		ECHO_DEBUGPRINTF( ("OsAllocateNonPaged : Failed on %ld bytes\n",
								 dwByteCt) );
		ECHO_DEBUGBREAK();				 
		return ECHOSTATUS_NO_MEM;
	}
	
	OsZeroMemory( *ppMemAddr, dwByteCt );
	
	gAllocNonPagedCount++;
	ECHO_DEBUGPRINTF(("gAllocNonPagedCount %ld\n",gAllocNonPagedCount));
	
	return ECHOSTATUS_OK;
	
}	// ECHOSTATUS OsAllocateNonPaged


// ***********************************************************************
//
// Unlock and free, non-pageable block of memory.
//
// ***********************************************************************
ECHOSTATUS OsFreeNonPaged
(
    PVOID	pMemAddr
)
{
	echo_mem_free( pMemAddr );

	gAllocNonPagedCount--;
	ECHO_DEBUGPRINTF(("gAllocNonPagedCount %ld\n",gAllocNonPagedCount));

	return ECHOSTATUS_OK;

}	// ECHOSTATUS OsFreeNonPaged



// ***********************************************************************
//
// This class is optional and uniquely defined for each OS.  It provides
//	information that other components may require.
// For example, in Windows NT it contains a device object used by various
//	memory management methods.
// Since static variables are used in place of globals, an instance must
//	be constructed and initialized by the OS Interface object prior to
//	constructing the CEchoGals derived object.  The CEchoGals and
//	CDspCommObject classes must have access to it during their respective 
// construction times.
//
// ***********************************************************************

COsSupport::COsSupport
(
	WORD				wDeviceId,		// PCI bus device ID
	WORD				wCardRev			// Card revision number
)
{
   ECHO_DEBUGPRINTF(("COsSupport::COsSupport born, device id = 0x%x.\n", wDeviceId));

	m_wDeviceId = wDeviceId;
	m_wCardRev = wCardRev;
}

COsSupport::~COsSupport()
{
	ECHO_DEBUGPRINTF(("COsSupport is all gone - m_dwPageBlockCount %ld\n",m_dwPageBlockCount));
}

//
//	Timer Methods
//

ECHOSTATUS COsSupport::OsGetSystemTime
(
	PULONGLONG	pullTime					// Where to return system time
)
{
	*pullTime = ULONGLONG(system_time());

	return ECHOSTATUS_OK;

}	// ECHOSTATUS COsSupport::OsGetSystemTime


ECHOSTATUS COsSupport::OsSnooze
(
	DWORD	dwTime						// Duration in micro seconds
)
{
	status_t status;
	status = snooze(bigtime_t(dwTime));
	switch (status) {
		case B_OK:
			return ECHOSTATUS_OK;
			break;
		case B_INTERRUPTED:
			return ECHOSTATUS_OPERATION_CANCELED; // maybe not appropriate, but anyway
			break;
		default:
			return ECHOSTATUS_NOT_SUPPORTED; // no generic error?
			break;
	}
}


//
//	Memory Management Methods
//

//---------------------------------------------------------------------------
//
//	Allocate a physical page block that can be used for DSP bus mastering.
//
//---------------------------------------------------------------------------

ECHOSTATUS COsSupport::AllocPhysPageBlock
(
	DWORD			dwBytes,
	PPAGE_BLOCK	&pPageBlock
)
{
	DWORD	dwRoundedBytes;
	
	//
	// Allocate
	//
	dwRoundedBytes = (dwBytes + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
	ECHO_DEBUGPRINTF(("COsSupport::AllocPhysPageBlock - dwBytes %ld  dwRoundedBytes %ld\n",
							dwBytes,dwRoundedBytes));
	
	pPageBlock = echo_mem_alloc ( dwRoundedBytes );

	if (NULL == pPageBlock)
	{
		ECHO_DEBUGPRINTF(("AllocPhysPageBlock failed for %ld bytes\n",dwBytes));

		pPageBlock = NULL;
		return ECHOSTATUS_NO_MEM;
	}
	
	ECHO_DEBUGPRINTF(("\tIOBufferMemoryDescriptor is OK\n"));

	OsZeroMemory( pPageBlock->log_base, dwRoundedBytes );
	
#ifdef _DEBUG
	m_dwPageBlockCount++;
	ECHO_DEBUGPRINTF(("\tm_dwPageBlockCount %ld\n",m_dwPageBlockCount));
#endif
	
	return ECHOSTATUS_OK;

}	// AllocPageBlock


//---------------------------------------------------------------------------
//
//	Free a physical page block
//
//---------------------------------------------------------------------------

ECHOSTATUS COsSupport::FreePhysPageBlock
(
	DWORD			dwBytes,
	PPAGE_BLOCK	pPageBlock
)
{
	echo_mem_free(pPageBlock->log_base);
	
#ifdef _DEBUG
	m_dwPageBlockCount--;
	ECHO_DEBUGPRINTF(("\tm_dwPageBlockCount %ld\n",m_dwPageBlockCount));
#endif
	
	return ECHOSTATUS_OK;
	
}	// FreePageBlock


//---------------------------------------------------------------------------
//
//	Get the virtual address for the buffer corresponding to the MDL
//
//---------------------------------------------------------------------------

PVOID COsSupport::GetPageBlockVirtAddress
(
	PPAGE_BLOCK	pPageBlock
)
{

	return pPageBlock->log_base;
		
}	// GetPageBlockVirtAddress


//---------------------------------------------------------------------------
//
//	Get the physical address for part of the buffer corresponding to the MDL
//
//---------------------------------------------------------------------------

ECHOSTATUS COsSupport::GetPageBlockPhysSegment
(
	PPAGE_BLOCK	pPageBlock,			// pass in a previously allocated block
	DWORD			dwOffset,			// pass in the offset into the block
	PHYS_ADDR	&PhysAddr,			// returns the physical address
	DWORD			&dwSegmentSize		// and the length of the segment
)
{

	PhysAddr = ((PHYS_ADDR)pPageBlock->phy_base + dwOffset);
	
	return ECHOSTATUS_OK;

} // GetPageBlockPhysSegment


//
// Add additional methods here
//

//
//	Display an error message w/title
//
void COsSupport::EchoErrorMsg(const char* pszMsg, const char* pszTitle)
{
}

PVOID COsSupport::operator new(size_t size)
{
	PVOID 		pMemory;

	pMemory = malloc(size);
	
	if ( NULL == pMemory )
	{
		ECHO_DEBUGPRINTF(("COsSupport::operator new - memory allocation failed\n"));

		pMemory = NULL;
	}
	else
	{
		memset( pMemory, 0, size );
	}
		
	return pMemory;
}

VOID COsSupport::operator delete(PVOID memory)
{
	free(memory);
}