#include <ctype.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFSerialize.h>
#include <IOKit/network/IONetworkLib.h>
#include <IOKit/IOTypes.h>
#include <mach/mach.h>
#include <mach/mach_interface.h>
#include <sys/time.h>
#include <sys/file.h>
int DoIt( int );
void OutputBuffer();
kern_return_t io_connect_method_structureI_structureO
(
mach_port_t connection,
int selector,
io_struct_inband_t input,
mach_msg_type_number_t inputCnt,
io_struct_inband_t output,
mach_msg_type_number_t *outputCnt
);
enum
{
kRltkUserCmd_GetLog = 0x30, kRltkUserCmd_GetRegs = 0x31, kRltkUserCmd_GetOneReg = 0x32, kRltkUserCmd_GetTxRing = 0x33, kRltkUserCmd_GetRxRing = 0x34, kRltkUserCmd_WriteOneReg = 0x35,
kRltkUserCmd_ReadAllMII = 0x50, kRltkUserCmd_ReadMII = 0x51, kRltkUserCmd_WriteMII = 0x52 };
typedef struct
{
UInt32 reqID;
UInt8 *pBuffer;
UInt32 bufferSz;
} UCRequest;
UCRequest gInUCRequest;
UInt8 gBuffer[ 4096 ];
kern_return_t doRequest( io_connect_t connection,
unsigned char reqID,
void *inputData,
unsigned long inputDataSize,
void *outputData,
mach_msg_type_number_t *outputDataSize );
io_object_t getInterfaceWithName( mach_port_t masterPort, char *className );
int main( int argc, char **argv )
{
UInt32 regNum, regValue;
int rc;
gInUCRequest.reqID = 0;
gInUCRequest.pBuffer = 0;
gInUCRequest.bufferSz = 0;
if ( argc == 1 )
return DoIt( kRltkUserCmd_GetRegs );
if ( argc == 2 && strcmp( argv[1], "-r" ) == 0 )
return DoIt( kRltkUserCmd_GetRegs );
if ( argc == 3 && strcmp( argv[1], "-r" ) == 0 )
{
rc = sscanf( argv[2], "%lx", ®Num );
if ( rc == 1 && regNum < 0x9060 )
{
gInUCRequest.pBuffer = (UInt8*)regNum;
return DoIt( kRltkUserCmd_GetOneReg );
}
else
printf( "Bad register number?\n" );
return 0;
}
if ( argc == 4 && strcmp( argv[1], "-w" ) == 0 )
{
if ( strncmp( argv[2], "0x", 2) == 0 ) argv[2] += 2;
rc = sscanf( argv[2], "%lx", ®Num );
if ( rc == 1 && regNum < 0x9060 )
{
if ( strncmp( argv[3], "0x", 2) == 0 ) argv[3] += 2;
rc = sscanf( argv[3], "%lx", ®Value );
if ( rc == 1 )
{
gInUCRequest.pBuffer = (UInt8*)regNum;
gInUCRequest.bufferSz = regValue;
return DoIt( kRltkUserCmd_WriteOneReg );
}
else
printf( "Bad value?\n" );
}
else
printf( "Bad register number?\n" );
return 0;
}
printf( "\n\t\t\tUsage:\n" );
printf( "%s\t\tto dump all Rltk registers.\n", argv[0] );
printf( "%s -r\t\t\t\tditto.\n", argv[0] );
printf( "%s -r 0xAAAA \t\tto dump Rltk register AAAA.\n", argv[0] );
printf( "%s -w 0xAAAA VVVVVVVV\tto write Rltk register AAAA with VVVVVVVVV.\n", argv[0] );
return 1;
}
io_object_t getInterfaceWithName( mach_port_t masterPort, char *className )
{
io_iterator_t ite;
io_object_t obj = 0;
io_name_t name;
kern_return_t rc;
kern_return_t kr;
kr = IORegistryCreateIterator( masterPort,
kIOServicePlane,
true,
&ite );
if ( kr != kIOReturnSuccess )
{
printf( "IORegistryCreateIterator() error %08lx\n", (unsigned long)kr );
return 0;
}
while ( (obj = IOIteratorNext( ite )) )
{
if ( IOObjectConformsTo( obj, (char*)className ) )
{
break;
}
else
{
rc = IOObjectGetClass( obj, name );
if ( rc == kIOReturnSuccess )
{
}
}
IOObjectRelease( obj );
obj = 0;
}
IORegistryDisposeEnumerator( ite );
return obj;
}
void OutputBuffer()
{
UInt8 *pb = (UInt8*)gBuffer; UInt32 i;
for ( i = 0; i < 0x80; i++ )
{
if ( (i & 0xF) == 0 )
printf( "\n%02x:", (unsigned int)i );
if ( (i & 0x3) == 0 )
printf( " " );
printf( " %02x", pb[i] );
}
printf( "\n\n\tEnd of Realtek register dump.\n\n" );
return;
}
int DoIt( int doWhat )
{
mach_port_t masterPort;
io_object_t netif; io_connect_t conObj; kern_return_t kr;
UInt32 outSize = sizeof( gBuffer );
kr = IOMasterPort( bootstrap_port, &masterPort );
if ( kr != KERN_SUCCESS )
{
printf( "IOMasterPort() failed: %08lx\n", (unsigned long)kr );
exit( 0 );
}
netif = getInterfaceWithName( masterPort, "com_apple_driver_RTL8139" );
if ( !netif )
{
printf( "getInterfaceWithName failed.\n" );
exit( 0 );
}
kr = IOServiceOpen( netif, mach_task_self(), 'Rltk', &conObj );
if ( kr != kIOReturnSuccess )
{
printf( "open device failed 0x%x\n", kr );
IOObjectRelease( netif );
exit( 0 );
}
gInUCRequest.reqID = doWhat;
kr = io_connect_method_structureI_structureO(
conObj,
0,
(void*)&gInUCRequest,
sizeof( gInUCRequest ),
(void*)&gBuffer,
(mach_msg_type_number_t*)&outSize );
if ( kr != kIOReturnSuccess )
{
printf( "Request failed 0x%x\n", kr );
}
else
{
switch ( doWhat )
{
case kRltkUserCmd_GetRegs:
OutputBuffer();
break;
case kRltkUserCmd_GetOneReg:
printf( "Register %04lx: %08lx\n", (UInt32)gInUCRequest.pBuffer, *(UInt32*)gBuffer );
break;
case kRltkUserCmd_WriteOneReg:
printf( "Writing register %02lx with %08lx.\n",
(UInt32)gInUCRequest.pBuffer, gInUCRequest.bufferSz );
break;
}
}
IOServiceClose( conObj );
IOObjectRelease( netif );
exit( 0 );
}