/* * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 2002 Apple Computer * * User Client CLI tool for the Sun GEM Ethernet Controller * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // find this elsewhere ... 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 /* request codes to send to the user client: */ { kGMACUserCmd_GetLog = 0x30, // get entire GMAC ELG buffer kGMACUserCmd_GetRegs = 0x31, // get all GMAC registers kGMACUserCmd_GetOneReg = 0x32, // get one particular GMAC register kGMACUserCmd_GetTxRing = 0x33, // get Tx DMA elements kGMACUserCmd_GetRxRing = 0x34, // get Rx DMA elements kGMACUserCmd_WriteOneReg = 0x35, // write one particular GMAC register kGMACUserCmd_ReadAllMII = 0x50, // read MII registers 0 thru 31 kGMACUserCmd_ReadMII = 0x51, // read one MII register kGMACUserCmd_WriteMII = 0x52 // write one MII register }; enum { // operation codes: kUsage, kReadAll, kReadOne, kWrite }; typedef struct /* User Client Request structure: */ { UInt32 reqID; /* kGMACUserCmd_GetLog */ UInt8 *pLogBuffer; /* buffer addr - really reg # */ UInt32 logBufferSz; /* buffer size - really value */ } UCRequest; /* Globals: */ UCRequest gUCRequest; /* Prototypes: */ io_object_t getInterfaceWithName( mach_port_t masterPort, char *className ); void Usage( char *myname ); void DumpMII( UInt16 phyAddr ); void DumpOneMII( UInt16 phyAddr, UInt16 regnum ); void WriteOneMII( UInt16 phyAddr, UInt16 regnum, UInt16 value ); int main( int argc, char** argv ) { int i, rc; UInt32 regnum, regval, phyAddr, op; phyAddr = 0xFF; op = kReadAll; for ( i = 1; i < argc; ++i ) { if ( strcmp( argv[ i ], "-h" ) == 0 ) { op = kUsage; break; } else if ( strcmp( argv[ i ], "-r" ) == 0 ) { if ( ++i >= argc ) { op = kReadAll; break; } rc = sscanf( argv[ i ], "%ld", ®num ); if ( rc != 1 || regnum > 31 ) { printf( "Bad register number?\n" ); return 0; } op = kReadOne; continue; }/* end IF -r */ else if ( strcmp( argv[ i ], "-w" ) == 0 ) { if ( i + 2 >= argc ) /* need to pick up register number and value. */ { printf( "Need register number and value for write.\n" ); return 0; } ++i; rc = sscanf( argv[ i ], "%ld", ®num ); if ( rc != 1 || regnum > 31 ) { printf( "Bad register number.\n" ); return 0; } ++i; if ( strncmp( argv[ i ], "0x", 2 ) == 0 ) // skip over any leading 0x argv[ i ] += 2; rc = sscanf( argv[ i ], "%lx", ®val ); if ( rc != 1 ) { printf( "Bad value.\n" ); return 0; } op = kWrite; continue; }/* end IF -w */ else if ( strcmp( argv[ i ], "-p" ) == 0 ) { if ( ++i >= argc ) /* need to pick up phy address. */ { printf( "PHY address not specified.\n" ); return 0; } rc = sscanf( argv[ i ], "%ld", &phyAddr ); if ( rc != 1 || phyAddr > 31 ) { printf( "Bad PHY address.\n" ); return 0; } continue; }/* end IF -p */ else { op = kUsage; break; } }/* end FOR arguments */ switch ( op ) { case kReadAll: printf( "\n\tReading all PHY registers:\n" ); DumpMII( phyAddr ); break; case kReadOne: printf( "Reading PHY register %ld:\n", regnum ); DumpOneMII( phyAddr, regnum ); break; case kWrite: printf( "Writing PHY register %ld with 0x%lx.\n", regnum, regval ); WriteOneMII( phyAddr, regnum, regval ); break; default: Usage( argv[0] ); break; } return 1; }/* end main */ void Usage( char *myname ) { printf( "Usage:\n" ); printf( " %s -h // Display this help text.\n", myname ); printf( " %s // Read all 32 registers from the default PHY address.\n", myname ); printf( " %s -r // ditto.\n", myname ); printf( " %s -r N // Read just register N from the default PHY address\n", myname ); printf( " %s -w N 0xValue // Write hex value V to register N at the default PHY address\n", myname ); printf( " %s -p A // Read all 32 registers from PHY at address A\n", myname ); printf( " %s -p A ... // Specify PHY at address A and do -r or -w\n", myname ); printf( " // Put -p first if using specific PHY address.\n" ); printf( "\n" ); return; }/* end Usage */ io_object_t getInterfaceWithName( mach_port_t masterPort, char *className ) { io_object_t obj = 0; io_iterator_t ite; io_name_t name; kern_return_t kr; kr = IORegistryCreateIterator( masterPort, kIOServicePlane, true, /* recursive */ &ite ); if ( kr != kIOReturnSuccess ) { printf( "IORegistryCreateIterator() error %08lx\n", (UInt32)kr ); return 0; } while ( (obj = IOIteratorNext( ite )) ) { if (IOObjectConformsTo( obj, (char*)className) ) { // printf( "Found our userClient '%s' !!\n", className ); break; } else { kr = IOObjectGetClass( obj, name ); if ( kr == kIOReturnSuccess ) { // printf( "Skipping class %s\n", name); } } IOObjectRelease( obj ); obj = 0; } IORegistryDisposeEnumerator( ite ); return obj; }/* end getInterfaceWithName */ void DumpMII( UInt16 phyAddr ) { mach_port_t masterPort; io_object_t netif; io_connect_t conObj; kern_return_t kr; int i; UCRequest inStruct; UInt16 buffer[ 33 ]; mach_msg_type_number_t bufferSize = sizeof( buffer ); // Get master device port kr = IOMasterPort( bootstrap_port, &masterPort ); if ( kr != KERN_SUCCESS ) { printf( "IOMasterPort() failed: %08lx\n", (UInt32)kr ); return; } netif = getInterfaceWithName( masterPort, "UniNEnet" ); if ( !netif ) return; // printf( "netif=0x%x\n", netif ); kr = IOServiceOpen( netif, mach_task_self(), 'GMAC', &conObj ); if ( kr == kIOReturnSuccess ) { inStruct.reqID = kGMACUserCmd_ReadAllMII; inStruct.pLogBuffer = (UInt8*)(phyAddr << 16); inStruct.logBufferSz = 0; /* Finally get the data: */ kr = io_connect_method_structureI_structureO( conObj, 0, /* method index */ (char*)&inStruct, sizeof( inStruct ), (UInt8*)&buffer, &bufferSize ); if ( kr == kIOReturnSuccess ) { // printf( "read all MII worked\n" ); for ( i = 0 ; i < 32; i++ ) { if ( (i & 3) == 0 ) printf( "\n[%2d]", i ); printf( "\t0x%04x", buffer[i] ); } printf( "\n" ); } else printf( "command/request failed 0x%x\n", kr ); IOServiceClose( conObj ); } else printf( "open device failed 0x%x\n", kr ); IOObjectRelease( netif ); printf( "\nEnd of PHY register dump.\n" ); return; }/* end DumpMII */ void DumpOneMII( UInt16 phyAddr, UInt16 regnum ) { mach_port_t masterPort; io_object_t netif; io_connect_t conObj; kern_return_t kr; UCRequest inStruct; UInt32 r = regnum; UInt16 buffer[ 3 ]; // 1 needed, just testing outsize mach_msg_type_number_t bufferSize = sizeof( buffer ); // Get master device port kr = IOMasterPort( bootstrap_port, &masterPort ); if ( kr != KERN_SUCCESS ) { printf( "IOMasterPort() failed: %08lx\n", (unsigned long)kr ); return; } netif = getInterfaceWithName( masterPort, "UniNEnet" ); if ( !netif ) return; // printf( "netif=0x%x\n", netif ); kr = IOServiceOpen( netif, mach_task_self(), 'GMAC', &conObj ); if ( kr != kIOReturnSuccess ) { printf( "open device failed 0x%x\n", kr ); return; } inStruct.reqID = kGMACUserCmd_ReadMII; inStruct.pLogBuffer = (UInt8*)(phyAddr << 16 | r); // buffer size is really reg number inStruct.logBufferSz = 0; // unused. /* Get the datum: */ kr = io_connect_method_structureI_structureO( conObj, 0, /* method index */ (char*)&inStruct, sizeof( inStruct ), (UInt8*)buffer, &bufferSize ); if ( kr == kIOReturnSuccess ) { // printf( "Read of PHY register successful.\n" ); printf( "PHY register[ %d ] 0x%04x\n", regnum, buffer[0] ); } else printf( "command/request failed 0x%x\n", kr ); IOServiceClose( conObj ); IOObjectRelease( netif ); return; }/* end DumpOneMII */ void WriteOneMII( UInt16 phyAddr, UInt16 regnum, UInt16 regval ) { mach_port_t masterPort; io_object_t netif; io_connect_t conObj; kern_return_t kr; UCRequest inStruct; UInt32 r = regnum; UInt8 dummy[ 9 ]; // 1 needed, just testing outsize mach_msg_type_number_t dummySize; // Get master device port kr = IOMasterPort( bootstrap_port, &masterPort ); if ( kr != KERN_SUCCESS ) { printf( "IOMasterPort() failed: %08lx\n", (UInt32)kr ); return; } netif = getInterfaceWithName( masterPort, "UniNEnet" ); if ( !netif ) return; // printf( "netif=0x%x\n", netif ); kr = IOServiceOpen( netif, mach_task_self(), 'GMAC', &conObj ); if ( kr == kIOReturnSuccess ) { inStruct.reqID = kGMACUserCmd_WriteMII; inStruct.pLogBuffer = (UInt8*)(phyAddr << 16 | r); inStruct.logBufferSz = regval; /* Set the PHY's register: */ kr = io_connect_method_structureI_structureO( conObj, 0, /* method index */ (char*)&inStruct, sizeof( inStruct ), dummy, &dummySize ); if ( kr == kIOReturnSuccess ) printf( "Write of PHY register successful.\n" ); else printf( "command/request failed 0x%x\n", kr ); IOServiceClose( conObj ); } else printf( "open device failed 0x%x\n", kr ); IOObjectRelease( netif ); return; }/* end WriteOneMII */