1/* 2 File: IrEvent.cpp 3 Contains: Implementation of IrDATool to IrDA glue 4 5 6*/ 7 8#include "IrEvent.h" 9#include "CList.h" 10#include "CListIterator.h" 11#include "CBufferSegment.h" 12#include "IrDALog.h" 13 14#define private static 15 16#if (hasTracing > 0 && hasIrEventTracing > 0) 17 18enum TraceCodes 19{ 20 kLogInitEventLists = 1, 21 kLogDeleteEventList, 22 23 kAllocateEventBlock, 24 kGrabEventBlock, 25 kReleaseEventBlock, 26 27 kLogReleaseErr1, 28 kLogReleaseErr2, 29 kLogReleaseErr3, 30 31 kLogGrabErr1, 32 kLogGrabErr2, 33 kLogGrabErr3 34 /* 35 kLogChecking, 36 kLogCheckOk, 37 kLogCheckFailed, 38 39 kLogCList, 40 kLogCListSize, 41 kLogCListElemSize, 42 kLogCListChunk, 43 44 kLogCListAllocated, 45 kLogCListBuffer, 46 kLogCListIters, 47 kLogCListContents 48 */ 49 50}; 51 52private 53EventTraceCauseDesc TraceEvents[] = { 54 55 {kLogInitEventLists, "IrEvent: Init event block lists"}, 56 {kLogDeleteEventList, "IrEvent: Delete event list, contents=, count="}, 57 58 {kAllocateEventBlock, "IrEvent: Allocate Event Block, list size="}, 59 {kGrabEventBlock, "IrEvent: Grab Event Block"}, 60 {kReleaseEventBlock, "IrEvent: Release Event Block"}, 61 62 {kLogReleaseErr1, "IrEvent: Release ERROR, not on in use list, err="}, 63 {kLogReleaseErr2, "IrEvent: Release ERROR, in use list="}, 64 {kLogReleaseErr3, "IrEvent: Release ERROR, in use size, members="}, 65 66 {kLogGrabErr1, "IrEvent: Grab ERROR, failed to add to in-use list, err="}, 67 {kLogGrabErr2, "IrEvent: Grab ERROR, in use list="}, 68 {kLogGrabErr3, "IrEvent: Grab ERROR, in use size, members="} 69 70 /* 71 72 {kLogChecking, "IrEvent: checking event="}, 73 {kLogCheckOk, "IrEvent: check passed, index="}, 74 {kLogCheckFailed, "IrEvent: check failed, size,members="}, 75 76 {kLogCList, "IrEvent: clist obj="}, 77 {kLogCListSize, "IrEvent: clist size="}, 78 {kLogCListElemSize, "IrEvent: clist element size="}, 79 {kLogCListChunk, "IrEvent: clist chunk size="}, 80 81 {kLogCListAllocated, "IrEvent: clist allocated size="}, 82 {kLogCListBuffer, "IrEvent: clist buffer="}, 83 {kLogCListIters, "IrEvent: clist iters="}, 84 {kLogCListContents, "IrEvent: clist data"} 85 */ 86}; 87 88#define XTRACE(x, y, z) IrDALogAdd (x, y, (uintptr_t)z & 0xffff, TraceEvents, true ) 89#else 90 #define XTRACE(x, y, z) ((void)0) 91#endif 92 93// 94// review: make these static entries in the event record? 95// 96CList *gFreeEventList = nil; 97CList *gInUseEventList = nil; 98void DeleteEventListItems(CList *eventlist, Boolean check_contents); 99 100//-------------------------------------------------------------------------------- 101#define super OSObject 102 OSDefineMetaClassAndStructors(TIrEvent, OSObject); 103 104//-------------------------------------------------------------------------------- 105 106 107//-------------------------------------------------------------------------------- 108// InitEventLists 109//-------------------------------------------------------------------------------- 110/* static */ 111IrDAErr 112TIrEvent::InitEventLists() 113{ 114 XTRACE(kLogInitEventLists, 0, 0); 115 116 ncheck(gFreeEventList); 117 ncheck(gInUseEventList); 118 119 // sanity checks on sizes of overlaid classes 120 // todo: switch to simple union. 121 check(sizeof(TIrLargestEvent) >= sizeof(TIrEvent)); 122 check(sizeof(TIrLargestEvent) >= sizeof(TIrDiscoverEvent)); 123 check(sizeof(TIrLargestEvent) >= sizeof(TIrExtDiscoverEvent)); 124 check(sizeof(TIrLargestEvent) >= sizeof(TIrLSAPConnEvent)); 125 check(sizeof(TIrLargestEvent) >= sizeof(TIrConnectEvent)); 126 check(sizeof(TIrLargestEvent) >= sizeof(TIrDataXferEvent)); 127 check(sizeof(TIrLargestEvent) >= sizeof(TIrLookupEvent)); 128 129 // initial debugging 130 /* 131 XTRACE(kLogInitEventBlockList, sizeof(TIrLargestEvent), sizeof(TIrEvent)); 132 XTRACE(kLogInitEventBlockList, sizeof(TIrLargestEvent), sizeof(TIrDiscoverEvent)); 133 XTRACE(kLogInitEventBlockList, sizeof(TIrLargestEvent), sizeof(TIrExtDiscoverEvent)); 134 XTRACE(kLogInitEventBlockList, sizeof(TIrLargestEvent), sizeof(TIrLSAPConnEvent)); 135 XTRACE(kLogInitEventBlockList, sizeof(TIrLargestEvent), sizeof(TIrConnectEvent)); 136 XTRACE(kLogInitEventBlockList, sizeof(TIrLargestEvent), sizeof(TIrDataXferEvent)); 137 XTRACE(kLogInitEventBlockList, sizeof(TIrLargestEvent), sizeof(TIrLookupEvent)); 138 */ 139 140 // Init the lists of ir event block's 141 gFreeEventList = CList::cList(); 142 require(gFreeEventList, Fail); 143 144 gInUseEventList = CList::cList(); 145 require(gInUseEventList, Fail); 146 147 return noErr; 148 149Fail: 150 if (gFreeEventList) gFreeEventList->release(); 151 gFreeEventList->release(); 152 153 if (gInUseEventList) gInUseEventList->release(); 154 gInUseEventList->release(); 155 156 return kIrDAErrNoMemory; 157 158} // TIrEvent::InitEventLists 159 160 161//-------------------------------------------------------------------------------- 162// DeleteEventLists 163//-------------------------------------------------------------------------------- 164/* static */ 165void 166TIrEvent::DeleteEventLists(void) 167{ 168 if (gFreeEventList) { // free events off our free list 169 DeleteEventListItems(gFreeEventList, false); 170 gFreeEventList->release(); 171 gFreeEventList = nil; 172 } 173 if (gInUseEventList) { // free allocated events, and their contents too 174 DeleteEventListItems(gInUseEventList, true); 175 gInUseEventList->release(); 176 gInUseEventList = nil; 177 } 178} // DeleteEventLists 179 180void 181DeleteEventListItems(CList *eventlist, Boolean check_contents) 182{ 183 XTRACE(kLogDeleteEventList, check_contents, eventlist->GetArraySize()); 184 185 if (eventlist->GetArraySize() > 0) { 186 TIrEvent *event; 187 188 // removing from end is much faster 189 for (int index = eventlist->GetArraySize() - 1; index >= 0 ; index--) { 190 event = (TIrEvent*)eventlist->At(index); 191 eventlist->RemoveAt(index); 192 require(event, Fail); 193 XTRACE(kLogDeleteEventList, 0, event); 194 XTRACE(kLogDeleteEventList, 0, event->fEvent); 195 /** this appears to not work well ... 196 if (check_contents) { 197 switch (event->fEvent) { 198 case kIrPutDataRequestEvent: 199 case kIrPutDataReplyEvent: 200 { 201 TIrPutEvent *putevent = (TIrPutEvent *)event; 202 CBufferSegment *buf; 203 buf = OSDynamicCast(CBufferSegment, putevent->fData); 204 if (buf) 205 IOLog("Could have freed 0x%lx\n", (UInt32) buf); 206 else 207 IOLog("logic err in event/buf stuff\n"); 208 } 209 break; 210 } 211 } 212 ****/ 213 event->release(); 214 } 215 } 216Fail: 217 return; 218 219} // DeleteEventListItems 220 221 222//-------------------------------------------------------------------------------- 223// GrabEventBlock 224//-------------------------------------------------------------------------------- 225/*static*/ 226TIrEvent * 227TIrEvent::GrabEventBlock(ULong event, ULong size) 228{ 229#pragma unused(size) 230 TIrEvent* eventBlock = nil; 231 IrDAErr err; 232 233 require(gFreeEventList, Fail_New_EventBlock); 234 require(gInUseEventList, Fail_New_EventBlock); 235 236 check( size <= sizeof( TIrLargestEvent ) ); 237 238 if (gFreeEventList->GetArraySize() > 0) { 239 // Pull last one off list (more efficient that way) 240 eventBlock = (TIrEvent *)gFreeEventList->Last(); 241 require(eventBlock, Fail_New_EventBlock); 242 check(eventBlock->fAllocated == false); 243 gFreeEventList->RemoveLast(); 244 } 245 else { 246 // List is empty, so allocate a new one 247 XTRACE(kAllocateEventBlock, gInUseEventList->GetArraySize(), gFreeEventList->GetArraySize()); 248 eventBlock = TIrLargestEvent::tIrLargestEvent(); 249 require(eventBlock, Fail_New_EventBlock); 250 } 251 252 err = gInUseEventList->InsertLast(eventBlock); // keep a list of allocated events 253 ncheck(err); 254 if (err) { 255 XTRACE(kLogGrabErr1, err >> 16, err); 256 XTRACE(kLogGrabErr2, 0, gInUseEventList); 257 XTRACE(kLogGrabErr3, 0, gInUseEventList->GetArraySize()); 258 /*for (int index = 0; index < gInUseEventList->GetArraySize(); index++ ) { 259 ULong member; 260 member = (ULong)gInUseEventList->At(index); 261 XTRACE(kLogGrabErr3, member >> 16, member); 262 }*/ 263 } 264 //check(CheckAllocated(eventBlock)); 265 266 eventBlock->fEvent = (UByte)event; 267 eventBlock->fClient = nil; 268 eventBlock->fDest = nil; 269 eventBlock->fResult = noErr; 270 eventBlock->fAllocated = true; 271 272Fail_New_EventBlock: 273 XTRACE( kGrabEventBlock, 0, eventBlock); 274 275 return eventBlock; 276 277} // TIrEvent::GrabEventBlock 278 279 280//-------------------------------------------------------------------------------- 281// ReleaseEventBlock 282//-------------------------------------------------------------------------------- 283/*static*/ 284void 285TIrEvent::ReleaseEventBlock(TIrEvent * eventBlock) 286{ 287 XTRACE( kReleaseEventBlock, 0, eventBlock); 288 require(eventBlock, Fail); 289 require(eventBlock->fAllocated == true, Fail); 290 291 if (gInUseEventList) { // take it off the in-use list 292 IrDAErr err; 293 err = gInUseEventList->Remove(eventBlock); 294 ncheck(err); 295 if (err) { 296 XTRACE(kLogReleaseErr1, err >> 16, err); 297 XTRACE(kLogReleaseErr2, 0, gInUseEventList); 298 XTRACE(kLogReleaseErr3, 0, gInUseEventList->GetArraySize()); 299 /* 300 for (int index = 0; index < gInUseEventList->GetArraySize(); index++ ) { 301 ULong member; 302 member = (ULong)gInUseEventList->At(index); 303 XTRACE(kLogReleaseErr3, member >> 16, member); 304 }*/ 305 } 306 } 307 308 eventBlock->fAllocated = false; 309 310 if (gFreeEventList) { // add it to the free list 311 gFreeEventList->InsertLast(eventBlock); 312 } 313 else { // this probably won't happen anymore ... 314 eventBlock->release(); 315 } 316 317 318Fail: 319 return; 320 321} // TIrEvent::ReleaseEventBlock 322 323#if (hasTracing > 0 && hasIrEventTracing > 1) 324 325 326 327#endif // #if hasIrEventTracing > 1 328 329 330#undef super 331#define super TIrEvent 332 OSDefineMetaClassAndStructors(TIrLargestEvent, TIrEvent); 333//-------------------------------------------------------------------------------- 334// TIrLargestEvent::tIrLargestEvent 335//-------------------------------------------------------------------------------- 336/*static*/ 337TIrLargestEvent * 338TIrLargestEvent::tIrLargestEvent() 339{ 340 TIrLargestEvent *obj; 341 342 obj = new TIrLargestEvent; 343 if (obj && !obj->init()) { 344 obj->release(); 345 obj = nil; 346 } 347 return obj; 348} 349 350 351#pragma mark ------ Code recycle bin 352#ifdef never 353 354Boolean 355TIrEvent::CheckAllocated(TIrEvent * eventBlock) 356{ 357 int index; 358 XTRACE(kLogChecking, (int)eventBlock >> 16, eventBlock); 359 360 if (gInUseEventList) { 361 DumpCList(gInUseEventList); // dump the clist to xtrace buffer 362 363 index = gInUseEventList->GetIdentityIndex(eventBlock); 364 if (index >= 0) { 365 XTRACE(kLogCheckOk, 0, index); 366 return true; 367 } 368 else { 369 IOLog("Event check failed\n"); 370 371 XTRACE(kLogCheckFailed, 0xffff, 0xffff); 372 /* 373 for (int index = 0; index < gInUseEventList->GetArraySize(); index++ ) { 374 ULong member; 375 member = (ULong)gInUseEventList->At(index); 376 XTRACE(kLogCheckFailed, member >> 16, member); 377 }*/ 378 return false; 379 } 380 } 381 return false; 382} 383 384void DumpCList(CList *list) 385{ 386 XTRACE(kLogCList, (int)list >> 16, list); 387 XTRACE(kLogCListSize, list->fSize >> 16, list->fSize); 388 XTRACE(kLogCListElemSize, list->fElementSize >> 16, list->fElementSize); 389 XTRACE(kLogCListChunk, list->fChunkSize >> 16, list->fChunkSize); 390 391 XTRACE(kLogCListAllocated, list->fAllocatedSize >> 16, list->fAllocatedSize); 392 XTRACE(kLogCListBuffer, (int)list->fArrayBlock >> 16, list->fArrayBlock); 393 XTRACE(kLogCListIters, (int)list->fIterator >> 16, list->fIterator); 394 395 if (list->fElementSize == 4 && list->fArrayBlock) { // sanity 396 int i; 397 UInt32 *block = (UInt32 *)list->fArrayBlock; 398 399 for (i = 0 ; i < list->fAllocatedSize; i++) { 400 UInt32 x; 401 x = *block++; 402 XTRACE(kLogCListContents, x >> 16, x); 403 } 404 } 405} 406 407#endif // never 408 409