#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 );
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
{
kSelectLoopbackMAC = 0x20,
kSelectLoopbackPHY = 0x21,
kRltkUserCmd_GetLog = 0x30, kRltkUserCmd_GetRegs = 0x31, kRltkUserCmd_GetOneReg = 0x32, kRltkUserCmd_WriteOneReg = 0x35, };
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 )
{
gInUCRequest.reqID = 0;
gInUCRequest.pBuffer = 0;
gInUCRequest.bufferSz = 0;
if ( argc == 2 && strcmp( argv[1], "MAC" ) == 0 )
return DoIt( kSelectLoopbackMAC );
if ( argc == 2 && strcmp( argv[1], "PHY" ) == 0 )
return DoIt( kSelectLoopbackPHY );
printf( "\n\t\t\tUsage:\n" );
printf( "\tto set Realtek ethernet loopback mode to PHY loopback or MAC loopback.\n" );
printf( "%s MAC\n", argv[0] );
printf( "%s PHY\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;
}
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 );
}
IOServiceClose( conObj );
IOObjectRelease( netif );
exit( 0 );
}