1/* 2 File: IrDALog.c 3 4 Contains: Logging support for IrDA. 5 6 Written by: Clark Donahue, Jim Guyton 7 8 Todo: add copyright 9 10 11*/ 12//#include <Kernel/kern/clock.h> 13#include <IOKit/IOLib.h> 14#include "IrDALog.h" 15#include "IrDADebugging.h" 16#include "IrDALogPriv.h" 17 18#ifndef nil 19#define nil 0 20#endif 21 22#define DEBUGGER(x) panic(x) // revisit this! 23 24/////////////////////////////////////////////////////////////////////////////////////////////////////// 25// Following moved to IrDALogPriv.h (or IrDADebugging.h) 26// 27//#define hasTracing 1 // set to one to have tracing, to zero to compile out 28//#define USE_IOLOG 1 // true if want to go to IOLog 29//#define IOSLEEPTIME 700 // ms delay after each IOLog 30//#define kEntryCount (10*1024) // Number of log entries. *** Change to runtime alloc? 31//#define kMaxModuleNames 50 // max number of clients (unique module names) 32//#define kMaxModuleNameLen 32 // max length of module name 33//#define kMaxIndex 200 // max event index (# of msgs) per module 34//#define kMsgBufSize (20*1024) // way overkill -- 20k for copies of msgs 35/////////////////////////////////////////////////////////////////////////////////////////////////////// 36 37 38#if (hasTracing > 0) 39 40char *GetCachedMsg(EventTraceCauseDesc *desc, UInt16 eventIndex); 41 42// Globals 43IrDAEventDesc fBuffer[kEntryCount+10]; // Buffer (+10 is hack so wrap race condition doesn't smash memory) 44 45#pragma export on // Start of public code 46#pragma mark Start Exported ------------- 47 48IrDALogHdr gIrDALog = { // the log header 49 &fBuffer[0], // fEventBuffer 50 0, // fEventIndex 51 0, // fPrintIndex 52 kEntryCount, // fNumEntries 53 true, // fTracingOn 54 false // fWrapped 55 //true // fWrappingEnabled 56}; 57 58#endif // hasTracing > 0 59 60 61#if (hasTracing > 0) 62#ifdef __cplusplus 63extern "C" 64#endif // __cplusplus 65void IrDALogAdd( UInt16 eventIndex, UInt16 data1, UInt16 data2, EventTraceCauseDesc * desc, Boolean timeStamp) 66{ 67 68 IrDAEventDesc *logEntry; 69 UInt32 cTime; 70 71 // sanity checks 72 require(eventIndex > 0, Fail); 73 require(desc, Fail); 74 75 if(!gIrDALog.fTracingOn) // nop if tracing not enabled 76 return; 77 78 eventIndex--; // FOO. EventIndex is 1 based instead of zero based. 79 80#if (USE_IOLOG > 0) 81 { 82 IOLog("%04x %04x %s\n", data1, data2, desc[eventIndex].description); 83 IOSleep(IOSLEEPTIME); // in ms 84 } 85#endif 86 87 if( gIrDALog.fEventIndex >= gIrDALog.fNumEntries ) { // Wrap if hit end of buffer (this one shouldn't be hit, sanity only) 88 gIrDALog.fEventIndex = 0; 89 if (gIrDALog.fEventIndex == gIrDALog.fPrintIndex) // if newly wrapped index now matches print index 90 gIrDALog.fWrapped = true; // then we've wrapped past it 91 } 92 93 logEntry = &gIrDALog.fEventBuffer[gIrDALog.fEventIndex++]; // Get the log entry pointer & incr ptr 94 95 if( gIrDALog.fEventIndex >= gIrDALog.fNumEntries) { // Wrap if hit end of buffer (this one should be hit) 96 gIrDALog.fEventIndex = 0; 97 } 98 99 if (gIrDALog.fEventIndex == gIrDALog.fPrintIndex) // if the (incr'd) index matches printing index 100 gIrDALog.fWrapped = true; // then we've wrapped past it 101 102 //if (gIrDALog.fWrappingEnabled == false && gIrDALog.fWrapped == true) // if not allowed to wrap 103 // return; 104 105 // 106 // Now that we have a record, get the current time (if requested) 107 // 108 if (timeStamp) { 109 AbsoluteTime now; 110 UInt64 nanoseconds; 111 clock_get_uptime(&now); 112 absolutetime_to_nanoseconds(now, &nanoseconds); 113 cTime = nanoseconds / 1000; // microseconds is plenty for me 114 } 115 else cTime = 0; 116 117 // Ok, stuff a log entry 118 logEntry->data1 = data1; // Stuff in the data 119 logEntry->data2 = data2; 120 logEntry->timeStamp = cTime; // log the time 121 logEntry->msg = GetCachedMsg(desc, eventIndex); // get pointer to copy of msg (or nil) 122 123Fail: 124 return; 125 126} // IrDALogAdd 127 128 129void 130IrDALogTracingOn(void) 131{ 132 gIrDALog.fTracingOn = true; 133} 134 135void 136IrDALogTracingOff(void) 137{ 138 gIrDALog.fTracingOn = false; 139} 140 141/* 142void 143IrDALogWrappingOn() 144{ 145 gIrDALog.fWrappingEnabled = true; 146} 147 148void 149IrDALogWrappingOff() 150{ 151 gIrDALog.fWrappingEnabled = false; 152} 153*/ 154 155#endif // hasTracing > 0 156 157#pragma mark Message Cache ------------- 158 159#if (hasTracing > 0) 160 161 162char gMsgBuf[kMsgBufSize]; // the big buffer for copies of msgs 163char gModuleNames[kMaxModuleNames][kMaxModuleNameLen]; // table client module names 164char *gMsgPtrs[kMaxModuleNames][kMaxIndex]; // pointers to copies of msgs 165char *gNextMsg = &gMsgBuf[0]; // pointer to next avail byte in gMsgBuf 166int gNextModuleIndex = 0; // index of next avail entry in gModuleNames 167 168UInt32 GetModuleIndex(EventTraceCauseDesc *desc); 169char *CopyMsg(const char *msg); 170 171//EventTraceCauseDesc* gDebugTable; // temp 172//UInt32 gDebugIndex; 173//char *gDebugMsg; 174//char **gDebugMsgAddr; 175//int gDebugSize; 176 177char * 178GetCachedMsg(EventTraceCauseDesc *desc, UInt16 eventIndex) 179{ 180 UInt32 moduleIndex; // index to module name in gModuleNames 181 char *msg; 182 183 // TEMP 184 //gDebugTable = desc; 185 //gDebugIndex = eventIndex; 186 187 // Sanity checks 188 if (desc[eventIndex].cause != (eventIndex + 1)) return nil; 189 if (eventIndex >= kMaxIndex) { 190 DEBUGGER("IrDALog: need to incr kMaxIndex"); 191 return nil; 192 } 193 194 // if msgcopy in the client array is already set, use that 195 // note: hopefully this will be true a lot more often than not 196 if (desc[eventIndex].msgcopy != nil) 197 return desc[eventIndex].msgcopy; 198 199 // Ok, haven't seen this event msg before. Find this module 200 // in our cache. 201 202 moduleIndex = GetModuleIndex(desc); // find existing module name or make new entry and return that 203 if (moduleIndex == -1) return nil; // error return if too many modules 204 205 // If msg is in the module table (but not in the client table) then 206 // the client has died and come back. Set all msgcopy ptrs for it. 207 if (gMsgPtrs[moduleIndex][eventIndex]) { 208 int i; 209 //DebugStr("\pAbout to set ptrs for an entire module"); 210 for (i = 0 ; i < kMaxIndex; i++) { 211 if (gMsgPtrs[moduleIndex][i]) // if a copy exists 212 desc[i].msgcopy = gMsgPtrs[moduleIndex][i]; // set the msgcopy ptr 213 } 214 return desc[eventIndex].msgcopy; 215 } 216 217 // Ok, time to make a copy of the msg 218 //gDebugMsg = desc[eventIndex].description; // TEMP 219 //gDebugMsgAddr = &desc[eventIndex].description; 220 //gDebugSize = sizeof(desc[0]); 221 222 msg = CopyMsg(desc[eventIndex].description); // get a copy of the msg 223 desc[eventIndex].msgcopy = msg; // save msg pointer in client! 224 gMsgPtrs[moduleIndex][eventIndex] = msg; // and in per-module table 225 return msg; 226} 227 228// This should be rewritten to use a hash table 229int gModuleIndex; 230 231UInt32 GetModuleIndex(EventTraceCauseDesc *desc) 232{ 233 int i; 234 const char *modstart; 235 int namelen; 236 char modulename[kMaxModuleNameLen]; // copy of module name (need the trailing null) 237 238 modstart = desc[0].description; // extract module name from 1st msg in client table 239 { const char *t; 240 t = strchr(modstart, ':'); 241 if (t == nil) return -1; 242 namelen = t - modstart; 243 if (namelen < 1 || namelen-1 > kMaxModuleNameLen) { // check length 244 DEBUGGER("IrDALog: rejecting module name(len)"); 245 return -1; 246 } 247 } 248 strncpy(modulename, modstart, namelen); // copy the name 249 modulename[namelen] = 0; // make it a C string 250 251 for (i = 0 ; i < gNextModuleIndex; i++) { // Sigh. Search the module table. 252 if (strcmp(modulename, gModuleNames[i]) == 0) { 253 gModuleIndex = i; 254 return i; // found it! 255 } 256 } 257 258 // Not in the current list of module names 259 // make a new entry 260 261 if (gNextModuleIndex < kMaxModuleNames) { // if room in the table 262 strlcpy(gModuleNames[gNextModuleIndex++], modulename, sizeof(gModuleNames[0])); // copy it in 263 gModuleIndex = gNextModuleIndex-1; 264 return gNextModuleIndex-1; 265 } 266 DEBUGGER("IrDALog: need to increase kMaxModuleNames"); 267 return -1; 268} 269 270 271// return ptr to a copy of the msg or nil if out of memory 272char *CopyMsg(const char *msg) 273{ 274 char *result; 275 int len; 276 277 result = gNextMsg; // start of next avail msg 278 len = strlen(msg) + 1; // how much to copy 279 280 if (gNextMsg + len >= &gMsgBuf[kMsgBufSize]) { // to many msgs? 281 DEBUGGER("IrDALog: need to incr kMsgBufSize"); 282 return nil; 283 } 284 285 memcpy(result, msg, len); // copy msg including null 286 gNextMsg += len; // incr avail ptr for next msg 287 288 return result; 289} 290 291IrDALogInfo gIrDALogInfo = { 292 &gIrDALog, sizeof(gIrDALog), 293 fBuffer, sizeof(fBuffer), 294 gMsgBuf, sizeof(gMsgBuf) }; 295 296 297IrDALogInfo * 298IrDALogGetInfo(void) 299{ 300 return &gIrDALogInfo; 301/* 302 if (info == nil) return; 303 info->hdr = &gIrDALog; 304 info->hdrSize = sizeof(gIrDALog); 305 info->eventLog = fBuffer; 306 info->eventLogSize = sizeof(fBuffer); 307 info->msgBuffer = gMsgBuf; 308 info->msgBufferSize = sizeof(gMsgBuf); 309*/ 310} 311 312void 313IrDALogReset(void) 314{ 315 gIrDALog.fEventIndex = 0; 316 gIrDALog.fPrintIndex = 0; 317 gIrDALog.fNumEntries = kEntryCount; 318 // don't reset fTracingOn 319 //gIrDALog.fTracingOn = true; 320 gIrDALog.fWrapped = false; 321 // don't reset fWrappingEnabled 322} 323 324#endif // hasTracing > 0 325 326 327 328