AppleSamplePCIUserClient.cpp [plain text]
#include "AppleSamplePCI.h"
#include <IOKit/IOLib.h>
#include <IOKit/assert.h>
#define super IOUserClient
OSDefineMetaClassAndStructors( AppleSamplePCIUserClient, IOUserClient );
bool AppleSamplePCIUserClient::initWithTask( task_t owningTask, void * securityID,
UInt32 type, OSDictionary * properties )
{
IOLog("AppleSamplePCIUserClient::initWithTask(type %ld)\n", type);
fTask = owningTask;
return( super::initWithTask( owningTask, securityID, type, properties ));
}
bool AppleSamplePCIUserClient::start( IOService * provider )
{
IOLog("AppleSamplePCIUserClient::start\n");
if( !super::start( provider ))
return( false );
assert( OSDynamicCast( AppleSamplePCI, provider ));
fDriver = (AppleSamplePCI *) provider;
fClientSharedMemory = IOBufferMemoryDescriptor::withOptions(
kIOMemoryKernelUserShared, sizeof( AppleSampleSharedMemory ));
if( !fClientSharedMemory)
return( false );
fClientShared = (AppleSampleSharedMemory *) fClientSharedMemory->getBytesNoCopy();
fClientShared->field1 = 0x11111111;
fClientShared->field2 = 0x22222222;
fClientShared->field3 = 0x33333333;
strcpy( fClientShared->string, "some data" );
fOpenCount = 1;
return( true );
}
IOReturn AppleSamplePCIUserClient::clientClose( void )
{
if( !isInactive())
terminate();
return( kIOReturnSuccess );
}
void AppleSamplePCIUserClient::stop( IOService * provider )
{
IOLog("AppleSamplePCIUserClient::stop\n");
if( fClientSharedMemory) {
fClientSharedMemory->release();
fClientShared = 0;
}
super::stop( provider );
}
IOExternalMethod * AppleSamplePCIUserClient::getTargetAndMethodForIndex(
IOService ** targetP, UInt32 index )
{
static const IOExternalMethod methodDescs[kAppleSampleNumMethods] = {
{ NULL, (IOMethod) &AppleSamplePCIUserClient::method1,
kIOUCStructIStructO, kIOUCVariableStructureSize, kIOUCVariableStructureSize },
{ NULL, (IOMethod) &AppleSamplePCIUserClient::method2,
kIOUCStructIStructO, sizeof(AppleSampleStructForMethod2), sizeof(AppleSampleResultsForMethod2) },
};
*targetP = this;
if( index < kAppleSampleNumMethods)
return( (IOExternalMethod *)(methodDescs + index) );
else
return NULL;
}
IOReturn AppleSamplePCIUserClient::externalMethod(
uint32_t selector, IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch, OSObject * target, void * reference )
{
return (super::externalMethod(selector, arguments, NULL, this, NULL));
IOReturn err;
switch (selector)
{
case kAppleSampleMethod1:
err = method1( (UInt32 *) arguments->structureInput,
(UInt32 *) arguments->structureOutput,
arguments->structureInputSize, (IOByteCount *) &arguments->structureOutputSize );
break;
case kAppleSampleMethod2:
err = method2( (AppleSampleStructForMethod2 *) arguments->structureInput,
(AppleSampleResultsForMethod2 *) arguments->structureOutput,
arguments->structureInputSize, (IOByteCount *) &arguments->structureOutputSize );
break;
default:
err = kIOReturnBadArgument;
break;
}
IOLog("externalMethod(%d) 0x%x", selector, err);
return (err);
}
IOReturn AppleSamplePCIUserClient::method1(
UInt32 * dataIn, UInt32 * dataOut,
IOByteCount inputSize, IOByteCount * outputSize )
{
IOReturn ret;
IOItemCount count;
IOLog("AppleSamplePCIUserClient::method1(");
if( *outputSize < inputSize)
return( kIOReturnNoSpace );
count = inputSize / sizeof( UInt32 );
for( UInt32 i = 0; i < count; i++ ) {
IOLog("%08lx, ", dataIn[i]);
dataOut[i] = dataIn[i] ^ 0xffffffff;
}
ret = kIOReturnSuccess;
IOLog(")\n");
*outputSize = count * sizeof( UInt32 );
return( ret );
}
IOReturn AppleSamplePCIUserClient::method2( AppleSampleStructForMethod2 * structIn,
AppleSampleResultsForMethod2 * structOut,
IOByteCount inputSize, IOByteCount * outputSize )
{
IOReturn err;
IOMemoryDescriptor * memDesc = 0;
UInt32 param1 = structIn->parameter1;
mach_vm_address_t clientAddr = structIn->data_pointer;
mach_vm_size_t size = structIn->data_length;
IOLog("AppleSamplePCIUserClient::method2(%lx)\n", param1);
IOLog( "fClientShared->string == \"%s\"\n", fClientShared->string );
structOut->results1 = 0x87654321;
do
{
memDesc = IOMemoryDescriptor::withAddress( clientAddr, size, kIODirectionNone, fTask );
if( !memDesc) {
IOLog("IOMemoryDescriptor::withAddress failed\n");
} else {
memDesc->release();
}
memDesc = IOMemoryDescriptor::withAddressRange( clientAddr, size, kIODirectionNone, fTask );
if( !memDesc) {
IOLog("IOMemoryDescriptor::withAddress failed\n");
err = kIOReturnVMError;
continue;
}
err = memDesc->prepare( kIODirectionOutIn );
if( kIOReturnSuccess != err) {
IOLog("IOMemoryDescriptor::prepare failed(%x)\n", err);
continue;
}
err = fDriver->generateDMAAddresses(memDesc);
char pioBuffer[ 200 ];
memDesc->readBytes(32, &pioBuffer, sizeof( pioBuffer));
IOLog("readBytes: \"%s\"\n", pioBuffer);
IOMemoryMap * memMap = memDesc->map();
if( memMap) {
char * address = (char *) memMap->getVirtualAddress();
IOLog("kernel mapped: \"%s\"\n", address + 32);
memMap->release();
} else
IOLog("memDesc map(kernel) failed\n");
memMap = memDesc->map(fTask, 0, kIOMapAnywhere);
if( memMap)
{
IOVirtualAddress address32 = memMap->getVirtualAddress();
IOLog("user32 mapped: 0x%x\n", address32);
mach_vm_address_t address64 = memMap->getAddress();
IOLog("user64 mapped: 0x%qx\n", address64);
memMap->release();
} else
IOLog("memDesc map(user) failed\n");
memDesc->complete( kIODirectionOutIn );
} while( false );
if( memDesc)
memDesc->release();
return( err );
}
IOReturn AppleSamplePCIUserClient::clientMemoryForType(
UInt32 type,
IOOptionBits * options,
IOMemoryDescriptor ** memory )
{
IOReturn ret;
IOLog("AppleSamplePCIUserClient::clientMemoryForType(%ld)\n", type);
switch( type ) {
case kAppleSamplePCIMemoryType1:
fClientSharedMemory->retain();
*memory = fClientSharedMemory;
ret = kIOReturnSuccess;
break;
case kAppleSamplePCIMemoryType2:
*memory = fDriver->copyGlobalMemory();
ret = kIOReturnSuccess;
break;
default:
ret = kIOReturnBadArgument;
break;
}
return( ret );
}