/* * 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 * */ #ifdef UNDEFINED To do: options: continuous until ^c raw data to disk Cocoa app Log to file Reset or clear buffer #endif // UNDEFINED //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int DumpLog(); void OutputBuffer(); // FILE* CreateLogFile(); // make the output file // 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 }; typedef struct /* User Client Request structure: */ { UInt32 reqID; /* kGMACUserCmd_GetLog */ UInt8 *pLogBuffer; /* address of the 64KB buffer */ UInt32 logBufferSz; /* size of the 64KB buffer */ } UCRequest; /* Globals: */ UCRequest gUCRequest; /* Prototypes: */ io_object_t getInterfaceWithName( mach_port_t masterPort, char *className ); int main( int argc, char **argv ) { if ( argc == 1 ) return DumpLog(); /// else if ( argc == 3 ) return DumpRemoteLog( argc, argv ); printf( "usage: %s # to dump UniNEnet log on local machine\n", argv[0] ); return 1; }/* end main */ /* Search the registry for an IONetworkInterface object with */ /* the given name. If a match is found, the object is returned. */ 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, /* recursive */ &ite ); if ( kr != kIOReturnSuccess ) { printf( "IORegistryCreateIterator() error %08lx\n", (unsigned long)kr); return 0; } while ( (obj = IOIteratorNext( ite )) ) { if ( IOObjectConformsTo( obj, (char*)className ) ) { // printf( "Found UniNEnet UserClient !!\n" ); break; } else { rc = IOObjectGetClass( obj, name ); if ( rc == kIOReturnSuccess ) { // printf( "Skipping class %s\n", name ); } } IOObjectRelease( obj ); obj = 0; } IORegistryDisposeEnumerator( ite ); return obj; }/* end getInterfaceWithName */ FILE* CreateLogFile() { time_t now; struct tm *lt; char filename[ 100 ]; time( &now ); lt = localtime( &now ); sprintf( filename, "log.%d.%d.%02d%02d.%02d", lt->tm_mon+1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec ); printf( "Writing log to %s\n", filename ); return fopen( filename, "w" ); }/* end CreateLogFile */ void OutputBuffer() { char buffer[ 256 ]; UInt32 *pl; // pointer to LONG UInt8 lefty; // leftmost byte of event UInt32 microsec; // approx microsecond UInt32 i, x, p1, p2; buffer[ 4 ] = 0; // for ending 4 ASCII char string. pl = (UInt32*)gUCRequest.pLogBuffer; x = pl[ 3 ] - pl[ 1 ] - 0x30; // calc relative offset of next entry to log printf( "\n\t%8lx %8lx %8lx %8lx\t[%lx:]\n", pl[0], pl[1], pl[2], pl[3], x ); pl += 4; printf( "\t%8lx %8lx %8lx %8lx\n", pl[0], pl[1], pl[2], pl[3] ); pl += 4; printf( "\t%8lx %8lx %8lx %8lx\n", pl[0], pl[1], pl[2], pl[3] ); pl += 4; for ( i = 3; i < gUCRequest.logBufferSz / 0x10; ++i ) { if ( *pl == 0xDEBEEFED || *pl == 0 ) break; lefty = *(UInt8*)pl; microsec = *pl++ & 0x00FFFFFF; p1 = *pl++; p2 = *pl++; *(UInt32*)buffer = *pl++; printf( "%8lx: %3d %6ld %8lx %8lx\t%s\n", i * 0x10, lefty, microsec, p1, p2, buffer ); } *(UInt32*)gUCRequest.pLogBuffer = 0xFeedBeef; // get the juices flowing again. return; }/* end OutputBuffer */ int DumpLog() { mach_port_t masterPort; io_object_t netif; // network interface io_connect_t conObj; // connection object kern_return_t kr; /// FILE *out; UCRequest inStruct; UInt32 outSize = sizeof( UCRequest ); // Get master device port kr = IOMasterPort( bootstrap_port, &masterPort ); if ( kr != KERN_SUCCESS ) { printf( "IOMasterPort() failed: %08lx\n", (unsigned long)kr ); return -1; } netif = getInterfaceWithName( masterPort, "UniNEnet" ); if ( !netif ) { printf( "getInterfaceWithName failed.\n" ); exit( 0 ); } kr = IOServiceOpen( netif, mach_task_self(), 'GMAC', &conObj ); if ( kr != kIOReturnSuccess ) { printf( "open device failed 0x%x\n", kr ); IOObjectRelease( netif ); exit( 0 ); } // printf( "open device succeeded.\n" ); inStruct.reqID = kGMACUserCmd_GetLog; /* Now we can get the elg buffer mapped into my space: */ kr = io_connect_method_structureI_structureO( conObj, /* connection object */ 0, /* method index for doRequest */ (void*)&inStruct, /* input struct */ sizeof( inStruct ), /* input size */ (void*)&gUCRequest, /* output struct */ (mach_msg_type_number_t*)&outSize ); /* output size */ if ( kr != kIOReturnSuccess ) { printf( "Request failed 0x%x\n", kr ); } else { // printf( "Request allegedly worked - buffer/size: %8lx/%lx\n", // (UInt32)gUCRequest.pLogBuffer, gUCRequest.logBufferSz ); /// out = CreateLogFile(); /// if ( out ) { OutputBuffer(); /// fclose( out ); } } IOServiceClose( conObj ); // printf( "Closed device.\n" ); IOObjectRelease( netif ); exit( 0 ); }/* end DumpLog */