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