/*
 *   Creation Date: <2002/01/09 22:43:20 samuel>
 *   Time-stamp: <2002/01/20 21:55:13 samuel>
 *   
 *	<MolExt.cpp>
 *	
 *	
 *   
 *   Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se)
 *   
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation
 *   
 */

#include "archinclude.h"
#include "alloc.h"

#include "MolExt.h"
#include "MolUserClient.h"

extern "C" {
#include "version.h"
#include "misc.h"
#include "kernel_vars.h"
}


#define super IOService
OSDefineMetaClassAndStructors( MolExt, IOService )

void *
map_phys_range( ulong paddr, ulong size, char **ret_addr )
{
	IOMemoryDescriptor *desc;
	IOMemoryMap *m;
	
	if( !(desc = IOMemoryDescriptor::withPhysicalAddress( paddr, size, kIODirectionOutIn )) )
		return NULL;

	if( !(m = desc->map( kIOMapAnywhere | kIOMapCopybackCache )) ) {
		desc->release();
		return NULL;
	}
	*ret_addr = (char*)m->getVirtualAddress();

	IOLog("map_phys_range called\n");
	return (void*)desc;
}

void
unmap_phys_range( void *handle )
{
	IOMemoryDescriptor *desc = (IOMemoryDescriptor*)handle;
	desc->release();
}


/************************************************************************/
/*	MolExt Object							*/
/************************************************************************/


bool
MolExt::init( OSDictionary *dictionary )
{
	bool res = super::init(dictionary);
	return res;
}

void
MolExt::free( void )
{
	super::free();
}

bool
MolExt::attach( IOService *provider )
{
	bool res = super::attach( provider );
	return res;
}

void
MolExt::detach( IOService *provider )
{
	super::detach(provider);
}

IOService *
MolExt::probe( IOService *provider, SInt32 *score )
{
	IOService *res = super::probe( provider, score );
	return res;
}

bool
MolExt::start( IOService *provider )
{
	bool res = super::start( provider );

	if( init_module() )
		return kIOReturnError;

        registerService();
	return res;
}

void
MolExt::stop( IOService *provider )
{
	IOLog("MolExt::stop - before\n");
	cleanup_module();
	IOLog("MolExt::stop - after\n");
	super::stop( provider );
}


/************************************************************************/
/*	F U N C T I O N S						*/
/************************************************************************/

IOReturn 
MolExt::newUserClient( task_t owningTask, void *security_id, UInt32 type, IOUserClient **handler )
{
	IOUserClient *newConnect = 0;
	
	IOLog("NewUserClient: Type %ld\n", type );

	newConnect = MolUserClient::withTask(owningTask);

	if( newConnect ) {
		if( !newConnect->attach(this) || !newConnect->start(this) ){
			newConnect->detach(this);
			newConnect->release();
			newConnect = 0;
		}
	}

	*handler = newConnect;
	return kIOReturnSuccess;
}


#if 0
/************************************************************************/
/*	Experimental							*/
/************************************************************************/

IOReturn
MolExt::clientFunc0( void )
{
	IOLog("clientFunc0 scalled - YES IT REALLY WORKS!\n");
	return kIOReturnSuccess;
}

IOReturn
MolExt::clientFunc1( int arg1, int arg2 )
{
	IOLog("clientFunc1 called %d %d\n", arg1, arg2 );
	return kIOReturnSuccess;
}

IOReturn
MolExt::clientFunc2( int arg1, int *ret1 )
{
	*ret1 = arg1*2;
	IOLog("clientFunc2 called %d\n", arg1 );
	return kIOReturnSuccess;
}

/* ScalarIStructI 2,0xffffffff */
IOReturn
MolExt::clientFunc3( int arg1, int arg2, int *data, IOByteCount size  )
{
	IOLog("clientFunc3 called %d %d %08X %ld\n", 
	      arg1, arg2, (int)data, size );
	IOLog("data[0]=%d, data[1]=%d, data[2]=%d, data[3]=%d\n", 
	      data[0],data[1], data[2], data[3] );
	return kIOReturnSuccess;
}

/* StructIStructO (0xfffff,0xfffff) */
IOReturn
MolExt::clientFunc4( int *in, int *out, IOByteCount inSize, IOByteCount *outSize )
{
	IOLog("clientFunc4 %d %d %d %d\n", 
	      (int)in, (int)out, (int)inSize, (int)outSize );
	return kIOReturnSuccess;
}

/* ScalarIStructO ( 2,sizeof(retdata) ) */
IOReturn
MolExt::clientFunc5( int scalar1, int scalar2, void *retdata )
{
	IOLog("clientFunc5 %d %d %d\n", scalar1, scalar2, (int)retdata );
	*(int*)retdata = 4;
	return kIOReturnSuccess;
}

/* ScalarIStructO ( 2,0xffffffff ) */
IOReturn
MolExt::clientFunc6( int scalar1, int scalar2, void *retdata, IOByteCount *length )
{
	IOLog("clientFunc6 %d %d %d %d\n", scalar1, scalar2, (int)retdata, (int)length );
	return kIOReturnBadArgument;
}

#endif
